diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-09 13:20:54 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-09 13:20:54 -0400 |
commit | d8cacd3a259bf522ea5e6c4c60eba67ba22f599c (patch) | |
tree | 24af775fc95240a5be8fdc7bbdb4c25d44ed644c | |
parent | d75671e36e14b73d7c0d3cec49328dcd984af699 (diff) | |
parent | 9e266ece2178784a1027e04a56c8547dc51b15ce (diff) |
Merge tag 'virtio-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux
Pull virtio update from Rusty Russell:
"More console fixes; these are the theoretical ones which didn't get
CC:stable. But for that reason, I did a merge with master partway
through to avoid an unnecessary conflict.
Also: a fun lguest bug turns out if you don't clear the TF flag when
trapping Bad Things happen to the guest kernel as the stack
overflows..."
* tag 'virtio-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux:
virtio_pci: pm: Use CONFIG_PM_SLEEP instead of CONFIG_PM
lguest: fix GPF in guest when using gdb.
lguest: fix guest kernel stack overflow when TF bit set.
lguest: fix BUG_ON() in invalid guest page table.
virtio: console: prevent use-after-free of port name in port unplug
virtio: console: cleanup an error message
virtio: console: fix locking around send_sigio_to_port()
virtio: console: add locking in port unplug path
virtio: console: add locks around buffer removal in port unplug path
tools/lguest: offer VIRTIO_F_ANY_LAYOUT for net device.
virtio tools: add .gitignore
lguest: Point to the right directory for the lguest launcher
-rw-r--r-- | arch/x86/lguest/boot.c | 10 | ||||
-rw-r--r-- | drivers/char/virtio_console.c | 27 | ||||
-rw-r--r-- | drivers/lguest/interrupts_and_traps.c | 10 | ||||
-rw-r--r-- | drivers/lguest/page_tables.c | 4 | ||||
-rw-r--r-- | drivers/virtio/virtio_pci.c | 4 | ||||
-rw-r--r-- | tools/lguest/lguest.c | 6 | ||||
-rw-r--r-- | tools/virtio/.gitignore | 3 |
7 files changed, 48 insertions, 16 deletions
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index 6a22c19da663..bdf8532494fe 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c | |||
@@ -7,8 +7,7 @@ | |||
7 | * kernel and insert a module (lg.ko) which allows us to run other Linux | 7 | * kernel and insert a module (lg.ko) which allows us to run other Linux |
8 | * kernels the same way we'd run processes. We call the first kernel the Host, | 8 | * kernels the same way we'd run processes. We call the first kernel the Host, |
9 | * and the others the Guests. The program which sets up and configures Guests | 9 | * and the others the Guests. The program which sets up and configures Guests |
10 | * (such as the example in Documentation/virtual/lguest/lguest.c) is called the | 10 | * (such as the example in tools/lguest/lguest.c) is called the Launcher. |
11 | * Launcher. | ||
12 | * | 11 | * |
13 | * Secondly, we only run specially modified Guests, not normal kernels: setting | 12 | * Secondly, we only run specially modified Guests, not normal kernels: setting |
14 | * CONFIG_LGUEST_GUEST to "y" compiles this file into the kernel so it knows | 13 | * CONFIG_LGUEST_GUEST to "y" compiles this file into the kernel so it knows |
@@ -1057,6 +1056,12 @@ static void lguest_load_sp0(struct tss_struct *tss, | |||
1057 | } | 1056 | } |
1058 | 1057 | ||
1059 | /* Let's just say, I wouldn't do debugging under a Guest. */ | 1058 | /* Let's just say, I wouldn't do debugging under a Guest. */ |
1059 | static unsigned long lguest_get_debugreg(int regno) | ||
1060 | { | ||
1061 | /* FIXME: Implement */ | ||
1062 | return 0; | ||
1063 | } | ||
1064 | |||
1060 | static void lguest_set_debugreg(int regno, unsigned long value) | 1065 | static void lguest_set_debugreg(int regno, unsigned long value) |
1061 | { | 1066 | { |
1062 | /* FIXME: Implement */ | 1067 | /* FIXME: Implement */ |
@@ -1304,6 +1309,7 @@ __init void lguest_init(void) | |||
1304 | pv_cpu_ops.load_tr_desc = lguest_load_tr_desc; | 1309 | pv_cpu_ops.load_tr_desc = lguest_load_tr_desc; |
1305 | pv_cpu_ops.set_ldt = lguest_set_ldt; | 1310 | pv_cpu_ops.set_ldt = lguest_set_ldt; |
1306 | pv_cpu_ops.load_tls = lguest_load_tls; | 1311 | pv_cpu_ops.load_tls = lguest_load_tls; |
1312 | pv_cpu_ops.get_debugreg = lguest_get_debugreg; | ||
1307 | pv_cpu_ops.set_debugreg = lguest_set_debugreg; | 1313 | pv_cpu_ops.set_debugreg = lguest_set_debugreg; |
1308 | pv_cpu_ops.clts = lguest_clts; | 1314 | pv_cpu_ops.clts = lguest_clts; |
1309 | pv_cpu_ops.read_cr0 = lguest_read_cr0; | 1315 | pv_cpu_ops.read_cr0 = lguest_read_cr0; |
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index fc45567ad3ac..b79cf3e1b793 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
@@ -1529,18 +1529,22 @@ static void remove_port_data(struct port *port) | |||
1529 | { | 1529 | { |
1530 | struct port_buffer *buf; | 1530 | struct port_buffer *buf; |
1531 | 1531 | ||
1532 | spin_lock_irq(&port->inbuf_lock); | ||
1532 | /* Remove unused data this port might have received. */ | 1533 | /* Remove unused data this port might have received. */ |
1533 | discard_port_data(port); | 1534 | discard_port_data(port); |
1534 | 1535 | ||
1535 | reclaim_consumed_buffers(port); | ||
1536 | |||
1537 | /* Remove buffers we queued up for the Host to send us data in. */ | 1536 | /* Remove buffers we queued up for the Host to send us data in. */ |
1538 | while ((buf = virtqueue_detach_unused_buf(port->in_vq))) | 1537 | while ((buf = virtqueue_detach_unused_buf(port->in_vq))) |
1539 | free_buf(buf, true); | 1538 | free_buf(buf, true); |
1539 | spin_unlock_irq(&port->inbuf_lock); | ||
1540 | |||
1541 | spin_lock_irq(&port->outvq_lock); | ||
1542 | reclaim_consumed_buffers(port); | ||
1540 | 1543 | ||
1541 | /* Free pending buffers from the out-queue. */ | 1544 | /* Free pending buffers from the out-queue. */ |
1542 | while ((buf = virtqueue_detach_unused_buf(port->out_vq))) | 1545 | while ((buf = virtqueue_detach_unused_buf(port->out_vq))) |
1543 | free_buf(buf, true); | 1546 | free_buf(buf, true); |
1547 | spin_unlock_irq(&port->outvq_lock); | ||
1544 | } | 1548 | } |
1545 | 1549 | ||
1546 | /* | 1550 | /* |
@@ -1554,6 +1558,7 @@ static void unplug_port(struct port *port) | |||
1554 | list_del(&port->list); | 1558 | list_del(&port->list); |
1555 | spin_unlock_irq(&port->portdev->ports_lock); | 1559 | spin_unlock_irq(&port->portdev->ports_lock); |
1556 | 1560 | ||
1561 | spin_lock_irq(&port->inbuf_lock); | ||
1557 | if (port->guest_connected) { | 1562 | if (port->guest_connected) { |
1558 | /* Let the app know the port is going down. */ | 1563 | /* Let the app know the port is going down. */ |
1559 | send_sigio_to_port(port); | 1564 | send_sigio_to_port(port); |
@@ -1564,6 +1569,7 @@ static void unplug_port(struct port *port) | |||
1564 | 1569 | ||
1565 | wake_up_interruptible(&port->waitqueue); | 1570 | wake_up_interruptible(&port->waitqueue); |
1566 | } | 1571 | } |
1572 | spin_unlock_irq(&port->inbuf_lock); | ||
1567 | 1573 | ||
1568 | if (is_console_port(port)) { | 1574 | if (is_console_port(port)) { |
1569 | spin_lock_irq(&pdrvdata_lock); | 1575 | spin_lock_irq(&pdrvdata_lock); |
@@ -1585,9 +1591,8 @@ static void unplug_port(struct port *port) | |||
1585 | device_destroy(pdrvdata.class, port->dev->devt); | 1591 | device_destroy(pdrvdata.class, port->dev->devt); |
1586 | cdev_del(port->cdev); | 1592 | cdev_del(port->cdev); |
1587 | 1593 | ||
1588 | kfree(port->name); | ||
1589 | |||
1590 | debugfs_remove(port->debugfs_file); | 1594 | debugfs_remove(port->debugfs_file); |
1595 | kfree(port->name); | ||
1591 | 1596 | ||
1592 | /* | 1597 | /* |
1593 | * Locks around here are not necessary - a port can't be | 1598 | * Locks around here are not necessary - a port can't be |
@@ -1681,7 +1686,9 @@ static void handle_control_message(struct ports_device *portdev, | |||
1681 | * If the guest is connected, it'll be interested in | 1686 | * If the guest is connected, it'll be interested in |
1682 | * knowing the host connection state changed. | 1687 | * knowing the host connection state changed. |
1683 | */ | 1688 | */ |
1689 | spin_lock_irq(&port->inbuf_lock); | ||
1684 | send_sigio_to_port(port); | 1690 | send_sigio_to_port(port); |
1691 | spin_unlock_irq(&port->inbuf_lock); | ||
1685 | break; | 1692 | break; |
1686 | case VIRTIO_CONSOLE_PORT_NAME: | 1693 | case VIRTIO_CONSOLE_PORT_NAME: |
1687 | /* | 1694 | /* |
@@ -1801,13 +1808,13 @@ static void in_intr(struct virtqueue *vq) | |||
1801 | if (!port->guest_connected && !is_rproc_serial(port->portdev->vdev)) | 1808 | if (!port->guest_connected && !is_rproc_serial(port->portdev->vdev)) |
1802 | discard_port_data(port); | 1809 | discard_port_data(port); |
1803 | 1810 | ||
1811 | /* Send a SIGIO indicating new data in case the process asked for it */ | ||
1812 | send_sigio_to_port(port); | ||
1813 | |||
1804 | spin_unlock_irqrestore(&port->inbuf_lock, flags); | 1814 | spin_unlock_irqrestore(&port->inbuf_lock, flags); |
1805 | 1815 | ||
1806 | wake_up_interruptible(&port->waitqueue); | 1816 | wake_up_interruptible(&port->waitqueue); |
1807 | 1817 | ||
1808 | /* Send a SIGIO indicating new data in case the process asked for it */ | ||
1809 | send_sigio_to_port(port); | ||
1810 | |||
1811 | if (is_console_port(port) && hvc_poll(port->cons.hvc)) | 1818 | if (is_console_port(port) && hvc_poll(port->cons.hvc)) |
1812 | hvc_kick(); | 1819 | hvc_kick(); |
1813 | } | 1820 | } |
@@ -2241,10 +2248,8 @@ static int __init init(void) | |||
2241 | } | 2248 | } |
2242 | 2249 | ||
2243 | pdrvdata.debugfs_dir = debugfs_create_dir("virtio-ports", NULL); | 2250 | pdrvdata.debugfs_dir = debugfs_create_dir("virtio-ports", NULL); |
2244 | if (!pdrvdata.debugfs_dir) { | 2251 | if (!pdrvdata.debugfs_dir) |
2245 | pr_warning("Error %ld creating debugfs dir for virtio-ports\n", | 2252 | pr_warning("Error creating debugfs dir for virtio-ports\n"); |
2246 | PTR_ERR(pdrvdata.debugfs_dir)); | ||
2247 | } | ||
2248 | INIT_LIST_HEAD(&pdrvdata.consoles); | 2253 | INIT_LIST_HEAD(&pdrvdata.consoles); |
2249 | INIT_LIST_HEAD(&pdrvdata.portdevs); | 2254 | INIT_LIST_HEAD(&pdrvdata.portdevs); |
2250 | 2255 | ||
diff --git a/drivers/lguest/interrupts_and_traps.c b/drivers/lguest/interrupts_and_traps.c index 28433a155d67..70dfcdc29f1f 100644 --- a/drivers/lguest/interrupts_and_traps.c +++ b/drivers/lguest/interrupts_and_traps.c | |||
@@ -140,6 +140,16 @@ static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi, | |||
140 | cpu->regs->eip = idt_address(lo, hi); | 140 | cpu->regs->eip = idt_address(lo, hi); |
141 | 141 | ||
142 | /* | 142 | /* |
143 | * Trapping always clears these flags: | ||
144 | * TF: Trap flag | ||
145 | * VM: Virtual 8086 mode | ||
146 | * RF: Resume | ||
147 | * NT: Nested task. | ||
148 | */ | ||
149 | cpu->regs->eflags &= | ||
150 | ~(X86_EFLAGS_TF|X86_EFLAGS_VM|X86_EFLAGS_RF|X86_EFLAGS_NT); | ||
151 | |||
152 | /* | ||
143 | * There are two kinds of interrupt handlers: 0xE is an "interrupt | 153 | * There are two kinds of interrupt handlers: 0xE is an "interrupt |
144 | * gate" which expects interrupts to be disabled on entry. | 154 | * gate" which expects interrupts to be disabled on entry. |
145 | */ | 155 | */ |
diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c index a35d8d100165..bfb39bb56ef1 100644 --- a/drivers/lguest/page_tables.c +++ b/drivers/lguest/page_tables.c | |||
@@ -669,8 +669,10 @@ unsigned long guest_pa(struct lg_cpu *cpu, unsigned long vaddr) | |||
669 | 669 | ||
670 | #ifdef CONFIG_X86_PAE | 670 | #ifdef CONFIG_X86_PAE |
671 | gpmd = lgread(cpu, gpmd_addr(gpgd, vaddr), pmd_t); | 671 | gpmd = lgread(cpu, gpmd_addr(gpgd, vaddr), pmd_t); |
672 | if (!(pmd_flags(gpmd) & _PAGE_PRESENT)) | 672 | if (!(pmd_flags(gpmd) & _PAGE_PRESENT)) { |
673 | kill_guest(cpu, "Bad address %#lx", vaddr); | 673 | kill_guest(cpu, "Bad address %#lx", vaddr); |
674 | return -1UL; | ||
675 | } | ||
674 | gpte = lgread(cpu, gpte_addr(cpu, gpmd, vaddr), pte_t); | 676 | gpte = lgread(cpu, gpte_addr(cpu, gpmd, vaddr), pte_t); |
675 | #else | 677 | #else |
676 | gpte = lgread(cpu, gpte_addr(cpu, gpgd, vaddr), pte_t); | 678 | gpte = lgread(cpu, gpte_addr(cpu, gpgd, vaddr), pte_t); |
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index 1aba255b5879..98917fc872a4 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c | |||
@@ -766,7 +766,7 @@ static void virtio_pci_remove(struct pci_dev *pci_dev) | |||
766 | kfree(vp_dev); | 766 | kfree(vp_dev); |
767 | } | 767 | } |
768 | 768 | ||
769 | #ifdef CONFIG_PM | 769 | #ifdef CONFIG_PM_SLEEP |
770 | static int virtio_pci_freeze(struct device *dev) | 770 | static int virtio_pci_freeze(struct device *dev) |
771 | { | 771 | { |
772 | struct pci_dev *pci_dev = to_pci_dev(dev); | 772 | struct pci_dev *pci_dev = to_pci_dev(dev); |
@@ -824,7 +824,7 @@ static struct pci_driver virtio_pci_driver = { | |||
824 | .id_table = virtio_pci_id_table, | 824 | .id_table = virtio_pci_id_table, |
825 | .probe = virtio_pci_probe, | 825 | .probe = virtio_pci_probe, |
826 | .remove = virtio_pci_remove, | 826 | .remove = virtio_pci_remove, |
827 | #ifdef CONFIG_PM | 827 | #ifdef CONFIG_PM_SLEEP |
828 | .driver.pm = &virtio_pci_pm_ops, | 828 | .driver.pm = &virtio_pci_pm_ops, |
829 | #endif | 829 | #endif |
830 | }; | 830 | }; |
diff --git a/tools/lguest/lguest.c b/tools/lguest/lguest.c index 68f67cf3d318..32cf2ce15d69 100644 --- a/tools/lguest/lguest.c +++ b/tools/lguest/lguest.c | |||
@@ -42,6 +42,10 @@ | |||
42 | #include <pwd.h> | 42 | #include <pwd.h> |
43 | #include <grp.h> | 43 | #include <grp.h> |
44 | 44 | ||
45 | #ifndef VIRTIO_F_ANY_LAYOUT | ||
46 | #define VIRTIO_F_ANY_LAYOUT 27 | ||
47 | #endif | ||
48 | |||
45 | /*L:110 | 49 | /*L:110 |
46 | * We can ignore the 43 include files we need for this program, but I do want | 50 | * We can ignore the 43 include files we need for this program, but I do want |
47 | * to draw attention to the use of kernel-style types. | 51 | * to draw attention to the use of kernel-style types. |
@@ -1544,6 +1548,8 @@ static void setup_tun_net(char *arg) | |||
1544 | add_feature(dev, VIRTIO_NET_F_HOST_ECN); | 1548 | add_feature(dev, VIRTIO_NET_F_HOST_ECN); |
1545 | /* We handle indirect ring entries */ | 1549 | /* We handle indirect ring entries */ |
1546 | add_feature(dev, VIRTIO_RING_F_INDIRECT_DESC); | 1550 | add_feature(dev, VIRTIO_RING_F_INDIRECT_DESC); |
1551 | /* We're compliant with the damn spec. */ | ||
1552 | add_feature(dev, VIRTIO_F_ANY_LAYOUT); | ||
1547 | set_config(dev, sizeof(conf), &conf); | 1553 | set_config(dev, sizeof(conf), &conf); |
1548 | 1554 | ||
1549 | /* We don't need the socket any more; setup is done. */ | 1555 | /* We don't need the socket any more; setup is done. */ |
diff --git a/tools/virtio/.gitignore b/tools/virtio/.gitignore new file mode 100644 index 000000000000..1cfbb0157a46 --- /dev/null +++ b/tools/virtio/.gitignore | |||
@@ -0,0 +1,3 @@ | |||
1 | *.d | ||
2 | virtio_test | ||
3 | vringh_test | ||