Page 1 of 1

Paging Problem - 4MB PSE OK, 4K PTE causes not-present fault

Posted: Thu Nov 24, 2011 9:24 am
by sentientnz
I decided to dig out my old code and have a play while I'm on night shifts at work (its quiet at nights so I needed something to do :) )

I spent a few days tidying up the code, and realised that I was using 4MB PSE entries to map all the physical memory into virtual memory space. This wasn't as big a deal when I started coding this a while ago, but my laptop has 4GB of memory, and in 32bit mode, the kernel ended up filling the entire VM space. It was also doing it with 4MB PSE entries in the page directory so I thought it might be nice to just map a bit less and work on an ioremap function.

At the moment, I use a single 4MB entry in the PD to map the first 4MB of physical memory 1:1 into VM. The kernel is loaded at 0x100000. I thought a nice easy test for ioremap would be to map 0xB8000 (physical) into VM somewhere and try writing to the screen. This is when it all went wrong.

I tried to map a single 4K page into the VM space - details follow from debugging:

Page Directory (PD) Entry 0 is a 4MB 1:1 mapping from 0-4MB physical/virtual.
Physical Address: 0x000B8000
Virtual Address: 0x00500000

PD[1] is allocated at physical 0x00124000 and zero'd.
PD[1] is set WRITEABLE | PRESENT (final value is 0x00124003)

PD[1] Entry[256] = 0x000B8000
Entry[256] is set WRITEABLE | PRESENT (final value is 0x000B8003)

PD is invalidated by writing CR3.

Best I can figure out this looks like it should work. PD[1] would start at Virtual 4MB, Entry 256 would be at 5MB (or 0x00500000 - right where I want it to be).
When I try to write an unsigned short to 0x00500000, I get a #PF.

CR2 = 0x500000
Error Code = 2 (Faulted while writing, caused by non-present page)

None of the general registers seem to show anything important. EAX = 0x00500000.
Strangely, none of the registers seem to have the constant 0x0740 stored in them which is the value I'm trying to write.

After a few hours of trying to find an obvious cause (or a silly little bug), I thought I would try using 4KB pages to map the first 4MB. I changed the code to map 1024 4KB pages in PD[0], disabled PSE (or rather, didn't enable it), and now it triple-faults because the IDT is loaded after PG is enabled - but presumably its another not-present fault.

Hopefully something obvious jumps out to someone with fresh eyes.

Re: Paging Problem - 4MB PSE OK, 4K PTE causes not-present f

Posted: Thu Nov 24, 2011 10:08 am
by sentientnz
Cup of tea and a break away sorted everything out.

Forgot to mask off the flags before accessing the Page Table (used 0x00124003 rather than 0x00124000). Knew it had to be something stupid.