Rusty Russell <rusty at rustcorp.com.au> writes: > On Sun, 2006-07-30 at 19:05 +0200, Andi Kleen wrote: >> > (1) We can make startup_32 work for every known and future reasonable >> > hypervisor as well as native, by testing if ring isn't 0 and paging is >> > enabled and jumping to the paravirt entry path. >> >> Somehow the right Hypervisor still needs to be discovered though >> so that the right paravirt ops can be installed. >> >> We would need a standard interface for this. > > Yes, that's %ebx here (0 == Xen): we call paravirts[%ebx]->init(). > > Of course if you do full virtualization and then later want to insert > paravirt_ops, you can just use the normal boot path (Zach has indicated > that VMWare will do this in the short to medium term anyway). > > FYI, here's the actual patch. > > Thanks! > Rusty. > > First cut (compiles, untested) of generic startup_paravirt entry point. Well I can tell to some extent it doesn't work as you got the x86 calling conventions wrong. > > 1) Each hypervisor type creates a paravirt_ops struct and puts an > agreed-on entry in the paravirts[] array. Strictly, this need > only have the init function populated. > > 2) The hypervisor type is handed through %ebx to the startup_paravirt > function at boot. Currently 0 = Xen 3.0, 1 = VMI. > > 3) The init function (called with all regs except for %ebx and %esp > intact), with first arg pointing to the paravirt_ops structure > we're using. This is responsible for overwriting the paravirt_ops: > a helper called initialize_ops_struct is provided. I like the concept of passing as much through as possible to the init function, but in practice I'm not certain it make sense. Especially where the C calling conventions pass everything on the stack. Anyway here is roughly what I was thinking... > Signed-off-by: Rusty Russell <rusty at rustcorp.com.au> diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S index eb79aa2..a1c21b3 100644 --- a/arch/i386/kernel/head.S +++ b/arch/i386/kernel/head.S @@ -54,6 +54,13 @@ #define INIT_MAP_BEYOND_END (128*1024) * can. */ ENTRY(startup_32) +/* + * See if we need to run paravirtualized + */ + xorl %ebx, %ebx + movw 0x226(%esi), %bx + testl %ebx, %ebx + jnz startup_paravirt /* * Set segments to known values. @@ -411,6 +418,19 @@ #endif #endif iret +startup_paravirt: +#ifdef CONFIG_PARAVIRT + cld + movl $(init_thread_union+THREAD_SIZE), %esp + + /* ebx contains index into paravirt to copy. Hand to init as a ptr */ + movl paravirts(,%ebx,4), %ebx + pushl %ebx + call *PARAVIRT_init_offset(%ebx) +#endif +1: jmp 1b + /* * Real beginning of normal "text" segment */