Re: GDT reset code seems to have no effect
Posted: Thu Jan 26, 2023 11:25 am
I was able to confirm that the reset_gdt() function is overwriting the boot_data table, specifically in the call to memset(). Here is the results when watching boot->mem_table in gdb.
I now think that it is due to a problem in my boot loader's default page definitions, but I am not certain where. Here is what comes up when I use info mem in the QEMU monitor.
This appears to show that the page table identity maps the first 1MiB, and then maps the first 18 MiB in the higher half region, which is in fact what I intended.
The current version of the bootloader paging code is
The variables in question are defined in the linker script, as shown earlier.
My suspicion is that there is an issue in the physical->virtual address mapping, but I don't see where - as things stand, I am (or at least I think I am) defining the page tables particularly sparsely - all of the page entries are fully populated, and the physical addresses are spread out over the full 4 MiB range. I am aware that this is far from necessary, but I was doing it deliberately to limit the risk of overlapping. Apparently, this caution was not enough.
Code: Select all
(gdb) c
Continuing.
Hardware watchpoint 3: -location boot_data->mem_table
Old value = {{base = 0, length = 654336, type = 1, ext = 1}, {base = 654336, length = 1024, type = 2, ext = 1}, {base = 983040, length = 65536, type = 2, ext = 1}, {base = 1048576, length = 133038080, type = 1, ext = 1}, {base = 134086656, length = 131072, type = 2, ext = 1}, {base = 4294705152, length = 262144, type = 2, ext = 1}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}}
New value = {{base = 0, length = 589824, type = 1, ext = 1}, {base = 654336, length = 1024, type = 2, ext = 1}, {base = 983040, length = 65536, type = 2, ext = 1}, {base = 1048576, length = 133038080, type = 1, ext = 1}, {base = 134086656, length = 131072, type = 2, ext = 1}, {base = 4294705152, length = 262144, type = 2, ext = 1}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}}
memset (ptr=0x0, value=0 '\000', num=28145) at src/mem.c:46
46 while (num--)
(gdb) c
Continuing.
Hardware watchpoint 3: -location boot_data->mem_table
Old value = {{base = 0, length = 589824, type = 1, ext = 1}, {base = 654336, length = 1024, type = 2, ext = 1}, {base = 983040, length = 65536, type = 2, ext = 1}, {base = 1048576, length = 133038080, type = 1, ext = 1}, {base = 134086656, length = 131072, type = 2, ext = 1}, {base = 4294705152, length = 262144, type = 2, ext = 1}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}}
New value = {{base = 0, length = 0, type = 1, ext = 1}, {base = 654336, length = 1024, type = 2, ext = 1}, {base = 983040, length = 65536, type = 2, ext = 1}, {base = 1048576, length = 133038080, type = 1, ext = 1}, {base = 134086656, length = 131072, type = 2, ext = 1}, {base = 4294705152, length = 262144, type = 2, ext = 1}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}}
memset (ptr=0x0, value=0 '\000', num=28144) at src/mem.c:46
46 while (num--)
(gdb) c
Continuing.
Hardware watchpoint 3: -location boot_data->mem_table
Old value = {{base = 0, length = 0, type = 1, ext = 1}, {base = 654336, length = 1024, type = 2, ext = 1}, {base = 983040, length = 65536, type = 2, ext = 1}, {base = 1048576, length = 133038080, type = 1, ext = 1}, {base = 134086656, length = 131072, type = 2, ext = 1}, {base = 4294705152, length = 262144, type = 2, ext = 1}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}}
New value = {{base = 0, length = 0, type = 0, ext = 1}, {base = 654336, length = 1024, type = 2, ext = 1}, {base = 983040, length = 65536, type = 2, ext = 1}, {base = 1048576, length = 133038080, type = 1, ext = 1}, {base = 134086656, length = 131072, type = 2, ext = 1}, {base = 4294705152, length = 262144, type = 2, ext = 1}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}, {base = 0, length = 0, type = 0, ext = 0}}
memset (ptr=0x0, value=0 '\000', num=28138) at src/mem.c:46
Code: Select all
(qemu) info mem
0000000000000000-0000000000100000 0000000000100000 -r-
00000000c0000000-00000000c1800000 0000000001800000 -r-
The current version of the bootloader paging code is
Code: Select all
%ifndef _PAGING__INC__
%define _PAGING__INC__
%define PDE_Present 0b00000000000000000000000000000001
%define PDE_Read_Write 0b00000000000000000000000000000010
%define PDE_User 0b00000000000000000000000000000100
%define PDE_Write_Thru 0b00000000000000000000000000001000
%define PDE_Cache_Disable 0b00000000000000000000000000010000
%define PDE_Acccessed 0b00000000000000000000000000100000
%define PDE_Dirty 0b00000000000000000000000001000000
%define PDE_Page_Size 0b00000000000000000000000010000000
%define PDE_Global 0b00000000000000000000000100000000
%define PDE_Availability_Mask 0b00000000000000000000111000000000
%define PDE_Page_Attr_Table 0b00000000000000000001000000000000
%define PDE_Page_Index_Mask 0b11111111111111111110000000000000
%define PTE_Present 0b00000000000000000000000000000001
%define PTE_Read_Write 0b00000000000000000000000000000010
%define PTE_User 0b00000000000000000000000000000100
%define PTE_Write_Through 0b00000000000000000000000000001000
%define PTE_Cache_Disable 0b00000000000000000000000000010000
%define PTE_Acccessed 0b00000000000000000000000000100000
%define PTE_Dirty 0b00000000000000000000000001000000
%define PTE_Page_Attr_Table 0b00000000000000000000000010000000
%define PTE_Global 0b00000000000000000000000100000000
%define PTE_Availability_Mask 0b00000000000000000000111000000000
%define PTE_Page_Index_Mask 0b11111111111111111111000000000000
%macro populate_pte 4
; set up the page table
mov ebx, dword %1 ; location to save the table entry
mov ecx, dword %2 ; number of entries to fill
mov eax, dword %3 ; the physical address to map
memset32 0, 0x1000, ebx ; clear the table entries
%%pt_fill:
mov edx, eax
and edx, PTE_Page_Index_Mask ; clear the flags before setting them
or edx, %4 ; flags
mov [ebx], dword edx
add eax, 0x1000
add ebx, 4
loop %%pt_fill
%endmacro
%macro populate_pde 3
mov ebx, page_directory
mov eax, %1 ; directory entry address
add ebx, %2 * 4 ; directory entry index
or eax, %3 ; flags
mov [ebx], eax
%endmacro
%endif
Code: Select all
%ifndef _PAGING_CODE__INC__
%define _PAGING_CODE__INC__
%include "paging.inc"
%line 0, "paging.asm"
bits 32
page_directory equ 0x0040000
page_table_0x0000 equ page_directory + 0x1000
page_table_0x0300 equ page_table_0x0000 + 0x1000
page_table_0x0301 equ page_table_0x0300 + 0x1000
page_table_0x0302 equ page_table_0x0301 + 0x1000
page_table_0x0303 equ page_table_0x0302 + 0x1000
page_table_0x0304 equ page_table_0x0303 + 0x1000
page_table_0x0305 equ page_table_0x0304 + 0x1000
init_page_directory:
mov ebx, dword page_directory
memset32 0, 0x1000, ebx ; clear the page dir table
populate_pte page_table_0x0000, 0x0100, 0x00000000, PTE_Present
populate_pte page_table_0x0300, 0x1000, 0x00100000, PTE_Present
populate_pte page_table_0x0301, 0x1000, 0x00400000, PTE_Present
populate_pte page_table_0x0302, 0x1000, 0x00800000, PTE_Present
populate_pte page_table_0x0303, 0x1000, 0x00C00000, PTE_Present
populate_pte page_table_0x0304, 0x1000, 0x01000000, PTE_Present
populate_pte page_table_0x0305, 0x1000, 0x01400000, PTE_Present
.setup_directory:
populate_pde page_table_0x0000, 0x0000, PDE_Present
populate_pde page_table_0x0300, 0x0300, PDE_Present
populate_pde page_table_0x0301, 0x0301, PDE_Present
populate_pde page_table_0x0302, 0x0302, PDE_Present
populate_pde page_table_0x0303, 0x0303, PDE_Present
populate_pde page_table_0x0304, 0x0304, PDE_Present
populate_pde page_table_0x0305, 0x0305, PDE_Present
; set the page directory
mov eax, page_directory
mov cr3, eax
ret
%endif
My suspicion is that there is an issue in the physical->virtual address mapping, but I don't see where - as things stand, I am (or at least I think I am) defining the page tables particularly sparsely - all of the page entries are fully populated, and the physical addresses are spread out over the full 4 MiB range. I am aware that this is far from necessary, but I was doing it deliberately to limit the risk of overlapping. Apparently, this caution was not enough.