Paging problem - 4 MB -> 4 KB switch

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.
Post Reply
DrMcKay
Posts: 5
Joined: Wed Sep 01, 2010 1:28 pm

Paging problem - 4 MB -> 4 KB switch

Post by DrMcKay »

Hi!

I decided to get my kernel to the higher half of a memory. Everything went good with using a bit modified Higher_Half_bare_bones example. The only thing that suprised me was that I wasn't able to perform operations on video memory without adding 3 GB to it's address (while tutorial says that lower 4 MB are identity-mapped). However, never mind it.

The real problem is: I set up GDT, IDT and I want to set up my own paging (replacing boot page directory). As I decided to use 4 KB paging, it seemed obvious that I need to disable 4 MB pages in CR4 register. So I did:

Code: Select all

asm volatile(
      "mov %%cr4,       %%eax \n\t"
      "xor $0x00000010, %%eax \n\t"
      "mov %%eax,       %%cr4 \n\t"
    :::);
After that, even more obvious thing, I try to load my page directory into CR0, doing:

Code: Select all

asm volatile("mov %0,          %%cr3 \n\t": : "r" (a));
a is physical address of directory.

Unfortunately, it didn't work. Bosch fires an exception 14 on next instruction performed after leaving first ASM block - the one where a is copied to some register. I also tried putting these instructions in one block, didn't work as well.

So, the problem is: how to go from 4 MB to 4 KB paging and change page directory.

If you wish, I may send my paging and memory allocation unit, but I think it isn't necessary for now.
Thank's for your time :).
Greetings,
DrMcKay
davidv1992
Member
Member
Posts: 223
Joined: Thu Jul 05, 2007 8:58 am

Re: Paging problem - 4 MB -> 4 KB switch

Post by davidv1992 »

My suggestion: Rewrite the boot code to start with 4KB page maps to begin with, otherwise the only failsafe way I think is to go completely back (ie turn paging off) and then back into 4K paging.
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Paging problem - 4 MB -> 4 KB switch

Post by gerryg400 »

'4MB pages' is not a mode so there is no need to disable it. All you need to do is build your own paging structures using 4kB pages and reload CR3.

After that is done you can disable the 4MB page feature, but there is no need.
If a trainstation is where trains stop, what is a workstation ?
DrMcKay
Posts: 5
Joined: Wed Sep 01, 2010 1:28 pm

Re: Paging problem - 4 MB -> 4 KB switch

Post by DrMcKay »

Thanks for your response. I don't know why did I forgot to try the simplest possible way :/.
After that, CR3 seems to be loaded with new physical address of directory, but right after that (there's even no way to execute next instruction in inline assembly) there is a General Protection Fault (13) exception raised. Bochs says, that this happends because of instruction:

Code: Select all

add byte ptr ds:[eax+eax*4+477385724], bl : 009C80FC53741C
which seems similar, but not the same as one which caused some people to have problems with their bootloaders.

My page directory is:
  • 0 - whole first table identity-mapped,
  • 768 - 1022 - mapped from 0x0 to 0x3F800000,
  • 1023 - mapped to directory itself.
Any hints?
Greetings,
DrMcKay
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Paging problem - 4 MB -> 4 KB switch

Post by gerryg400 »

Is that instruction the correct instruction after loading cr3. That would mean that the identity mapping is okay. Can you see the eip, cs and error code on the stack ? The error code may tell you something.
If a trainstation is where trains stop, what is a workstation ?
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Paging problem - 4 MB -> 4 KB switch

Post by Brendan »

Hi,
gerryg400 wrote:'4MB pages' is not a mode so there is no need to disable it. All you need to do is build your own paging structures using 4kB pages and reload CR3.

After that is done you can disable the 4MB page feature, but there is no need.
There is a need if you want to support old CPUs that don't support 4 MiB pages, because most of them don't have a CR4 register and any attempt to "mov cr4, reg32" causes an invalid opcode exception.
DrMcKay wrote:My page directory is:
  • 0 - whole first table identity-mapped,
  • 768 - 1022 - mapped from 0x0 to 0x3F800000,
  • 1023 - mapped to directory itself.
Any hints?
For Bochs, enable the inbuilt debugger, etc and put "magic_break: enabled=1" into your "bochsrc.txt". Then insert the special breakpoint instruction ("xchg bx,bx") just before the code that crashes. Then run Bochs, and after it reaches the special breakpoint instruction single step ("s" command) and examine memory ("x" command for virtual memory and "xp" for physical memory), the registers ("r"), etc to see exactly what happens. Don't forget to try the "info tab" command (which shows exactly which areas in the physical address space are mapped to which areas in the virtual address space). For some of these commands you'll want a better description - in that case try the "help <command>" command to get help on a specific command.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
DrMcKay
Posts: 5
Joined: Wed Sep 01, 2010 1:28 pm

Re: Paging problem - 4 MB -> 4 KB switch

Post by DrMcKay »

Thanks Brendan, solved :).
When I used Bochs debugger, I noticed that page directory entries point to page tables by their virtual addresses. It shouldn't happen, though gcc used it's special forces.

Code: Select all

page_table = paging_create_page_table(PAGE_DEFAULT_MASK, addr);
kernel_directory[i] = PAGE_DEFAULT_MASK | (uint32) page_table - 0xC0000000; // as far as I remeber, the syntax was something like this
didn't want to work, but:

Code: Select all

page_table = paging_create_page_table(PAGE_DEFAULT_MASK, addr);
uint32 paddr = (uint32) page_table - 0xC0000000;
kernel_directory[i] = PAGE_DEFAULT_MASK | paddr;
did.

Thank you very much guys :). And, if I may, one small question: why does Bochs fail with page fault while accessing BDA at 0x400 and (0x400 + 0xC0000000) and QEMU doesn't? AFAIK they run the same BIOS.
Greetings,
DrMcKay
Post Reply