Page 1 of 1
Paging problem - 4 MB -> 4 KB switch
Posted: Tue Dec 28, 2010 11:44 am
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
.
Re: Paging problem - 4 MB -> 4 KB switch
Posted: Tue Dec 28, 2010 1:08 pm
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.
Re: Paging problem - 4 MB -> 4 KB switch
Posted: Tue Dec 28, 2010 2:27 pm
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.
Re: Paging problem - 4 MB -> 4 KB switch
Posted: Tue Dec 28, 2010 7:19 pm
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?
Re: Paging problem - 4 MB -> 4 KB switch
Posted: Tue Dec 28, 2010 10:06 pm
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.
Re: Paging problem - 4 MB -> 4 KB switch
Posted: Tue Dec 28, 2010 11:25 pm
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
Re: Paging problem - 4 MB -> 4 KB switch
Posted: Wed Dec 29, 2010 12:19 pm
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.