lkml.org 
[lkml]   [2007]   [Mar]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Subject[PATCH] lguest: Compile hypervisor.S into the lg module directly
    From
    Date
    Because of legacy-induced blindness, I insisted on separately building
    the hypervisor.S switcher code (which is mapped at 0xFFC0000 in host
    and guest). However, the lguest64 patches showed the error of my
    ways: it has no relocations, so it can be linked into the module like
    normal then remapped.

    The only downside is that we can no longer use sizeof(hypervisor_blob),
    so we need to allocate our page-array dynamically.

    Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

    diff -r 9d462a93e1fa arch/i386/lguest/Makefile
    --- a/arch/i386/lguest/Makefile Wed Mar 21 08:56:52 2007 +1100
    +++ b/arch/i386/lguest/Makefile Thu Mar 22 11:43:20 2007 +1100
    @@ -4,19 +4,4 @@ obj-$(CONFIG_LGUEST_GUEST) += lguest.o l
    # Host requires the other files, which can be a module.
    obj-$(CONFIG_LGUEST) += lg.o
    lg-objs := core.o hypercalls.o page_tables.o interrupts_and_traps.o \
    - segments.o io.o lguest_user.o
    -
    -# We use top 4MB for hypervisor. */
    -HYPE_ADDR := 0xFFC00000
    -# The data is only 1k (256 interrupt handler pointers)
    -HYPE_DATA_SIZE := 1024
    -CFLAGS += -DHYPE_ADDR="$(HYPE_ADDR)" -DHYPE_DATA_SIZE="$(HYPE_DATA_SIZE)"
    -
    -$(obj)/core.o: $(obj)/hypervisor-blob.c
    -# This links the hypervisor in the right place and turns it into a C array.
    -$(obj)/hypervisor-raw: $(obj)/hypervisor.o
    - @$(LD) -static -Tdata=`printf %#x $$(($(HYPE_ADDR)))` -Ttext=`printf %#x $$(($(HYPE_ADDR)+$(HYPE_DATA_SIZE)))` -o $@ $< && $(OBJCOPY) -O binary $@
    -$(obj)/hypervisor-blob.c: $(obj)/hypervisor-raw
    - @od -tx1 -An -v $< | sed -e 's/^ /0x/' -e 's/$$/,/' -e 's/ /,0x/g' > $@
    -
    -clean-files := hypervisor-blob.c hypervisor-raw
    + segments.o io.o lguest_user.o hypervisor.o
    diff -r 9d462a93e1fa arch/i386/lguest/core.c
    --- a/arch/i386/lguest/core.c Wed Mar 21 08:56:52 2007 +1100
    +++ b/arch/i386/lguest/core.c Thu Mar 22 11:44:17 2007 +1100
    @@ -19,17 +19,21 @@
    #include <asm/i387.h>
    #include "lg.h"

    -/* This is our hypervisor, compiled from hypervisor.S. */
    -static char __initdata hypervisor_blob[] = {
    -#include "hypervisor-blob.c"
    -};
    +/* Found in hypervisor.S */
    +extern char start_hyper_text[], end_hyper_text[], switch_to_guest[];
    +extern unsigned long default_idt_entries[];

    /* Every guest maps the core hypervisor blob. */
    -#define SHARED_HYPERVISOR_PAGES DIV_ROUND_UP(sizeof(hypervisor_blob),PAGE_SIZE)
    +#define SHARED_HYPERVISOR_PAGES \
    + DIV_ROUND_UP(end_hyper_text - start_hyper_text, PAGE_SIZE)
    +/* Pages for hypervisor itself, then two pages per cpu */
    +#define TOTAL_HYPE_PAGES (SHARED_HYPERVISOR_PAGES + 2 * NR_CPUS)
    +
    +/* We map at -4M for ease of mapping into the guest (one PTE page). */
    +#define HYPE_ADDR 0xFFC00000

    static struct vm_struct *hypervisor_vma;
    -/* Pages for hypervisor itself, then two pages per cpu */
    -static struct page *hype_page[SHARED_HYPERVISOR_PAGES+2*NR_CPUS];
    +static struct page **hype_page;

    static int cpu_had_pge;
    static struct {
    @@ -43,16 +47,10 @@ static DEFINE_PER_CPU(struct lguest *, l
    #define MAX_LGUEST_GUESTS 16
    struct lguest lguests[MAX_LGUEST_GUESTS];

    -/* IDT entries are at start of hypervisor. */
    -static const unsigned long *lguest_default_idt_entries(void)
    -{
    - return (void *)HYPE_ADDR;
    -}
    -
    -/* Next is switch_to_guest */
    -static void *__lguest_switch_to_guest(void)
    -{
    - return (void *)HYPE_ADDR + HYPE_DATA_SIZE;
    +/* Offset from where hypervisor.S was compiled to where we've copied it */
    +static unsigned long hype_offset(void)
    +{
    + return HYPE_ADDR - (unsigned long)start_hyper_text;
    }

    /* This cpu's struct lguest_pages. */
    @@ -65,9 +63,15 @@ static __init int map_hypervisor(void)
    static __init int map_hypervisor(void)
    {
    int i, err;
    - struct page **pagep = hype_page;
    -
    - for (i = 0; i < ARRAY_SIZE(hype_page); i++) {
    + struct page **pagep;
    +
    + hype_page = kmalloc(sizeof(hype_page[0])*TOTAL_HYPE_PAGES, GFP_KERNEL);
    + if (!hype_page) {
    + err = -ENOMEM;
    + goto out;
    + }
    +
    + for (i = 0; i < TOTAL_HYPE_PAGES; i++) {
    unsigned long addr = get_zeroed_page(GFP_KERNEL);
    if (!addr) {
    err = -ENOMEM;
    @@ -76,7 +80,7 @@ static __init int map_hypervisor(void)
    hype_page[i] = virt_to_page(addr);
    }

    - hypervisor_vma = __get_vm_area(ARRAY_SIZE(hype_page) * PAGE_SIZE,
    + hypervisor_vma = __get_vm_area(TOTAL_HYPE_PAGES * PAGE_SIZE,
    VM_ALLOC, HYPE_ADDR, VMALLOC_END);
    if (!hypervisor_vma) {
    err = -ENOMEM;
    @@ -84,12 +88,18 @@ static __init int map_hypervisor(void)
    goto free_pages;
    }

    + pagep = hype_page;
    err = map_vm_area(hypervisor_vma, PAGE_KERNEL, &pagep);
    if (err) {
    printk("lguest: map_vm_area failed: %i\n", err);
    goto free_vma;
    }
    - memcpy(hypervisor_vma->addr, hypervisor_blob, sizeof(hypervisor_blob));
    + memcpy(hypervisor_vma->addr, start_hyper_text,
    + end_hyper_text - start_hyper_text);
    +
    + /* Fix up IDT entries to point into copied text. */
    + for (i = 0; i < IDT_ENTRIES; i++)
    + default_idt_entries[i] += hype_offset();

    for_each_possible_cpu(i) {
    struct lguest_pages *pages = lguest_pages(i);
    @@ -107,7 +117,7 @@ static __init int map_hypervisor(void)
    /* No I/O for you! */
    state->guest_tss.io_bitmap_base = sizeof(state->guest_tss);
    setup_default_gdt_entries(state);
    - setup_default_idt_entries(state, lguest_default_idt_entries());
    + setup_default_idt_entries(state, default_idt_entries);

    /* Setup LGUEST segments on all cpus */
    get_cpu_gdt_table(i)[GDT_ENTRY_LGUEST_CS] = FULL_EXEC_SEGMENT;
    @@ -115,7 +125,7 @@ static __init int map_hypervisor(void)
    }

    /* Initialize entry point into hypervisor. */
    - lguest_entry.offset = (long)__lguest_switch_to_guest();
    + lguest_entry.offset = (long)switch_to_guest + hype_offset();
    lguest_entry.segment = LGUEST_CS;

    printk("lguest: mapped hypervisor at %p\n", hypervisor_vma->addr);
    @@ -124,10 +134,12 @@ free_vma:
    free_vma:
    vunmap(hypervisor_vma->addr);
    free_pages:
    - i = ARRAY_SIZE(hype_page);
    + i = TOTAL_HYPE_PAGES;
    free_some_pages:
    for (--i; i >= 0; i--)
    __free_pages(hype_page[i], 0);
    + kfree(hype_page);
    +out:
    return err;
    }

    @@ -136,7 +148,7 @@ static __exit void unmap_hypervisor(void
    unsigned int i;

    vunmap(hypervisor_vma->addr);
    - for (i = 0; i < ARRAY_SIZE(hype_page); i++)
    + for (i = 0; i < TOTAL_HYPE_PAGES; i++)
    __free_pages(hype_page[i], 0);
    }

    @@ -277,8 +289,7 @@ static void copy_in_guest_info(struct lg

    /* Copy direct trap entries. */
    if (lg->changed & CHANGED_IDT)
    - copy_traps(lg, pages->state.guest_idt,
    - lguest_default_idt_entries());
    + copy_traps(lg, pages->state.guest_idt, default_idt_entries);

    /* Copy all GDT entries but the TSS. */
    if (lg->changed & CHANGED_GDT)
    diff -r 9d462a93e1fa arch/i386/lguest/hypervisor.S
    --- a/arch/i386/lguest/hypervisor.S Wed Mar 21 08:56:52 2007 +1100
    +++ b/arch/i386/lguest/hypervisor.S Thu Mar 22 11:43:20 2007 +1100
    @@ -10,11 +10,11 @@
    #include "lg.h"

    .text
    -ENTRY(_start) /* ld complains unless _start is defined. */
    +ENTRY(start_hyper_text)

    /* %eax points to lguest pages for this CPU. %ebx contains cr3 value.
    All normal registers can be clobbered! */
    -switch_to_guest:
    +ENTRY(switch_to_guest)
    /* Save host segments on host stack. */
    pushl %es
    pushl %ds
    @@ -148,8 +148,8 @@ handle_nmi:
    * host. Unfortunately we can't tell them apart except by entry
    * point, so we need 256 entry points.
    */
    -irq_stubs:
    .data
    +.global default_idt_entries
    default_idt_entries:
    .text
    IRQ_STUBS 0 1 return_to_host /* First two traps */
    @@ -159,5 +159,5 @@ default_idt_entries:
    IRQ_STUB 128 return_to_host /* System call (overridden) */
    IRQ_STUBS 129 255 deliver_to_host /* Other real interrupts */

    -/* Everything after this is used for the lguest_state structs. */
    -ALIGN
    +.text
    +ENTRY(end_hyper_text)

    -
    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-03-22 04:07    [W:0.037 / U:0.856 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site