Page 1 of 1

MP trampoline code

Posted: Mon Oct 26, 2009 4:13 am
by mutex
Hi all,

I have implemented the MP spec 1.4 and have all my AP's running the trampoline. I put it at physical 0x00000000 and have everything started there.

The AP's enter there in 16bit realmode, and i setup a temp gdt (idmapped) and set AP in pmode.

Now everything should be ready for doing the last bit. That last bit of course need calling a 32bit function that is part of the linked kernel.. Here is my problem.. I cannot link this 16bit code together with the 32bit code.. So i wonder, maby i should solve this totally different.. I just cannot see a nice way to do this yet...

Basically whats needed further is loading the TSS for each AP, then loading the IDT and GDT (shared between all cpus) and then calling the dispatcher to jump to AP idle thread..

Any thoughts?

-
Thomas

Code: Select all

[bits 16]
[global _mp_trampoline]
[global _mp_trampoline_end]
_mp_trampoline:
	cli
	jmp mpstart
	
mpgdtr: 					; 0x00000004
	dw mpgdt_end-mpgdt-1	; Size
	dd 0x0000000a			; Where GDT is located..

mpgdt:
	; Null
	dd 0x00
	dd 0x00
	; Code
	dw 0xffff
	dw 0x0000
	db 0x00
	db 0x9a
	db 0xcf
	db 0x00
	; Data
	dw 0xffff
	dw 0x0000
	db 0x00
	db 0x92
	db 0xcf
	db 0x00
mpgdt_end:
	
mpstart:
	lgdt [0x00000004]		; load gdtr
	
	mov eax,cr0				; Switch to pmode
	or al,1
	mov cr0,eax

	jmp 0x08:0x00000034		; Flush GDT by jumping far jmp

[bits 32]
	mov eax,0x10
	mov ds,eax
	mov es,eax
	mov fs,eax
	mov gs,eax
	mov ss,eax
	
	lock					; Make MP safe
	inc dword [0x00000100]	; Increment AP processor count
	
	; Jump to code that can
	
	; Load real GDT
	; Load task register
	; Load IDT
	
	jmp $-0
	
_mp_trampoline_end:

Re: MP trampoline code

Posted: Mon Oct 26, 2009 12:41 pm
by Combuster
What you can do, is create some position-independent (or with hardcoded addresses) code in assembly, so that it has no relocations that could mess up linking. By adding a symbol for the start and end, you can copy the binary blob at runtime to the desired location before bootstrapping the APs with it.

Of course you could mess a whole lot with linker scripts...

Re: MP trampoline code

Posted: Mon Oct 26, 2009 1:06 pm
by mutex
Hi,

I was thinking about doing special/nasty stuff with ld script, variables etc.

I ended actually up with jumping the AP to 0x100000 from the trampoline (same as kernel start asm stub). Did a bit toggle stuff there so that after BSP has booted the AP's will go trough all the same pagedir setup etc, and then jump to a special C function that detects cpu number, loads apropriate tss, and then kicks of the interrupt dispatch routine.. Now i only need to expand my gdt with some more tss'es and then i can remove the HLT before ltr and the iret :) Hopefully everything will work just nice :)

Pseudo code bellow if someone is interrested;

Code: Select all

# trampoline.asm 0x00000000
- 16bit realmode
- setup temp gdt
- do pmode
- flush gdt
- jmp to CS:0x100000

# init.asm 0x100000
- setup temp pagedir vm=pm
- map kernel 0xC0000000 to pm 0x100000
- set BSP'has booted flag
- if(AP) jump cs:_HalMpApEntry
- clear bss
- jump to cs:_KeEntry

#_KeEntry at 0xc00xxxxx
 - Setup everything, including task environment, tss'es etc.
 - Init and Startup ap's using apic.
 - while(1)

#_HalMpApEntry at 0xc00xxxxx
 - Load task register
 - iret

Re: MP trampoline code

Posted: Tue Oct 27, 2009 12:12 am
by Brendan
Hi,

I have a small piece of ("position independent") 16-bit assembly that I copy to a (dynamically allocated) page below 0x00100000. Then I set a few variables inside this page (a GDTR, address of page allocated for the AP CPU's stack, address for the AP CPU to jump to once it's in protected mode, etc). When the AP CPU starts it loads the GDT, enables protected mode, sets it's SS:ESP, and does a "jmp far" to wherever it's told.

Probably the only tricky part is realising that when the AP CPUs starts, CS points to the trampoline code; so the trampoline code can use CS to access the variables that are stored in the same page. For an example "o32 lgdt [cs:TRAMPOLINE_GDTR - TRAMPOLINE_START]".


Cheers,

Brendan