aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/lguest
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2012-02-10 10:52:55 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2012-02-10 11:14:49 -0500
commit9edd576d89a5b6d3e136d7dcab654d887c0d25b7 (patch)
treed19670de2256f8187321de3a41fa4a10d3c8e402 /drivers/lguest
parente21af88d39796c907c38648c824be3d646ffbe35 (diff)
parent28a4d5675857f6386930a324317281cb8ed1e5d0 (diff)
Merge remote-tracking branch 'airlied/drm-fixes' into drm-intel-next-queued
Back-merge from drm-fixes into drm-intel-next to sort out two things: - interlaced support: -fixes contains a bugfix to correctly clear interlaced configuration bits in case the bios sets up an interlaced mode and we want to set up the progressive mode (current kernels don't support interlaced). The actual feature work to support interlaced depends upon (and conflicts with) this bugfix. - forcewake voodoo to workaround missed IRQ issues: -fixes only enabled this for ivybridge, but some recent bug reports indicate that we need this on Sandybridge, too. But in a slightly different flavour and with other fixes and reworks on top. Additionally there are some forcewake cleanup patches heading to -next that would conflict with currrent -fixes. Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/lguest')
-rw-r--r--drivers/lguest/Makefile2
-rw-r--r--drivers/lguest/lguest_device.c24
-rw-r--r--drivers/lguest/segments.c28
-rw-r--r--drivers/lguest/x86/core.c2
4 files changed, 37 insertions, 19 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 0dc30ffde5ad..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:
@@ -381,6 +387,11 @@ error:
381 return PTR_ERR(vqs[i]); 387 return PTR_ERR(vqs[i]);
382} 388}
383 389
390static const char *lg_bus_name(struct virtio_device *vdev)
391{
392 return "";
393}
394
384/* The ops structure which hooks everything together. */ 395/* The ops structure which hooks everything together. */
385static struct virtio_config_ops lguest_config_ops = { 396static struct virtio_config_ops lguest_config_ops = {
386 .get_features = lg_get_features, 397 .get_features = lg_get_features,
@@ -392,6 +403,7 @@ static struct virtio_config_ops lguest_config_ops = {
392 .reset = lg_reset, 403 .reset = lg_reset,
393 .find_vqs = lg_find_vqs, 404 .find_vqs = lg_find_vqs,
394 .del_vqs = lg_del_vqs, 405 .del_vqs = lg_del_vqs,
406 .bus_name = lg_bus_name,
395}; 407};
396 408
397/* 409/*
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
diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c
index 65af42f2d593..39809035320a 100644
--- a/drivers/lguest/x86/core.c
+++ b/drivers/lguest/x86/core.c
@@ -697,7 +697,7 @@ void lguest_arch_setup_regs(struct lg_cpu *cpu, unsigned long start)
697 * interrupts are enabled. We always leave interrupts enabled while 697 * interrupts are enabled. We always leave interrupts enabled while
698 * running the Guest. 698 * running the Guest.
699 */ 699 */
700 regs->eflags = X86_EFLAGS_IF | 0x2; 700 regs->eflags = X86_EFLAGS_IF | X86_EFLAGS_BIT1;
701 701
702 /* 702 /*
703 * The "Extended Instruction Pointer" register says where the Guest is 703 * The "Extended Instruction Pointer" register says where the Guest is