aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/lguest
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/lguest')
-rw-r--r--drivers/lguest/Makefile2
-rw-r--r--drivers/lguest/lguest_device.c18
-rw-r--r--drivers/lguest/segments.c28
3 files changed, 30 insertions, 18 deletions
diff --git a/drivers/lguest/Makefile b/drivers/lguest/Makefile
index 8ac947c7e7c7..c4197503900e 100644
--- a/drivers/lguest/Makefile
+++ b/drivers/lguest/Makefile
@@ -18,7 +18,7 @@ Mastery: PREFIX=M
18Beer: 18Beer:
19 @for f in Preparation Guest Drivers Launcher Host Switcher Mastery; do echo "{==- $$f -==}"; make -s $$f; done; echo "{==-==}" 19 @for f in Preparation Guest Drivers Launcher Host Switcher Mastery; do echo "{==- $$f -==}"; make -s $$f; done; echo "{==-==}"
20Preparation Preparation! Guest Drivers Launcher Host Switcher Mastery: 20Preparation Preparation! Guest Drivers Launcher Host Switcher Mastery:
21 @sh ../../Documentation/virtual/lguest/extract $(PREFIX) `find ../../* -name '*.[chS]' -wholename '*lguest*'` 21 @sh ../../tools/lguest/extract $(PREFIX) `find ../../* -name '*.[chS]' -wholename '*lguest*'`
22Puppy: 22Puppy:
23 @clear 23 @clear
24 @printf " __ \n (___()'\`;\n /, /\`\n \\\\\\\"--\\\\\\ \n" 24 @printf " __ \n (___()'\`;\n /, /\`\n \\\\\\\"--\\\\\\ \n"
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c
index 595d73197016..9e8388efd88e 100644
--- a/drivers/lguest/lguest_device.c
+++ b/drivers/lguest/lguest_device.c
@@ -241,7 +241,7 @@ static void lg_notify(struct virtqueue *vq)
241} 241}
242 242
243/* An extern declaration inside a C file is bad form. Don't do it. */ 243/* An extern declaration inside a C file is bad form. Don't do it. */
244extern void lguest_setup_irq(unsigned int irq); 244extern int lguest_setup_irq(unsigned int irq);
245 245
246/* 246/*
247 * This routine finds the Nth virtqueue described in the configuration of 247 * This routine finds the Nth virtqueue described in the configuration of
@@ -292,17 +292,21 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
292 292
293 /* 293 /*
294 * OK, tell virtio_ring.c to set up a virtqueue now we know its size 294 * OK, tell virtio_ring.c to set up a virtqueue now we know its size
295 * and we've got a pointer to its pages. 295 * and we've got a pointer to its pages. Note that we set weak_barriers
296 * to 'true': the host just a(nother) SMP CPU, so we only need inter-cpu
297 * barriers.
296 */ 298 */
297 vq = vring_new_virtqueue(lvq->config.num, LGUEST_VRING_ALIGN, 299 vq = vring_new_virtqueue(lvq->config.num, LGUEST_VRING_ALIGN, vdev,
298 vdev, lvq->pages, lg_notify, callback, name); 300 true, lvq->pages, lg_notify, callback, name);
299 if (!vq) { 301 if (!vq) {
300 err = -ENOMEM; 302 err = -ENOMEM;
301 goto unmap; 303 goto unmap;
302 } 304 }
303 305
304 /* Make sure the interrupt is allocated. */ 306 /* Make sure the interrupt is allocated. */
305 lguest_setup_irq(lvq->config.irq); 307 err = lguest_setup_irq(lvq->config.irq);
308 if (err)
309 goto destroy_vring;
306 310
307 /* 311 /*
308 * Tell the interrupt for this virtqueue to go to the virtio_ring 312 * Tell the interrupt for this virtqueue to go to the virtio_ring
@@ -315,7 +319,7 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
315 err = request_irq(lvq->config.irq, vring_interrupt, IRQF_SHARED, 319 err = request_irq(lvq->config.irq, vring_interrupt, IRQF_SHARED,
316 dev_name(&vdev->dev), vq); 320 dev_name(&vdev->dev), vq);
317 if (err) 321 if (err)
318 goto destroy_vring; 322 goto free_desc;
319 323
320 /* 324 /*
321 * Last of all we hook up our 'struct lguest_vq_info" to the 325 * Last of all we hook up our 'struct lguest_vq_info" to the
@@ -324,6 +328,8 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
324 vq->priv = lvq; 328 vq->priv = lvq;
325 return vq; 329 return vq;
326 330
331free_desc:
332 irq_free_desc(lvq->config.irq);
327destroy_vring: 333destroy_vring:
328 vring_del_virtqueue(vq); 334 vring_del_virtqueue(vq);
329unmap: 335unmap:
diff --git a/drivers/lguest/segments.c b/drivers/lguest/segments.c
index ede46581351a..c4fb424dfddb 100644
--- a/drivers/lguest/segments.c
+++ b/drivers/lguest/segments.c
@@ -81,8 +81,8 @@ static void fixup_gdt_table(struct lg_cpu *cpu, unsigned start, unsigned end)
81 * sometimes careless and leaves this as 0, even though it's 81 * sometimes careless and leaves this as 0, even though it's
82 * running at privilege level 1. If so, we fix it here. 82 * running at privilege level 1. If so, we fix it here.
83 */ 83 */
84 if ((cpu->arch.gdt[i].b & 0x00006000) == 0) 84 if (cpu->arch.gdt[i].dpl == 0)
85 cpu->arch.gdt[i].b |= (GUEST_PL << 13); 85 cpu->arch.gdt[i].dpl |= GUEST_PL;
86 86
87 /* 87 /*
88 * Each descriptor has an "accessed" bit. If we don't set it 88 * Each descriptor has an "accessed" bit. If we don't set it
@@ -90,7 +90,7 @@ static void fixup_gdt_table(struct lg_cpu *cpu, unsigned start, unsigned end)
90 * that entry into a segment register. But the GDT isn't 90 * that entry into a segment register. But the GDT isn't
91 * writable by the Guest, so bad things can happen. 91 * writable by the Guest, so bad things can happen.
92 */ 92 */
93 cpu->arch.gdt[i].b |= 0x00000100; 93 cpu->arch.gdt[i].type |= 0x1;
94 } 94 }
95} 95}
96 96
@@ -114,13 +114,19 @@ void setup_default_gdt_entries(struct lguest_ro_state *state)
114 114
115 /* 115 /*
116 * The TSS segment refers to the TSS entry for this particular CPU. 116 * The TSS segment refers to the TSS entry for this particular CPU.
117 * Forgive the magic flags: the 0x8900 means the entry is Present, it's
118 * privilege level 0 Available 386 TSS system segment, and the 0x67
119 * means Saturn is eclipsed by Mercury in the twelfth house.
120 */ 117 */
121 gdt[GDT_ENTRY_TSS].a = 0x00000067 | (tss << 16); 118 gdt[GDT_ENTRY_TSS].a = 0;
122 gdt[GDT_ENTRY_TSS].b = 0x00008900 | (tss & 0xFF000000) 119 gdt[GDT_ENTRY_TSS].b = 0;
123 | ((tss >> 16) & 0x000000FF); 120
121 gdt[GDT_ENTRY_TSS].limit0 = 0x67;
122 gdt[GDT_ENTRY_TSS].base0 = tss & 0xFFFF;
123 gdt[GDT_ENTRY_TSS].base1 = (tss >> 16) & 0xFF;
124 gdt[GDT_ENTRY_TSS].base2 = tss >> 24;
125 gdt[GDT_ENTRY_TSS].type = 0x9; /* 32-bit TSS (available) */
126 gdt[GDT_ENTRY_TSS].p = 0x1; /* Entry is present */
127 gdt[GDT_ENTRY_TSS].dpl = 0x0; /* Privilege level 0 */
128 gdt[GDT_ENTRY_TSS].s = 0x0; /* system segment */
129
124} 130}
125 131
126/* 132/*
@@ -135,8 +141,8 @@ void setup_guest_gdt(struct lg_cpu *cpu)
135 */ 141 */
136 cpu->arch.gdt[GDT_ENTRY_KERNEL_CS] = FULL_EXEC_SEGMENT; 142 cpu->arch.gdt[GDT_ENTRY_KERNEL_CS] = FULL_EXEC_SEGMENT;
137 cpu->arch.gdt[GDT_ENTRY_KERNEL_DS] = FULL_SEGMENT; 143 cpu->arch.gdt[GDT_ENTRY_KERNEL_DS] = FULL_SEGMENT;
138 cpu->arch.gdt[GDT_ENTRY_KERNEL_CS].b |= (GUEST_PL << 13); 144 cpu->arch.gdt[GDT_ENTRY_KERNEL_CS].dpl |= GUEST_PL;
139 cpu->arch.gdt[GDT_ENTRY_KERNEL_DS].b |= (GUEST_PL << 13); 145 cpu->arch.gdt[GDT_ENTRY_KERNEL_DS].dpl |= GUEST_PL;
140} 146}
141 147
142/*H:650 148/*H:650