OSDev.org https://forum.osdev.org/ |
|
Paging https://forum.osdev.org/viewtopic.php?f=1&t=43505 |
Page 1 of 1 |
Author: | Matt1223 [ Sun May 09, 2021 3:37 am ] |
Post subject: | Paging |
Hi, I try to enable paging but it doesn't work. When I enable it system just stops. It doesn't even print info about what interrupt caused the system to stop although it should. My kernel is loaded at 0x400000 so when initializing paging I'm identity mapping two first page Directories (8MiB). That's the code I try to enable paging with. paging_init() is called: Code: typedef uint32_t PTE; // Page Table Entry typedef uint32_t PDE; // Page Directory Entry // page table struct pTable { PTE entries[1024]; } __attribute__((packed)); // make sure it's not alligned by compiler typedef struct pTable pTable; // page directory struct pDirectoryTable { PDE entries[1024]; } __attribute__((packed)); // make sure it's not alligned by compiler typedef struct pDirectoryTable pDirectoryTable; // ... static void paging_set_pDirectoryTable( pDirectoryTable *dir ) { Paging.currPDirectoryTable = dir; __asm("mov %0, %%cr3" : : "r" (dir)); } static void enable_paging() { uint32_t cr0; __asm("mov %%cr0, %0" : "=r" (cr0)); cr0 |= 0x80000001; __asm("mov %0, %%cr0" : : "r" (cr0)); /*__asm("mov %%cr0, %%eax" : : : "%eax"); __asm("or $0x80000000, %%eax" : : : "%eax"); __asm("mov %%eax, %%cr0");*/ } //_________________________________________________________________________________________ void paging_init() { // 0-4 MiB (identity mapped) pTable *table1 = (pTable *)memory_alloc_block(); if (!table1) { terminal_print(debugTerminal, "paging.c, paging_initialize(): initialization failed no space for Paging Table 1"); return; } memsetk(table1, (uint8_t)0x00, sizeof(pTable)); // 4 MiB - 8MiB (identity mapped) pTable *table2 = (pTable *)memory_alloc_block(); if (!table2) { terminal_print(debugTerminal, "paging.c, paging_initialize(): initialization failed no space for Paging Table 2"); return; } memsetk(table2, (uint8_t)0x00, sizeof(pTable)); //! 1st 4mb are idenitity mapped for (int i=0, frame=0x0; i<1024; i++, frame+=4096) { // create a new page PTE page = 0; PTE_set_adress(&page, frame); PTE_set_present_flag(&page, true); // present PTE_set_rw_flag(&page, true); // writable PTE_set_usm_flag(&page, false); // supervisor mode // ...and add it to the page table table1->entries[i] = page; } for (int i=0, frame=0x400000; i<1024; i++, frame+=4096) { // create a new page PTE page = 0; PTE_set_adress (&page, frame); PTE_set_present_flag(&page, true); // present PTE_set_rw_flag(&page, true); // writable PTE_set_usm_flag(&page, false); // supervisor mode // ...and add it to the page table table2->entries[i] = page; } // create default directory table pDirectoryTable *dir = (pDirectoryTable *) memory_alloc_block(); // memory_alloc_block() returns 4096 alligned pointer if (!dir) { terminal_print(debugTerminal, "paging.c, paging_initialize(): initialization failed no space for Paging Directory Table"); return; } memsetk(dir, 0, sizeof (pDirectoryTable)); PDE *entry = &dir->entries[0]; PDE_set_adress(entry, (uint32_t)table1); PDE_set_present_flag(entry, true); PDE_set_rw_flag(entry, true); PDE_set_usm_flag(entry, false); // supervisor mode entry = &dir->entries[1]; PDE_set_adress(entry, (uint32_t)table2); PDE_set_present_flag(entry, true); PDE_set_rw_flag(entry, true); PDE_set_usm_flag(entry, false); // supervisor mode //! switch to our page directory paging_set_pDirectoryTable(dir); //! enable paging enable_paging(); terminal_print(debugTerminal, "Paging initialized and enabled!\n"); } I don't know what's the problem can you help me with that? Also, I try to compile this function but it gives an error. Do you know what's the problem with this assembly? Code: void paging_flush_tlb_entry( uint32_t addr )
{ disable_interrupts(); __asm("invlpg %0" : : "r"(addr)); enable_interrupts(); } |
Author: | Octocontrabass [ Sun May 09, 2021 10:45 pm ] |
Post subject: | Re: Paging |
Matt1223 wrote: I don't know what's the problem can you help me with that? Have you tried stepping through the code in a debugger? Be sure to try stepping individual instructions, not just lines of C code. If the CPU is throwing an exception, you might have better luck running it under a virtual machine that can log CPU exceptions, such as QEMU with the "-d int" option. Matt1223 wrote: Do you know what's the problem with this assembly? The INVLPG instruction requires a memory operand, but you're trying to use a register operand. Also, it's a good idea to use (u)intptr_t for an integer that needs to be the size of a pointer. For example: Code: void paging_flush_tlb_entry( uintptr_t addr )
{ __asm("invlpg %0" : : "m"(*(uint8_t *)addr)); } |
Author: | Matt1223 [ Tue May 25, 2021 3:20 pm ] |
Post subject: | Re: Paging |
Sorry for such a delay but I didn't have the time recently to work on it. Octocontrabass wrote: Have you tried stepping through the code in a debugger? Be sure to try stepping individual instructions, not just lines of C code. I don't really know how to debug kernel. I know there is bochsdbg but I have no idea how to gain control just before enabling paging. Octocontrabass wrote: The INVLPG instruction requires a memory operand, but you're trying to use a register operand. Also, it's a good idea to use (u)intptr_t for an integer that needs to be the size of a pointer. For example: Code: void paging_flush_tlb_entry( uintptr_t addr ) { __asm("invlpg %0" : : "m"(*(uint8_t *)addr)); } Thank you that helped! I have some news about the error. It looks like calling some functions - for example, memory_alloc_block() - right before calling enable_paging() causes this crush., but some functions called after them can prevent the error from happening. For example, calling terminal_print(...) before enable_paging() eliminates the error: Code: paging_set_pDirectoryTable(dir); terminal_print(debugTerminal, "It makes it doesn't crush\n"); enable_paging(); However, the error doesn't occur, the system behaves as if paging hasn't been enabled. That means writing to virtual memory that hasn't been mapped to physical memory doesn't throw page fault. Weird, right? |
Author: | Octocontrabass [ Tue May 25, 2021 5:09 pm ] |
Post subject: | Re: Paging |
Matt1223 wrote: I don't really know how to debug kernel. Sounds like it's time for you to learn. Here's a good starting point. Be sure to look at the section about using debuggers with VMs. Matt1223 wrote: I know there is bochsdbg but I have no idea how to gain control just before enabling paging. Set a breakpoint. Since you're using Bochs, you can embed a magic breakpoint, but every debugger has ways to set breakpoints. |
Author: | Matt1223 [ Mon May 31, 2021 8:22 am ] |
Post subject: | Re: Paging |
The problem was that Code: __asm("mov %%cr0, %0" : "=r" (cr0)); compiled to Code: mov cr0, eax insted of Code: mov eax, cr0 It surprized me as I thought in gcc asm syntax you give sorce at the beggining and then destiny so opposite to the intel syntax. However it looks like I was wrong. |
Author: | iansjack [ Mon May 31, 2021 8:54 am ] |
Post subject: | Re: Paging |
Matt1223 wrote: However it looks like I was wrong. No, you were correct. However, AT&T syntax also mandate the use of '%' before register names; the disassembly you show doesn't have this, so must be Intel syntax. |
Page 1 of 1 | All times are UTC - 6 hours |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |