Commit d91dfbb4 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-lguest-and-virtio

* git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-lguest-and-virtio:
  lguest: document 32-bit and PAE requirements
  lguest: tell git to ignore Documentation/lguest/lguest
  virtio: fix suspend when using virtio_balloon
  lguest: fix guest crash on non-linear addresses in gdt pvops
  lguest: fix crash on vmlinux images
parents af8f9372 38cfe968
...@@ -3,11 +3,11 @@ ...@@ -3,11 +3,11 @@
/, /` - or, A Young Coder's Illustrated Hypervisor /, /` - or, A Young Coder's Illustrated Hypervisor
\\"--\\ http://lguest.ozlabs.org \\"--\\ http://lguest.ozlabs.org
Lguest is designed to be a minimal hypervisor for the Linux kernel, for Lguest is designed to be a minimal 32-bit x86 hypervisor for the Linux kernel,
Linux developers and users to experiment with virtualization with the for Linux developers and users to experiment with virtualization with the
minimum of complexity. Nonetheless, it should have sufficient minimum of complexity. Nonetheless, it should have sufficient features to
features to make it useful for specific tasks, and, of course, you are make it useful for specific tasks, and, of course, you are encouraged to fork
encouraged to fork and enhance it (see drivers/lguest/README). and enhance it (see drivers/lguest/README).
Features: Features:
...@@ -37,6 +37,7 @@ Running Lguest: ...@@ -37,6 +37,7 @@ Running Lguest:
"Paravirtualized guest support" = Y "Paravirtualized guest support" = Y
"Lguest guest support" = Y "Lguest guest support" = Y
"High Memory Support" = off/4GB "High Memory Support" = off/4GB
"PAE (Physical Address Extension) Support" = N
"Alignment value to which kernel should be aligned" = 0x100000 "Alignment value to which kernel should be aligned" = 0x100000
(CONFIG_PARAVIRT=y, CONFIG_LGUEST_GUEST=y, CONFIG_HIGHMEM64G=n and (CONFIG_PARAVIRT=y, CONFIG_LGUEST_GUEST=y, CONFIG_HIGHMEM64G=n and
CONFIG_PHYSICAL_ALIGN=0x100000) CONFIG_PHYSICAL_ALIGN=0x100000)
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
#define LHCALL_FLUSH_ASYNC 0 #define LHCALL_FLUSH_ASYNC 0
#define LHCALL_LGUEST_INIT 1 #define LHCALL_LGUEST_INIT 1
#define LHCALL_SHUTDOWN 2 #define LHCALL_SHUTDOWN 2
#define LHCALL_LOAD_GDT 3
#define LHCALL_NEW_PGTABLE 4 #define LHCALL_NEW_PGTABLE 4
#define LHCALL_FLUSH_TLB 5 #define LHCALL_FLUSH_TLB 5
#define LHCALL_LOAD_IDT_ENTRY 6 #define LHCALL_LOAD_IDT_ENTRY 6
...@@ -17,6 +16,7 @@ ...@@ -17,6 +16,7 @@
#define LHCALL_SET_PMD 15 #define LHCALL_SET_PMD 15
#define LHCALL_LOAD_TLS 16 #define LHCALL_LOAD_TLS 16
#define LHCALL_NOTIFY 17 #define LHCALL_NOTIFY 17
#define LHCALL_LOAD_GDT_ENTRY 18
#define LGUEST_TRAP_ENTRY 0x1F #define LGUEST_TRAP_ENTRY 0x1F
......
...@@ -273,15 +273,15 @@ static void lguest_load_idt(const struct desc_ptr *desc) ...@@ -273,15 +273,15 @@ static void lguest_load_idt(const struct desc_ptr *desc)
* controls the entire thing and the Guest asks it to make changes using the * controls the entire thing and the Guest asks it to make changes using the
* LOAD_GDT hypercall. * LOAD_GDT hypercall.
* *
* This is the opposite of the IDT code where we have a LOAD_IDT_ENTRY * This is the exactly like the IDT code.
* hypercall and use that repeatedly to load a new IDT. I don't think it
* really matters, but wouldn't it be nice if they were the same? Wouldn't
* it be even better if you were the one to send the patch to fix it?
*/ */
static void lguest_load_gdt(const struct desc_ptr *desc) static void lguest_load_gdt(const struct desc_ptr *desc)
{ {
BUG_ON((desc->size + 1) / 8 != GDT_ENTRIES); unsigned int i;
kvm_hypercall2(LHCALL_LOAD_GDT, __pa(desc->address), GDT_ENTRIES); struct desc_struct *gdt = (void *)desc->address;
for (i = 0; i < (desc->size+1)/8; i++)
kvm_hypercall3(LHCALL_LOAD_GDT_ENTRY, i, gdt[i].a, gdt[i].b);
} }
/* For a single GDT entry which changes, we do the lazy thing: alter our GDT, /* For a single GDT entry which changes, we do the lazy thing: alter our GDT,
...@@ -291,7 +291,9 @@ static void lguest_write_gdt_entry(struct desc_struct *dt, int entrynum, ...@@ -291,7 +291,9 @@ static void lguest_write_gdt_entry(struct desc_struct *dt, int entrynum,
const void *desc, int type) const void *desc, int type)
{ {
native_write_gdt_entry(dt, entrynum, desc, type); native_write_gdt_entry(dt, entrynum, desc, type);
kvm_hypercall2(LHCALL_LOAD_GDT, __pa(dt), GDT_ENTRIES); /* Tell Host about this new entry. */
kvm_hypercall3(LHCALL_LOAD_GDT_ENTRY, entrynum,
dt[entrynum].a, dt[entrynum].b);
} }
/* OK, I lied. There are three "thread local storage" GDT entries which change /* OK, I lied. There are three "thread local storage" GDT entries which change
......
...@@ -158,7 +158,8 @@ void free_interrupts(void); ...@@ -158,7 +158,8 @@ void free_interrupts(void);
/* segments.c: */ /* segments.c: */
void setup_default_gdt_entries(struct lguest_ro_state *state); void setup_default_gdt_entries(struct lguest_ro_state *state);
void setup_guest_gdt(struct lg_cpu *cpu); void setup_guest_gdt(struct lg_cpu *cpu);
void load_guest_gdt(struct lg_cpu *cpu, unsigned long table, u32 num); void load_guest_gdt_entry(struct lg_cpu *cpu, unsigned int i,
u32 low, u32 hi);
void guest_load_tls(struct lg_cpu *cpu, unsigned long tls_array); void guest_load_tls(struct lg_cpu *cpu, unsigned long tls_array);
void copy_gdt(const struct lg_cpu *cpu, struct desc_struct *gdt); void copy_gdt(const struct lg_cpu *cpu, struct desc_struct *gdt);
void copy_gdt_tls(const struct lg_cpu *cpu, struct desc_struct *gdt); void copy_gdt_tls(const struct lg_cpu *cpu, struct desc_struct *gdt);
......
...@@ -144,18 +144,19 @@ void copy_gdt(const struct lg_cpu *cpu, struct desc_struct *gdt) ...@@ -144,18 +144,19 @@ void copy_gdt(const struct lg_cpu *cpu, struct desc_struct *gdt)
gdt[i] = cpu->arch.gdt[i]; gdt[i] = cpu->arch.gdt[i];
} }
/*H:620 This is where the Guest asks us to load a new GDT (LHCALL_LOAD_GDT). /*H:620 This is where the Guest asks us to load a new GDT entry
* We copy it from the Guest and tweak the entries. */ * (LHCALL_LOAD_GDT_ENTRY). We tweak the entry and copy it in. */
void load_guest_gdt(struct lg_cpu *cpu, unsigned long table, u32 num) void load_guest_gdt_entry(struct lg_cpu *cpu, u32 num, u32 lo, u32 hi)
{ {
/* We assume the Guest has the same number of GDT entries as the /* We assume the Guest has the same number of GDT entries as the
* Host, otherwise we'd have to dynamically allocate the Guest GDT. */ * Host, otherwise we'd have to dynamically allocate the Guest GDT. */
if (num > ARRAY_SIZE(cpu->arch.gdt)) if (num > ARRAY_SIZE(cpu->arch.gdt))
kill_guest(cpu, "too many gdt entries %i", num); kill_guest(cpu, "too many gdt entries %i", num);
/* We read the whole thing in, then fix it up. */ /* Set it up, then fix it. */
__lgread(cpu, cpu->arch.gdt, table, num * sizeof(cpu->arch.gdt[0])); cpu->arch.gdt[num].a = lo;
fixup_gdt_table(cpu, 0, ARRAY_SIZE(cpu->arch.gdt)); cpu->arch.gdt[num].b = hi;
fixup_gdt_table(cpu, num, num+1);
/* Mark that the GDT changed so the core knows it has to copy it again, /* Mark that the GDT changed so the core knows it has to copy it again,
* even if the Guest is run on the same CPU. */ * even if the Guest is run on the same CPU. */
cpu->changed |= CHANGED_GDT; cpu->changed |= CHANGED_GDT;
......
...@@ -324,6 +324,11 @@ static void rewrite_hypercall(struct lg_cpu *cpu) ...@@ -324,6 +324,11 @@ static void rewrite_hypercall(struct lg_cpu *cpu)
u8 insn[3] = {0xcd, 0x1f, 0x90}; u8 insn[3] = {0xcd, 0x1f, 0x90};
__lgwrite(cpu, guest_pa(cpu, cpu->regs->eip), insn, sizeof(insn)); __lgwrite(cpu, guest_pa(cpu, cpu->regs->eip), insn, sizeof(insn));
/* The above write might have caused a copy of that page to be made
* (if it was read-only). We need to make sure the Guest has
* up-to-date pagetables. As this doesn't happen often, we can just
* drop them all. */
guest_pagetable_clear_all(cpu);
} }
static bool is_hypercall(struct lg_cpu *cpu) static bool is_hypercall(struct lg_cpu *cpu)
...@@ -563,8 +568,8 @@ void __exit lguest_arch_host_fini(void) ...@@ -563,8 +568,8 @@ void __exit lguest_arch_host_fini(void)
int lguest_arch_do_hcall(struct lg_cpu *cpu, struct hcall_args *args) int lguest_arch_do_hcall(struct lg_cpu *cpu, struct hcall_args *args)
{ {
switch (args->arg0) { switch (args->arg0) {
case LHCALL_LOAD_GDT: case LHCALL_LOAD_GDT_ENTRY:
load_guest_gdt(cpu, args->arg1, args->arg2); load_guest_gdt_entry(cpu, args->arg1, args->arg2, args->arg3);
break; break;
case LHCALL_LOAD_IDT_ENTRY: case LHCALL_LOAD_IDT_ENTRY:
load_guest_idt_entry(cpu, args->arg1, args->arg2, args->arg3); load_guest_idt_entry(cpu, args->arg1, args->arg2, args->arg3);
......
...@@ -190,7 +190,8 @@ static int balloon(void *_vballoon) ...@@ -190,7 +190,8 @@ static int balloon(void *_vballoon)
try_to_freeze(); try_to_freeze();
wait_event_interruptible(vb->config_change, wait_event_interruptible(vb->config_change,
(diff = towards_target(vb)) != 0 (diff = towards_target(vb)) != 0
|| kthread_should_stop()); || kthread_should_stop()
|| freezing(current));
if (diff > 0) if (diff > 0)
fill_balloon(vb, diff); fill_balloon(vb, diff);
else if (diff < 0) else if (diff < 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment