Commit 7874d351 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus

* git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus:
  lguest: turn Waker into a thread, not a process
  lguest: Enlarge virtio rings
  lguest: Use GSO/IFF_VNET_HDR extensions on tun/tap
  lguest: Remove 'network: no dma buffer!' warning
  lguest: Adaptive timeout
  lguest: Tell Guest net not to notify us on every packet xmit
  lguest: net block unneeded receive queue update notifications
  lguest: wrap last_avail accesses.
  lguest: use cpu capability accessors
  lguest: virtio-rng support
  lguest: Support assigning a MAC address
  lguest: Don't leak /dev/zero fd
  lguest: fix verbose printing of device features.
  lguest: fix switcher_page leak on unload
  lguest: Guest int3 fix
  lguest: set max_pfn_mapped, growl loudly at Yinghai Lu
parents 5dfb66ba 8c79873d
This diff is collapsed.
...@@ -1014,6 +1014,9 @@ __init void lguest_init(void) ...@@ -1014,6 +1014,9 @@ __init void lguest_init(void)
init_pg_tables_start = __pa(pg0); init_pg_tables_start = __pa(pg0);
init_pg_tables_end = __pa(pg0); init_pg_tables_end = __pa(pg0);
/* As described in head_32.S, we map the first 128M of memory. */
max_pfn_mapped = (128*1024*1024) >> PAGE_SHIFT;
/* Load the %fs segment register (the per-cpu segment register) with /* Load the %fs segment register (the per-cpu segment register) with
* the normal data segment to get through booting. */ * the normal data segment to get through booting. */
asm volatile ("mov %0, %%fs" : : "r" (__KERNEL_DS) : "memory"); asm volatile ("mov %0, %%fs" : : "r" (__KERNEL_DS) : "memory");
......
...@@ -135,6 +135,7 @@ static void unmap_switcher(void) ...@@ -135,6 +135,7 @@ static void unmap_switcher(void)
/* Now we just need to free the pages we copied the switcher into */ /* Now we just need to free the pages we copied the switcher into */
for (i = 0; i < TOTAL_SWITCHER_PAGES; i++) for (i = 0; i < TOTAL_SWITCHER_PAGES; i++)
__free_pages(switcher_page[i], 0); __free_pages(switcher_page[i], 0);
kfree(switcher_page);
} }
/*H:032 /*H:032
......
...@@ -406,7 +406,8 @@ void load_guest_idt_entry(struct lg_cpu *cpu, unsigned int num, u32 lo, u32 hi) ...@@ -406,7 +406,8 @@ void load_guest_idt_entry(struct lg_cpu *cpu, unsigned int num, u32 lo, u32 hi)
* deliver_trap() to bounce it back into the Guest. */ * deliver_trap() to bounce it back into the Guest. */
static void default_idt_entry(struct desc_struct *idt, static void default_idt_entry(struct desc_struct *idt,
int trap, int trap,
const unsigned long handler) const unsigned long handler,
const struct desc_struct *base)
{ {
/* A present interrupt gate. */ /* A present interrupt gate. */
u32 flags = 0x8e00; u32 flags = 0x8e00;
...@@ -415,6 +416,10 @@ static void default_idt_entry(struct desc_struct *idt, ...@@ -415,6 +416,10 @@ static void default_idt_entry(struct desc_struct *idt,
* the Guest to use the "int" instruction to trigger it. */ * the Guest to use the "int" instruction to trigger it. */
if (trap == LGUEST_TRAP_ENTRY) if (trap == LGUEST_TRAP_ENTRY)
flags |= (GUEST_PL << 13); flags |= (GUEST_PL << 13);
else if (base)
/* Copy priv. level from what Guest asked for. This allows
* debug (int 3) traps from Guest userspace, for example. */
flags |= (base->b & 0x6000);
/* Now pack it into the IDT entry in its weird format. */ /* Now pack it into the IDT entry in its weird format. */
idt->a = (LGUEST_CS<<16) | (handler&0x0000FFFF); idt->a = (LGUEST_CS<<16) | (handler&0x0000FFFF);
...@@ -428,7 +433,7 @@ void setup_default_idt_entries(struct lguest_ro_state *state, ...@@ -428,7 +433,7 @@ void setup_default_idt_entries(struct lguest_ro_state *state,
unsigned int i; unsigned int i;
for (i = 0; i < ARRAY_SIZE(state->guest_idt); i++) for (i = 0; i < ARRAY_SIZE(state->guest_idt); i++)
default_idt_entry(&state->guest_idt[i], i, def[i]); default_idt_entry(&state->guest_idt[i], i, def[i], NULL);
} }
/*H:240 We don't use the IDT entries in the "struct lguest" directly, instead /*H:240 We don't use the IDT entries in the "struct lguest" directly, instead
...@@ -442,6 +447,8 @@ void copy_traps(const struct lg_cpu *cpu, struct desc_struct *idt, ...@@ -442,6 +447,8 @@ void copy_traps(const struct lg_cpu *cpu, struct desc_struct *idt,
/* We can simply copy the direct traps, otherwise we use the default /* We can simply copy the direct traps, otherwise we use the default
* ones in the Switcher: they will return to the Host. */ * ones in the Switcher: they will return to the Host. */
for (i = 0; i < ARRAY_SIZE(cpu->arch.idt); i++) { for (i = 0; i < ARRAY_SIZE(cpu->arch.idt); i++) {
const struct desc_struct *gidt = &cpu->arch.idt[i];
/* If no Guest can ever override this trap, leave it alone. */ /* If no Guest can ever override this trap, leave it alone. */
if (!direct_trap(i)) if (!direct_trap(i))
continue; continue;
...@@ -449,12 +456,15 @@ void copy_traps(const struct lg_cpu *cpu, struct desc_struct *idt, ...@@ -449,12 +456,15 @@ void copy_traps(const struct lg_cpu *cpu, struct desc_struct *idt,
/* Only trap gates (type 15) can go direct to the Guest. /* Only trap gates (type 15) can go direct to the Guest.
* Interrupt gates (type 14) disable interrupts as they are * Interrupt gates (type 14) disable interrupts as they are
* entered, which we never let the Guest do. Not present * entered, which we never let the Guest do. Not present
* entries (type 0x0) also can't go direct, of course. */ * entries (type 0x0) also can't go direct, of course.
if (idt_type(cpu->arch.idt[i].a, cpu->arch.idt[i].b) == 0xF) *
idt[i] = cpu->arch.idt[i]; * If it can't go direct, we still need to copy the priv. level:
* they might want to give userspace access to a software
* interrupt. */
if (idt_type(gidt->a, gidt->b) == 0xF)
idt[i] = *gidt;
else else
/* Reset it to the default. */ default_idt_entry(&idt[i], i, def[i], gidt);
default_idt_entry(&idt[i], i, def[i]);
} }
} }
......
...@@ -480,7 +480,7 @@ void __init lguest_arch_host_init(void) ...@@ -480,7 +480,7 @@ void __init lguest_arch_host_init(void)
* bit on its CPU, depending on the argument (0 == unset). */ * bit on its CPU, depending on the argument (0 == unset). */
on_each_cpu(adjust_pge, (void *)0, 1); on_each_cpu(adjust_pge, (void *)0, 1);
/* Turn off the feature in the global feature set. */ /* Turn off the feature in the global feature set. */
clear_bit(X86_FEATURE_PGE, boot_cpu_data.x86_capability); clear_cpu_cap(&boot_cpu_data, X86_FEATURE_PGE);
} }
put_online_cpus(); put_online_cpus();
}; };
...@@ -491,7 +491,7 @@ void __exit lguest_arch_host_fini(void) ...@@ -491,7 +491,7 @@ void __exit lguest_arch_host_fini(void)
/* If we had PGE before we started, turn it back on now. */ /* If we had PGE before we started, turn it back on now. */
get_online_cpus(); get_online_cpus();
if (cpu_had_pge) { if (cpu_had_pge) {
set_bit(X86_FEATURE_PGE, boot_cpu_data.x86_capability); set_cpu_cap(&boot_cpu_data, X86_FEATURE_PGE);
/* adjust_pge's argument "1" means set PGE. */ /* adjust_pge's argument "1" means set PGE. */
on_each_cpu(adjust_pge, (void *)1, 1); on_each_cpu(adjust_pge, (void *)1, 1);
} }
......
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