diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-02-10 10:52:55 -0500 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-02-10 11:14:49 -0500 |
commit | 9edd576d89a5b6d3e136d7dcab654d887c0d25b7 (patch) | |
tree | d19670de2256f8187321de3a41fa4a10d3c8e402 /drivers/lguest | |
parent | e21af88d39796c907c38648c824be3d646ffbe35 (diff) | |
parent | 28a4d5675857f6386930a324317281cb8ed1e5d0 (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/Makefile | 2 | ||||
-rw-r--r-- | drivers/lguest/lguest_device.c | 24 | ||||
-rw-r--r-- | drivers/lguest/segments.c | 28 | ||||
-rw-r--r-- | drivers/lguest/x86/core.c | 2 |
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 | |||
18 | Beer: | 18 | Beer: |
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 "{==-==}" |
20 | Preparation Preparation! Guest Drivers Launcher Host Switcher Mastery: | 20 | Preparation 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*'` |
22 | Puppy: | 22 | Puppy: |
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. */ |
244 | extern void lguest_setup_irq(unsigned int irq); | 244 | extern 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 | ||
331 | free_desc: | ||
332 | irq_free_desc(lvq->config.irq); | ||
327 | destroy_vring: | 333 | destroy_vring: |
328 | vring_del_virtqueue(vq); | 334 | vring_del_virtqueue(vq); |
329 | unmap: | 335 | unmap: |
@@ -381,6 +387,11 @@ error: | |||
381 | return PTR_ERR(vqs[i]); | 387 | return PTR_ERR(vqs[i]); |
382 | } | 388 | } |
383 | 389 | ||
390 | static 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. */ |
385 | static struct virtio_config_ops lguest_config_ops = { | 396 | static 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 |