Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c9ccf30d authored by Rusty Russell's avatar Rusty Russell Committed by Andi Kleen
Browse files

[PATCH] paravirt: Add startup infrastructure for paravirtualization



1) Each hypervisor writes a probe function to detect whether we are
   running under that hypervisor.  paravirt_probe() registers this
   function.

2) If vmlinux is booted with ring != 0, we call all the probe
   functions (with registers except %esp intact) in link order: the
   winner will not return.

Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
Signed-off-by: default avatarChris Wright <chrisw@sous-sol.org>
Signed-off-by: default avatarAndi Kleen <ak@suse.de>
Cc: Jeremy Fitzhardinge <jeremy@goop.org>
Cc: Zachary Amsden <zach@vmware.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
parent d7cd5611
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -39,6 +39,8 @@ obj-$(CONFIG_VM86) += vm86.o
obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
obj-$(CONFIG_HPET_TIMER) 	+= hpet.o
obj-$(CONFIG_K8_NB)		+= k8.o

# Make sure this is linked after any other paravirt_ops structs: see head.S
obj-$(CONFIG_PARAVIRT)		+= paravirt.o

EXTRA_AFLAGS   := -traditional
+33 −0
Original line number Diff line number Diff line
@@ -55,6 +55,12 @@
 */
ENTRY(startup_32)

#ifdef CONFIG_PARAVIRT
        movl %cs, %eax
        testl $0x3, %eax
        jnz startup_paravirt
#endif

/*
 * Set segments to known values.
 */
@@ -486,6 +492,33 @@ ignore_int:
#endif
	iret

#ifdef CONFIG_PARAVIRT
startup_paravirt:
	cld
 	movl $(init_thread_union+THREAD_SIZE),%esp

	/* We take pains to preserve all the regs. */
	pushl	%edx
	pushl	%ecx
	pushl	%eax

	/* paravirt.o is last in link, and that probe fn never returns */
	pushl	$__start_paravirtprobe
1:
	movl	0(%esp), %eax
	pushl	(%eax)
	movl	8(%esp), %eax
	call	*(%esp)
	popl	%eax

	movl	4(%esp), %eax
	movl	8(%esp), %ecx
	movl	12(%esp), %edx

	addl	$4, (%esp)
	jmp	1b
#endif

/*
 * Real beginning of normal "text" segment
 */
+4 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <linux/module.h>
#include <linux/efi.h>
#include <linux/bcd.h>
#include <linux/start_kernel.h>

#include <asm/bug.h>
#include <asm/paravirt.h>
@@ -387,6 +388,9 @@ static int __init print_banner(void)
}
core_initcall(print_banner);

/* We simply declare start_kernel to be the paravirt probe of last resort. */
paravirt_probe(start_kernel);

struct paravirt_ops paravirt_ops = {
	.name = "bare hardware",
	.paravirt_enabled = 0,
+6 −0
Original line number Diff line number Diff line
@@ -65,6 +65,12 @@ SECTIONS
	CONSTRUCTORS
	} :data

  __start_paravirtprobe = .;
  .paravirtprobe : AT(ADDR(.paravirtprobe) - LOAD_OFFSET) {
	*(.paravirtprobe)
  }
  __stop_paravirtprobe = .;

  . = ALIGN(4096);
  .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) {
  	__nosave_begin = .;
+5 −0
Original line number Diff line number Diff line
@@ -120,6 +120,11 @@ struct paravirt_ops
	void (fastcall *iret)(void);
};

/* Mark a paravirt probe function. */
#define paravirt_probe(fn)						\
 static asmlinkage void (*__paravirtprobe_##fn)(void) __attribute_used__ \
		__attribute__((__section__(".paravirtprobe"))) = fn

extern struct paravirt_ops paravirt_ops;

#define paravirt_enabled() (paravirt_ops.paravirt_enabled)