computing the page directory and page table entries

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
User avatar
Schol-R-LEA
Member
Member
Posts: 1925
Joined: Fri Oct 27, 2006 9:42 am
Location: Athens, GA, USA

computing the page directory and page table entries

Post by Schol-R-LEA »

I have been working on my kernel paging code, and specifically have been working on a function which
  • takes a physical address, a virtual address, a memory block size, and a set of flags,
  • computes which page directory and page table entries corresponding to the beginning and end of the virtual memory block,
  • populates these corresponding page directory entries and page table entries with the physical addresses (auto-incremented by 4KiB for each table entry) and the set of flags.
For the time being, the page tables are stored in a single large table 4MiB in size, representing the whole virtual memory map; this is simply to simplify the design, and will probably get revamped later. The directory and table indices are used to index into this single map.

Code: Select all

#define PD_ENTRY_COUNT 0x0400
#define PT_ENTRY_COUNT 0x0400
#define PT_ENTRY_TOTAL_COUNT (PD_ENTRY_COUNT * PT_ENTRY_COUNT)


#define PAGE_SPAN 0x1000
#define PD_ENTRY_SPAN (PT_ENTRY_COUNT * PAGE_SPAN)

#define PD_SIZE (PD_ENTRY_COUNT * sizeof(union Page_Directory_Entry))
#define PT_SIZE (PT_ENTRY_TOTAL_COUNT * sizeof(union Page_Table_Entry))

Code: Select all

/* set a block of page directory and page table entries matching a block of memory */
void set_page_block(uint32_t phys_address,
                    uint32_t virt_address,
                    uint32_t block_size,
                    bool page_size, bool rw,
                    bool user, bool write_thru,
                    bool no_caching)
{
    // determine the page directory entry and page table entry
    // corresponding to the virtual address
    uint32_t pd_start = virt_address / PD_ENTRY_SPAN;
    uint32_t directory_offset = virt_address - (pd_start * PD_ENTRY_SPAN);
    uint32_t pe_start = directory_offset / PAGE_SPAN;

    // determine the page directory entry and page table entry
    // corresponding to the end of the block of memory
    uint32_t block_end = virt_address + block_size - 1;
    uint32_t pd_end = block_end / PD_ENTRY_SPAN;
    uint32_t trailing_block_size = block_size % PD_ENTRY_SPAN;
    uint32_t pe_end = pe_start + (trailing_block_size / PAGE_SPAN) - 1;

    size_t addr = phys_address;
    for (uint32_t pd_e = pd_start; pd_e < pd_end; pd_e++)
    {
        set_page_directory_entry(pd_e,
                                 addr,
                                 page_size, rw,
                                 user, write_thru,
                                 no_caching);

        for (uint32_t pt_e = pe_start; pt_e < PT_ENTRY_COUNT; pt_e++, addr += PAGE_SPAN)
        {
            set_page_table_entry(pd_e,
                                 pt_e,
                                 addr,
                                 page_size, rw,
                                 user, write_thru,
                                 no_caching);
        }
    }
}

I believe I have figured out how to compute the start and end indices correctly, as well as the index for the monoblock page table. At this time I have instrumented the code to print out the results of these calculations, and they appear to be correct for the test values I am using, though I probably need to test various edge cases to be sure. I can use to have some eyes on this code to be sure, if anyone is willing to take a look.

Image

I also have a driver function which calls this function with arguments which are intended to match those in my bootloader's paging code. While I am not pleased to have to manually repeat these values, the bigger issue is that I am having some trouble getting them to line up.

Code: Select all

void reset_default_paging(uint32_t map_size, struct memory_map_entry mt[KDATA_MAX_MEMTABLE_SIZE])
{

    // first, set all of the page directory entries to a default state
    memset(page_directory, 0, PD_SIZE);

    // do the same for all of the page table entries
    memset(page_tables, 0, PT_SIZE);

    // next, identity map the first 1MiB
    set_page_block(0, 0, 0x00100000, false, true, false, false, false);

    // map in the kernel region
    set_page_block(0x00100000, KERNEL_BASE, 0x00100000, false, true, false, false, false);

    // map in the various tables
    set_page_block(0x00400000, (size_t) tables_base, 0x01000000, false, true, false, false, false);

    // map in the stack
    set_page_block(0x01400000, (size_t) &kernel_stack_base, 0x4000, false, true, false, false, false);


    // reset the paging address control register
    // to point to the new page directory
/*     __asm__ __volatile__ (
    "    mov %0, %%cr3"
    :
    : "a" (page_directory)
    );

    // confirm that the paging bit is set
    // in the main control register
    __asm__ __volatile__ (
    "    mov %cr0, %eax;"
    "    or $0x80000000, %eax;"
    "    mov %eax, %cr0;"
    ); */
}
For comparison, the equivalent settings in the bootloader are:

Code: Select all

%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

Code: Select all

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
As things stand, when I un-comment the code for setting CR3, it triple faults. I am not certain where in this code the error, or more likely errors, lie.
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.
User avatar
Schol-R-LEA
Member
Member
Posts: 1925
Joined: Fri Oct 27, 2006 9:42 am
Location: Athens, GA, USA

Re: computing the page directory and page table entries

Post by Schol-R-LEA »

Sometimes, just explaining a problem to someone else helps you solve it. The address field of the page directory entries is suppose to hold the page table's physical address, not the physical address of the memory block.

Also, for the calls to memset() I need to pass the pointers to page_directory and page_tables, not the values.

Code: Select all

void set_page_directory_entry(uint32_t index,
                              size_t pte_address,
                              bool page_size, bool rw,
                              bool user, bool write_thru, bool no_caching)
{
    // first, clear the directory entry
    memset(page_directory, 0, sizeof(union Page_Directory_Entry));

    if (page_size)
    {

        page_directory[index].mpage_entry.present = true;
        page_directory[index].mpage_entry.read_write = rw;
        page_directory[index].mpage_entry.user = user;
        page_directory[index].mpage_entry.write_thru = write_thru;
        page_directory[index].mpage_entry.cache_disable = no_caching;
        page_directory[index].mpage_entry.accessed = false;
        page_directory[index].mpage_entry.dirty = false;
        page_directory[index].mpage_entry.page_size = true;
        page_directory[index].mpage_entry.global = false;
        page_directory[index].mpage_entry.available = 0;
        page_directory[index].mpage_entry.page_attribute_table = false;
        page_directory[index].mpage_entry.address_hi = (pte_address >> 20) & 0x1FF;
        page_directory[index].mpage_entry.reserved = false;
        page_directory[index].mpage_entry.address_lo = pte_address & 0xFF;
    }
    else
    {
        page_directory[index].kpage_entry.present = true;
        page_directory[index].kpage_entry.read_write = rw;
        page_directory[index].kpage_entry.user = user;
        page_directory[index].kpage_entry.write_thru = write_thru;
        page_directory[index].kpage_entry.cache_disable = no_caching;
        page_directory[index].kpage_entry.accessed = false;
        page_directory[index].kpage_entry.dirty = false;
        page_directory[index].kpage_entry.page_size = false;
        page_directory[index].kpage_entry.available = 0;
        page_directory[index].kpage_entry.address = pte_address & 0xFFFFF;
    }
}

Code: Select all

    uint32_t pt_e = pe_start;
    size_t addr = phys_address;
    for (uint32_t pd_e = pd_start; pd_e < pd_end; pd_e++)
    {
        set_page_directory_entry(pd_e,
                                 (size_t) &page_tables[pt_e],
                                 page_size, rw,
                                 user, write_thru,
                                 no_caching);


        for (; pt_e < PT_ENTRY_COUNT; pt_e++, addr += PAGE_SPAN)
        {
            set_page_table_entry(pd_e,
                                 pt_e,
                                 addr,
                                 page_size, rw,
                                 user, write_thru,
                                 no_caching);
        }
    }
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.
User avatar
Schol-R-LEA
Member
Member
Posts: 1925
Joined: Fri Oct 27, 2006 9:42 am
Location: Athens, GA, USA

Re: computing the page directory and page table entries

Post by Schol-R-LEA »

I have branched my repo to experiment further with the paging setup, mainly to accommodate the changes in the boot loader paging code which are necessitated by the requirement that the page table entries need to be physically mapped. I started by changing my linker script to place the tables in question into the second 4MiB + 4KiB block in physical memory.

Code: Select all

/* The bootloader will look at this image and start execution at the symbol
   designated at the entry point. */
ENTRY(kstart)


INPUT(
	obj/kernel.o
	obj/terminal.o
	obj/mem.o
	obj/idt.o
	obj/gdt.o
	obj/gdt_set.o
    obj/paging.o
	obj/acpi.o
)


OUTPUT(obj/kernel.elf)

OUTPUT_FORMAT(elf32-i386)
STARTUP(obj/kstart.o)

/* Tell where the various sections of the object files will be put in the final
   kernel image. */
SECTIONS
{
	/* place the identity-mapped section for
	   the page directory and page tables at the 6MiB
	   point in physical memory (i.e., past the
	   1MiB low memory plus the 4MiB kernel space). */
    . = 0x000400000;

    .paging : ALIGN(4K)
	{
		page_tables = .;
		. = . + (4M);
		page_directory = .;
        . = . + 4K;
	}


	/* place the kernel at the start of the higher half */
	. = 0xC0000000;

	/* the .text section. */
	.text : ALIGN(4K)
	{
		kernel_base = .;
		*(.text)
	}

	/* Read-only data. */
	.rodata : ALIGN(4K)
	{
		*(.rodata)
	}

	/* Read-write data (initialized) */
	.data : ALIGN(4K)
	{
		*(.data)
	}

	/* Read-write data (uninitialized) and stack */
	.bss : ALIGN(4K)
	{
		*(COMMON)
		*(.bss)
	}

    /* hardware tables */
    . = 0xC0100000;

    .tables :
	{
		tables_base = .;
	}

    .boot_data : ALIGN (4K)
    {
        boot_data = .;
		. = . + 8K;
    }

	.gdt : ALIGN (4K)
	{
		gdt = .;
		. = . + 64K;
	}

	.tss : ALIGN(4K)
	{
		default_tss = .;
		. = . + 4K;
	}

    .idt : ALIGN(4K)
	{
		idt = .;
		. = . + 4K;
	}


    /* set up the kernel stack */
    . = 0xC1000000;

	.stack : ALIGN(4K)
	{
		kernel_stack_base = .;
		*(.stack)
		kernel_stack_top = . + 16K;
	}
}

I then altered the bootloader paging code to match this:

Code: Select all

page_directory           equ 0x0040000
page_table_0x0000        equ page_directory    + 0x1000
page_table_0x0001        equ page_table_0x0000 + 0x1000
page_table_0x0002        equ page_table_0x0001 + 0x1000
page_table_0x0300        equ page_table_0x0002 + 0x1000
page_table_0x0301        equ page_table_0x0300 + 0x1000
page_table_0x0304        equ page_table_0x0301 + 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_0x0001, 0x1000, 0x00400000, PTE_Present
        populate_pte page_table_0x0002, 0x0004, 0x00800000, PTE_Present
        populate_pte page_table_0x0300, 0x0C00, 0x00100000, PTE_Present
        populate_pte page_table_0x0301, 0x1000, 0x00C00000, PTE_Present
        populate_pte page_table_0x0304, 0x0010, 0x01000000, PTE_Present


    .setup_directory:
        populate_pde page_table_0x0000, 0x0000, PDE_Present
        populate_pde page_table_0x0001, 0x0001, PDE_Present
        populate_pde page_table_0x0002, 0x0002, PDE_Present
        populate_pde page_table_0x0300, 0x0300, PDE_Present
        populate_pde page_table_0x0301, 0x0301, PDE_Present
        populate_pde page_table_0x0304, 0x0304, PDE_Present

        ; set the page directory
        mov eax, page_directory
        mov cr3, eax
        ret
However, this now causes the kernel to triple fault as soon as it is launched.

I'm still trying to find the source of this problem, but any help or advice would be appreciated.
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.
Octocontrabass
Member
Member
Posts: 5562
Joined: Mon Mar 25, 2013 7:01 pm

Re: computing the page directory and page table entries

Post by Octocontrabass »

Does QEMU's "info tlb" and "info mem" show the correct mappings at the time of the triple fault? (You might need to add "-no-reboot" or "-no-shutdown" to your command line so you can use the QEMU monitor after the triple fault.)

If those look good, what does the "-d int" log say about the faults leading up to the triple fault?
User avatar
Schol-R-LEA
Member
Member
Posts: 1925
Joined: Fri Oct 27, 2006 9:42 am
Location: Athens, GA, USA

Re: computing the page directory and page table entries

Post by Schol-R-LEA »

Addressing the last question first:

Code: Select all

$ ./run.sh -d int -no-reboot
SMM: enter
EAX=00000001 EBX=00000000 ECX=02000000 EDX=02000628
ESI=0000000b EDI=02000000 EBP=000a0000 ESP=00006c58
EIP=000ef1cd EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9b00 DPL=0 CS32 [-RA]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     000f7460 00000037
IDT=     000f749e 00000000
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000080 CCD=00000001 CCO=LOGICB
EFER=0000000000000000
SMM: after RSM
EAX=00000001 EBX=00000000 ECX=02000000 EDX=02000628
ESI=0000000b EDI=02000000 EBP=000a0000 ESP=00006c58
EIP=000ef1cd EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA]
SS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     000f7460 00000037
IDT=     000f749e 00000000
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000000 CCD=00000000 CCO=EFLAGS
EFER=0000000000000000
Servicing hardware INT=0x08
SMM: enter
EAX=000000b5 EBX=000f8743 ECX=00001234 EDX=00006cff
ESI=00006cc0 EDI=1efff5fd EBP=00006c80 ESP=00006c80
EIP=00008742 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =dd80 000dd800 ffffffff 008f9300
CS =f000 000f0000 ffffffff 008f9b00
SS =0000 00000000 ffffffff 008f9300
DS =0000 00000000 ffffffff 008f9300
FS =0000 00000000 ffffffff 008f9300
GS =0000 00000000 ffffffff 008f9300
LDT=0000 00000000 0000ffff 00008200
TR =0000 00000000 0000ffff 00008b00
GDT=     00000000 00000000
IDT=     00000000 000003ff
CR0=00000010 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000000 CCD=00006c80 CCO=EFLAGS
EFER=0000000000000000
SMM: after RSM
EAX=000000b5 EBX=000f8743 ECX=00001234 EDX=00006cff
ESI=00006cc0 EDI=1efff5fd EBP=00006c80 ESP=00006c80
EIP=000f8743 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA]
SS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     000f7460 00000037
IDT=     000f749e 00000000
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000000 CCD=00000000 CCO=EFLAGS
EFER=0000000000000000
SMM: enter
EAX=000000b5 EBX=0000875d ECX=00005678 EDX=1efeb0c0
ESI=000ecae0 EDI=1efff5fd EBP=00006c80 ESP=00006c80
EIP=000f875c EFL=00000006 [-----P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA]
SS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     000f7460 00000037
IDT=     000f749e 00000000
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000004 CCD=00006c6c CCO=EFLAGS
EFER=0000000000000000
SMM: after RSM
EAX=000000b5 EBX=0000875d ECX=00005678 EDX=1efeb0c0
ESI=000ecae0 EDI=1efff5fd EBP=00006c80 ESP=00006c80
EIP=0000875d EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =dd80 000dd800 ffffffff 00809300
CS =f000 000f0000 ffffffff 00809b00
SS =0000 00000000 ffffffff 00809300
DS =0000 00000000 ffffffff 00809300
FS =0000 00000000 ffffffff 00809300
GS =0000 00000000 ffffffff 00809300
LDT=0000 00000000 0000ffff 00008200
TR =0000 00000000 0000ffff 00008b00
GDT=     00000000 00000000
IDT=     00000000 000003ff
CR0=00000010 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000000 CCD=00000001 CCO=EFLAGS
EFER=0000000000000000
SMM: enter
EAX=000000b5 EBX=000f8743 ECX=00001234 EDX=000069ff
ESI=000069aa EDI=1efff5fd EBP=0000696a ESP=0000696a
EIP=00008742 EFL=00000006 [-----P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =dd80 000dd800 ffffffff 008f9300
CS =f000 000f0000 ffffffff 008f9b00
SS =0000 00000000 ffffffff 008f9300
DS =0000 00000000 ffffffff 008f9300
FS =0000 00000000 ffffffff 008f9300
GS =c900 000c9000 ffffffff 008f9300
LDT=0000 00000000 0000ffff 00008200
TR =0000 00000000 0000ffff 00008b00
GDT=     00000000 00000000
IDT=     00000000 000003ff
CR0=00000010 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000004 CCD=0000696a CCO=EFLAGS
EFER=0000000000000000
SMM: after RSM
EAX=000000b5 EBX=000f8743 ECX=00001234 EDX=000069ff
ESI=000069aa EDI=1efff5fd EBP=0000696a ESP=0000696a
EIP=000f8743 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA]
SS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     000f7460 00000037
IDT=     000f749e 00000000
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000000 CCD=00000000 CCO=EFLAGS
EFER=0000000000000000
SMM: enter
EAX=000000b5 EBX=0000875d ECX=00005678 EDX=00000005
ESI=00000000 EDI=1efff5fd EBP=0000696a ESP=0000696a
EIP=000f875c EFL=00000046 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA]
SS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     000f7460 00000037
IDT=     000f749e 00000000
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000044 CCD=00000000 CCO=EFLAGS
EFER=0000000000000000
SMM: after RSM
EAX=000000b5 EBX=0000875d ECX=00005678 EDX=00000005
ESI=00000000 EDI=1efff5fd EBP=0000696a ESP=0000696a
EIP=0000875d EFL=00000006 [-----P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =dd80 000dd800 ffffffff 00809300
CS =f000 000f0000 ffffffff 00809b00
SS =0000 00000000 ffffffff 00809300
DS =0000 00000000 ffffffff 00809300
FS =0000 00000000 ffffffff 00809300
GS =c900 000c9000 ffffffff 00809300
LDT=0000 00000000 0000ffff 00008200
TR =0000 00000000 0000ffff 00008b00
GDT=     00000000 00000000
IDT=     00000000 000003ff
CR0=00000010 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000004 CCD=00000001 CCO=EFLAGS
EFER=0000000000000000
SMM: enter
EAX=000000b5 EBX=000f8743 ECX=00001234 EDX=000069ff
ESI=000069a4 EDI=1efff5fd EBP=00006964 ESP=00006964
EIP=00008742 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =dd80 000dd800 ffffffff 00809300
CS =f000 000f0000 ffffffff 00809b00
SS =0000 00000000 ffffffff 00809300
DS =0000 00000000 ffffffff 00809300
FS =0000 00000000 ffffffff 00809300
GS =c900 000c9000 ffffffff 00809300
LDT=0000 00000000 0000ffff 00008200
TR =0000 00000000 0000ffff 00008b00
GDT=     00000000 00000000
IDT=     00000000 000003ff
CR0=00000010 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000000 CCD=00006964 CCO=EFLAGS
EFER=0000000000000000
SMM: after RSM
EAX=000000b5 EBX=000f8743 ECX=00001234 EDX=000069ff
ESI=000069a4 EDI=1efff5fd EBP=00006964 ESP=00006964
EIP=000f8743 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA]
SS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     000f7460 00000037
IDT=     000f749e 00000000
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000000 CCD=00000000 CCO=EFLAGS
EFER=0000000000000000
SMM: enter
EAX=000000b5 EBX=0000875d ECX=00005678 EDX=00000003
ESI=1efd3490 EDI=1efff5fd EBP=00006964 ESP=00006964
EIP=000f875c EFL=00000016 [----AP-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA]
SS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     000f7460 00000037
IDT=     000f749e 00000000
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000014 CCD=00006950 CCO=EFLAGS
EFER=0000000000000000
SMM: after RSM
EAX=000000b5 EBX=0000875d ECX=00005678 EDX=00000003
ESI=1efd3490 EDI=1efff5fd EBP=00006964 ESP=00006964
EIP=0000875d EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =dd80 000dd800 ffffffff 00809300
CS =f000 000f0000 ffffffff 00809b00
SS =0000 00000000 ffffffff 00809300
DS =0000 00000000 ffffffff 00809300
FS =0000 00000000 ffffffff 00809300
GS =c900 000c9000 ffffffff 00809300
LDT=0000 00000000 0000ffff 00008200
TR =0000 00000000 0000ffff 00008b00
GDT=     00000000 00000000
IDT=     00000000 000003ff
CR0=00000010 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000000 CCD=00000001 CCO=EFLAGS
EFER=0000000000000000
SMM: enter
EAX=000000b5 EBX=000f8743 ECX=00001234 EDX=000069ff
ESI=000069aa EDI=1efff5fd EBP=0000696a ESP=0000696a
EIP=00008742 EFL=00000006 [-----P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =dd80 000dd800 ffffffff 00809300
CS =f000 000f0000 ffffffff 00809b00
SS =0000 00000000 ffffffff 00809300
DS =0000 00000000 ffffffff 00809300
FS =0000 00000000 ffffffff 00809300
GS =c900 000c9000 ffffffff 00809300
LDT=0000 00000000 0000ffff 00008200
TR =0000 00000000 0000ffff 00008b00
GDT=     00000000 00000000
IDT=     00000000 000003ff
CR0=00000010 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000004 CCD=0000696a CCO=EFLAGS
EFER=0000000000000000
SMM: after RSM
EAX=000000b5 EBX=000f8743 ECX=00001234 EDX=000069ff
ESI=000069aa EDI=1efff5fd EBP=0000696a ESP=0000696a
EIP=000f8743 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA]
SS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     000f7460 00000037
IDT=     000f749e 00000000
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000000 CCD=00000000 CCO=EFLAGS
EFER=0000000000000000
SMM: enter
EAX=000000b5 EBX=0000875d ECX=00005678 EDX=00000005
ESI=00000000 EDI=1efff5fd EBP=0000696a ESP=0000696a
EIP=000f875c EFL=00000046 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA]
SS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     000f7460 00000037
IDT=     000f749e 00000000
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000044 CCD=00000000 CCO=EFLAGS
EFER=0000000000000000
SMM: after RSM
EAX=000000b5 EBX=0000875d ECX=00005678 EDX=00000005
ESI=00000000 EDI=1efff5fd EBP=0000696a ESP=0000696a
EIP=0000875d EFL=00000006 [-----P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =dd80 000dd800 ffffffff 00809300
CS =f000 000f0000 ffffffff 00809b00
SS =0000 00000000 ffffffff 00809300
DS =0000 00000000 ffffffff 00809300
FS =0000 00000000 ffffffff 00809300
GS =c900 000c9000 ffffffff 00809300
LDT=0000 00000000 0000ffff 00008200
TR =0000 00000000 0000ffff 00008b00
GDT=     00000000 00000000
IDT=     00000000 000003ff
CR0=00000010 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000004 CCD=00000001 CCO=EFLAGS
EFER=0000000000000000
SMM: enter
EAX=000000b5 EBX=000f8743 ECX=00001234 EDX=000069ff
ESI=000069a4 EDI=1efff5fd EBP=00006964 ESP=00006964
EIP=00008742 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =dd80 000dd800 ffffffff 00809300
CS =f000 000f0000 ffffffff 00809b00
SS =0000 00000000 ffffffff 00809300
DS =0000 00000000 ffffffff 00809300
FS =0000 00000000 ffffffff 00809300
GS =c900 000c9000 ffffffff 00809300
LDT=0000 00000000 0000ffff 00008200
TR =0000 00000000 0000ffff 00008b00
GDT=     00000000 00000000
IDT=     00000000 000003ff
CR0=00000010 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000000 CCD=00006964 CCO=EFLAGS
EFER=0000000000000000
SMM: after RSM
EAX=000000b5 EBX=000f8743 ECX=00001234 EDX=000069ff
ESI=000069a4 EDI=1efff5fd EBP=00006964 ESP=00006964
EIP=000f8743 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA]
SS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     000f7460 00000037
IDT=     000f749e 00000000
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000000 CCD=00000000 CCO=EFLAGS
EFER=0000000000000000
SMM: enter
EAX=000000b5 EBX=0000875d ECX=00005678 EDX=00000003
ESI=1ef33490 EDI=1efff5fd EBP=00006964 ESP=00006964
EIP=000f875c EFL=00000016 [----AP-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA]
SS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     000f7460 00000037
IDT=     000f749e 00000000
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000014 CCD=00006950 CCO=EFLAGS
EFER=0000000000000000
SMM: after RSM
EAX=000000b5 EBX=0000875d ECX=00005678 EDX=00000003
ESI=1ef33490 EDI=1efff5fd EBP=00006964 ESP=00006964
EIP=0000875d EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =dd80 000dd800 ffffffff 00809300
CS =f000 000f0000 ffffffff 00809b00
SS =0000 00000000 ffffffff 00809300
DS =0000 00000000 ffffffff 00809300
FS =0000 00000000 ffffffff 00809300
GS =c900 000c9000 ffffffff 00809300
LDT=0000 00000000 0000ffff 00008200
TR =0000 00000000 0000ffff 00008b00
GDT=     00000000 00000000
IDT=     00000000 000003ff
CR0=00000010 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000000 CCD=00000001 CCO=EFLAGS
EFER=0000000000000000
Servicing hardware INT=0x08
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x08
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x08
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
Servicing hardware INT=0x08
Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
check_exception old: 0xffffffff new 0xe
     0: v=0e e=0000 i=0 cpl=0 IP=0008:00000000c0000000 pc=00000000c0000000 SP=0010:00000000c00ffffc CR2=0000000080006407
EAX=80006407 EBX=00040c10 ECX=fffffff2 EDX=01fff001
ESI=0000b482 EDI=00000004 EBP=0000ffde ESP=c00ffffc
EIP=c0000000 EFL=00000046 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     0000b616 00000100
IDT=     00000000 000003ff
CR0=80000011 CR2=80006407 CR3=00040000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000000 CCD=00000000 CCO=SUBB
EFER=0000000000000000
check_exception old: 0xe new 0xd
     1: v=08 e=0000 i=0 cpl=0 IP=0008:00000000c0000000 pc=00000000c0000000 SP=0010:00000000c00ffffc env->regs[R_EAX]=0000000080006407
EAX=80006407 EBX=00040c10 ECX=fffffff2 EDX=01fff001
ESI=0000b482 EDI=00000004 EBP=0000ffde ESP=c00ffffc
EIP=c0000000 EFL=00000046 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     0000b616 00000100
IDT=     00000000 000003ff
CR0=80000011 CR2=80006407 CR3=00040000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000000 CCD=00000000 CCO=SUBB
EFER=0000000000000000
check_exception old: 0x8 new 0xd
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.
Octocontrabass
Member
Member
Posts: 5562
Joined: Mon Mar 25, 2013 7:01 pm

Re: computing the page directory and page table entries

Post by Octocontrabass »

Something other than your kernel code is mapped at 0xC0000000. Probably zero-filled memory, since CR2 is equal to EAX.
User avatar
Schol-R-LEA
Member
Member
Posts: 1925
Joined: Fri Oct 27, 2006 9:42 am
Location: Athens, GA, USA

Re: computing the page directory and page table entries

Post by Schol-R-LEA »

The memory map is

Code: Select all

0000000000000000-0000000000100000 0000000000100000 -r-
0000000000400000-0000000000810000 0000000000410000 -r-
00000000c0000000-00000000c0800000 0000000000800000 -r-
00000000c1000000-00000000c1400000 0000000000400000 -r-
The touched TLB entries are:

Code: Select all

0000000000000000: 0000000000000000 ----A----
0000000000001000: 0000000000001000 ---------
0000000000002000: 0000000000002000 ---------
0000000000003000: 0000000000003000 ---------
0000000000004000: 0000000000004000 ---------
0000000000005000: 0000000000005000 ---------
0000000000006000: 0000000000006000 ---------
0000000000007000: 0000000000007000 ---------
0000000000008000: 0000000000008000 ---------
0000000000009000: 0000000000009000 ---------
000000000000a000: 000000000000a000 ----A----
000000000000b000: 000000000000b000 ---DA----

...

00000000000b7000: 00000000000b7000 ---------
00000000000b8000: 00000000000b8000 ---DA----
00000000000b9000: 00000000000b9000 ---------

...

000000000080f000: 000000000080f000 ---------
00000000c0000000: 0000000000100000 ----A----
00000000c0001000: 0000000000101000 ---------

...

00000000c00fe000: 00000000001fe000 ---------
00000000c00ff000: 00000000001ff000 ---DA----
00000000c0100000: 0000000000200000 ---------
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.
User avatar
Schol-R-LEA
Member
Member
Posts: 1925
Joined: Fri Oct 27, 2006 9:42 am
Location: Athens, GA, USA

Re: computing the page directory and page table entries

Post by Schol-R-LEA »

The problem is with the linker script, specifically the change at the beginning,

Code: Select all

SECTIONS
{
	/* place the identity-mapped section for
	   the page directory and page tables at the 4MiB
	   point in physical memory (i.e., past the
	   1MiB low memory plus the 3MiB kernel space). */

    . = 0x000400000;

    .paging : ALIGN(4K)
	{
		page_tables = .;
		. = . + (4M);
		page_directory = .;
        . = . + 4K;
	}
According to the ld manual (emphasis added),
The MEMORY command complements SECTIONS by describing the available memory in the target architecture. This command is optional; if you don't use a MEMORY command, ld assumes sufficient memory is available in a contiguous block for all output.
Which seems to rule out this approach to linking a section that is identity mapped much lower in memory than the kernel, at least without delving deep into the MEMORY command details.

As a (rather disgusting) stopgap, I tried to simply define the page directory and page tables as hard-coded pointers, while allowed the kernel to load but triple faulted when it got to the functions which reference them. I'll see if can narrow this down further, but honestly that approach isn't satisfactory to me; I will probably have to learn more about linker scripts before continuing.
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.
MichaelPetch
Member
Member
Posts: 797
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: computing the page directory and page table entries

Post by MichaelPetch »

Likely not related to your problems (especially since you aren't using optimizations) but your inline assembly could conceivably cause issues:

Code: Select all

     __asm__ __volatile__ (
    "    mov %0, %%cr3"
    :
    : "a" (page_directory)
    );
Since you are modifying CR3 you really need a memory clobber to prevent the compiler from reordering memory across the update of CR3. This would be preferable:

Code: Select all

     __asm__ __volatile__ (
    "    mov %0, %%cr3"
    :
    : "a" (page_directory)
    : "memory"
    );
Here you are clobbering EAX without informing the compiler that it has been clobbered and you'll probably want a compiler memory barrier if paging was off and you enable it:

Code: Select all

    // confirm that the paging bit is set
    // in the main control register
    __asm__ __volatile__ (
    "    mov %cr0, %eax;"
    "    or $0x80000000, %eax;"
    "    mov %eax, %cr0;"
    );
Should be:

Code: Select all

    // confirm that the paging bit is set
    // in the main control register
    __asm__ __volatile__ (
    "    mov %cr0, %eax;"
    "    or $0x80000000, %eax;"
    "    mov %eax, %cr0;"
    :
    :
    : "eax", "memory"
    );
You could create a temporary variable in C and pass it as an output parameter and that way you could have the compiler choose an available register instead of using EAX specifically. Something like:

Code: Select all

    uint32_t temp;

    __asm__ __volatile__ (
    "    mov %%cr0, %0;"
    "    or $0x80000000, %0;"
    "    mov %0, %%cr0;"
    : "=r"(temp)
    :
    : "memory"
    );
User avatar
Schol-R-LEA
Member
Member
Posts: 1925
Joined: Fri Oct 27, 2006 9:42 am
Location: Athens, GA, USA

Re: computing the page directory and page table entries

Post by Schol-R-LEA »

I did find some issues with how I was computing the page directory and table entries, but fixing this did not change much.

Presently, the relevant part of the results from the `-d int` log are

Code: Select all

Servicing hardware INT=0x0e
Servicing hardware INT=0x0e
check_exception old: 0xffffffff new 0xe
     0: v=0e e=0000 i=0 cpl=0 IP=0008:00000000c0001af2 pc=00000000c0001af2 SP=0010:00000000c1003fb0 CR2=00000000c0001af2
EAX=00800000 EBX=00040c14 ECX=06000000 EDX=06000003
ESI=0000b482 EDI=00000004 EBP=c1003fc8 ESP=c1003fb0
EIP=c0001af2 EFL=00000082 [--S----] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     c0102000 00007fff
IDT=     00000000 000003ff
CR0=80000011 CR2=c0001af2 CR3=00800000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000020 CCD=c1003fb0 CCO=ADDL
EFER=0000000000000000
check_exception old: 0xe new 0xd
     1: v=08 e=0000 i=0 cpl=0 IP=0008:00000000c0001af2 pc=00000000c0001af2 SP=0010:00000000c1003fb0 env->regs[R_EAX]=0000000000800000
EAX=00800000 EBX=00040c14 ECX=06000000 EDX=06000003
ESI=0000b482 EDI=00000004 EBP=c1003fc8 ESP=c1003fb0
EIP=c0001af2 EFL=00000082 [--S----] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     c0102000 00007fff
IDT=     00000000 000003ff
CR0=80000011 CR2=c0001af2 CR3=00800000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000020 CCD=c1003fb0 CCO=ADDL
EFER=0000000000000000
check_exception old: 0x8 new 0xd
Similarly, the output of `info mem` is

Code: Select all

0000000000000000-0000000000005000 0000000000005000 -rw
0000000000006000-0000000000008000 0000000000002000 -rw
0000000000008000-0000000000009000 0000000000001000 -r-
0000000000009000-000000000000a000 0000000000001000 -rw
000000000000e000-000000000000f000 0000000000001000 -rw
0000000000010000-0000000000013000 0000000000003000 -r-
0000000000014000-0000000000016000 0000000000002000 -r-
0000000000018000-0000000000019000 0000000000001000 -rw
000000000001b000-000000000001e000 0000000000003000 -rw
0000000000020000-0000000000040000 0000000000020000 -rw
0000000000040000-0000000000041000 0000000000001000 -r-
0000000000041000-0000000000043000 0000000000002000 -rw
0000000000044000-0000000000060000 000000000001c000 -rw
0000000000067000-0000000000074000 000000000000d000 -rw
0000000000075000-0000000000076000 0000000000001000 -r-
0000000000077000-0000000000079000 0000000000002000 -rw
000000000007a000-0000000000100000 0000000000086000 -rw
0000000000104000-0000000000105000 0000000000001000 -rw
0000000000110000-0000000000111000 0000000000001000 -r-
0000000000118000-000000000011a000 0000000000002000 -rw
0000000000122000-0000000000123000 0000000000001000 -r-
0000000000124000-0000000000126000 0000000000002000 -rw
0000000000800000-0000000000805000 0000000000005000 -rw
0000000000806000-0000000000808000 0000000000002000 -rw
0000000000808000-0000000000809000 0000000000001000 -r-
0000000000809000-000000000080a000 0000000000001000 -rw
000000000080e000-000000000080f000 0000000000001000 -rw
0000000000810000-0000000000813000 0000000000003000 -r-
0000000000814000-0000000000816000 0000000000002000 -r-
0000000000818000-0000000000819000 0000000000001000 -rw
000000000081b000-000000000081e000 0000000000003000 -rw
0000000000820000-0000000000840000 0000000000020000 -rw
0000000000840000-0000000000841000 0000000000001000 -r-
0000000000841000-0000000000843000 0000000000002000 -rw
0000000000844000-0000000000860000 000000000001c000 -rw
0000000000867000-0000000000874000 000000000000d000 -rw
0000000000875000-0000000000876000 0000000000001000 -r-
0000000000877000-0000000000879000 0000000000002000 -rw
000000000087a000-0000000000900000 0000000000086000 -rw
0000000000904000-0000000000905000 0000000000001000 -rw
0000000000910000-0000000000911000 0000000000001000 -r-
0000000000918000-000000000091a000 0000000000002000 -rw
0000000000922000-0000000000923000 0000000000001000 -r-
0000000000924000-0000000000926000 0000000000002000 -rw
0000000001000000-0000000001005000 0000000000005000 -rw
0000000001006000-0000000001008000 0000000000002000 -rw
0000000001008000-0000000001009000 0000000000001000 -r-
0000000001009000-000000000100a000 0000000000001000 -rw
000000000100e000-000000000100f000 0000000000001000 -rw
0000000001010000-0000000001013000 0000000000003000 -r-
0000000001014000-0000000001016000 0000000000002000 -r-
0000000001018000-0000000001019000 0000000000001000 -rw
000000000101b000-000000000101e000 0000000000003000 -rw
0000000001020000-0000000001040000 0000000000020000 -rw
0000000001040000-0000000001041000 0000000000001000 -r-
0000000001041000-0000000001043000 0000000000002000 -rw
0000000001044000-0000000001060000 000000000001c000 -rw
0000000001067000-0000000001074000 000000000000d000 -rw
0000000001075000-0000000001076000 0000000000001000 -r-
0000000001077000-0000000001079000 0000000000002000 -rw
000000000107a000-0000000001100000 0000000000086000 -rw
0000000001104000-0000000001105000 0000000000001000 -rw
0000000001110000-0000000001111000 0000000000001000 -r-
0000000001118000-000000000111a000 0000000000002000 -rw
0000000001122000-0000000001123000 0000000000001000 -r-
0000000001124000-0000000001126000 0000000000002000 -rw
Clearly this is not what I expect from this; it should be more like this:

Code: Select all

0000000000000000-0000000000100000 0000000000100000 -r-
0000000000400000-0000000000810000 0000000000410000 -r-
00000000c0000000-00000000c0800000 0000000000800000 -r-
00000000c1000000-00000000c1400000 0000000000400000 -r-
Based on this, I am assuming that the fault is either in the calculations (though those seem to be correct based on the printouts I've used to monitor them), the function which iterates over the set of entries, or the functions which populate the entries themselves.

This means the following code:

Code: Select all

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#include "paging.h"
#include "mem.h"
#include "terminal.h"
#include "port_io.h"


union Page_Table_Entry *page_tables;
union Page_Directory_Entry *page_directory;


void set_page_directory_entry(uint32_t index,
                              size_t pte_address,
                              bool page_size, bool rw,
                              bool user, bool write_thru, bool no_caching)
{
    // first, clear the directory entry
    // memset(&page_directory[index], 0, sizeof(union Page_Directory_Entry));

    if (page_size)
    {

        page_directory[index].mpage_entry.present = true;
        page_directory[index].mpage_entry.read_write = rw;
        page_directory[index].mpage_entry.user = user;
        page_directory[index].mpage_entry.write_thru = write_thru;
        page_directory[index].mpage_entry.cache_disable = no_caching;
        page_directory[index].mpage_entry.accessed = false;
        page_directory[index].mpage_entry.dirty = false;
        page_directory[index].mpage_entry.page_size = true;
        page_directory[index].mpage_entry.global = false;
        page_directory[index].mpage_entry.available = 0;
        page_directory[index].mpage_entry.page_attribute_table = false;
        page_directory[index].mpage_entry.address_hi = (pte_address >> 20) & 0x1FF;
        page_directory[index].mpage_entry.reserved = false;
        page_directory[index].mpage_entry.address_lo = pte_address & 0xFF;
    }
    else
    {
        page_directory[index].kpage_entry.present = true;
        page_directory[index].kpage_entry.read_write = rw;
        page_directory[index].kpage_entry.user = user;
        page_directory[index].kpage_entry.write_thru = write_thru;
        page_directory[index].kpage_entry.cache_disable = no_caching;
        page_directory[index].kpage_entry.accessed = false;
        page_directory[index].kpage_entry.dirty = false;
        page_directory[index].kpage_entry.page_size = false;
        page_directory[index].kpage_entry.available = 0;
        page_directory[index].kpage_entry.address = pte_address & 0xFFFFF;
    }
}


void set_page_table_entry(uint32_t de,
                          uint32_t te,
                          size_t address,
                          bool page_size, bool rw,
                          bool user, bool write_thru,
                          bool no_caching)
{
    uint16_t index = te + (de * PT_ENTRY_COUNT);
   // kprintf("Page dir:table = %x:%x -> index %x\n", de, te, index);


    page_tables[index].fields.present = true;
    page_tables[index].fields.read_write = rw;
    page_tables[index].fields.user = user;
    page_tables[index].fields.write_thru = write_thru;
    page_tables[index].fields.cache_disable = no_caching;
    page_tables[index].fields.accessed = false;
    page_tables[index].fields.dirty = false;
    page_tables[index].fields.page_size = page_size;
    page_tables[index].fields.page_attribute_table = false;
    page_tables[index].fields.global = false;
    page_tables[index].fields.available = 0;
    page_tables[index].fields.address = address;
}

struct Page_Directory_Frame
{
    size_t dir_start, dir_end, page_start, page_end;
};


struct Page_Directory_Frame* get_frame(struct Page_Directory_Frame *frame, size_t virt_address, size_t block_size)
{
    // determine the page directory entry and page table entry
    // corresponding to the virtual address
    bool trailing_directory = ((virt_address % PD_ENTRY_SPAN) != 0) ? true : false;
    frame->dir_start = virt_address / PD_ENTRY_SPAN;
    uint32_t directory_offset = virt_address - (frame->dir_start * PD_ENTRY_SPAN);
    frame->page_start = directory_offset / PAGE_SPAN;

    // determine the page directory entry and page table entry
    // corresponding to the end of the block of memory
    uint32_t block_end = virt_address + block_size - 1;
    frame->dir_end = (block_end / PD_ENTRY_SPAN) + (trailing_directory ? 1 : 0);

    //bool trailing_block_size = block_size % PD_ENTRY_SPAN;
    //trailing_block_size = (trailing_block_size == block_size) ? 0 : trailing_block_size;
    frame->page_end = (frame->page_start + (block_size / PAGE_SPAN) - 1) % PAGE_SPAN;

    //kprintf("virtual address: %p, ", virt_address);
    //kprintf("trailing directory: %s\n", (trailing_directory) ? "yes" : "no");
    //kprintf("page directory start: %x, ", frame->dir_start);
    //kprintf("page table start: %x\n", frame->page_start);
    //kprintf("end address   : %p, ", block_end);
    //kprintf("page directory end  : %x, ", frame->dir_end);
    //kprintf("page table end  : %x\n\n", frame->page_end);
    // kprintf("trailing block %s, trailing block size : %x, trailing page %s\n", (trailing_block) ? "yes" : "no", trailing_block_size, (trailing_page) ? "yes" : "no");

    return frame;
}



/* set a block of page directory and page table entries matching a block of memory */
void set_page_block(uint32_t phys_address,
                    uint32_t virt_address,
                    uint32_t block_size,
                    bool page_size, bool rw,
                    bool user, bool write_thru,
                    bool no_caching)
{
    struct Page_Directory_Frame frame;

    get_frame(&frame, virt_address, block_size);

    uint32_t pd_entry = frame.dir_start;
    uint32_t pt_entry;
    size_t addr = phys_address;

    for (bool first_entry = true; pd_entry <= frame.dir_end; pd_entry++, first_entry = false)
    {
        pt_entry = first_entry ? frame.page_start : 0;
        uint32_t pt_current_end = (pd_entry == frame.dir_end) ? frame.page_end : PT_ENTRY_COUNT;

        set_page_directory_entry(pd_entry,
                                 (size_t) &page_tables[pt_entry],
                                 page_size, rw,
                                 user, write_thru,
                                 no_caching);


        for (; pt_entry <= pt_current_end; pt_entry++, addr += PAGE_SPAN)
        {
            set_page_table_entry(pd_entry,
                                 pt_entry,
                                 addr,
                                 page_size, rw,
                                 user, write_thru,
                                 no_caching);
        }
    }
}


void reset_default_paging(uint32_t map_size, struct memory_map_entry mt[KDATA_MAX_MEMTABLE_SIZE])
{
    page_tables = (union Page_Table_Entry *) 0x00400000;
    page_directory = (union Page_Directory_Entry *) 0x00800000;

    // first, set all of the page directory entries to a default state
    //memset(&page_directory[0], 0, PD_SIZE);

    // do the same for all of the page table entries
    //memset(&page_tables[0], 0, PT_SIZE);

    // identity map the first 1MiB
    set_page_block(0, 0, 0x00100000, false, true, false, false, false);

    // identity map the section for the page directory and page tables
    // these need to have physical addresses, not virtual ones
    set_page_block((size_t) page_tables, (size_t) page_tables, 0x00400000, false, true, false, false, false);
    set_page_block((size_t) page_directory, (size_t) page_directory, 0x00000400, false, true, false, false, false);

    // map in the kernel region
    set_page_block(0x00100000, (size_t) &kernel_base, 0x00300000, false, true, false, false, false);

    // map in the other various tables
    // provision 4MiB for these just to cover future needs
    set_page_block(0x00400000, (size_t) &tables_base, 0x00400000, false, true, false, false, false);

    // map in the stack
    set_page_block(0x01000000, (size_t) &kernel_stack_base, 0x4000, false, true, false, false, false);


    // reset the paging address control register
    // to point to the new page directory
    __asm__ __volatile__ (
    "    mov %0, %%cr3"
    :
    : "a" (page_directory)
    : "memory"
    );

    // confirm that the paging bit is set
    // in the main control register
    uint32_t temp;

    __asm__ __volatile__ (
    "    mov %%cr0, %0;"
    "    or $0x80000000, %0;"
    "    mov %0, %%cr0;"
    : "=r"(temp)
    :
    : "memory"
    );
}
The trailing output from the insertion function is
Image

If someone could put eyes on this code to see if anything stands out as wrong, I would appreciate it. Also, if there is any part of this which isn't clear, let me know, as I will try to document it more effectively.
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.
User avatar
Schol-R-LEA
Member
Member
Posts: 1925
Joined: Fri Oct 27, 2006 9:42 am
Location: Athens, GA, USA

Re: computing the page directory and page table entries

Post by Schol-R-LEA »

Note to self: pay closer attention to the potential ranges of values. In set_page_table_entry() I should declared index as uint32_t, not uint16_t.

This doesn't solve all of the problems, but it does solve an important one.

The output from info mem is now:

Code: Select all

0000000000000000-0000000000100000 0000000000100000 -r-
0000000000400000-0000000000804000 0000000000404000 -r-
00000000c0000000-00000000c0800000 0000000000800000 -r-
00000000c1000000-00000000c1800000 0000000000800000 -r-
while -d int shows

Code: Select all

check_exception old: 0xffffffff new 0xe
     0: v=0e e=0000 i=0 cpl=0 IP=0008:00000000c000166b pc=00000000c000166b SP=0010:00000000c1003eb0 CR2=0000000000a00000
EAX=00a00000 EBX=00000001 ECX=00000000 EDX=00600000
ESI=00000000 EDI=00000000 EBP=c1003ef8 ESP=c1003eb0
EIP=c000166b EFL=00000006 [-----P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     c0102000 00007fff
IDT=     00000000 000003ff
CR0=80000011 CR2=00a00000 CR3=00040000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00600000 CCD=00a00000 CCO=ADDL
EFER=0000000000000000
check_exception old: 0xe new 0xd
     1: v=08 e=0000 i=0 cpl=0 IP=0008:00000000c000166b pc=00000000c000166b SP=0010:00000000c1003eb0 env->regs[R_EAX]=0000000000a00000
EAX=00a00000 EBX=00000001 ECX=00000000 EDX=00600000
ESI=00000000 EDI=00000000 EBP=c1003ef8 ESP=c1003eb0
EIP=c000166b EFL=00000006 [-----P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     c0102000 00007fff
IDT=     00000000 000003ff
CR0=80000011 CR2=00a00000 CR3=00040000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00600000 CCD=00a00000 CCO=ADDL
EFER=0000000000000000
check_exception old: 0x8 new 0xd
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.
nullplan
Member
Member
Posts: 1790
Joined: Wed Aug 30, 2017 8:24 am

Re: computing the page directory and page table entries

Post by nullplan »

There are several issues here, the most important of which being that you do not identity map the memory the kernel is currently executing in. You have loaded the kernel to the 1MB line, so you must identity map the 1MB block as well. Yes, you map it to the desired address as well; you can map the same physical memory to more than one virtual address. And you can remove the identity mapping once you are no longer using it, but in the moment of enabling paging, you are still using it.

Second question is what your stack is doing. You will also need to identity map the stack if it is not part of your kernel image. That is because you are still using it. Otherwise you will jump off into nirvana by the time you reach a "ret" instruction. Again, it appears your code is executing zeroed memory (which on QEMU is everything). Two zero-bytes translate to "add [eax], al" in 32-bit mode, and again CR2 equals EAX while EIP points... somewhere in the 1st MB? What's it doing there? It would appear the control flow is being subverted, which may stem from improper mapping of the stack.
Carpe diem!
Octocontrabass
Member
Member
Posts: 5562
Joined: Mon Mar 25, 2013 7:01 pm

Re: computing the page directory and page table entries

Post by Octocontrabass »

Schol-R-LEA wrote:

Code: Select all

IP=0008:00000000c000166b
CR2=0000000000a00000
I would guess one of your loops is iterating far beyond the end of an array. Try addr2line or objdump to track down which one.
User avatar
Schol-R-LEA
Member
Member
Posts: 1925
Joined: Fri Oct 27, 2006 9:42 am
Location: Athens, GA, USA

Re: computing the page directory and page table entries

Post by Schol-R-LEA »

Ah, I wasn't aware that both the kernel and stack needed to be identity mapped, and am somewhat perplexed, given that I wasn't identity mapping them in the bootloader, either. I'm not certain how they were working at all in light of this.

I have extended the bootloader page mapping to identity map the kernel and stack, and

Code: Select all

%ifndef _PAGING_CODE__INC__
%define _PAGING_CODE__INC__

%include "paging.inc"

%line 0, "paging.asm"
bits 32

page_directory           equ 0x0040000

; 4 MiB - identity mapping the low memory and kernel
page_table_0x0000        equ page_directory    + 0x1000

; 16 MiB - the page tables
page_table_0x0001        equ page_table_0x0000 + 0x1000
page_table_0x0002        equ page_table_0x0001 + 0x1000
page_table_0x0003        equ page_table_0x0002 + 0x1000
page_table_0x0004        equ page_table_0x0003 + 0x1000

; 20 KiB - the page directory and the kernel stack
page_table_0x0005        equ page_table_0x0004 + 0x1000

; 3MiB - high-half mapping of the kernel
page_table_0x0300        equ page_table_0x0005 + 0x1000

; 4MiB - system tables
page_table_0x0301        equ page_table_0x0300 + 0x1000

; 16 KiB - virtual address of the stack
page_table_0x0304        equ page_table_0x0301 + 0x1000


init_page_directory:
        mov ebx, dword page_directory
        memset32 0, 0x1000, ebx              ; clear the page dir table

        ; 4 MiB - identity mapping the low memory and kernel 
        populate_pte page_table_0x0000, 0x1000, 0x00000000, PTE_Present

        ; 16 MiB - the page tables
        populate_pte page_table_0x0001, 0x1000, 0x00400000, PTE_Present
        populate_pte page_table_0x0002, 0x1000, 0x00800000, PTE_Present
        populate_pte page_table_0x0003, 0x1000, 0x00C00000, PTE_Present
        populate_pte page_table_0x0004, 0x1000, 0x01000000, PTE_Present

        ; 20 KiB - the page directory and the kernel stack 
        populate_pte page_table_0x0005, 0x1000, 0x01400000, PTE_Present
        
        ; 3MiB - high-half mapping of the kernel
        populate_pte page_table_0x0300, 0x0C00, 0x00100000, PTE_Present

        ; 4MiB - system tables
        populate_pte page_table_0x0301, 0x1000, 0x01400000, PTE_Present

        ; 16 KiB - virtual address of the stack
        populate_pte page_table_0x0304, 0x0010, 0x01800000, PTE_Present


    .setup_directory:
        populate_pde page_table_0x0000, 0x0000, PDE_Present
        populate_pde page_table_0x0001, 0x0001, PDE_Present
        populate_pde page_table_0x0002, 0x0002, PDE_Present
        populate_pde page_table_0x0003, 0x0003, PDE_Present
        populate_pde page_table_0x0004, 0x0004, PDE_Present
        populate_pde page_table_0x0005, 0x0005, PDE_Present
        populate_pde page_table_0x0300, 0x0300, PDE_Present
        populate_pde page_table_0x0301, 0x0301, PDE_Present
        populate_pde page_table_0x0304, 0x0304, PDE_Present


        ; set the page directory
        mov eax, page_directory
        mov cr3, eax
        ret


%endif
This appears to be correct based on the info mem results when the kernel paging code is disabled:

Code: Select all

0000000000000000-0000000001800000 0000000001800000 -r-
00000000c0000000-00000000c0800000 0000000000800000 -r-
00000000c1000000-00000000c1010000 0000000000010000 -r-
However, this does not hold for the matching changes in the kernel paging code.

Code: Select all

void reset_default_paging(uint32_t map_size, struct memory_map_entry mt[KDATA_MAX_MEMTABLE_SIZE])
{
    size_t* kernel_physical_base = (size_t *) 0x00100000;
    size_t kernel_size = 0x00300000;                             // 3 MiB
    page_tables = (union Page_Table_Entry *) ((size_t) kernel_physical_base + kernel_size);
    size_t page_table_size = 0x01000000;                         // 16 MiB
    page_directory = (union Page_Directory_Entry *) ((size_t) page_tables + page_table_size);
    size_t page_directory_size = 0x000001000;                    // 4 KiB
    size_t* kernel_stack_physical_base = (size_t *) ((size_t) page_directory + page_directory_size);
    size_t kernel_stack_size = 0x00004000;                       // 16 KiB
    size_t* tables_physical_base = (size_t *) ((size_t) page_directory + 0x00400000);
    size_t tables_size = 0x00400000;


    // identity map the first 1MiB
    set_page_block(0, 0, 0x00100000, false, true, false, false, false);

    // identity map the kernel
    set_page_block((size_t) kernel_physical_base, (size_t) kernel_physical_base, kernel_size, false, true, false, false, false);

    // identity map the section for the page directory and page tables
    // these need to have physical addresses, not virtual ones
    set_page_block((size_t) page_tables, (size_t) page_tables, page_table_size, false, true, false, false, false);
    set_page_block((size_t) page_directory, (size_t) page_directory, page_directory_size, false, true, false, false, false);

    // identity map in the stack
    set_page_block((size_t) kernel_stack_physical_base, (size_t) kernel_stack_physical_base, kernel_stack_size, false, true, false, false, false);

    // map in the kernel region
    set_page_block((size_t) kernel_physical_base, (size_t) &kernel_base, kernel_size, false, true, false, false, false);

    // map in the other various tables
    // provision 4MiB for these just to cover future needs
    set_page_block((size_t) tables_physical_base, (size_t) &tables_base, tables_size, false, true, false, false, false);

    // map in the stack
    set_page_block((size_t) kernel_stack_physical_base, (size_t) &kernel_stack_base, kernel_stack_size, false, true, false, false, false);


    // reset the paging address control register
    // to point to the new page directory
     __asm__ __volatile__ (
    "    mov %0, %%cr3"
    :
    : "a" (page_directory)
    : "memory"
    );

    // confirm that the paging bit is set
    // in the main control register
    uint32_t temp;

    __asm__ __volatile__ (
    "    mov %%cr0, %0;"
    "    or $0x80000000, %0;"
    "    mov %0, %%cr0;"
    : "=r"(temp)
    :
    : "memory"
    );
}
The info mem for this is

Code: Select all

0000000000800000-0000000000805000 0000000000005000 -rw
0000000000806000-0000000000808000 0000000000002000 -rw
0000000000808000-0000000000809000 0000000000001000 -r-
0000000000809000-000000000080a000 0000000000001000 -rw
000000000080e000-000000000080f000 0000000000001000 -rw
0000000000810000-0000000000813000 0000000000003000 -r-
0000000000814000-0000000000816000 0000000000002000 -r-
0000000000818000-0000000000819000 0000000000001000 -rw
000000000081b000-000000000081e000 0000000000003000 -rw
0000000000820000-0000000000840000 0000000000020000 -rw
0000000000840000-0000000000841000 0000000000001000 -r-
0000000000841000-0000000000843000 0000000000002000 -rw
0000000000844000-0000000000860000 000000000001c000 -rw
0000000000867000-0000000000874000 000000000000d000 -rw
0000000000875000-0000000000876000 0000000000001000 -r-
0000000000877000-0000000000879000 0000000000002000 -rw
000000000087a000-0000000000900000 0000000000086000 -rw
0000000000904000-0000000000905000 0000000000001000 -rw
0000000000918000-000000000091a000 0000000000002000 -rw
0000000000922000-0000000000923000 0000000000001000 -r-
0000000000924000-0000000000926000 0000000000002000 -rw
0000000001000000-0000000001005000 0000000000005000 -rw
0000000001006000-0000000001008000 0000000000002000 -rw
0000000001008000-0000000001009000 0000000000001000 -r-
0000000001009000-000000000100a000 0000000000001000 -rw
000000000100e000-000000000100f000 0000000000001000 -rw
0000000001010000-0000000001013000 0000000000003000 -r-
0000000001014000-0000000001016000 0000000000002000 -r-
0000000001018000-0000000001019000 0000000000001000 -rw
000000000101b000-000000000101e000 0000000000003000 -rw
0000000001020000-0000000001040000 0000000000020000 -rw
0000000001040000-0000000001041000 0000000000001000 -r-
0000000001041000-0000000001043000 0000000000002000 -rw
0000000001044000-0000000001060000 000000000001c000 -rw
0000000001067000-0000000001074000 000000000000d000 -rw
0000000001075000-0000000001076000 0000000000001000 -r-
0000000001077000-0000000001079000 0000000000002000 -rw
000000000107a000-0000000001100000 0000000000086000 -rw
0000000001104000-0000000001105000 0000000000001000 -rw
0000000001118000-000000000111a000 0000000000002000 -rw
0000000001122000-0000000001123000 0000000000001000 -r-
0000000001124000-0000000001126000 0000000000002000 -rw
0000000001800000-0000000001805000 0000000000005000 -rw
0000000001806000-0000000001808000 0000000000002000 -rw
0000000001808000-0000000001809000 0000000000001000 -r-
0000000001809000-000000000180a000 0000000000001000 -rw
000000000180e000-000000000180f000 0000000000001000 -rw
0000000001810000-0000000001813000 0000000000003000 -r-
0000000001814000-0000000001816000 0000000000002000 -r-
0000000001818000-0000000001819000 0000000000001000 -rw
000000000181b000-000000000181e000 0000000000003000 -rw
0000000001820000-0000000001840000 0000000000020000 -rw
0000000001840000-0000000001841000 0000000000001000 -r-
0000000001841000-0000000001843000 0000000000002000 -rw
0000000001844000-0000000001860000 000000000001c000 -rw
0000000001867000-0000000001874000 000000000000d000 -rw
0000000001875000-0000000001876000 0000000000001000 -r-
0000000001877000-0000000001879000 0000000000002000 -rw
000000000187a000-0000000001900000 0000000000086000 -rw
0000000001904000-0000000001905000 0000000000001000 -rw
0000000001918000-000000000191a000 0000000000002000 -rw
0000000001922000-0000000001923000 0000000000001000 -r-
0000000001924000-0000000001926000 0000000000002000 -rw
0000000002000000-0000000002005000 0000000000005000 -rw
0000000002006000-0000000002008000 0000000000002000 -rw
0000000002008000-0000000002009000 0000000000001000 -r-
0000000002009000-000000000200a000 0000000000001000 -rw
000000000200e000-000000000200f000 0000000000001000 -rw
0000000002010000-0000000002013000 0000000000003000 -r-
0000000002014000-0000000002016000 0000000000002000 -r-
0000000002018000-0000000002019000 0000000000001000 -rw
000000000201b000-000000000201e000 0000000000003000 -rw
0000000002020000-0000000002040000 0000000000020000 -rw
0000000002040000-0000000002041000 0000000000001000 -r-
0000000002041000-0000000002043000 0000000000002000 -rw
0000000002044000-0000000002060000 000000000001c000 -rw
0000000002067000-0000000002074000 000000000000d000 -rw
0000000002075000-0000000002076000 0000000000001000 -r-
0000000002077000-0000000002079000 0000000000002000 -rw
000000000207a000-0000000002100000 0000000000086000 -rw
0000000002104000-0000000002105000 0000000000001000 -rw
0000000002118000-000000000211a000 0000000000002000 -rw
0000000002122000-0000000002123000 0000000000001000 -r-
0000000002124000-0000000002126000 0000000000002000 -rw
0000000003000000-0000000003005000 0000000000005000 -rw
0000000003006000-0000000003008000 0000000000002000 -rw
0000000003008000-0000000003009000 0000000000001000 -r-
0000000003009000-000000000300a000 0000000000001000 -rw
000000000300e000-000000000300f000 0000000000001000 -rw
0000000003010000-0000000003013000 0000000000003000 -r-
0000000003014000-0000000003016000 0000000000002000 -r-
0000000003018000-0000000003019000 0000000000001000 -rw
000000000301b000-000000000301e000 0000000000003000 -rw
0000000003020000-0000000003040000 0000000000020000 -rw
0000000003040000-0000000003041000 0000000000001000 -r-
0000000003041000-0000000003043000 0000000000002000 -rw
0000000003044000-0000000003060000 000000000001c000 -rw
0000000003067000-0000000003074000 000000000000d000 -rw
0000000003075000-0000000003076000 0000000000001000 -r-
0000000003077000-0000000003079000 0000000000002000 -rw
000000000307a000-0000000003100000 0000000000086000 -rw
0000000003104000-0000000003105000 0000000000001000 -rw
0000000003118000-000000000311a000 0000000000002000 -rw
0000000003122000-0000000003123000 0000000000001000 -r-
0000000003124000-0000000003126000 0000000000002000 -rw
Clearly, the mapping isn't quite going as I intended.
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.
Octocontrabass
Member
Member
Posts: 5562
Joined: Mon Mar 25, 2013 7:01 pm

Re: computing the page directory and page table entries

Post by Octocontrabass »

Schol-R-LEA wrote:Ah, I wasn't aware that both the kernel and stack needed to be identity mapped, and am somewhat perplexed, given that I wasn't identity mapping them in the bootloader, either.
Nothing needs to be identity-mapped unless you're relying on it being identity-mapped. As far as I can tell, you've correctly jumped to the kernel in the higher half and set up a stack in the higher half, so you don't need either of those to be identity-mapped anymore.
Post Reply