Page 1 of 1

GPF on trying to go back to real mode

Posted: Sat Mar 22, 2008 6:05 pm
by thomasloven
Good evening.

Im trying to go back from protected mode to (un)real
Problems arise immediately...

First of all; GDT is declared as such:

Code: Select all

	gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); //CODE segment 0x08
	gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); //DATA segment 0x10
	gdt_set_gate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); //User mode CODE 0x18
	gdt_set_gate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); //User DATA 0x20
	gdt_set_gate(5, 0, 0xFFFF, 0x9A, 0x00); //16 bit CODE 0x28
	gdt_set_gate(6, 0, 0xFFFF, 0x92, 0x00); //16 bit DATA 0x30
	gdt_set_gate(7, (int)&global_tss, sizeof(TSS_t), 0x89, 0x0F); //TSS 0x38
I load my real mode task

Code: Select all

		current_directory->tables_physical[0] = current_directory->tables_physical[0xC0000000>>22]; //Identity map first mb
		switch_page_directory(current_directory);
		extern void switch_16bit();
		extern void s16();
		memcpy(0x7c00, &s16, 0x1000); //Copy 16 bit code to 0x7C00. It should be safe to use now, right?
		switch_16bit();
And finaly my 16 bit code with switcher

Code: Select all

global switch_16bit
global s16
switch_16bit:
	cli
	mov al, 0xFF ; Mask all irqs
	out 0x21, al
	out 0xA1, al
	jmp 0x7c00 ;Jump to the place s16 was loaded
s16:
	pushad
	jmp 0x28:$+2 //<---GPF HERE
[bits 16]
do_16_bitm:
	mov ax, 0x30
	mov ds, ax
	mov ss, ax
	jmp $
The long jump causes a General Protection Fault.
Is there something else I must do first?
Move the stack? Turn off paging?

Posted: Sun Mar 23, 2008 6:26 am
by JoeKayzA
Hi,

what's the exact error code you get in the gpf? The jump target "0x28:$+2" seems a bit risky to me, why don't you just use do_16_bitm as the target? If the target address is wrong, it would probably result in an invalid opcode gpf.

Posted: Sun Mar 23, 2008 7:08 am
by thomasloven
It gives 0x28 as error code. That would indicate a problem with the 5th entry in the gdt (right?) which is my 16 bit code.

I use $+2 because the function I want to jump to is linked together with my kernel at 0xCxxxxxxx and that would mean jmp do_16_bitm would jump there. Or is it assembled relative?
Anyway, changing it gives the same error.

Posted: Sun Mar 23, 2008 8:39 am
by lukem95
Well paging is not supported in real mode, so id turn that off to be safe.

Posted: Sun Mar 23, 2008 4:07 pm
by Combuster
My guess is that your 16-bit protected mode code is above the 1MB together with the kernel. In this case you get a segment limit violation because 1MB+something > 64k

In that case, you'll need to set a base for that segment, or copy the 16-bit code to a location under 64k.

Posted: Sun Mar 23, 2008 4:24 pm
by thomasloven
I do copy the 16 bit code to 0x7c00

Code: Select all

memcpy(0x7c00, &s16, 0x1000);
I also tried moving the gdt and gdt pointer to below 0xAC00 and 0xBC00 respectively.

Edit
I'm giving this line up since I just got V86 to work.
It was just a distraction to get my mind of general protection faults for a while anyway.

...didn't work too well...