8#include "pedigree/kernel/Log.h"
9#include "pedigree/kernel/process/Event.h"
10#include "pedigree/kernel/process/Ipc.h"
11#include "pedigree/kernel/processor/PhysicalMemoryManager.h"
12#include "pedigree/kernel/processor/Processor.h"
13#include "pedigree/kernel/processor/ProcessorInformation.h"
14#include "pedigree/kernel/processor/VirtualAddressSpace.h"
15#include "pedigree/kernel/utilities/MemoryPool.h"
17static_assert(Event::getHostedHandlerBufferSize(1024) == EVENT_LIMIT);
18static_assert(Event::getHostedHandlerBufferSize(4096) == EVENT_LIMIT);
19static_assert(Event::getHostedHandlerBufferSize(16384) == 16384);
20static_assert(Ipc::IpcMessage::getHostedInlinePageCount(1024) == 4);
21static_assert(Ipc::IpcMessage::getHostedInlinePageCount(4096) == 1);
22static_assert(Ipc::IpcMessage::getHostedInlinePageCount(16384) == 1);
23static_assert(Ipc::IpcMessage::getHostedInlineSlotSize(1024) == 4096);
24static_assert(Ipc::IpcMessage::getHostedInlineSlotSize(4096) == 4096);
25static_assert(Ipc::IpcMessage::getHostedInlineSlotSize(16384) == 16384);
26static_assert(Ipc::IpcMessage::getHostedInlinePoolPageCount(1024) == 4096);
27static_assert(Ipc::IpcMessage::getHostedInlinePoolPageCount(4096) == 1024);
28static_assert(Ipc::IpcMessage::getHostedInlinePoolPageCount(16384) == 1024);
31bool check(
bool condition,
const char* test,
const char* detail) {
35 ERROR(
"HOSTED-WAIT-TEST: FAIL " << test <<
": " << detail);
39bool eventPayloadGeometry() {
40 constexpr const char* Test =
"event-payload-page-span";
42 const size_t pageCount = (EVENT_LIMIT / pageSize) + ((EVENT_LIMIT % pageSize) ? 1 : 0);
43 const size_t expectedSpan = pageCount * pageSize;
46 passed &= check(Event::getHostedHandlerBufferSize(1024) == EVENT_LIMIT, Test,
47 "a 4 KiB event did not span four 1 KiB pages");
48 passed &= check(Event::getHostedHandlerBufferSize(4096) == EVENT_LIMIT, Test,
49 "the 4 KiB target changed its event slot size");
50 passed &= check(Event::getHostedHandlerBufferSize(16384) == 16384, Test,
51 "a sub-page event slot was not rounded to one target page");
53 "the live event slot does not match target-page geometry");
55 (EVENT_TID_MAX * MAX_NESTED_EVENTS * expectedSpan),
56 Test,
"the reserved handler-buffer range does not use the rounded slot span");
58 NOTICE(
"HOSTED-WAIT-TEST: PASS event-payload-page-span");
63bool multiPagePoolMapping() {
64 constexpr const char* Test =
"memory-pool-page-span";
65 constexpr size_t PageCount = 4;
67 if (pageSize > (~
size_t{0} / PageCount)) {
68 return check(
false, Test,
"the target page size overflows the regression buffer");
71 MemoryPool pool(
"hosted-payload-page-regression");
72 if (!pool.initialise(PageCount, PageCount * pageSize)) {
73 return check(
false, Test,
"the multi-page pool could not be initialised");
76 const uintptr_t buffer = pool.allocateNow();
77 bool passed = check(buffer != 0, Test,
"the multi-page buffer could not be allocated");
80 for (
size_t page = 0; page < PageCount; ++page) {
81 passed &= check(va.
isMapped(
reinterpret_cast<void*
>(buffer + (page * pageSize))), Test,
82 "allocation left part of the buffer unmapped");
86 passed &= check(pool.trim(), Test,
"the released multi-page buffer was not reclaimed");
87 for (
size_t page = 0; page < PageCount; ++page) {
88 passed &= check(!va.
isMapped(
reinterpret_cast<void*
>(buffer + (page * pageSize))), Test,
89 "trim left part of the buffer mapped");
94 NOTICE(
"HOSTED-WAIT-TEST: PASS memory-pool-page-span");
99bool ipcPayloadGeometry() {
100 constexpr const char* Test =
"ipc-payload-page-span";
103 "the conventional inline IPC capacity changed");
104 passed &= check(Ipc::IpcMessage::getHostedInlinePageCount(1024) == 4, Test,
105 "the 4 KiB IPC buffer did not span four 1 KiB pages");
106 passed &= check(Ipc::IpcMessage::getHostedInlinePageCount(4096) == 1, Test,
107 "the 4 KiB target changed its IPC buffer span");
108 passed &= check(Ipc::IpcMessage::getHostedInlinePageCount(16384) == 1, Test,
109 "the IPC buffer used more than one 16 KiB page");
110 passed &= check(Ipc::IpcMessage::getHostedInlineSlotSize(1024) == 4096 &&
111 Ipc::IpcMessage::getHostedInlineSlotSize(4096) == 4096 &&
112 Ipc::IpcMessage::getHostedInlineSlotSize(16384) == 16384,
113 Test,
"an inline IPC slot shared a target page with another message");
114 passed &= check(Ipc::IpcMessage::getHostedInlinePoolPageCount(1024) == 4096 &&
115 Ipc::IpcMessage::getHostedInlinePoolPageCount(4096) == 1024 &&
116 Ipc::IpcMessage::getHostedInlinePoolPageCount(16384) == 1024,
117 Test,
"the IPC pool did not retain its logical buffer capacity");
120 uint8_t* buffer =
reinterpret_cast<uint8_t*
>(inlineMessage.getBuffer());
121 passed &= check(buffer !=
nullptr && inlineMessage.getHandle() ==
nullptr, Test,
122 "an inline IPC message did not use the message pool");
126 const size_t pageCount = Ipc::IpcMessage::getHostedInlinePageCount(pageSize);
127 passed &= check(!(
reinterpret_cast<uintptr_t
>(buffer) & (pageSize - 1)), Test,
128 "the inline IPC slot was not target-page aligned");
129 for (
size_t page = 0; page < pageCount; ++page) {
130 void* address = buffer + (page * pageSize);
131 const bool mapped = va.
isMapped(address);
132 passed &= check(mapped, Test,
"part of the inline IPC buffer is unmapped");
139 Test,
"part of the inline IPC buffer is not user-writable");
145 "the inline IPC payload was not writable end-to-end");
149 passed &= check(sharedMessage.getBuffer() !=
nullptr && sharedMessage.getHandle() !=
nullptr,
150 Test,
"the exact 4 KiB threshold did not use a shared region");
152 NOTICE(
"HOSTED-WAIT-TEST: PASS ipc-payload-page-span");
158bool runHostedPayloadPageRegressions() {
159 return eventPayloadGeometry() && multiPagePoolMapping() && ipcPayloadGeometry();
static size_t getHandlerBufferSize()
static uintptr_t getLastHandlerBuffer()
static uintptr_t getHandlerBuffer()
static constexpr size_t InlineCapacity
static constexpr size_t getPageSize() PURE
static ProcessorInformation & information()
virtual bool isMapped(void *virtualAddress)=0
static const size_t KernelMode
virtual bool getMapping(void *virtualAddress, physical_uintptr_t &physicalAddress, size_t &flags)=0
static const size_t Write
static EXPORTED_PUBLIC VirtualAddressSpace & getKernelAddressSpace()
uintptr_t physicalAddress(physical_uintptr_t address) PURE