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    [W:0.053 / U:29.768 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site