Skip to content

Commit 0ab7284

Browse files
Sploder12Real-Septicake
authored andcommitted
Add page fault test
gcc makes things so difficult
1 parent 0afde9d commit 0ab7284

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed

tests/expected/os/paging.expect

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ test_composition done
22
test_identity done
33
test_swap done
44
test_modify_in_place done
5+
test_entry_not_present done

tests/src/os/paging.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "../test_helper.h"
22

3+
#include <../os/hard/idt.h>
34
#include <../os/paging.h>
45

56
// 1st megabyte is a safe place to read from, but not to write to
@@ -158,6 +159,60 @@ void test_modify_in_place(PageDirectory *base) {
158159
serialWrite(COM1, (uint8_t *)(done), sizeof(done) - 1);
159160
}
160161

162+
volatile uint32_t errCode = -1;
163+
164+
void test_handler(isr_registers_t *regs) {
165+
errCode = regs->err_code;
166+
167+
// We are manually incrementing the instruction pointer.
168+
// This is to avoid faulting on the same instruction forever.
169+
// But it can cause some unexpected things to happen.
170+
regs->eip++;
171+
}
172+
173+
void assert_on_fault_code(uint32_t expected) {
174+
InterruptState iprev = disableInterrupts();
175+
uint32_t got = errCode;
176+
errCode = -1;
177+
setInterrupts(iprev);
178+
179+
// ASSERT must be called with interrupts enabled!
180+
ASSERT_M(expected == got, "Expected %i but got %i as fault error code.",
181+
expected, got);
182+
}
183+
184+
void test_entry_not_present(PageDirectory *base) {
185+
// steal the 3MiB page and 2 more
186+
PageDirectory *newDir = (PageDirectory *)(MiB3);
187+
PageTable *tables = (PageTable *)(MiB3 + sizeof(PageDirectory));
188+
189+
// setup identity paged dir
190+
addTableToDirectory(newDir, 0, tables, DEFAULT_ENTRY_FLAGS);
191+
addTableToDirectory(newDir, 1, tables + 1, DEFAULT_ENTRY_FLAGS);
192+
193+
identityMapTable(newDir, 0, DEFAULT_ENTRY_FLAGS);
194+
identityMapTable(newDir, 1, ENTRY_RW | ENTRY_US);
195+
196+
setActivePageDir(newDir);
197+
198+
volatile uint32_t *faulter = (uint32_t *)(BOUND);
199+
200+
// cause a page fault
201+
*faulter;
202+
203+
// this nop helps eip++ not do bad things
204+
__asm__ volatile("nop");
205+
206+
// confusingly, the not present error code is 0.
207+
assert_on_fault_code(0);
208+
209+
// swap back
210+
setActivePageDir(base);
211+
212+
char done[] = "test_entry_not_present done\n";
213+
serialWrite(COM1, (uint8_t *)(done), sizeof(done) - 1);
214+
}
215+
161216
void test_main() {
162217
test_composition();
163218

@@ -169,4 +224,9 @@ void test_main() {
169224
test_swap_page(idDir);
170225

171226
test_modify_in_place(idDir);
227+
228+
// beware the page fault handler is overriden from this point on.
229+
isrSetHandler(14, test_handler);
230+
231+
test_entry_not_present(idDir);
172232
}

0 commit comments

Comments
 (0)