Page 1 of 1

LongMode - Strange Jump address after Paging Initialization

Posted: Thu Feb 25, 2010 5:00 am
by ciaala
Hi,
I'm Francesco from italy.
I'm trying to activate the long mode and reach longmode c code.
QEmu has a strange behaviour and I guess, I miss something.

1) I have included the source code of the boot entry point (multiboot grub2)
2) qemu-monitor: dumps of the cpu registers.
3) qemu-monitor: dump of the "page frames" i guess.
4) objdump disassemble

Code: Select all

// Virtual Address of the Kernel Base
#define kernel_VMA_BASE (0xffffc0000000)
// Linear Address of the Kernel Base
#define kernel_LMA_BASE (0x100000)

#define CR4_PAE 	0x0020
#define CR4_PSE 	0x0010
#define EFER_LME 	0x0100
#define MSR_EFER	0xc0000080
// paging
#define CR0_PG		0x80000000
// protected environment
#define CR0_PE		0x00000001

Code: Select all

_entry:
	/** disable the interrupts */
	/** setup the 32bit stack with 32bit physical address*/
	movl $entry_stack, %esp
	pushl $0
	pushl $0
	movl %esp, %ebp
	/** save the bootloader information stored in eax e ebx */
	movl %ebx, %esi
	movl %eax, %edi
	/** prepare the call to console_reset */
	movl %esp, %ebp
	movl $0xb8000, %eax
	movl %eax, base
	call console_reset
	/** print a welcome message */
	s_print(s_OS_VERSION)
	s_println(s_COMPILE_TIME)

pae:
	movl %cr4, %eax
	orl $(CR4_PAE| CR4_PSE), %eax
	movl %eax, %cr4
	s_print(s_PAE)

efer_lme:
	cli
	movl $MSR_EFER, %ecx
	rdmsr
	//Attenzione orl usa %eax come destinazione.
	orl $EFER_LME, %eax
	wrmsr
	s_print(s_EFER_LME)


	/** setup page table in cr3 the page table is at the 32bit address, we copied only 32bit address of the page table. we will need a 64bit page table */
prepare_paging:
	/** prepare the page table */
	call mm_setup_identity_map
	s_print(s_IDENTITYMAP)

	movl mm_main_paging_table, %eax
	movl %eax, %cr3

	/** activate paging */
activate_paging:
	movl %cr0, %eax
	orl $(CR0_PG | CR0_PE ), %eax
	movl %eax, %cr0
/**
 * Flush the instruction prefetch with the shortest jump ever.
 */
	jmp prepare_longmode_jump

[color=#0000FF]/**
 * We are in compatibility mode
 * We need to do a jump to switch to long mode
 * The jump should use a Code Segment marked as a 64bit code segment
 */[/color]
prepare_longmode_jump:
	movl $gdt64,%eax
	lgdt (%eax)
	movl $farjump64bit, %eax
	ljmp *(%eax)

/**
 * First bytes of 64bit code
 * we are in long mode,
 * we prepare the jump to the C kernel entry point
 */
.code64
prepare_main_jump:
	movabsq main64, %rax
	jmpq *%rax

farjump64bit:
	.long prepare_main_jump
	.word 0x8
.globl gdt64
gdt64:
	.word gdt64_table_end - gdt64_table_start 
	.long gdt64_table_start
	.long 0x0
	
.align 64
gdt64_table_start:
	.quad 0x0 // null descriptor
	.quad 0x00af9a000000ffff
	.quad 0x00cf92000000ffff
gdt64_table_end:
The Emulator switch to an Execution address that i cannot understand.
Breakpoint 1, 0x00000000001000a8 in activate_paging ()
(gdb) si
0x00000000001000ab in activate_paging ()
(gdb) si
0x00000000001000b0 in activate_paging ()
(gdb) si
Cannot access memory at address 0x1000a8
(gdb) si
0x000000000000e05b in ?? ()
(gdb)
0x00000000001000b0 in activate_paging () wrote: (qemu) info registers
info registers
EAX=e0000011 EBX=0022300c ECX=0010eff8 EDX=0000005d
ESI=0022300c EDI=2badb002 EBP=00109072 ESP=00109072
EIP=001000b0 EFL=00200086 [--S--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= 00008340 00000027
IDT= 00000000 000003ff
CR0=60000011 CR2=00000000 CR3=0010b007 CR4=00000030
Cannot access memory at address 0x1000a8 wrote: EAX=e0000011 EBX=0022300c ECX=0010eff8 EDX=0000005d
ESI=0022300c EDI=2badb002 EBP=00109072 ESP=00109072
EIP=001000b3 EFL=00200086 [--S--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 TSS64-busy
GDT= 0000000000008340 00000027
IDT= 0000000000000000 000003ff
CR0=e0000011 CR2=0000000000000000 CR3=000000000010b007 CR4=00000030

(qemu) info mem
info mem
00000000-00001000 00001000 urw
00002000-00003000 00001000 urw
00004000-00005000 00001000 urw
00006000-00007000 00001000 urw
....
003f8000-003f9000 00001000 urw
003fa000-003fb000 00001000 urw
003fc000-003fd000 00001000 urw
003fe000-003ff000 00001000 urw
0x000000000000e05b in ?? () wrote: EAX=00000000 EBX=00000000 ECX=00000000 EDX=00000623
ESI=00000000 EDI=00000000 EBP=00000000 ESP=00000000
EIP=0000e05b EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0000 00000000 0000ffff 00009300
CS =f000 000f0000 0000ffff 00009b00
SS =0000 00000000 0000ffff 00009300
DS =0000 00000000 0000ffff 00009300
FS =0000 00000000 0000ffff 00009300
GS =0000 00000000 0000ffff 00009300
LDT=0000 00000000 0000ffff 00008200
TR =0000 00000000 0000ffff 00008b00
GDT= 00000000 0000ffff
IDT= 00000000 0000ffff
CR0=60000010 CR2=00000000 CR3=00000000 CR4=00000000
000000000010008e <prepare_paging>:
10008e: e8 5a 0c 02 00 callq 120ced <mm_setup_identity_map>
100093: a1 e4 09 12 00 89 04 mov 0xe8240489001209e4,%eax
10009a: 24 e8
10009c: 70 00 jo 10009e <prepare_paging+0x10>
10009e: 02 00 add (%rax),%al
1000a0: a1 00 a0 10 00 0f 22 mov 0xfd8220f0010a000,%eax
1000a7: d8 0f

00000000001000a8 <activate_paging>:
1000a8: 0f 20 c0 mov %cr0,%rax
1000ab: 0d 01 00 00 80 or $0x80000001,%eax
1000b0: 0f 22 c0 mov %rax,%cr0
1000b3: eb 00 jmp 1000b5 <prepare_longmode_jump>

00000000001000b5 <prepare_longmode_jump>:
1000b5: b8 00 10 10 00 mov $0x101000,%eax
1000ba: 0f 01 10 lgdt (%rax)
1000bd: b8 d2 00 10 00 mov $0x1000d2,%eax
1000c2: ff 28 ljmpq *(%rax)

00000000001000c4 <prepare_main_jump>:
1000c4: 48 a1 c8 1d 12 c0 ff mov 0xffffc0121dc8,%rax
1000cb: ff 00 00
1000ce: ff e0 jmpq *%rax

Re: LongMode - Strange Jump address after Paging Initialization

Posted: Thu Feb 25, 2010 11:55 am
by Combuster
Your paging tables are off. There is no mapping for the page at 0x00000000 00100000, so it runs into nothingness when you enable the paging bit, causing an exception and a changed address.

Re: LongMode - Strange Jump address after Paging Initialization

Posted: Thu Feb 25, 2010 12:25 pm
by ciaala
Thanks for the replay Combuster,
QEmu-monitor gives me a dump of the page frames i have created.
I have setup a page frame of 2MB size but the tool dumps them as a 4KB pages, and if i try to setup the 1GB page frame it replays that 4MB Page table are up.
I think qemu-monitor thinks about the page frames as they were for 32bit.
I set 512 page frames from 0 to 1GB in 64bit mode, 2MB Page frame size.
If they are misinterpreted as 4KB they will have holes between.
As soon i will home i will prepare a memory dump of the tables I create, and i will also try to move the kernel in one of such strange 4kb page frame.
(qemu) info mem
info mem
00000000-00001000 00001000 urw
00002000-00003000 00001000 urw
00004000-00005000 00001000 urw
00006000-00007000 00001000 urw
....
003f8000-003f9000 00001000 urw
003fa000-003fb000 00001000 urw
003fc000-003fd000 00001000 urw
003fe000-003ff000 00001000 urw