OSDev.org

The Place to Start for Operating System Developers
It is currently Fri Apr 19, 2024 5:45 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 16 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Problems initializing paging
PostPosted: Fri Oct 04, 2019 1:10 pm 
Offline
Member
Member

Joined: Sun Sep 16, 2018 6:46 am
Posts: 56
I'm working on paging. At the moment I only finished the init function while mapping and unmapping is still undone.
This is the init:
Code:
void vmm_init() {
    uint32_t eflags = interrupt_save_disable();
    uint32_t *pd __attribute__((aligned(4096))) = kmalloc();

    /**
     * Using the 'recursive mapping' technique.
     */
    uint32_t self_pde;
    memset(&self_pde, 0, sizeof(self_pde));
    self_pde |= (uint32_t)pd | BIT_PD_PT_PRESENT | BIT_PD_PT_RW;
   pd[PAGE_DIRECTORY_INDEX(PD_VADDR)] = self_pde;

   /**
    * Mapping the kernel to a 4MB page.
    */
   uint32_t kernel_pde;
   memset(&kernel_pde, 0, sizeof(kernel_pde));
   kernel_pde |= BIT_PD_PT_PRESENT | BIT_PD_PT_RW | BIT_PD_PAGE_SIZE;
   pd[PAGE_DIRECTORY_INDEX(KERNEL_VIRTUAL_BASE)] = (uint32_t)kernel_pde;

   set_cr3((uint32_t)pd);
   interrupt_restore(eflags);
}


The problem is that I can access pd until I set it as the "official" page directory. In fact when later I try to map a page (or just print it), it Page Faults.

Could you please help me? Am I missing something? Thanks.

This is the mapping code if you need it:
Code:
#define PD_VADDR 0xFFFFF000

#define PAGE_DIRECTORY_ADDR_OFFSET 22
#define PAGE_TABLE_ADDR_OFFSET 12

#define PAGE_DIRECTORY_INDEX(x) (((x) >> PAGE_DIRECTORY_ADDR_OFFSET) & 0x3ff)
#define PAGE_TABLE_INDEX(x) (((x) >> PAGE_TABLE_ADDR_OFFSET) & 0x3ff)

...

uint32_t map_page(uint32_t *phys, uint32_t *virt, uint32_t flags) {
   uint32_t *pd = PD_VADDR;
   uint32_t *pde = pd[(PAGE_DIRECTORY_INDEX((uint32_t)virt))];

   if (!(*pde & BIT_PD_PT_PRESENT)) {
      // Need to create a new page table
      uint32_t pde_phys = kmalloc();
      memset(&pde, 0, sizeof(pde));
      *pde |= pde_phys;
      pd[PAGE_DIRECTORY_INDEX((uint32_t)pde)] = pde;

      memset(PD_INDEX_TO_PT_VADDR(PAGE_DIRECTORY_INDEX((uint32_t)virt)), 0b10, PAGE_SIZE);
      pd[PAGE_DIRECTORY_INDEX((uint32_t)pde)] |= flags;
   }

   uint32_t *pte = pde[PAGE_TABLE_INDEX((uint32_t)virt)];
   memset(&pte, 0, sizeof(pte));

   *pte |= (uint32_t)phys | flags;

   pde[PAGE_TABLE_INDEX((uint32_t)virt)] = pte;
   pd[PAGE_DIRECTORY_INDEX((uint32_t)virt)] = pde;
   return 0;
}

It crashes as soon as pd[something] is accessed.


Top
 Profile  
 
 Post subject: Re: Problems initializing paging
PostPosted: Fri Oct 04, 2019 2:13 pm 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4594
Location: Chichester, UK
Does the page that you have mapped for the kernel include all of the memory used by the page tables?

Edit: Sorry, I missed the fact that you were using recursive mapping. I can never really get my head around that (I find it easier to just map all physical memory to a particular virtual address range). Are you sure you are using the correct virtual addresses to access your page table?


Top
 Profile  
 
 Post subject: Re: Problems initializing paging
PostPosted: Sat Oct 05, 2019 12:31 am 
Offline
Member
Member

Joined: Wed Mar 09, 2011 3:55 am
Posts: 509
I suspect you may have a problem with dereferencing a pointer one too many or one too few times, because C pointer syntax is sometimes less clear than it could be.

At first, I thought I'd found the error in:

Code:
uint32_t *pd = PD_VADDR;


But after reviewing pointer syntax that is correct, though it would probably be clearer to do the same thing in two statements:

Code:
uint32_t *pd;
pd = PD_VADDR;


Your code is equivalent to the above, but because C pointer syntax can be deceptive, it looked at first like it was equivalent to:

Code:
uint32_t *pd;
*pd = PD_VADDR;


By doing it in two statements, you can make clearer to the reader (including yourself, later) that you mean the first and not the second.

It may well be that your problem is hiding behind a similar statement somewhere else that doesn't do quite what you think it does.


Top
 Profile  
 
 Post subject: Re: Problems initializing paging
PostPosted: Sat Oct 05, 2019 3:30 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4594
Location: Chichester, UK
Looking more closely, in your mapping function you aren't converting the addresses for the page table entries into virtual addresses before accessing the tables. So as soon as you try to access them you are likely to get a page fault. If that's not handled you'll get a triple fault.

Do you have an exception handler for page faults? You should, even if all it does is to halt the processor. Then, running under a debugger, you will be able to see where the page fault is happening, and why. Similarly, you should have a basic handler for GP exceptions.


Top
 Profile  
 
 Post subject: Re: Problems initializing paging
PostPosted: Mon Oct 07, 2019 12:58 pm 
Offline
Member
Member

Joined: Sun Sep 16, 2018 6:46 am
Posts: 56
linguofreak wrote:
By doing it in two statements, you can make clearer to the reader (including yourself, later) that you mean the first and not the second.


Ok, I’ll take your advice!

iansjack wrote:
Looking more closely, in your mapping function you aren't converting the addresses for the page table entries into virtual addresses before accessing the tables. So as soon as you try to access them you are likely to get a page fault. If that's not handled you'll get a triple fault.

Sorry, could you explain this further with some examples?

iansjack wrote:
Do you have an exception handler for page faults? You should, even if all it does is to halt the processor. Then, running under a debugger, you will be able to see where the page fault is happening, and why. Similarly, you should have a basic handler for GP exceptions.

I have an exception handler, in fact it prints the type of fault and every register. Maybe I can attach the bochs debugger...


Top
 Profile  
 
 Post subject: Re: Problems initializing paging
PostPosted: Mon Oct 07, 2019 1:34 pm 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4594
Location: Chichester, UK
Each level of the page table (except the lowest) contains the physical address of a lower-level table. You are just taking these addresses and using them to access the next level. But you can't do this when paging is enabled. You need to take the physical address and then convert it to the corresponding virtual address, then use that as the address of the next-level table.

What you are doing will only work if all the addresses you are using are identity mapped. This, in general, won't be the case.

PS: One of the clearest explanations of page tables that I've seen is here: https://os.phil-opp.com/paging-introduction/ It's written from the perspective of Rust rather than C but, together with the following article in the series, explains things very clearly.


Top
 Profile  
 
 Post subject: Re: Problems initializing paging
PostPosted: Tue Oct 08, 2019 2:06 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5137
iansjack wrote:
You need to take the physical address and then convert it to the corresponding virtual address, then use that as the address of the next-level table.

Recursive mapping makes it easier. All of the paging structures are located at fixed virtual addresses, and you can index them directly from the address of the page you want to manipulate.

For example, assuming plain 32-bit paging with recursion in the last PDE, you'd access the PTE and PDE for a particular page something like this:

Code:
uint32_t * pt = (uint32_t *)0xFFC00000;
uint32_t pte = pt[(uint32_t)virt >> 12];

uint32_t * pd = (uint32_t *)0xFFFFF000;
uint32_t pde = pd[(uint32_t)virt >> 22];

(Note: this is for illustration purposes only; I haven't verified this code works correctly, and it may invoke undefined behavior.)


Top
 Profile  
 
 Post subject: Re: Problems initializing paging
PostPosted: Tue Oct 08, 2019 3:30 pm 
Offline
Member
Member

Joined: Sun Sep 16, 2018 6:46 am
Posts: 56
Octocontrabass wrote:
For example, assuming plain 32-bit paging with recursion in the last PDE, you'd access the PTE and PDE for a particular page something like this:

Code:
uint32_t * pt = (uint32_t *)0xFFC00000;
uint32_t pte = pt[(uint32_t)virt >> 12];

uint32_t * pd = (uint32_t *)0xFFFFF000;
uint32_t pde = pd[(uint32_t)virt >> 22];

(Note: this is for illustration purposes only; I haven't verified this code works correctly, and it may invoke undefined behavior.)

I'm doing this for the PD only, should I do it for every PT too? Isn't that too much?

Currently the init function works like this:
Code:
void init_vmm() {
    uint32_t eflags = interrupt_save_disable();
    uint32_t *pd __attribute__((aligned(4096))) = kmalloc();
    uint32_t self_pde;
    memset(&self_pde, 0, sizeof(self_pde));
    self_pde |= (uint32_t)pd | BIT_PD_PT_PRESENT | BIT_PD_PT_RW;
    pd[PAGE_DIRECTORY_INDEX(PD_VADDR)] = self_pde;

    // repeat for kernel (4MB page), set CR3 and restore registers
}

Maybe self_pde/other pdes should point to a physical address obtained by the pmm? Sorry for the dumb questions, still a noob :lol:


Top
 Profile  
 
 Post subject: Re: Problems initializing paging
PostPosted: Tue Oct 08, 2019 11:38 pm 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4594
Location: Chichester, UK
All addresses in all page tables are physical addresses. To access them you have to use virtual addresses mapped to the corresponding physical address. The articles that I linked to explain this with diagrams.


Top
 Profile  
 
 Post subject: Re: Problems initializing paging
PostPosted: Wed Oct 09, 2019 12:39 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5137
Thpertic wrote:
I'm doing this for the PD only, should I do it for every PT too? Isn't that too much?

This is the easiest way to access your page structures when you're using recursive mapping, why wouldn't you want to do it this way?

Thpertic wrote:
Maybe self_pde/other pdes should point to a physical address obtained by the pmm? Sorry for the dumb questions, still a noob :lol:

All entries in your page tables must be physical addresses.


Top
 Profile  
 
 Post subject: Re: Problems initializing paging
PostPosted: Wed Oct 09, 2019 11:42 am 
Offline
Member
Member

Joined: Sun Sep 16, 2018 6:46 am
Posts: 56
Octocontrabass wrote:
Thpertic wrote:
I'm doing this for the PD only, should I do it for every PT too? Isn't that too much?

This is the easiest way to access your page structures when you're using recursive mapping, why wouldn't you want to do it this way?

Aren't one for each Page Table too many addresses to "remember"?

When mapping the single frame, it has to be physical, all right.

Now, I need the physical address of the Page Directory (to set in CR3), but I need to map it otherwise a PF comes when I try to access it. But how do I map it if I don't have a PD yet? Or better, I have one but I don't want to use it as that was just to boot. Then the same thing happens for the Page Tables, however, I don't need to access them now (probably this problem will come later while mapping the page).

For example:
Code:
void init() {
    int *pd;
    pd = get_physical_addr();

    int *self_pde
    self_pde = get_physical_addr() | flags;
    pd[0xFFFFFF000 >> 22] = self_pde;  // <-- here the os Page Faults because pd is a physical address not mapped

    // Other things...
}


Top
 Profile  
 
 Post subject: Re: Problems initializing paging
PostPosted: Wed Oct 09, 2019 11:39 pm 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4594
Location: Chichester, UK
The follow up article to the one I linked you to explains this problem and the various options to deal with it.

https://os.phil-opp.com/paging-implementation/


Top
 Profile  
 
 Post subject: Re: Problems initializing paging
PostPosted: Sun Oct 13, 2019 3:14 am 
Offline
Member
Member

Joined: Sun Sep 16, 2018 6:46 am
Posts: 56
Thank you! Just for curiosity, what approach do you think is the best?

I think i’m going with the recursive paging technique because the others seems too “expensive”.
For example, mapping the entire memory with a fixed offset at boot doesn’t sound very well? I mean, it will work without a doubt but I won’t map 1024 page tables :lol:


Top
 Profile  
 
 Post subject: Re: Problems initializing paging
PostPosted: Sun Oct 13, 2019 3:59 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4594
Location: Chichester, UK
I use the "mapping all memory" technique, but I am working in 64-bit mode where there is loads of virtual memory address space.


Top
 Profile  
 
 Post subject: Re: Problems initializing paging
PostPosted: Sun Oct 13, 2019 4:31 pm 
Offline
Member
Member
User avatar

Joined: Wed Oct 27, 2004 11:00 pm
Posts: 874
Location: WA
personally, I consider mapping all physical memory to be a basic security violation -- you are giving access to memory that belongs to another context


there is never a reason to map physical memory, never (there is nothing that mapping physical memory will make possible)
physical memory should never be mapped (violation of both separation and isolation)
physical memory must never be mapped (security violation)


just my opinion

_________________
## ---- ----- ------ Intel Manuals
OSdev wiki


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 16 posts ]  Go to page 1, 2  Next

All times are UTC - 6 hours


Who is online

Users browsing this forum: SemrushBot [Bot] and 98 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