OSDev.org

The Place to Start for Operating System Developers
It is currently Tue Jun 15, 2021 5:05 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: Paging
PostPosted: Sun May 09, 2021 3:37 am 
Offline

Joined: Mon Jul 30, 2018 2:58 am
Posts: 16
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();
}


Top
 Profile  
 
 Post subject: Re: Paging
PostPosted: Sun May 09, 2021 10:45 pm 
Online
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 3119
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));
}


Top
 Profile  
 
 Post subject: Re: Paging
PostPosted: Tue May 25, 2021 3:20 pm 
Offline

Joined: Mon Jul 30, 2018 2:58 am
Posts: 16
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?


Top
 Profile  
 
 Post subject: Re: Paging
PostPosted: Tue May 25, 2021 5:09 pm 
Online
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 3119
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.


Top
 Profile  
 
 Post subject: Re: Paging
PostPosted: Mon May 31, 2021 8:22 am 
Offline

Joined: Mon Jul 30, 2018 2:58 am
Posts: 16
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.


Top
 Profile  
 
 Post subject: Re: Paging
PostPosted: Mon May 31, 2021 8:54 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4178
Location: Chichester, UK
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.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot] and 12 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group