lkml.org 
[lkml]   [2007]   [May]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Subject[RFC PATCH 1/3] Replace paravirt_probe with "platform type" boot header field
From
Date
[ This patch won't apply, even to -mm: it comes after the documentation
patch. But it's hopefully readable ]

1) This code assumes that 0x23C is going to be the "platform type"
field of the next version of the Linux boot header format.

2) This doesn't actually assume that P=V, but unlike the paravirt
probe code doesn't assume that V=P+PAGE_OFFSET either.

The following patch actually fixes up lguest to boot with P=V.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
---
arch/i386/kernel/head.S | 31 +++++++------------------------
drivers/lguest/lguest.c | 6 +-----
drivers/lguest/lguest_asm.S | 26 ++------------------------
include/asm-i386/paravirt.h | 5 -----
4 files changed, 10 insertions(+), 58 deletions(-)
diff -r 0e7e7991bd30 arch/i386/kernel/head.S
--- a/arch/i386/kernel/head.S Fri May 04 16:59:07 2007 +1000
+++ b/arch/i386/kernel/head.S Fri May 04 20:38:08 2007 +1000
@@ -503,35 +503,13 @@ ignore_int:
.section .text
#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
-
- pushl $__start_paravirtprobe
-1:
- movl 0(%esp), %eax
- cmpl $__stop_paravirtprobe, %eax
- je unhandled_paravirt
- 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
-
-unhandled_paravirt:
+#ifdef CONFIG_LGUEST_GUEST
+ cmpl $1, 0x23c(%esi)
+ je lguest_init
+#endif
/* Nothing wanted us: we're screwed. */
ud2
-#endif
+#endif /* CONFIG_PARAVIRT */

/*
* Real beginning of normal "text" segment
diff -r 0e7e7991bd30 arch/i386/kernel/vmlinux.lds.S
--- a/arch/i386/kernel/vmlinux.lds.S Fri May 04 16:59:07 2007 +1000
+++ b/arch/i386/kernel/vmlinux.lds.S Fri May 04 22:30:45 2007 +1000
@@ -80,12 +80,6 @@ SECTIONS
EXTRA_RWDATA
CONSTRUCTORS
} :data
-
- .paravirtprobe : AT(ADDR(.paravirtprobe) - LOAD_OFFSET) {
- __start_paravirtprobe = .;
- *(.paravirtprobe)
- __stop_paravirtprobe = .;
- }

. = ALIGN(4096);
.data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) {
diff -r 0e7e7991bd30 drivers/lguest/lguest.c
--- a/drivers/lguest/lguest.c Fri May 04 16:59:07 2007 +1000
+++ b/drivers/lguest/lguest.c Fri May 04 22:30:20 2007 +1000
@@ -799,10 +799,10 @@ static unsigned lguest_patch(u8 type, u1
return insn_len;
}

-/*G:030 Once we get to lguest_init(), we know we're a Guest. The paravirt_ops
- * structure in the kernel provides a single point for (almost) every routine
- * we have to override to avoid privileged instructions. */
-__init void lguest_init(void *boot)
+/*G:030 Once we get to do_lguest_init(), we know we're a Guest. The
+ * paravirt_ops structure in the kernel provides a single point for (almost)
+ * every routine we have to override to avoid privileged instructions. */
+__init void do_lguest_init(void *boot)
{
/* Copy boot parameters first: the Launcher put the physical location
* in %esi, and head.S converted that to a virtual address and handed
@@ -868,7 +868,7 @@ __init void lguest_init(void *boot)
* before returning to the rest of lguest_init(). :*/

/*G:070 Now we've seen all the paravirt_ops, we return to
- * lguest_init() where the rest of the fairly chaotic boot setup
+ * do_lguest_init() where the rest of the fairly chaotic boot setup
* occurs.
*
* The Host expects our first hypercall to tell it where our "struct
@@ -927,7 +927,3 @@ __init void lguest_init(void *boot)
* It is now time for us to explore the nooks and crannies of the three Guest
* devices and complete our understanding of the Guest in "make Drivers".
*/
-
-/*G:025 To complete the magic, lguest_maybe_init() from lguest_asm.S needs to
- * be registered as a paravirt probe function: */
-paravirt_probe(lguest_maybe_init);
diff -r 0e7e7991bd30 drivers/lguest/lguest_asm.S
--- a/drivers/lguest/lguest_asm.S Fri May 04 16:59:07 2007 +1000
+++ b/drivers/lguest/lguest_asm.S Fri May 04 22:30:20 2007 +1000
@@ -1,33 +1,26 @@
#include <linux/linkage.h>
#include <linux/lguest.h>
#include <asm/asm-offsets.h>
+#include <asm/thread_info.h>
#include <asm/page.h>

/* FIXME: Once asm/processor-flags.h goes in, include that */
#define X86_EFLAGS_IF 0x00000200

/*G:020 This is where we begin: head.S notes that we're not running at
- * privilege level 0 (as we would be in native boot) and calls the registered
- * paravirt_probe functions one at a time.
- *
- * This is expected to change to use the linux boot header in %esi and a
- * platform type in the future, so we test for that here (the final version
- * will be slightly different: we assume offset 0x23C and a value of "1" for
- * lguest). We know that %esi with the current launcher should be zero: we
- * pass that in %eax to lguest_init().
+ * privilege level 0 (as we would be in native boot) and looks at the
+ * platform type field in the boot structure (address in %esi). If 1 (lguest),
+ * it calls here.
*
* The .section line puts this code in .init.text so it will be discarded after
* boot. */
.section .init.text, "ax", @progbits
-ENTRY(lguest_maybe_init)
- cmpl $0, %esi
- jne out
+ENTRY(lguest_init)
+ /* Set up initial stack. */
+ movl $(init_thread_union+THREAD_SIZE),%esp
+ /* Hand boot information pointer to do_lguest_init() */
movl %esi, %eax
- addl $__PAGE_OFFSET, %eax
- cmpl $1, 0x23c(%eax)
- je lguest_init
-out:
- ret
+ jmp do_lguest_init

/*G:055 We create a macro which puts the assembler code between lgstart_ and
* lgend_ markers. These templates end up in the .init.text section, so they
diff -r 0e7e7991bd30 drivers/lguest/lguest_user.c
--- a/drivers/lguest/lguest_user.c Fri May 04 16:59:07 2007 +1000
+++ b/drivers/lguest/lguest_user.c Fri May 04 22:30:20 2007 +1000
@@ -14,7 +14,9 @@
*
* Most of the Guest's registers are left alone: we used get_zeroed_page() to
* allocate the structure, so they will be 0. */
-static void setup_regs(struct lguest_regs *regs, unsigned long start)
+static void setup_regs(struct lguest_regs *regs,
+ unsigned long start,
+ unsigned long page_offset)
{
/* There are four "segment" registers which the Guest needs to boot:
* The "code segment" register (cs) refers to the kernel code segment
@@ -36,8 +38,9 @@ static void setup_regs(struct lguest_reg
* running. */
regs->eip = start;

- /* %esi points to our boot information, at physical address 0, so don't
- * touch it. */
+ /* %esi points to the virtual address of the boot information (it's at
+ * physical address 0 == virtual address page_offset). */
+ regs->esi = page_offset;
}

/*L:310 To send DMA into the Guest, the Launcher needs to be able to ask for a
@@ -184,7 +187,7 @@ static int initialize(struct file *file,

/* Now we initialize the Guest's registers, handing it the start
* address. */
- setup_regs(lg->regs, args[2]);
+ setup_regs(lg->regs, args[2], lg->page_offset);

/* There are a couple of GDT entries the Guest expects when first
* booting. */
diff -r 0e7e7991bd30 include/asm-i386/paravirt.h
--- a/include/asm-i386/paravirt.h Fri May 04 16:59:07 2007 +1000
+++ b/include/asm-i386/paravirt.h Fri May 04 20:24:39 2007 +1000
@@ -221,11 +221,6 @@ struct paravirt_ops
void (*irq_enable_sysexit)(void);
void (*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;


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2007-05-04 15:03    [from the cache]
©2003-2011 Jasper Spaans