Page 1 of 1
Triple fault on editing page directory
Posted: Mon Jun 10, 2013 11:21 pm
by BMW
Hi all,
In my bootloader, I identity map the first 4MB of memory. Once in the kernel, I want to unmap it, because 0x00000000 - 0xBFFFFFFF will be reserved for userland. I remap the video memory, kernel stack and my memory management bitmap (which are all located in memory < 4MB) to kernel land virtual addresses. Then I try to clear the first entry in the page directory like so:
Code: Select all
pd_entry* pde = vmmngr_pdirectory_lookup_entry(vmmngr_get_directory(), 0x00000000);
*pde = 0;
And the PC/Emulator triple faults at that point.
If I do this -
Code: Select all
pd_entry* pde = vmmngr_pdirectory_lookup_entry(vmmngr_get_directory(), 0x00000000);
//*pde = 0;
DWORD* ptr = (DWORD*)0xA0000000; //unmapped virtual address
*ptr = 125235;
- comment out the page directory editing code then try to write to an unmapped memory location, I get a page fault, as expected.
So my suspicion now is that the IVT, which is located at 0x00000000 physical address, is trying to be accessed.
Is the IVT used in protected mode? I thought it was only for real mode, then the IDT takes over in protected mode.
Extra info:
The page directory is located at 0x80000 (within the first 4MB) - So I'm effectively unmapping memory at the same time I use it... this shouldn't matter though, as the CPU would have to find the physical location before actually editing the memory.
Re: Triple fault on editing page directory
Posted: Tue Jun 11, 2013 12:19 am
by iansjack
What is the value of RIP at the point of failure?
Re: Triple fault on editing page directory
Posted: Tue Jun 11, 2013 12:26 am
by BMW
iansjack wrote:What is the value of RIP at the point of failure?
It's 32-bit, so EIP = 0xC0000674 - Still in my kernel.
Here are all the registers at triple fault (from QEMU log):
Code: Select all
Triple fault
CPU Reset (CPU 0)
EAX=a0000000 EBX=c0000000 ECX=0003f000 EDX=00000000
ESI=00007c00 EDI=00084000 EBP=ffbfedb8 ESP=ffbfed60
EIP=c0000674 EFL=00000206 [-----P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT= 0000070b 00000017
IDT= c00043a0 000007ff
CR0=80000011 CR2=00000713 CR3=00080000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=00000000 CCD=00080000 CCO=ADDL
EFER=0000000000000000
FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
XMM00=00000000000000000000000000000000 XMM01=00000000000000000000000000000000
XMM02=00000000000000000000000000000000 XMM03=00000000000000000000000000000000
XMM04=00000000000000000000000000000000 XMM05=00000000000000000000000000000000
XMM06=00000000000000000000000000000000 XMM07=00000000000000000000000000000000
EDIT: Ahh wait... I just realised something while staring at the register dump while eating my noodles... The GDT is at below 4MB... would that be the cause? (I'll try it once I've finished my dinner)
Re: Triple fault on editing page directory
Posted: Tue Jun 11, 2013 2:08 am
by Kevin
BMW wrote:It's 32-bit, so EIP = 0xC0000674 - Still in my kernel.
Now disassemble your kernel and check which line of code is at 0xc0000674. For best readability, compile with debug information and without optimisation (-g -O0) and use objdump -S for disassembling the binary (and use the new eip value after a recompile, of course).
Here are all the registers at triple fault (from QEMU log):
In general it's more useful to get the CPU dump after the first of the three exceptions because it starts with a line that includes the error code as well. But it's not necessary here because we already
CR0=80000011 CR2=00000713 CR3=00080000 CR4=00000000
So it accessed the memory at 0x713. This is after the IVT, which already answers your other question. (And it isn't used in Protected Mode anyway.)
EDIT: Ahh wait... I just realised something while staring at the register dump while eating my noodles... The GDT is at below 4MB... would that be the cause? (I'll try it once I've finished my dinner)
The GDT is at 0x70b, cr2 points to 0x713, so yes, that's the problem.
Re: Triple fault on editing page directory
Posted: Tue Jun 11, 2013 2:54 am
by BMW
Wow, thanks Kevin!! Very thorough answer!
Quick question, when I use lgdt to load the gdt, I pass it a 6byte structure. If I use inline assembly with GCC, how does gcc know how many bytes to pass to lgdt? Does it just know that lgdt needs 6b?
Re: Triple fault on editing page directory
Posted: Tue Jun 11, 2013 3:05 am
by Combuster
BMW wrote:when I use lgdt to load the gdt, I pass it a 6byte structure
Wrong. It's a
pointer to a 6-byte structure
Re: Triple fault on editing page directory
Posted: Tue Jun 11, 2013 3:39 am
by BMW
Combuster wrote:BMW wrote:when I use lgdt to load the gdt, I pass it a 6byte structure
Wrong. It's a
pointer to a 6-byte structure
:O I thought it was. Hold on, I am confused atm.
Is this the correct way to use lgdt in NASM:
Code: Select all
GDTInfo:
dw (GDT size here)
dd (GDT pointer here)
lgdt [GDTInfo]
Or should I use
Because, in my bootloader, I use [GDTInfo]... that why I thought it passed the 6b structure... so am I doing it wrong? It seems to work like that in my bootloader!!?!?
Re: Triple fault on editing page directory
Posted: Tue Jun 11, 2013 4:21 am
by Combuster
Sounds like you have some gaping holes in your system architecture.
compare:
Code: Select all
mov al, [edx] ; you do know what this does, right?
mov ax, [edx] ; and this?
mov eax, [edx]
lgdt [edx] ; suddenly scary.
fnrstor [edx] ; wtf?
Does the assembler add one byte to the instruction
because one needs to be moved into AL? Does the assembler add two bytes because ax is 16-bits? 4 bytes because eax is 32 bits? Actually mov eax, [edx] is shorter than mov ax, [edx]
now, would mov gdtr, [edx] need 6 bytes in the instruction because GDT is involved? How would it know which six bytes they are since edx is not known in advance?
would fnrstor result in some 100 bytes worth of instructions because the FPU state is that big?
in all cases, the processor is given a pointer - in this case as a register, and the CPU goes off reading the memory involved. Not your assembler, not your compiler.
Now if we used [label] instead of [edx], would we be suddenly changing to passing actual bytes of data rather than the four bytes worth of a pointer?
now, the other way around. Let's drop the braces:
Now the "memory braces" are missing. And then you are telling the CPU not to treat inputs as pointers but as their actual values. Can you put 4 bytes into one? no. Can you put four bytes into another four bytes? that would probably work. Can you put four bytes into something that requires six? Bad idea.
In each of the "failing" cases, the assembler will complain because you're trying to tell the CPU something it couldn't possibly do.
(note: do not ever try to compare instructions this way in AT&T syntax. Its consistency is utterly broken by its attempts to guess what the developer really wants)
Re: Triple fault on editing page directory
Posted: Tue Jun 11, 2013 4:36 am
by BMW
In my bootloader, if I do this:
Code: Select all
lgdt [GDTInfo] ;GDTInfo is a label
Everything works fine.
But this:
doesn't compile "invalid combination of opcode and operands"....
So you do pass the data don't you? Not the pointer... - wrong sorry, my understanding of nasm was ****ed up.
Combuster wrote:
Now the "memory braces" are missing. And then you are telling the CPU not to treat inputs as pointers but as their actual values.
Other way around isn't it???? The "square brackets" dereference the pointer don't they??
http://www.nasm.us/doc/nasmdoc2.html wrote:
The rule is simply that any access to the contents of a memory location requires square brackets around the address, and any access to the address of a variable doesn't.
Re: Triple fault on editing page directory
Posted: Tue Jun 11, 2013 5:09 am
by Combuster
i.e. can't read.
Re: Triple fault on editing page directory
Posted: Tue Jun 11, 2013 5:17 am
by Combuster
BMW (deleted post) wrote:Are you just trying to confuse me here???
If I asked you for the value of EDX, would you give some arbitrary bytes in memory?
(...)
You just did exactly that.
Re: Triple fault on editing page directory
Posted: Tue Jun 11, 2013 5:22 am
by BMW
Sorry, I think I misunderstood your whole post before until just now...
So this
still passes a pointer to GDTInfo, and all the "memory brackets" do is tell the CPU that it's a pointer, not a value?
And this
just passes the address of memaddress as a pointer, not the value at memaddress?
If so, I think the NASM manual should explain it a bit better than this:
Code: Select all
The rule is simply that any access to the contents of a memory location requires square brackets around the address, and any access to the address of a variable doesn't.
Re: Triple fault on editing page directory
Posted: Tue Jun 11, 2013 6:53 am
by Gigasoft
I really don't think this is an appropriate forum for learning assembly. If you don't have a solid understanding of what you're doing, you're just going to end up frustrating yourself. First, you should familiarize yourself with the technology you'll use, so that you won't need to ask these questions but can concentrate on actual OS development related issues.