Rukog wrote:
Else the CPU does a reset since it cannot execute code or read data that share multiple pages.
No.
IA-32/x86-64 have weak rules regarding aligment. Any code can cross (linear) page boundaries. Any (application) data can cross page boundaries. At most you will have performance penalties.
It's specifically paging data that was the problem in this example. Any given paging structure must appear entirely on a single physical page of memory. For practical purposes, this needs to be for one reason. CR3 and the paging structures (e.g. page table entries) only have bits available for the Top-20- (32-bit paging) or Top-40- (PAE and Long Mode) -bits of of the paging structures physical address. This means it is impossible for you to reference a page table, page directory etc. with any other alignment.
EDIT: I'd like to harp on about this a little more...
Really think about this code.
Code:
mov DWORD [p4_table], p3_table + (PG_PRESENT + PG_WRITE + PG_READABLE)
mov DWORD [p3_table], p2_table + (PG_PRESENT + PG_WRITE + PG_READABLE)
mov DWORD [p2_table], p1_table + (PG_PRESENT + PG_WRITE + PG_READABLE)
Imagine your tables are misaligned such that p3_table is 0x8003. Then the first line becomes,
Code:
mov DWORD [p4_table], 0x8003 + (PG_PRESENT + PG_WRITE + PG_READABLE)
Ignoring the (intentional) flags for a second. This means you are placing the value 0x0000000000008003 in the first P4 entry. Go to page 132 of
https://software.intel.com/content/dam/develop/external/us/en/documents-tps/253668-sdm-vol-3a.pdf and look at the structures. The "Address of page-directory-pointer table " is being set to 0xXXX0000000008XXX (where X is outside the value "Address of page-directory-pointer table " and I put it there to make it it a 64-bit number).
The 0x3 is being places in the lower part of the structure, setting the present and read/write flags.
Worse yet, because you add, rather than or'ing, your flags, you then do the sum 0x8003 + 1 + 2 + 4, giving a value of 0x800A. In this value, you are clearing the Present, Supervisor bits, setting the writable bit, and accidentally setting the page write through caching flag. This lack of present flag is what probably caused the triple fault, as the processor could have never known you intended to use a mis-aligned page.
Incidentally, I'm not sure about,
Code:
%define PG_READABLE (1 << 2)
According the my reading of the page I linked above, this sets the User/Supervisor flag, not a flag setting read permissions.