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+
161216void 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