MP trampoline code

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
mutex
Member
Member
Posts: 131
Joined: Sat Jul 07, 2007 7:49 pm

MP trampoline code

Post 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:
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: MP trampoline code

Post 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...
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
mutex
Member
Member
Posts: 131
Joined: Sat Jul 07, 2007 7:49 pm

Re: MP trampoline code

Post 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
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: MP trampoline code

Post 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
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Post Reply