From 45e84a0f42d47f3aed719e487256ee458f98d9b6 Mon Sep 17 00:00:00 2001 From: Justin M. Forbes Date: Jan 11 2012 21:27:49 +0000 Subject: Add patches from 1.0.1 queue --- diff --git a/0001-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch b/0001-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch deleted file mode 100644 index 5a7dc4c..0000000 --- a/0001-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch +++ /dev/null @@ -1,57 +0,0 @@ ->From c0295cc7cc626a2d51de58ac0a9eeee94b6cc9d4 Mon Sep 17 00:00:00 2001 -From: Amit Shah -Date: Mon, 21 Mar 2011 21:57:47 +0100 -Subject: [PATCH 01/28] char: Split out tcp socket close code in a separate - function - -Signed-off-by: Amit Shah ---- - qemu-char.c | 25 ++++++++++++++++--------- - 1 files changed, 16 insertions(+), 9 deletions(-) - -diff --git a/qemu-char.c b/qemu-char.c -index 8e8cf31..5682aea 100644 ---- a/qemu-char.c -+++ b/qemu-char.c -@@ -1946,6 +1946,21 @@ typedef struct { - - static void tcp_chr_accept(void *opaque); - -+static void tcp_closed(void *opaque) -+{ -+ CharDriverState *chr = opaque; -+ TCPCharDriver *s = chr->opaque; -+ -+ s->connected = 0; -+ if (s->listen_fd >= 0) { -+ qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr); -+ } -+ qemu_set_fd_handler(s->fd, NULL, NULL, NULL); -+ closesocket(s->fd); -+ s->fd = -1; -+ qemu_chr_event(chr, CHR_EVENT_CLOSED); -+} -+ - static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len) - { - TCPCharDriver *s = chr->opaque; -@@ -2096,15 +2111,7 @@ static void tcp_chr_read(void *opaque) - len = s->max_size; - size = tcp_chr_recv(chr, (void *)buf, len); - if (size == 0) { -- /* connection closed */ -- s->connected = 0; -- if (s->listen_fd >= 0) { -- qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr); -- } -- qemu_set_fd_handler(s->fd, NULL, NULL, NULL); -- closesocket(s->fd); -- s->fd = -1; -- qemu_chr_event(chr, CHR_EVENT_CLOSED); -+ tcp_closed(chr); - } else if (size > 0) { - if (s->do_telnetopt) - tcp_chr_process_IAC_bytes(chr, s, buf, &size); --- -1.7.5.1 - diff --git a/0001-malta-Fix-regression-i8259-interrupts-did-not-work.patch b/0001-malta-Fix-regression-i8259-interrupts-did-not-work.patch new file mode 100644 index 0000000..a57f4ec --- /dev/null +++ b/0001-malta-Fix-regression-i8259-interrupts-did-not-work.patch @@ -0,0 +1,132 @@ +From 0b23c5d40ea933cfece3b4f69427f79c8a23256d Mon Sep 17 00:00:00 2001 +From: Stefan Weil +Date: Tue, 29 Nov 2011 06:34:48 +0100 +Subject: [PATCH 01/25] malta: Fix regression (i8259 interrupts did not work) + +Commit 5632ae46d5bda798e971dae48ebb318ac2c3686a passes the address +of i8259 to qemu_irq_proxy. i8259 is an auto variable with undefined +value outside of mips_malta_init. + +This made the interrupt proxy unusable: either QEMU crashes, or +the interrupt handler was not called. + +Ethernet for example no longer worked with MIPS Malta. + +v2: +While v1 used a static variable for i8259, this patch introduces +a qdev for the malta machine. i8259 is now part of the device status. +This is a minimal qdev implementation to keep the patch small. + +Signed-off-by: Stefan Weil +Signed-off-by: Aurelien Jarno +(cherry picked from commit e9b40fd34ceb23461083d505a444a389c094455b) +--- + hw/mips_malta.c | 39 +++++++++++++++++++++++++++++++++++---- + 1 files changed, 35 insertions(+), 4 deletions(-) + +diff --git a/hw/mips_malta.c b/hw/mips_malta.c +index bb49749..941b9bd 100644 +--- a/hw/mips_malta.c ++++ b/hw/mips_malta.c +@@ -47,6 +47,7 @@ + #include "mc146818rtc.h" + #include "blockdev.h" + #include "exec-memory.h" ++#include "sysbus.h" /* SysBusDevice */ + + //#define DEBUG_BOARD_INIT + +@@ -72,6 +73,11 @@ typedef struct { + SerialState *uart; + } MaltaFPGAState; + ++typedef struct { ++ SysBusDevice busdev; ++ qemu_irq *i8259; ++} MaltaState; ++ + static ISADevice *pit; + + static struct _loaderparams { +@@ -775,7 +781,7 @@ void mips_malta_init (ram_addr_t ram_size, + int64_t kernel_entry; + PCIBus *pci_bus; + CPUState *env; +- qemu_irq *i8259 = NULL, *isa_irq; ++ qemu_irq *isa_irq; + qemu_irq *cpu_exit_irq; + int piix4_devfn; + i2c_bus *smbus; +@@ -787,6 +793,11 @@ void mips_malta_init (ram_addr_t ram_size, + int fl_sectors = 0; + int be; + ++ DeviceState *dev = qdev_create(NULL, "mips-malta"); ++ MaltaState *s = DO_UPCAST(MaltaState, busdev.qdev, dev); ++ ++ qdev_init_nofail(dev); ++ + /* Make sure the first 3 serial ports are associated with a device. */ + for(i = 0; i < 3; i++) { + if (!serial_hds[i]) { +@@ -932,7 +943,7 @@ void mips_malta_init (ram_addr_t ram_size, + * qemu_irq_proxy() adds an extra bit of indirection, allowing us + * to resolve the isa_irq -> i8259 dependency after i8259 is initialized. + */ +- isa_irq = qemu_irq_proxy(&i8259, 16); ++ isa_irq = qemu_irq_proxy(&s->i8259, 16); + + /* Northbridge */ + pci_bus = gt64120_register(isa_irq); +@@ -944,9 +955,9 @@ void mips_malta_init (ram_addr_t ram_size, + + /* Interrupt controller */ + /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */ +- i8259 = i8259_init(env->irq[2]); ++ s->i8259 = i8259_init(env->irq[2]); + +- isa_bus_irqs(i8259); ++ isa_bus_irqs(s->i8259); + pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1); + usb_uhci_piix4_init(pci_bus, piix4_devfn + 2); + smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100, isa_get_irq(9), +@@ -990,6 +1001,20 @@ void mips_malta_init (ram_addr_t ram_size, + } + } + ++static int mips_malta_sysbus_device_init(SysBusDevice *sysbusdev) ++{ ++ return 0; ++} ++ ++static SysBusDeviceInfo mips_malta_device = { ++ .init = mips_malta_sysbus_device_init, ++ .qdev.name = "mips-malta", ++ .qdev.size = sizeof(MaltaState), ++ .qdev.props = (Property[]) { ++ DEFINE_PROP_END_OF_LIST(), ++ } ++}; ++ + static QEMUMachine mips_malta_machine = { + .name = "malta", + .desc = "MIPS Malta Core LV", +@@ -998,9 +1023,15 @@ static QEMUMachine mips_malta_machine = { + .is_default = 1, + }; + ++static void mips_malta_device_init(void) ++{ ++ sysbus_register_withprop(&mips_malta_device); ++} ++ + static void mips_malta_machine_init(void) + { + qemu_register_machine(&mips_malta_machine); + } + ++device_init(mips_malta_device_init); + machine_init(mips_malta_machine_init); +-- +1.7.7.5 + diff --git a/0002-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch b/0002-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch deleted file mode 100644 index 2f3bd6a..0000000 --- a/0002-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch +++ /dev/null @@ -1,882 +0,0 @@ ->From 9e799828d3a805184687792254c379ba4887ec60 Mon Sep 17 00:00:00 2001 -From: Amit Shah -Date: Mon, 21 Mar 2011 20:31:45 +0100 -Subject: [PATCH 02/28] char: Add a QemuChrHandlers struct to initialise - chardev handlers - -Instead of passing each handler in the qemu_add_handlers() function, -create a struct of handlers that can be passed to the function instead. - -Signed-off-by: Amit Shah ---- - gdbstub.c | 9 +++++++-- - hw/ccid-card-passthru.c | 11 +++++++---- - hw/debugcon.c | 2 +- - hw/escc.c | 9 +++++++-- - hw/etraxfs_ser.c | 13 +++++++++---- - hw/grlib_apbuart.c | 12 +++++++----- - hw/ivshmem.c | 28 ++++++++++++++++++++++------ - hw/lm32_juart.c | 8 +++++++- - hw/lm32_uart.c | 8 +++++++- - hw/mcf_uart.c | 9 +++++++-- - hw/milkymist-uart.c | 8 +++++++- - hw/pl011.c | 9 +++++++-- - hw/pxa2xx.c | 13 +++++++++---- - hw/serial.c | 9 +++++++-- - hw/sh_serial.c | 12 +++++++++--- - hw/spapr_vty.c | 8 ++++++-- - hw/strongarm.c | 12 +++++++----- - hw/syborg_serial.c | 9 +++++++-- - hw/usb-serial.c | 9 +++++++-- - hw/virtio-console.c | 11 ++++++++--- - hw/xen_console.c | 16 +++++++++++----- - hw/xilinx_uartlite.c | 11 +++++++++-- - monitor.c | 18 ++++++++++++++---- - net/slirp.c | 8 ++++++-- - qemu-char.c | 32 ++++++++++++++++++++++---------- - qemu-char.h | 13 +++++++++---- - usb-redir.c | 9 +++++++-- - 27 files changed, 233 insertions(+), 83 deletions(-) - -diff --git a/gdbstub.c b/gdbstub.c -index 27b0cfa..6639849 100644 ---- a/gdbstub.c -+++ b/gdbstub.c -@@ -2739,6 +2739,12 @@ static void gdb_sigterm_handler(int signal) - } - #endif - -+static const QemuChrHandlers gdb_handlers = { -+ .fd_can_read = gdb_chr_can_receive, -+ .fd_read = gdb_chr_receive, -+ .fd_event = gdb_chr_event, -+}; -+ - int gdbserver_start(const char *device) - { - GDBState *s; -@@ -2768,8 +2774,7 @@ int gdbserver_start(const char *device) - if (!chr) - return -1; - -- qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive, -- gdb_chr_event, NULL); -+ qemu_chr_add_handlers(chr, &gdb_handlers, NULL); - } - - s = gdbserver_state; -diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c -index 28eb9d1..1dee6f7 100644 ---- a/hw/ccid-card-passthru.c -+++ b/hw/ccid-card-passthru.c -@@ -273,6 +273,12 @@ static const uint8_t *passthru_get_atr(CCIDCardState *base, uint32_t *len) - return card->atr; - } - -+static const QemuChrHandlers passthru_handlers = { -+ .fd_can_read = ccid_card_vscard_can_read, -+ .fd_read = ccid_card_vscard_read, -+ .fd_event = ccid_card_vscard_event, -+}; -+ - static int passthru_initfn(CCIDCardState *base) - { - PassthruState *card = DO_UPCAST(PassthruState, base, base); -@@ -281,10 +287,7 @@ static int passthru_initfn(CCIDCardState *base) - card->vscard_in_hdr = 0; - if (card->cs) { - DPRINTF(card, D_INFO, "initing chardev\n"); -- qemu_chr_add_handlers(card->cs, -- ccid_card_vscard_can_read, -- ccid_card_vscard_read, -- ccid_card_vscard_event, card); -+ qemu_chr_add_handlers(card->cs, &passthru_handlers, card); - ccid_card_vscard_send_init(card); - } else { - error_report("missing chardev"); -diff --git a/hw/debugcon.c b/hw/debugcon.c -index 5ee6821..e79a595 100644 ---- a/hw/debugcon.c -+++ b/hw/debugcon.c -@@ -73,7 +73,7 @@ static void debugcon_init_core(DebugconState *s) - exit(1); - } - -- qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, s); -+ qemu_chr_add_handlers(s->chr, NULL, s); - } - - static int debugcon_isa_initfn(ISADevice *dev) -diff --git a/hw/escc.c b/hw/escc.c -index f6fd919..dfa329a 100644 ---- a/hw/escc.c -+++ b/hw/escc.c -@@ -898,6 +898,12 @@ void slavio_serial_ms_kbd_init(target_phys_addr_t base, qemu_irq irq, - sysbus_mmio_map(s, 0, base); - } - -+static const QemuChrHandlers serial_handlers = { -+ .fd_can_read = serial_can_receive, -+ .fd_read = serial_receive1, -+ .fd_event = serial_event, -+}; -+ - static int escc_init1(SysBusDevice *dev) - { - SerialState *s = FROM_SYSBUS(SerialState, dev); -@@ -911,8 +917,7 @@ static int escc_init1(SysBusDevice *dev) - s->chn[i].chn = 1 - i; - s->chn[i].clock = s->frequency / 2; - if (s->chn[i].chr) { -- qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive, -- serial_receive1, serial_event, &s->chn[i]); -+ qemu_chr_add_handlers(s->chn[i].chr, &serial_handlers, &s->chn[i]); - } - } - s->chn[0].otherchn = &s->chn[1]; -diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c -index b917d4d..ebbad77 100644 ---- a/hw/etraxfs_ser.c -+++ b/hw/etraxfs_ser.c -@@ -202,6 +202,12 @@ static void etraxfs_ser_reset(DeviceState *d) - - } - -+static const QemuChrHandlers serial_handlers = { -+ .fd_can_read = serial_can_receive, -+ .fd_read = serial_receive, -+ .fd_event = serial_event, -+}; -+ - static int etraxfs_ser_init(SysBusDevice *dev) - { - struct etrax_serial *s = FROM_SYSBUS(typeof (*s), dev); -@@ -212,10 +218,9 @@ static int etraxfs_ser_init(SysBusDevice *dev) - DEVICE_NATIVE_ENDIAN); - sysbus_init_mmio(dev, R_MAX * 4, ser_regs); - s->chr = qdev_init_chardev(&dev->qdev); -- if (s->chr) -- qemu_chr_add_handlers(s->chr, -- serial_can_receive, serial_receive, -- serial_event, s); -+ if (s->chr) { -+ qemu_chr_add_handlers(s->chr, &serial_handlers, s); -+ } - return 0; - } - -diff --git a/hw/grlib_apbuart.c b/hw/grlib_apbuart.c -index 169a56e..310687b 100644 ---- a/hw/grlib_apbuart.c -+++ b/hw/grlib_apbuart.c -@@ -144,16 +144,18 @@ static CPUWriteMemoryFunc * const grlib_apbuart_write[] = { - NULL, NULL, grlib_apbuart_writel, - }; - -+static const QemuChrHandlers grlib_handlers = { -+ .fd_can_read = grlib_apbuart_can_receive, -+ .fd_read = grlib_apbuart_receive, -+ .fd_event = grlib_apbuart_event, -+}; -+ - static int grlib_apbuart_init(SysBusDevice *dev) - { - UART *uart = FROM_SYSBUS(typeof(*uart), dev); - int uart_regs = 0; - -- qemu_chr_add_handlers(uart->chr, -- grlib_apbuart_can_receive, -- grlib_apbuart_receive, -- grlib_apbuart_event, -- uart); -+ qemu_chr_add_handlers(uart->chr, &grlib_handlers, uart); - - sysbus_init_irq(dev, &uart->irq); - -diff --git a/hw/ivshmem.c b/hw/ivshmem.c -index 3055dd2..4f59575 100644 ---- a/hw/ivshmem.c -+++ b/hw/ivshmem.c -@@ -312,6 +312,18 @@ static void fake_irqfd(void *opaque, const uint8_t *buf, int size) { - msix_notify(pdev, entry->vector); - } - -+static const QemuChrHandlers ivshmem_handlers = { -+ .fd_can_read = ivshmem_can_receive, -+ .fd_read = ivshmem_receive, -+ .fd_event = ivshmem_event, -+}; -+ -+static const QemuChrHandlers ivshmem_msi_handlers = { -+ .fd_can_read = ivshmem_can_receive, -+ .fd_read = fake_irqfd, -+ .fd_event = ivshmem_event, -+}; -+ - static CharDriverState* create_eventfd_chr_device(void * opaque, int eventfd, - int vector) - { -@@ -331,11 +343,10 @@ static CharDriverState* create_eventfd_chr_device(void * opaque, int eventfd, - s->eventfd_table[vector].pdev = &s->dev; - s->eventfd_table[vector].vector = vector; - -- qemu_chr_add_handlers(chr, ivshmem_can_receive, fake_irqfd, -- ivshmem_event, &s->eventfd_table[vector]); -+ qemu_chr_add_handlers(chr, &ivshmem_msi_handlers, -+ &s->eventfd_table[vector]); - } else { -- qemu_chr_add_handlers(chr, ivshmem_can_receive, ivshmem_receive, -- ivshmem_event, s); -+ qemu_chr_add_handlers(chr, &ivshmem_handlers, s); - } - - return chr; -@@ -666,6 +677,12 @@ static int ivshmem_load(QEMUFile* f, void *opaque, int version_id) - return 0; - } - -+static const QemuChrHandlers ivshmem_server_handlers = { -+ .fd_can_read = ivshmem_can_receive, -+ .fd_read = ivshmem_read, -+ .fd_event = ivshmem_event, -+}; -+ - static int pci_ivshmem_init(PCIDevice *dev) - { - IVShmemState *s = DO_UPCAST(IVShmemState, dev, dev); -@@ -749,8 +766,7 @@ static int pci_ivshmem_init(PCIDevice *dev) - - s->eventfd_chr = qemu_mallocz(s->vectors * sizeof(CharDriverState *)); - -- qemu_chr_add_handlers(s->server_chr, ivshmem_can_receive, ivshmem_read, -- ivshmem_event, s); -+ qemu_chr_add_handlers(s->server_chr, &ivshmem_server_handlers, s); - } else { - /* just map the file immediately, we're not using a server */ - int fd; -diff --git a/hw/lm32_juart.c b/hw/lm32_juart.c -index fddcf7e..12dd1e8 100644 ---- a/hw/lm32_juart.c -+++ b/hw/lm32_juart.c -@@ -110,13 +110,19 @@ static void juart_reset(DeviceState *d) - s->jrx = 0; - } - -+static const QemuChrHandlers juart_handlers = { -+ .fd_can_read = juart_can_rx, -+ .fd_read = juart_rx, -+ .fd_event = juart_event, -+}; -+ - static int lm32_juart_init(SysBusDevice *dev) - { - LM32JuartState *s = FROM_SYSBUS(typeof(*s), dev); - - s->chr = qdev_init_chardev(&dev->qdev); - if (s->chr) { -- qemu_chr_add_handlers(s->chr, juart_can_rx, juart_rx, juart_event, s); -+ qemu_chr_add_handlers(s->chr, juart_handlers, s); - } - - return 0; -diff --git a/hw/lm32_uart.c b/hw/lm32_uart.c -index 09090e9..5438660 100644 ---- a/hw/lm32_uart.c -+++ b/hw/lm32_uart.c -@@ -242,6 +242,12 @@ static void uart_reset(DeviceState *d) - s->regs[R_LSR] = LSR_THRE | LSR_TEMT; - } - -+static const QemuChrHandlers uart_handlers = { -+ .fd_can_read = uart_can_rx, -+ .fd_read = uart_rx, -+ .fd_event = uart_event, -+}; -+ - static int lm32_uart_init(SysBusDevice *dev) - { - LM32UartState *s = FROM_SYSBUS(typeof(*s), dev); -@@ -255,7 +261,7 @@ static int lm32_uart_init(SysBusDevice *dev) - - s->chr = qdev_init_chardev(&dev->qdev); - if (s->chr) { -- qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s); -+ qemu_chr_add_handlers(s->chr, uart_handlers, s); - } - - return 0; -diff --git a/hw/mcf_uart.c b/hw/mcf_uart.c -index 905e116..bb5740c 100644 ---- a/hw/mcf_uart.c -+++ b/hw/mcf_uart.c -@@ -268,6 +268,12 @@ static void mcf_uart_receive(void *opaque, const uint8_t *buf, int size) - mcf_uart_push_byte(s, buf[0]); - } - -+static const QemuChrHandlers mcf_uart_handlers = { -+ .fd_can_read = mcf_uart_can_receive, -+ .fd_read = mcf_uart_receive, -+ .fd_event = mcf_uart_event, -+}; -+ - void *mcf_uart_init(qemu_irq irq, CharDriverState *chr) - { - mcf_uart_state *s; -@@ -276,8 +282,7 @@ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr) - s->chr = chr; - s->irq = irq; - if (chr) { -- qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive, -- mcf_uart_event, s); -+ qemu_chr_add_handlers(chr, &mcf_uart_handlers, s); - } - mcf_uart_reset(s); - return s; -diff --git a/hw/milkymist-uart.c b/hw/milkymist-uart.c -index 56c90da..4412b1b 100644 ---- a/hw/milkymist-uart.c -+++ b/hw/milkymist-uart.c -@@ -133,6 +133,12 @@ static void milkymist_uart_reset(DeviceState *d) - } - } - -+static const QemuChrHandlers uart_handlers = { -+ .fd_can_read = uart_can_rx, -+ .fd_read = uart_rx, -+ .fd_event = uart_event, -+}; -+ - static int milkymist_uart_init(SysBusDevice *dev) - { - MilkymistUartState *s = FROM_SYSBUS(typeof(*s), dev); -@@ -147,7 +153,7 @@ static int milkymist_uart_init(SysBusDevice *dev) - - s->chr = qdev_init_chardev(&dev->qdev); - if (s->chr) { -- qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s); -+ qemu_chr_add_handlers(s->chr, uart_handlers, s); - } - - return 0; -diff --git a/hw/pl011.c b/hw/pl011.c -index 997ce84..37ba7f6 100644 ---- a/hw/pl011.c -+++ b/hw/pl011.c -@@ -260,6 +260,12 @@ static const VMStateDescription vmstate_pl011 = { - } - }; - -+static const QemuChrHandlers pl011_handlers = { -+ .fd_can_read = pl011_can_receive, -+ .fd_read = pl011_receive, -+ .fd_event = pl011_event, -+}; -+ - static int pl011_init(SysBusDevice *dev, const unsigned char *id) - { - int iomemtype; -@@ -278,8 +284,7 @@ static int pl011_init(SysBusDevice *dev, const unsigned char *id) - s->cr = 0x300; - s->flags = 0x90; - if (s->chr) { -- qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive, -- pl011_event, s); -+ qemu_chr_add_handlers(s->chr, &pl011_handlers, s); - } - vmstate_register(&dev->qdev, -1, &vmstate_pl011, s); - return 0; -diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c -index cf93110..18bbe48 100644 ---- a/hw/pxa2xx.c -+++ b/hw/pxa2xx.c -@@ -2019,6 +2019,12 @@ static int pxa2xx_fir_load(QEMUFile *f, void *opaque, int version_id) - return 0; - } - -+static const QemuChrHandlers pxa2xx_handlers = { -+ .fd_can_read = pxa2xx_fir_is_empty, -+ .fd_read = pxa2xx_fir_rx, -+ .fd_event = pxa2xx_fir_event, -+}; -+ - static PXA2xxFIrState *pxa2xx_fir_init(target_phys_addr_t base, - qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma, - CharDriverState *chr) -@@ -2038,10 +2044,9 @@ static PXA2xxFIrState *pxa2xx_fir_init(target_phys_addr_t base, - pxa2xx_fir_writefn, s, DEVICE_NATIVE_ENDIAN); - cpu_register_physical_memory(base, 0x1000, iomemtype); - -- if (chr) -- qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty, -- pxa2xx_fir_rx, pxa2xx_fir_event, s); -- -+ if (chr) { -+ qemu_chr_add_handlers(chr, &pxa2xx_handlers, s); -+ } - register_savevm(NULL, "pxa2xx_fir", 0, 0, pxa2xx_fir_save, - pxa2xx_fir_load, s); - -diff --git a/hw/serial.c b/hw/serial.c -index 0ee61dd..d496bcf 100644 ---- a/hw/serial.c -+++ b/hw/serial.c -@@ -727,6 +727,12 @@ static void serial_reset(void *opaque) - qemu_irq_lower(s->irq); - } - -+static const QemuChrHandlers serial_handlers = { -+ .fd_can_read = serial_can_receive1, -+ .fd_read = serial_receive1, -+ .fd_event = serial_event, -+}; -+ - static void serial_init_core(SerialState *s) - { - if (!s->chr) { -@@ -741,8 +747,7 @@ static void serial_init_core(SerialState *s) - - qemu_register_reset(serial_reset, s); - -- qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1, -- serial_event, s); -+ qemu_chr_add_handlers(s->chr, &serial_handlers, s); - } - - /* Change the main reference oscillator frequency. */ -diff --git a/hw/sh_serial.c b/hw/sh_serial.c -index 191f4a6..8b6460d 100644 ---- a/hw/sh_serial.c -+++ b/hw/sh_serial.c -@@ -350,6 +350,12 @@ static CPUWriteMemoryFunc * const sh_serial_writefn[] = { - &sh_serial_write, - }; - -+static const QemuChrHandlers sh_serial_handlers = { -+ .fd_can_read = sh_serial_can_receive1, -+ .fd_read = sh_serial_receive1, -+ .fd_event = sh_serial_event, -+}; -+ - void sh_serial_init (target_phys_addr_t base, int feat, - uint32_t freq, CharDriverState *chr, - qemu_irq eri_source, -@@ -389,9 +395,9 @@ void sh_serial_init (target_phys_addr_t base, int feat, - - s->chr = chr; - -- if (chr) -- qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1, -- sh_serial_event, s); -+ if (chr) { -+ qemu_chr_add_handlers(chr, &sh_serial_handlers, s); -+ } - - s->eri = eri_source; - s->rxi = rxi_source; -diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c -index 6fc0105..5968d85 100644 ---- a/hw/spapr_vty.c -+++ b/hw/spapr_vty.c -@@ -54,12 +54,16 @@ void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len) - qemu_chr_write(dev->chardev, buf, len); - } - -+static const QemuChrHandlers vty_handlers = { -+ .fd_can_read = vty_can_receive, -+ .fd_read = vty_receive, -+}; -+ - static int spapr_vty_init(VIOsPAPRDevice *sdev) - { - VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev; - -- qemu_chr_add_handlers(dev->chardev, vty_can_receive, -- vty_receive, NULL, dev); -+ qemu_chr_add_handlers(dev->chardev, vty_handlers, dev); - - return 0; - } -diff --git a/hw/strongarm.c b/hw/strongarm.c -index 0e03d61..c2dce95 100644 ---- a/hw/strongarm.c -+++ b/hw/strongarm.c -@@ -1188,6 +1188,12 @@ static CPUWriteMemoryFunc * const strongarm_uart_writefn[] = { - strongarm_uart_write, - }; - -+static const QemuChrHandlers strongarm_uart_handlers = { -+ .fd_can_read = strongarm_uart_can_receive, -+ .fd_read = strongarm_uart_receive, -+ .fd_event = strongarm_uart_event, -+}; -+ - static int strongarm_uart_init(SysBusDevice *dev) - { - StrongARMUARTState *s = FROM_SYSBUS(StrongARMUARTState, dev); -@@ -1202,11 +1208,7 @@ static int strongarm_uart_init(SysBusDevice *dev) - s->tx_timer = qemu_new_timer_ns(vm_clock, strongarm_uart_tx, s); - - if (s->chr) { -- qemu_chr_add_handlers(s->chr, -- strongarm_uart_can_receive, -- strongarm_uart_receive, -- strongarm_uart_event, -- s); -+ qemu_chr_add_handlers(s->chr, &strongarm_uart_handlers, s); - } - - return 0; -diff --git a/hw/syborg_serial.c b/hw/syborg_serial.c -index 2ef7175..ac68022 100644 ---- a/hw/syborg_serial.c -+++ b/hw/syborg_serial.c -@@ -292,6 +292,12 @@ static const VMStateDescription vmstate_syborg_serial = { - } - }; - -+static const QemuChrHandlers syborg_serial_handlers = { -+ .fd_can_read = syborg_serial_can_receive, -+ .fd_read = syborg_serial_receive, -+ .fd_event = syborg_serial_event, -+}; -+ - static int syborg_serial_init(SysBusDevice *dev) - { - SyborgSerialState *s = FROM_SYSBUS(SyborgSerialState, dev); -@@ -304,8 +310,7 @@ static int syborg_serial_init(SysBusDevice *dev) - sysbus_init_mmio(dev, 0x1000, iomemtype); - s->chr = qdev_init_chardev(&dev->qdev); - if (s->chr) { -- qemu_chr_add_handlers(s->chr, syborg_serial_can_receive, -- syborg_serial_receive, syborg_serial_event, s); -+ qemu_chr_add_handlers(s->chr, &syborg_serial_handlers, s); - } - if (s->fifo_size <= 0) { - fprintf(stderr, "syborg_serial: fifo too small\n"); -diff --git a/hw/usb-serial.c b/hw/usb-serial.c -index c69c437..45d48ee 100644 ---- a/hw/usb-serial.c -+++ b/hw/usb-serial.c -@@ -476,6 +476,12 @@ static void usb_serial_event(void *opaque, int event) - } - } - -+static const QemuChrHandlers usb_serial_handlers = { -+ .fd_can_read = usb_serial_can_read, -+ .fd_read = usb_serial_read, -+ .fd_event = usb_serial_event, -+}; -+ - static int usb_serial_initfn(USBDevice *dev) - { - USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev); -@@ -487,8 +493,7 @@ static int usb_serial_initfn(USBDevice *dev) - return -1; - } - -- qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read, -- usb_serial_event, s); -+ qemu_chr_add_handlers(s->cs, &usb_serial_handlers, s); - usb_serial_handle_reset(dev); - return 0; - } -diff --git a/hw/virtio-console.c b/hw/virtio-console.c -index fe5e188..cfc3087 100644 ---- a/hw/virtio-console.c -+++ b/hw/virtio-console.c -@@ -95,6 +95,12 @@ static void chr_event(void *opaque, int event) - } - } - -+static const QemuChrHandlers chr_handlers = { -+ .fd_can_read = chr_can_read, -+ .fd_read = chr_read, -+ .fd_event = chr_event, -+}; -+ - static int virtconsole_initfn(VirtIOSerialPort *port) - { - VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); -@@ -107,8 +113,7 @@ static int virtconsole_initfn(VirtIOSerialPort *port) - } - - if (vcon->chr) { -- qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event, -- vcon); -+ qemu_chr_add_handlers(vcon->chr, &chr_handlers, vcon); - info->have_data = flush_buf; - info->guest_open = guest_open; - info->guest_close = guest_close; -@@ -126,7 +131,7 @@ static int virtconsole_exitfn(VirtIOSerialPort *port) - * Instead of closing the chardev, free it so it can be used - * for other purposes. - */ -- qemu_chr_add_handlers(vcon->chr, NULL, NULL, NULL, NULL); -+ qemu_chr_add_handlers(vcon->chr, NULL, NULL); - } - - return 0; -diff --git a/hw/xen_console.c b/hw/xen_console.c -index 8ef104c..85e8a22 100644 ---- a/hw/xen_console.c -+++ b/hw/xen_console.c -@@ -212,6 +212,11 @@ out: - return ret; - } - -+static const QemuChrHandlers xencons_handlers = { -+ .fd_can_read = xencons_can_receive, -+ .fd_read = xencons_receive, -+}; -+ - static int con_connect(struct XenDevice *xendev) - { - struct XenConsole *con = container_of(xendev, struct XenConsole, xendev); -@@ -232,9 +237,9 @@ static int con_connect(struct XenDevice *xendev) - return -1; - - xen_be_bind_evtchn(&con->xendev); -- if (con->chr) -- qemu_chr_add_handlers(con->chr, xencons_can_receive, xencons_receive, -- NULL, con); -+ if (con->chr) { -+ qemu_chr_add_handlers(con->chr, &xencons_handlers, con); -+ } - - xen_be_printf(xendev, 1, "ring mfn %d, remote port %d, local port %d, limit %zd\n", - con->ring_ref, -@@ -248,8 +253,9 @@ static void con_disconnect(struct XenDevice *xendev) - { - struct XenConsole *con = container_of(xendev, struct XenConsole, xendev); - -- if (con->chr) -- qemu_chr_add_handlers(con->chr, NULL, NULL, NULL, NULL); -+ if (con->chr) { -+ qemu_chr_add_handlers(con->chr, NULL, NULL); -+ } - xen_be_unbind_evtchn(&con->xendev); - - if (con->sring) { -diff --git a/hw/xilinx_uartlite.c b/hw/xilinx_uartlite.c -index 9b94e98..1845577 100644 ---- a/hw/xilinx_uartlite.c -+++ b/hw/xilinx_uartlite.c -@@ -193,6 +193,12 @@ static void uart_event(void *opaque, int event) - - } - -+static const QemuChrHandlers uart_handlers = { -+ .fd_can_read = uart_can_rx, -+ .fd_read = uart_rx, -+ .fd_event = uart_event, -+}; -+ - static int xilinx_uartlite_init(SysBusDevice *dev) - { - struct xlx_uartlite *s = FROM_SYSBUS(typeof (*s), dev); -@@ -206,8 +212,9 @@ static int xilinx_uartlite_init(SysBusDevice *dev) - sysbus_init_mmio(dev, R_MAX * 4, uart_regs); - - s->chr = qdev_init_chardev(&dev->qdev); -- if (s->chr) -- qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s); -+ if (s->chr) { -+ qemu_chr_add_handlers(s->chr, &uart_handlers, s); -+ } - return 0; - } - -diff --git a/monitor.c b/monitor.c -index 718935b..5b79dde 100644 ---- a/monitor.c -+++ b/monitor.c -@@ -5249,6 +5249,18 @@ static void monitor_event(void *opaque, int event) - * End: - */ - -+static const QemuChrHandlers monitor_handlers = { -+ .fd_can_read = monitor_can_read, -+ .fd_read = monitor_read, -+ .fd_event = monitor_event, -+}; -+ -+static const QemuChrHandlers monitor_control_handlers = { -+ .fd_can_read = monitor_can_read, -+ .fd_read = monitor_control_read, -+ .fd_event = monitor_control_event, -+}; -+ - void monitor_init(CharDriverState *chr, int flags) - { - static int is_first_init = 1; -@@ -5271,12 +5283,10 @@ void monitor_init(CharDriverState *chr, int flags) - if (monitor_ctrl_mode(mon)) { - mon->mc = qemu_mallocz(sizeof(MonitorControl)); - /* Control mode requires special handlers */ -- qemu_chr_add_handlers(chr, monitor_can_read, monitor_control_read, -- monitor_control_event, mon); -+ qemu_chr_add_handlers(chr, &monitor_control_handlers, mon); - qemu_chr_set_echo(chr, true); - } else { -- qemu_chr_add_handlers(chr, monitor_can_read, monitor_read, -- monitor_event, mon); -+ qemu_chr_add_handlers(chr, &monitor_handlers, mon); - } - - QLIST_INSERT_HEAD(&mon_list, mon, entry); -diff --git a/net/slirp.c b/net/slirp.c -index 157b80a..8eeec7e 100644 ---- a/net/slirp.c -+++ b/net/slirp.c -@@ -577,6 +577,11 @@ static void guestfwd_read(void *opaque, const uint8_t *buf, int size) - slirp_socket_recv(fwd->slirp, fwd->server, fwd->port, buf, size); - } - -+static const QemuChrHandlers guestfwd_handlers = { -+ .fd_can_read = guestfwd_can_read, -+ .fd_read = guestfwd_read, -+}; -+ - static int slirp_guestfwd(SlirpState *s, const char *config_str, - int legacy_format) - { -@@ -633,8 +638,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str, - fwd->port = port; - fwd->slirp = s->slirp; - -- qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read, -- NULL, fwd); -+ qemu_chr_add_handlers(fwd->hd, &guestfwd_handlers, fwd); - return 0; - - fail_syntax: -diff --git a/qemu-char.c b/qemu-char.c -index 5682aea..52bcc0e 100644 ---- a/qemu-char.c -+++ b/qemu-char.c -@@ -195,19 +195,26 @@ void qemu_chr_send_event(CharDriverState *s, int event) - s->chr_send_event(s, event); - } - -+static const QemuChrHandlers null_handlers = { -+ /* All handlers are initialised to NULL */ -+}; -+ - void qemu_chr_add_handlers(CharDriverState *s, -- IOCanReadHandler *fd_can_read, -- IOReadHandler *fd_read, -- IOEventHandler *fd_event, -- void *opaque) -+ const QemuChrHandlers *handlers, void *opaque) - { -- if (!opaque && !fd_can_read && !fd_read && !fd_event) { -+ if (!s) { -+ return; -+ } -+ if (!opaque && !handlers) { - /* chr driver being released. */ - ++s->avail_connections; - } -- s->chr_can_read = fd_can_read; -- s->chr_read = fd_read; -- s->chr_event = fd_event; -+ if (!handlers) { -+ handlers = &null_handlers; -+ } -+ s->chr_can_read = handlers->fd_can_read; -+ s->chr_read = handlers->fd_read; -+ s->chr_event = handlers->fd_event; - s->handler_opaque = opaque; - if (s->chr_update_read_handler) - s->chr_update_read_handler(s); -@@ -447,6 +454,12 @@ static void mux_chr_event(void *opaque, int event) - mux_chr_send_event(d, i, event); - } - -+static const QemuChrHandlers mux_chr_handlers = { -+ .fd_can_read = mux_chr_can_read, -+ .fd_read = mux_chr_read, -+ .fd_event = mux_chr_event, -+}; -+ - static void mux_chr_update_read_handler(CharDriverState *chr) - { - MuxDriver *d = chr->opaque; -@@ -461,8 +474,7 @@ static void mux_chr_update_read_handler(CharDriverState *chr) - d->chr_event[d->mux_cnt] = chr->chr_event; - /* Fix up the real driver with mux routines */ - if (d->mux_cnt == 0) { -- qemu_chr_add_handlers(d->drv, mux_chr_can_read, mux_chr_read, -- mux_chr_event, chr); -+ qemu_chr_add_handlers(d->drv, &mux_chr_handlers, chr); - } - if (d->focus != -1) { - mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT); -diff --git a/qemu-char.h b/qemu-char.h -index f361c6d..b8372ea 100644 ---- a/qemu-char.h -+++ b/qemu-char.h -@@ -1,6 +1,7 @@ - #ifndef QEMU_CHAR_H - #define QEMU_CHAR_H - -+#include - #include "qemu-common.h" - #include "qemu-queue.h" - #include "qemu-option.h" -@@ -77,6 +78,13 @@ struct CharDriverState { - QTAILQ_ENTRY(CharDriverState) next; - }; - -+typedef struct QemuChrHandlers { -+ IOCanReadHandler *fd_can_read; -+ IOReadHandler *fd_read; -+ IOHandler *fd_write_unblocked; -+ IOEventHandler *fd_event; -+} QemuChrHandlers; -+ - QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename); - CharDriverState *qemu_chr_open_opts(QemuOpts *opts, - void (*init)(struct CharDriverState *s)); -@@ -89,10 +97,7 @@ void qemu_chr_printf(CharDriverState *s, const char *fmt, ...) - GCC_FMT_ATTR(2, 3); - int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len); - void qemu_chr_send_event(CharDriverState *s, int event); --void qemu_chr_add_handlers(CharDriverState *s, -- IOCanReadHandler *fd_can_read, -- IOReadHandler *fd_read, -- IOEventHandler *fd_event, -+void qemu_chr_add_handlers(CharDriverState *s, const QemuChrHandlers *handlers, - void *opaque); - int qemu_chr_ioctl(CharDriverState *s, int cmd, void *arg); - void qemu_chr_generic_open(CharDriverState *s); -diff --git a/usb-redir.c b/usb-redir.c -index e212993..e2b5a2c 100644 ---- a/usb-redir.c -+++ b/usb-redir.c -@@ -782,6 +782,12 @@ static void usbredir_chardev_event(void *opaque, int event) - } - } - -+static const QemuChrHandlers usbredir_chr_handlers = { -+ .fd_can_read = usbredir_chardev_can_read, -+ .fd_read = usbredir_chardev_read, -+ .fd_event = usbredir_chardev_event, -+}; -+ - /* - * init + destroy - */ -@@ -807,8 +813,7 @@ static int usbredir_initfn(USBDevice *udev) - /* We'll do the attach once we receive the speed from the usb-host */ - udev->auto_attach = 0; - -- qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read, -- usbredir_chardev_read, usbredir_chardev_event, dev); -+ qemu_chr_add_handlers(dev->cs, &usbredir_chr_handlers, dev); - - return 0; - } --- -1.7.5.1 - diff --git a/0002-exec.c-Fix-subpage-memory-access-to-RAM-MemoryRegion.patch b/0002-exec.c-Fix-subpage-memory-access-to-RAM-MemoryRegion.patch new file mode 100644 index 0000000..e49a049 --- /dev/null +++ b/0002-exec.c-Fix-subpage-memory-access-to-RAM-MemoryRegion.patch @@ -0,0 +1,134 @@ +From 2061800b85ddcc9b34b5ccbfaa87f7e8b94626a6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Andreas=20F=C3=A4rber?= +Date: Wed, 30 Nov 2011 16:26:21 +0100 +Subject: [PATCH 02/25] exec.c: Fix subpage memory access to RAM MemoryRegion +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Commit 95c318f5e1f88d7e5bcc6deac17330fd4806a2d3 (Fix segfault in mmio +subpage handling code.) prevented a segfault by making all subpage +registrations over an existing memory page perform an unassigned access. +Symptoms were writes not taking effect and reads returning zero. + +Very small page sizes are not currently supported either, +so subpage memory areas cannot fully be avoided. + +Therefore change the previous fix to use a new IO_MEM_SUBPAGE_RAM +instead of IO_MEM_UNASSIGNED. Suggested by Avi. + +Reviewed-by: Avi Kivity +Signed-off-by: Andreas Färber +Cc: Avi Kivity +Cc: Gleb Natapov +Signed-off-by: Anthony Liguori +--- + cpu-common.h | 1 + + exec.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 64 insertions(+), 2 deletions(-) + +diff --git a/cpu-common.h b/cpu-common.h +index c9878ba..3f45428 100644 +--- a/cpu-common.h ++++ b/cpu-common.h +@@ -172,6 +172,7 @@ void cpu_physical_memory_write_rom(target_phys_addr_t addr, + #define IO_MEM_ROM (1 << IO_MEM_SHIFT) /* hardcoded offset */ + #define IO_MEM_UNASSIGNED (2 << IO_MEM_SHIFT) + #define IO_MEM_NOTDIRTY (3 << IO_MEM_SHIFT) ++#define IO_MEM_SUBPAGE_RAM (4 << IO_MEM_SHIFT) + + /* Acts like a ROM when read and like a device when written. */ + #define IO_MEM_ROMD (1) +diff --git a/exec.c b/exec.c +index 6b92198..6c206ff 100644 +--- a/exec.c ++++ b/exec.c +@@ -3570,6 +3570,63 @@ static CPUWriteMemoryFunc * const subpage_write[] = { + &subpage_writel, + }; + ++static uint32_t subpage_ram_readb(void *opaque, target_phys_addr_t addr) ++{ ++ ram_addr_t raddr = addr; ++ void *ptr = qemu_get_ram_ptr(raddr); ++ return ldub_p(ptr); ++} ++ ++static void subpage_ram_writeb(void *opaque, target_phys_addr_t addr, ++ uint32_t value) ++{ ++ ram_addr_t raddr = addr; ++ void *ptr = qemu_get_ram_ptr(raddr); ++ stb_p(ptr, value); ++} ++ ++static uint32_t subpage_ram_readw(void *opaque, target_phys_addr_t addr) ++{ ++ ram_addr_t raddr = addr; ++ void *ptr = qemu_get_ram_ptr(raddr); ++ return lduw_p(ptr); ++} ++ ++static void subpage_ram_writew(void *opaque, target_phys_addr_t addr, ++ uint32_t value) ++{ ++ ram_addr_t raddr = addr; ++ void *ptr = qemu_get_ram_ptr(raddr); ++ stw_p(ptr, value); ++} ++ ++static uint32_t subpage_ram_readl(void *opaque, target_phys_addr_t addr) ++{ ++ ram_addr_t raddr = addr; ++ void *ptr = qemu_get_ram_ptr(raddr); ++ return ldl_p(ptr); ++} ++ ++static void subpage_ram_writel(void *opaque, target_phys_addr_t addr, ++ uint32_t value) ++{ ++ ram_addr_t raddr = addr; ++ void *ptr = qemu_get_ram_ptr(raddr); ++ stl_p(ptr, value); ++} ++ ++static CPUReadMemoryFunc * const subpage_ram_read[] = { ++ &subpage_ram_readb, ++ &subpage_ram_readw, ++ &subpage_ram_readl, ++}; ++ ++static CPUWriteMemoryFunc * const subpage_ram_write[] = { ++ &subpage_ram_writeb, ++ &subpage_ram_writew, ++ &subpage_ram_writel, ++}; ++ + static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end, + ram_addr_t memory, ram_addr_t region_offset) + { +@@ -3583,8 +3640,9 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end, + printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %ld\n", __func__, + mmio, start, end, idx, eidx, memory); + #endif +- if ((memory & ~TARGET_PAGE_MASK) == IO_MEM_RAM) +- memory = IO_MEM_UNASSIGNED; ++ if ((memory & ~TARGET_PAGE_MASK) == IO_MEM_RAM) { ++ memory = IO_MEM_SUBPAGE_RAM; ++ } + memory = (memory >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); + for (; idx <= eidx; idx++) { + mmio->sub_io_index[idx] = memory; +@@ -3817,6 +3875,9 @@ static void io_mem_init(void) + cpu_register_io_memory_fixed(IO_MEM_NOTDIRTY, error_mem_read, + notdirty_mem_write, NULL, + DEVICE_NATIVE_ENDIAN); ++ cpu_register_io_memory_fixed(IO_MEM_SUBPAGE_RAM, subpage_ram_read, ++ subpage_ram_write, NULL, ++ DEVICE_NATIVE_ENDIAN); + for (i=0; i<5; i++) + io_mem_used[i] = 1; + +-- +1.7.7.5 + diff --git a/0003-hw-9pfs-Improve-portability-to-older-systems.patch b/0003-hw-9pfs-Improve-portability-to-older-systems.patch new file mode 100644 index 0000000..4e91a9f --- /dev/null +++ b/0003-hw-9pfs-Improve-portability-to-older-systems.patch @@ -0,0 +1,101 @@ +From f03969b952bc2aaf9f4445b6da28aebb0a9abde5 Mon Sep 17 00:00:00 2001 +From: "Aneesh Kumar K.V" +Date: Sun, 4 Dec 2011 22:35:27 +0530 +Subject: [PATCH 03/25] hw/9pfs: Improve portability to older systems + +handle fs driver require a set of newly added syscalls. Don't +Compile handle FS driver if those syscalls are not available. +Instead of adding #ifdef for all those syscalls we check for +open by handle syscall. If that is available then rest of the +syscalls used by the driver should be available. + +Signed-off-by: Aneesh Kumar K.V +--- + Makefile.objs | 4 ++-- + fsdev/qemu-fsdev.c | 2 ++ + hw/9pfs/virtio-9p-handle.c | 33 --------------------------------- + 3 files changed, 4 insertions(+), 35 deletions(-) + +diff --git a/Makefile.objs b/Makefile.objs +index d7a6539..3a699ee 100644 +--- a/Makefile.objs ++++ b/Makefile.objs +@@ -310,8 +310,8 @@ hw-obj-$(CONFIG_SOUND) += $(sound-obj-y) + 9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-local.o virtio-9p-xattr.o + 9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-xattr-user.o virtio-9p-posix-acl.o + 9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-coth.o cofs.o codir.o cofile.o +-9pfs-nested-$(CONFIG_VIRTFS) += coxattr.o virtio-9p-handle.o +-9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-synth.o ++9pfs-nested-$(CONFIG_VIRTFS) += coxattr.o virtio-9p-synth.o ++9pfs-nested-$(CONFIG_OPEN_BY_HANDLE) += virtio-9p-handle.o + + hw-obj-$(CONFIG_REALLY_VIRTFS) += $(addprefix 9pfs/, $(9pfs-nested-y)) + $(addprefix 9pfs/, $(9pfs-nested-y)): QEMU_CFLAGS+=$(GLIB_CFLAGS) +diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c +index 7fd2aa7..6684f7e 100644 +--- a/fsdev/qemu-fsdev.c ++++ b/fsdev/qemu-fsdev.c +@@ -23,7 +23,9 @@ static QTAILQ_HEAD(FsDriverEntry_head, FsDriverListEntry) fsdriver_entries = + + static FsDriverTable FsDrivers[] = { + { .name = "local", .ops = &local_ops}, ++#ifdef CONFIG_OPEN_BY_HANDLE + { .name = "handle", .ops = &handle_ops}, ++#endif + { .name = "synth", .ops = &synth_ops}, + }; + +diff --git a/hw/9pfs/virtio-9p-handle.c b/hw/9pfs/virtio-9p-handle.c +index 7644ae5..a62f690 100644 +--- a/hw/9pfs/virtio-9p-handle.c ++++ b/hw/9pfs/virtio-9p-handle.c +@@ -45,7 +45,6 @@ struct handle_data { + int handle_bytes; + }; + +-#ifdef CONFIG_OPEN_BY_HANDLE + static inline int name_to_handle(int dirfd, const char *name, + struct file_handle *fh, int *mnt_id, int flags) + { +@@ -56,38 +55,6 @@ static inline int open_by_handle(int mountfd, const char *fh, int flags) + { + return open_by_handle_at(mountfd, (struct file_handle *)fh, flags); + } +-#else +- +-struct rpl_file_handle { +- unsigned int handle_bytes; +- int handle_type; +- unsigned char handle[0]; +-}; +-#define file_handle rpl_file_handle +- +-#ifndef AT_REMOVEDIR +-#define AT_REMOVEDIR 0x200 +-#endif +-#ifndef AT_EMPTY_PATH +-#define AT_EMPTY_PATH 0x1000 /* Allow empty relative pathname */ +-#endif +-#ifndef O_PATH +-#define O_PATH 010000000 +-#endif +- +-static inline int name_to_handle(int dirfd, const char *name, +- struct file_handle *fh, int *mnt_id, int flags) +-{ +- errno = ENOSYS; +- return -1; +-} +- +-static inline int open_by_handle(int mountfd, const char *fh, int flags) +-{ +- errno = ENOSYS; +- return -1; +-} +-#endif + + static int handle_update_file_cred(int dirfd, const char *name, FsCred *credp) + { +-- +1.7.7.5 + diff --git a/0003-iohandlers-Add-enable-disable_write_fd_handler-funct.patch b/0003-iohandlers-Add-enable-disable_write_fd_handler-funct.patch deleted file mode 100644 index 92d01aa..0000000 --- a/0003-iohandlers-Add-enable-disable_write_fd_handler-funct.patch +++ /dev/null @@ -1,77 +0,0 @@ ->From c8cf564bc5c080540287ecd5bd944d85873755df Mon Sep 17 00:00:00 2001 -From: Amit Shah -Date: Mon, 21 Mar 2011 20:32:58 +0100 -Subject: [PATCH 03/28] iohandlers: Add enable/disable_write_fd_handler() - functions - -These will be used to provide a cleaner API for the nonblocking case. - -Signed-off-by: Amit Shah ---- - iohandler.c | 35 +++++++++++++++++++++++++++++++++++ - qemu-char.h | 3 +++ - 2 files changed, 38 insertions(+), 0 deletions(-) - -diff --git a/iohandler.c b/iohandler.c -index 2b82421..8e6628b 100644 ---- a/iohandler.c -+++ b/iohandler.c -@@ -44,6 +44,41 @@ typedef struct IOHandlerRecord { - static QLIST_HEAD(, IOHandlerRecord) io_handlers = - QLIST_HEAD_INITIALIZER(io_handlers); - -+static IOHandlerRecord *find_iohandler(int fd) -+{ -+ IOHandlerRecord *ioh; -+ -+ QLIST_FOREACH(ioh, &io_handlers, next) { -+ if (ioh->fd == fd) { -+ return ioh; -+ } -+ } -+ return NULL; -+} -+ -+void enable_write_fd_handler(int fd, IOHandler *fd_write) -+{ -+ IOHandlerRecord *ioh; -+ -+ ioh = find_iohandler(fd); -+ if (!ioh) { -+ return; -+ } -+ -+ ioh->fd_write = fd_write; -+} -+ -+void disable_write_fd_handler(int fd) -+{ -+ IOHandlerRecord *ioh; -+ -+ ioh = find_iohandler(fd); -+ if (!ioh) { -+ return; -+ } -+ -+ ioh->fd_write = NULL; -+} - - /* XXX: fd_read_poll should be suppressed, but an API change is - necessary in the character devices to suppress fd_can_read(). */ -diff --git a/qemu-char.h b/qemu-char.h -index b8372ea..9fe1b82 100644 ---- a/qemu-char.h -+++ b/qemu-char.h -@@ -123,6 +123,9 @@ size_t qemu_chr_mem_osize(const CharDriverState *chr); - - /* async I/O support */ - -+void enable_write_fd_handler(int fd, IOHandler *fd_write); -+void disable_write_fd_handler(int fd); -+ - int qemu_set_fd_handler2(int fd, - IOCanReadHandler *fd_read_poll, - IOHandler *fd_read, --- -1.7.5.1 - diff --git a/0004-char-Add-framework-for-a-write-unblocked-callback.patch b/0004-char-Add-framework-for-a-write-unblocked-callback.patch deleted file mode 100644 index c4bd019..0000000 --- a/0004-char-Add-framework-for-a-write-unblocked-callback.patch +++ /dev/null @@ -1,61 +0,0 @@ ->From 3ad2ca8e46ba078e69254ca5886de89b30f823bb Mon Sep 17 00:00:00 2001 -From: Amit Shah -Date: Mon, 21 Mar 2011 21:41:42 +0100 -Subject: [PATCH 04/28] char: Add framework for a 'write unblocked' callback - -The char layer can let users know that the driver will block on further -input. For users interested in not blocking, they can assign a function -pointer that will be called back when the driver becomes writable. This -patch just adds the function pointers to the CharDriverState structure, -future patches will enable the nonblocking and callback functionality. - -Signed-off-by: Amit Shah ---- - qemu-char.c | 3 +++ - qemu-char.h | 4 ++++ - 2 files changed, 7 insertions(+), 0 deletions(-) - -diff --git a/qemu-char.c b/qemu-char.c -index 52bcc0e..bc07b20 100644 ---- a/qemu-char.c -+++ b/qemu-char.c -@@ -214,11 +214,14 @@ void qemu_chr_add_handlers(CharDriverState *s, - } - s->chr_can_read = handlers->fd_can_read; - s->chr_read = handlers->fd_read; -+ s->chr_write_unblocked = handlers->fd_write_unblocked; - s->chr_event = handlers->fd_event; - s->handler_opaque = opaque; - if (s->chr_update_read_handler) - s->chr_update_read_handler(s); - -+ s->write_blocked = false; -+ - /* We're connecting to an already opened device, so let's make sure we - also get the open event */ - if (s->opened) { -diff --git a/qemu-char.h b/qemu-char.h -index 9fe1b82..68e7b5b 100644 ---- a/qemu-char.h -+++ b/qemu-char.h -@@ -62,6 +62,9 @@ struct CharDriverState { - IOEventHandler *chr_event; - IOCanReadHandler *chr_can_read; - IOReadHandler *chr_read; -+ IOHandler *chr_write_unblocked; -+ void (*chr_enable_write_fd_handler)(struct CharDriverState *chr); -+ void (*chr_disable_write_fd_handler)(struct CharDriverState *chr); - void *handler_opaque; - void (*chr_send_event)(struct CharDriverState *chr, int event); - void (*chr_close)(struct CharDriverState *chr); -@@ -75,6 +78,7 @@ struct CharDriverState { - char *filename; - int opened; - int avail_connections; -+ bool write_blocked; /* Are we in a blocked state? */ - QTAILQ_ENTRY(CharDriverState) next; - }; - --- -1.7.5.1 - diff --git a/0004-hw-9pfs-use-migration-blockers-to-prevent-live-migra.patch b/0004-hw-9pfs-use-migration-blockers-to-prevent-live-migra.patch new file mode 100644 index 0000000..a63b9e1 --- /dev/null +++ b/0004-hw-9pfs-use-migration-blockers-to-prevent-live-migra.patch @@ -0,0 +1,171 @@ +From 77a02621812952acfde887244f6f480de1b51f95 Mon Sep 17 00:00:00 2001 +From: "Aneesh Kumar K.V" +Date: Sun, 4 Dec 2011 22:35:28 +0530 +Subject: [PATCH 04/25] hw/9pfs: use migration blockers to prevent live + migration when virtfs export path is mounted + +Now when you try to migrate with VirtFS export path mounted, you get a proper QMP error: + +(qemu) migrate tcp:localhost:4444 +Migration is disabled when VirtFS export path '/tmp/' is mounted in the guest using mount_tag 'v_tmp' +(qemu) + +Signed-off-by: Aneesh Kumar K.V +--- + hw/9pfs/virtio-9p-device.c | 22 +++++++++++----------- + hw/9pfs/virtio-9p.c | 19 +++++++++++++++++++ + hw/9pfs/virtio-9p.h | 5 +++-- + qerror.c | 5 +++++ + qerror.h | 3 +++ + 5 files changed, 41 insertions(+), 13 deletions(-) + +diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c +index bba4c54..c9bca8b 100644 +--- a/hw/9pfs/virtio-9p-device.c ++++ b/hw/9pfs/virtio-9p-device.c +@@ -33,13 +33,15 @@ static V9fsState *to_virtio_9p(VirtIODevice *vdev) + + static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config) + { ++ int len; + struct virtio_9p_config *cfg; + V9fsState *s = to_virtio_9p(vdev); + +- cfg = g_malloc0(sizeof(struct virtio_9p_config) + +- s->tag_len); +- stw_raw(&cfg->tag_len, s->tag_len); +- memcpy(cfg->tag, s->tag, s->tag_len); ++ len = strlen(s->tag); ++ cfg = g_malloc0(sizeof(struct virtio_9p_config) + len); ++ stw_raw(&cfg->tag_len, len); ++ /* We don't copy the terminating null to config space */ ++ memcpy(cfg->tag, s->tag, len); + memcpy(config, cfg, s->config_size); + g_free(cfg); + } +@@ -96,20 +98,18 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf) + } + + len = strlen(conf->tag); +- if (len > MAX_TAG_LEN) { ++ if (len > MAX_TAG_LEN - 1) { + fprintf(stderr, "mount tag '%s' (%d bytes) is longer than " +- "maximum (%d bytes)", conf->tag, len, MAX_TAG_LEN); ++ "maximum (%d bytes)", conf->tag, len, MAX_TAG_LEN - 1); + exit(1); + } +- /* s->tag is non-NULL terminated string */ +- s->tag = g_malloc(len); +- memcpy(s->tag, conf->tag, len); +- s->tag_len = len; ++ ++ s->tag = strdup(conf->tag); + s->ctx.uid = -1; + + s->ops = fse->ops; + s->vdev.get_features = virtio_9p_get_features; +- s->config_size = sizeof(struct virtio_9p_config) + s->tag_len; ++ s->config_size = sizeof(struct virtio_9p_config) + len; + s->vdev.get_config = virtio_9p_get_config; + s->fid_list = NULL; + qemu_co_rwlock_init(&s->rename_lock); +diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c +index 1b2fc5d..32b98dd 100644 +--- a/hw/9pfs/virtio-9p.c ++++ b/hw/9pfs/virtio-9p.c +@@ -23,6 +23,7 @@ + #include "virtio-9p-xattr.h" + #include "virtio-9p-coth.h" + #include "trace.h" ++#include "migration.h" + + int open_fd_hw; + int total_open_fd; +@@ -373,6 +374,19 @@ static void put_fid(V9fsPDU *pdu, V9fsFidState *fidp) + * Don't free the fid if it is in reclaim list + */ + if (!fidp->ref && fidp->clunked) { ++ if (fidp->fid == pdu->s->root_fid) { ++ /* ++ * if the clunked fid is root fid then we ++ * have unmounted the fs on the client side. ++ * delete the migration blocker. Ideally, this ++ * should be hooked to transport close notification ++ */ ++ if (pdu->s->migration_blocker) { ++ migrate_del_blocker(pdu->s->migration_blocker); ++ error_free(pdu->s->migration_blocker); ++ pdu->s->migration_blocker = NULL; ++ } ++ } + free_fid(pdu, fidp); + } + } +@@ -1235,6 +1249,11 @@ static void v9fs_attach(void *opaque) + err = offset; + trace_v9fs_attach_return(pdu->tag, pdu->id, + qid.type, qid.version, qid.path); ++ s->root_fid = fid; ++ /* disable migration */ ++ error_set(&s->migration_blocker, QERR_VIRTFS_FEATURE_BLOCKS_MIGRATION, ++ s->ctx.fs_root, s->tag); ++ migrate_add_blocker(s->migration_blocker); + out: + put_fid(pdu, fidp); + out_nofid: +diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h +index 7f88356..8b612da 100644 +--- a/hw/9pfs/virtio-9p.h ++++ b/hw/9pfs/virtio-9p.h +@@ -246,8 +246,7 @@ typedef struct V9fsState + V9fsFidState *fid_list; + FileOperations *ops; + FsContext ctx; +- uint16_t tag_len; +- uint8_t *tag; ++ char *tag; + size_t config_size; + enum p9_proto_version proto_version; + int32_t msize; +@@ -256,6 +255,8 @@ typedef struct V9fsState + * on rename. + */ + CoRwlock rename_lock; ++ int32_t root_fid; ++ Error *migration_blocker; + } V9fsState; + + typedef struct V9fsStatState { +diff --git a/qerror.c b/qerror.c +index fdf62b9..25bc91e 100644 +--- a/qerror.c ++++ b/qerror.c +@@ -235,6 +235,11 @@ static const QErrorStringTable qerror_table[] = { + "supported by this qemu version: %(feature)", + }, + { ++ .error_fmt = QERR_VIRTFS_FEATURE_BLOCKS_MIGRATION, ++ .desc = "Migration is disabled when VirtFS export path '%(path)' " ++ "is mounted in the guest using mount_tag '%(tag)'", ++ }, ++ { + .error_fmt = QERR_VNC_SERVER_FAILED, + .desc = "Could not start VNC server on %(target)", + }, +diff --git a/qerror.h b/qerror.h +index 2d3d43b..6414cd9 100644 +--- a/qerror.h ++++ b/qerror.h +@@ -192,6 +192,9 @@ QError *qobject_to_qerror(const QObject *obj); + #define QERR_UNKNOWN_BLOCK_FORMAT_FEATURE \ + "{ 'class': 'UnknownBlockFormatFeature', 'data': { 'device': %s, 'format': %s, 'feature': %s } }" + ++#define QERR_VIRTFS_FEATURE_BLOCKS_MIGRATION \ ++ "{ 'class': 'VirtFSFeatureBlocksMigration', 'data': { 'path': %s, 'tag': %s } }" ++ + #define QERR_VNC_SERVER_FAILED \ + "{ 'class': 'VNCServerFailed', 'data': { 'target': %s } }" + +-- +1.7.7.5 + diff --git a/0005-char-Update-send_all-to-handle-nonblocking-chardev-w.patch b/0005-char-Update-send_all-to-handle-nonblocking-chardev-w.patch deleted file mode 100644 index 383ba63..0000000 --- a/0005-char-Update-send_all-to-handle-nonblocking-chardev-w.patch +++ /dev/null @@ -1,199 +0,0 @@ ->From a962453ed73a671f566cc94858dc21ab694cc85f Mon Sep 17 00:00:00 2001 -From: Amit Shah -Date: Mon, 21 Mar 2011 22:00:27 +0100 -Subject: [PATCH 05/28] char: Update send_all() to handle nonblocking chardev - write requests - -The send_all function is modified to return to the caller in case the -driver cannot handle any more data. It returns -EAGAIN or -WSAEWOULDBLOCK on non-Windows and Windows platforms respectively. This -is only done when the caller sets a callback function handler indicating -it's not interested in blocking till the driver has written out all the -data. - -Currently there's no driver or caller that supports this. Future -commits will add such capability. - -Signed-off-by: Amit Shah ---- - net/socket.c | 4 +- - qemu-char.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- - qemu_socket.h | 2 +- - 3 files changed, 77 insertions(+), 9 deletions(-) - -diff --git a/net/socket.c b/net/socket.c -index 11fe5f3..14706fc 100644 ---- a/net/socket.c -+++ b/net/socket.c -@@ -56,8 +56,8 @@ static ssize_t net_socket_receive(VLANClientState *nc, const uint8_t *buf, size_ - uint32_t len; - len = htonl(size); - -- send_all(s->fd, (const uint8_t *)&len, sizeof(len)); -- return send_all(s->fd, buf, size); -+ send_all(NULL, s->fd, (const uint8_t *)&len, sizeof(len)); -+ return send_all(NULL, s->fd, buf, size); - } - - static ssize_t net_socket_receive_dgram(VLANClientState *nc, const uint8_t *buf, size_t size) -diff --git a/qemu-char.c b/qemu-char.c -index bc07b20..5dbf063 100644 ---- a/qemu-char.c -+++ b/qemu-char.c -@@ -513,7 +513,7 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv) - - - #ifdef _WIN32 --int send_all(int fd, const void *buf, int len1) -+static int do_send(int fd, const void *buf, int len1, bool nonblock) - { - int ret, len; - -@@ -521,9 +521,14 @@ int send_all(int fd, const void *buf, int len1) - while (len > 0) { - ret = send(fd, buf, len, 0); - if (ret < 0) { -+ if (nonblock && len1 - len) { -+ return len1 - len; -+ } - errno = WSAGetLastError(); - if (errno != WSAEWOULDBLOCK) { - return -1; -+ } else if (errno == WSAEWOULDBLOCK && nonblock) { -+ return WSAEWOULDBLOCK; - } - } else if (ret == 0) { - break; -@@ -537,7 +542,7 @@ int send_all(int fd, const void *buf, int len1) - - #else - --int send_all(int fd, const void *_buf, int len1) -+static int do_send(int fd, const void *_buf, int len1, bool nonblock) - { - int ret, len; - const uint8_t *buf = _buf; -@@ -546,8 +551,15 @@ int send_all(int fd, const void *_buf, int len1) - while (len > 0) { - ret = write(fd, buf, len); - if (ret < 0) { -- if (errno != EINTR && errno != EAGAIN) -+ if (nonblock && len1 - len) { -+ return len1 - len; -+ } -+ if (errno == EAGAIN && nonblock) { -+ return -EAGAIN; -+ } -+ if (errno != EINTR && errno != EAGAIN) { - return -1; -+ } - } else if (ret == 0) { - break; - } else { -@@ -559,6 +571,55 @@ int send_all(int fd, const void *_buf, int len1) - } - #endif /* !_WIN32 */ - -+int send_all(CharDriverState *chr, int fd, const void *_buf, int len1) -+{ -+ int ret, eagain_errno; -+ bool nonblock; -+ -+ if (chr && chr->write_blocked) { -+ /* -+ * We don't handle this situation: the caller should not send -+ * us data while we're blocked. -+ * -+ * We could buffer this data here but that'll only encourage -+ * bad behaviour on part of the callers. -+ * -+ * Also, the data already in fd's buffers isn't easily -+ * migratable. If we want full migration support, all the -+ * data landing here needs to be buffered and on migration, -+ * anything that's unsent needs to be transferred to the -+ * dest. machine (which again isn't a very good way of solving -+ * the problem, as the src may become writable just during -+ * migration and the reader could receive some data twice, -+ * essentially corrupting the data). -+ */ -+ abort(); -+ } -+ -+ nonblock = false; -+ /* -+ * Ensure the char backend is able to receive and handle the -+ * 'write unblocked' event before we turn on nonblock support. -+ */ -+ if (chr && chr->chr_enable_write_fd_handler && chr->chr_write_unblocked) { -+ nonblock = true; -+ } -+ ret = do_send(fd, _buf, len1, nonblock); -+ -+#ifdef _WIN32 -+ eagain_errno = WSAEWOULDBLOCK; -+#else -+ eagain_errno = -EAGAIN; -+#endif -+ -+ if (nonblock && (ret == eagain_errno || (ret >= 0 && ret < len1))) { -+ /* Update fd handler to wake up when chr becomes writable */ -+ chr->chr_enable_write_fd_handler(chr); -+ chr->write_blocked = true; -+ } -+ return ret; -+} -+ - #ifndef _WIN32 - - typedef struct { -@@ -572,7 +633,7 @@ static int stdio_nb_clients = 0; - static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len) - { - FDCharDriver *s = chr->opaque; -- return send_all(s->fd_out, buf, len); -+ return send_all(chr, s->fd_out, buf, len); - } - - static int fd_chr_read_poll(void *opaque) -@@ -897,7 +958,7 @@ static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len) - pty_chr_update_read_handler(chr); - return 0; - } -- return send_all(s->fd, buf, len); -+ return send_all(chr, s->fd, buf, len); - } - - static int pty_chr_read_poll(void *opaque) -@@ -1979,8 +2040,15 @@ static void tcp_closed(void *opaque) - static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len) - { - TCPCharDriver *s = chr->opaque; -+ - if (s->connected) { -- return send_all(s->fd, buf, len); -+ int ret; -+ -+ ret = send_all(chr, s->fd, buf, len); -+ if (ret == -1 && errno == EPIPE) { -+ tcp_closed(chr); -+ } -+ return ret; - } else { - /* XXX: indicate an error ? */ - return len; -diff --git a/qemu_socket.h b/qemu_socket.h -index 180e4db..6f453e5 100644 ---- a/qemu_socket.h -+++ b/qemu_socket.h -@@ -36,7 +36,7 @@ int inet_aton(const char *cp, struct in_addr *ia); - int qemu_socket(int domain, int type, int protocol); - int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen); - void socket_set_nonblock(int fd); --int send_all(int fd, const void *buf, int len1); -+int send_all(CharDriverState *chr, int fd, const void *buf, int len1); - - /* New, ipv6-ready socket helper functions, see qemu-sockets.c */ - int inet_listen_opts(QemuOpts *opts, int port_offset); --- -1.7.5.1 - diff --git a/0005-hw-9pfs-Reset-server-state-during-TVERSION.patch b/0005-hw-9pfs-Reset-server-state-during-TVERSION.patch new file mode 100644 index 0000000..585b7cc --- /dev/null +++ b/0005-hw-9pfs-Reset-server-state-during-TVERSION.patch @@ -0,0 +1,64 @@ +From c554919f74e5a79f15360c4c2f417003477634cf Mon Sep 17 00:00:00 2001 +From: Deepak C Shetty +Date: Sun, 4 Dec 2011 22:35:28 +0530 +Subject: [PATCH 05/25] hw/9pfs: Reset server state during TVERSION + +As per the 9p rfc, during TVERSION its necessary to clean all the active +fids, so that we start the session from a clean state. Its also needed in +scenarios where the guest is booting off 9p, and boot fails, and client +restarts, without any knowledge of the past, it will issue a TVERSION again +so this ensures that we always start from a clean state. + +Signed-off-by: Deepak C Shetty +Signed-off-by: Aneesh Kumar K.V +--- + hw/9pfs/virtio-9p.c | 26 ++++++++++++++++++++++++++ + 1 files changed, 26 insertions(+), 0 deletions(-) + +diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c +index 32b98dd..dd43209 100644 +--- a/hw/9pfs/virtio-9p.c ++++ b/hw/9pfs/virtio-9p.c +@@ -523,6 +523,30 @@ static int v9fs_mark_fids_unreclaim(V9fsPDU *pdu, V9fsPath *path) + return 0; + } + ++static void virtfs_reset(V9fsPDU *pdu) ++{ ++ V9fsState *s = pdu->s; ++ V9fsFidState *fidp = NULL; ++ ++ /* Free all fids */ ++ while (s->fid_list) { ++ fidp = s->fid_list; ++ s->fid_list = fidp->next; ++ ++ if (fidp->ref) { ++ fidp->clunked = 1; ++ } else { ++ free_fid(pdu, fidp); ++ } ++ } ++ if (fidp) { ++ /* One or more unclunked fids found... */ ++ error_report("9pfs:%s: One or more uncluncked fids " ++ "found during reset", __func__); ++ } ++ return; ++} ++ + #define P9_QID_TYPE_DIR 0x80 + #define P9_QID_TYPE_SYMLINK 0x02 + +@@ -1196,6 +1220,8 @@ static void v9fs_version(void *opaque) + pdu_unmarshal(pdu, offset, "ds", &s->msize, &version); + trace_v9fs_version(pdu->tag, pdu->id, s->msize, version.data); + ++ virtfs_reset(pdu); ++ + if (!strcmp(version.data, "9P2000.u")) { + s->proto_version = V9FS_PROTO_2000U; + } else if (!strcmp(version.data, "9P2000.L")) { +-- +1.7.7.5 + diff --git a/0006-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch b/0006-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch deleted file mode 100644 index 49bf64d..0000000 --- a/0006-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch +++ /dev/null @@ -1,81 +0,0 @@ ->From 5fc1c0fc4c8153ea927aa8580c78c484f966be64 Mon Sep 17 00:00:00 2001 -From: Amit Shah -Date: Mon, 21 Mar 2011 22:02:47 +0100 -Subject: [PATCH 06/28] char: Equip the unix/tcp backend to handle nonblocking - writes# - -Now that the infrastructure is in place to return -EAGAIN to callers, -individual char drivers can set their update_fd_handlers() function to -set or remove an fd's write handler. This handler checks if the driver -became writable. - -A generic callback routine is used for unblocking writes and letting -users of chardevs know that a driver became writable again. - -Signed-off-by: Amit Shah ---- - qemu-char.c | 34 ++++++++++++++++++++++++++++++++++ - 1 files changed, 34 insertions(+), 0 deletions(-) - -diff --git a/qemu-char.c b/qemu-char.c -index 5dbf063..f54ce04 100644 ---- a/qemu-char.c -+++ b/qemu-char.c -@@ -106,6 +106,19 @@ - static QTAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs = - QTAILQ_HEAD_INITIALIZER(chardevs); - -+/* -+ * Generic routine that gets called when chardev becomes writable. -+ * Lets chardev user know it's OK to send more data. -+ */ -+static void char_write_unblocked(void *opaque) -+{ -+ CharDriverState *chr = opaque; -+ -+ chr->write_blocked = false; -+ chr->chr_disable_write_fd_handler(chr); -+ chr->chr_write_unblocked(chr->handler_opaque); -+} -+ - static void qemu_chr_event(CharDriverState *s, int event) - { - /* Keep track if the char device is open */ -@@ -2309,6 +2322,25 @@ static void tcp_chr_close(CharDriverState *chr) - qemu_chr_event(chr, CHR_EVENT_CLOSED); - } - -+static void tcp_enable_write_fd_handler(CharDriverState *chr) -+{ -+ TCPCharDriver *s = chr->opaque; -+ -+ /* -+ * This function is called only after tcp_chr_connect() is called -+ * (either in 'server' mode or client mode. So we're sure of -+ * s->fd being initialised. -+ */ -+ enable_write_fd_handler(s->fd, char_write_unblocked); -+} -+ -+static void tcp_disable_write_fd_handler(CharDriverState *chr) -+{ -+ TCPCharDriver *s = chr->opaque; -+ -+ disable_write_fd_handler(s->fd); -+} -+ - static int qemu_chr_open_socket(QemuOpts *opts, CharDriverState **_chr) - { - CharDriverState *chr = NULL; -@@ -2365,6 +2397,8 @@ static int qemu_chr_open_socket(QemuOpts *opts, CharDriverState **_chr) - chr->chr_close = tcp_chr_close; - chr->get_msgfd = tcp_get_msgfd; - chr->chr_add_client = tcp_chr_add_client; -+ chr->chr_enable_write_fd_handler = tcp_enable_write_fd_handler; -+ chr->chr_disable_write_fd_handler = tcp_disable_write_fd_handler; - - if (is_listen) { - s->listen_fd = fd; --- -1.7.5.1 - diff --git a/0006-hw-9pfs-Add-qdev.reset-callback-for-virtio-9p-pci-de.patch b/0006-hw-9pfs-Add-qdev.reset-callback-for-virtio-9p-pci-de.patch new file mode 100644 index 0000000..aa49abb --- /dev/null +++ b/0006-hw-9pfs-Add-qdev.reset-callback-for-virtio-9p-pci-de.patch @@ -0,0 +1,57 @@ +From 64dd41bc2de392fa018c5ce804cc451b83f18b94 Mon Sep 17 00:00:00 2001 +From: "Aneesh Kumar K.V" +Date: Sun, 4 Dec 2011 22:35:28 +0530 +Subject: [PATCH 06/25] hw/9pfs: Add qdev.reset callback for virtio-9p-pci + device + +Add the device reset callback + +Signed-off-by: Aneesh Kumar K.V +--- + hw/9pfs/virtio-9p-device.c | 3 ++- + hw/virtio-pci.c | 2 +- + hw/virtio-pci.h | 1 + + 3 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c +index c9bca8b..cd343e1 100644 +--- a/hw/9pfs/virtio-9p-device.c ++++ b/hw/9pfs/virtio-9p-device.c +@@ -176,7 +176,8 @@ static PCIDeviceInfo virtio_9p_info = { + DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag), + DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id), + DEFINE_PROP_END_OF_LIST(), +- } ++ }, ++ .qdev.reset = virtio_pci_reset, + }; + + static void virtio_9p_register_devices(void) +diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c +index 64c6a94..c665f5c 100644 +--- a/hw/virtio-pci.c ++++ b/hw/virtio-pci.c +@@ -266,7 +266,7 @@ static void virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy) + proxy->ioeventfd_started = false; + } + +-static void virtio_pci_reset(DeviceState *d) ++void virtio_pci_reset(DeviceState *d) + { + VirtIOPCIProxy *proxy = container_of(d, VirtIOPCIProxy, pci_dev.qdev); + virtio_pci_stop_ioeventfd(proxy); +diff --git a/hw/virtio-pci.h b/hw/virtio-pci.h +index f8404de..344c22b 100644 +--- a/hw/virtio-pci.h ++++ b/hw/virtio-pci.h +@@ -45,6 +45,7 @@ typedef struct { + } VirtIOPCIProxy; + + void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev); ++void virtio_pci_reset(DeviceState *d); + + /* Virtio ABI version, if we increment this, we break the guest driver. */ + #define VIRTIO_PCI_ABI_VERSION 0 +-- +1.7.7.5 + diff --git a/0007-char-Throttle-when-host-connection-is-down.patch b/0007-char-Throttle-when-host-connection-is-down.patch deleted file mode 100644 index 7a131d8..0000000 --- a/0007-char-Throttle-when-host-connection-is-down.patch +++ /dev/null @@ -1,56 +0,0 @@ ->From 5121e48706408e28c811e74d3e6da5b78aa9137d Mon Sep 17 00:00:00 2001 -From: Amit Shah -Date: Mon, 21 Mar 2011 22:05:10 +0100 -Subject: [PATCH 07/28] char: Throttle when host connection is down# - -When the host-side connection goes down, throttle the virtio-serial bus -and later unthrottle when a connection gets established. This helps -prevent any lost IO (guest->host) while the host connection was down. - -Bugzilla: 621484 - -This commit actually helps the bug mentioned above as no writes will now -get lost because of the throttling done here. With just the patches -sent earlier for that bug, one write will end up getting lost in the -worst case (host d/c, guest write, host connect). - -Signed-off-by: Amit Shah ---- - qemu-char.c | 14 ++++++++++++++ - 1 files changed, 14 insertions(+), 0 deletions(-) - -diff --git a/qemu-char.c b/qemu-char.c -index f54ce04..8d39500 100644 ---- a/qemu-char.c -+++ b/qemu-char.c -@@ -140,6 +140,9 @@ static void qemu_chr_generic_open_bh(void *opaque) - { - CharDriverState *s = opaque; - qemu_chr_event(s, CHR_EVENT_OPENED); -+ if (s->write_blocked) { -+ char_write_unblocked(s); -+ } - qemu_bh_delete(s->bh); - s->bh = NULL; - } -@@ -2060,6 +2063,17 @@ static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len) - ret = send_all(chr, s->fd, buf, len); - if (ret == -1 && errno == EPIPE) { - tcp_closed(chr); -+ -+ if (chr->chr_enable_write_fd_handler && chr->chr_write_unblocked) { -+ /* -+ * Since we haven't written out anything, let's say -+ * we're throttled. This will prevent any output from -+ * the guest getting lost if host-side chardev goes -+ * down. Unthrottle when we re-connect. -+ */ -+ chr->write_blocked = true; -+ return 0; -+ } - } - return ret; - } else { --- -1.7.5.1 - diff --git a/0007-hw-9pfs-Use-the-correct-file-descriptor-in-Fsdriver-.patch b/0007-hw-9pfs-Use-the-correct-file-descriptor-in-Fsdriver-.patch new file mode 100644 index 0000000..446716c --- /dev/null +++ b/0007-hw-9pfs-Use-the-correct-file-descriptor-in-Fsdriver-.patch @@ -0,0 +1,210 @@ +From ed6857bf98e6c8b8080be208ffe15bb678591466 Mon Sep 17 00:00:00 2001 +From: "Aneesh Kumar K.V" +Date: Sun, 4 Dec 2011 22:35:28 +0530 +Subject: [PATCH 07/25] hw/9pfs: Use the correct file descriptor in Fsdriver + Callback + +Fsdriver callback that operate on file descriptor need to +differentiate between directory fd and file fd. + +Based on the original patch from Sassan Panahinejad + +Signed-off-by: Aneesh Kumar K.V +--- + fsdev/file-op-9p.h | 4 ++-- + hw/9pfs/cofile.c | 4 ++-- + hw/9pfs/virtio-9p-handle.c | 28 ++++++++++++++++++++++------ + hw/9pfs/virtio-9p-local.c | 36 ++++++++++++++++++++++++++---------- + hw/9pfs/virtio-9p-synth.c | 5 +++-- + 5 files changed, 55 insertions(+), 22 deletions(-) + +diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h +index 1928da2..a85ecd3 100644 +--- a/fsdev/file-op-9p.h ++++ b/fsdev/file-op-9p.h +@@ -112,10 +112,10 @@ typedef struct FileOperations + ssize_t (*pwritev)(FsContext *, V9fsFidOpenState *, + const struct iovec *, int, off_t); + int (*mkdir)(FsContext *, V9fsPath *, const char *, FsCred *); +- int (*fstat)(FsContext *, V9fsFidOpenState *, struct stat *); ++ int (*fstat)(FsContext *, int, V9fsFidOpenState *, struct stat *); + int (*rename)(FsContext *, const char *, const char *); + int (*truncate)(FsContext *, V9fsPath *, off_t); +- int (*fsync)(FsContext *, V9fsFidOpenState *, int); ++ int (*fsync)(FsContext *, int, V9fsFidOpenState *, int); + int (*statfs)(FsContext *s, V9fsPath *path, struct statfs *stbuf); + ssize_t (*lgetxattr)(FsContext *, V9fsPath *, + const char *, void *, size_t); +diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c +index 586b038..b15838c 100644 +--- a/hw/9pfs/cofile.c ++++ b/hw/9pfs/cofile.c +@@ -71,7 +71,7 @@ int v9fs_co_fstat(V9fsPDU *pdu, V9fsFidState *fidp, struct stat *stbuf) + } + v9fs_co_run_in_worker( + { +- err = s->ops->fstat(&s->ctx, &fidp->fs, stbuf); ++ err = s->ops->fstat(&s->ctx, fidp->fid_type, &fidp->fs, stbuf); + if (err < 0) { + err = -errno; + } +@@ -192,7 +192,7 @@ int v9fs_co_fsync(V9fsPDU *pdu, V9fsFidState *fidp, int datasync) + } + v9fs_co_run_in_worker( + { +- err = s->ops->fsync(&s->ctx, &fidp->fs, datasync); ++ err = s->ops->fsync(&s->ctx, fidp->fid_type, &fidp->fs, datasync); + if (err < 0) { + err = -errno; + } +diff --git a/hw/9pfs/virtio-9p-handle.c b/hw/9pfs/virtio-9p-handle.c +index a62f690..f97d898 100644 +--- a/hw/9pfs/virtio-9p-handle.c ++++ b/hw/9pfs/virtio-9p-handle.c +@@ -255,10 +255,17 @@ static int handle_mkdir(FsContext *fs_ctx, V9fsPath *dir_path, + return ret; + } + +-static int handle_fstat(FsContext *fs_ctx, V9fsFidOpenState *fs, +- struct stat *stbuf) ++static int handle_fstat(FsContext *fs_ctx, int fid_type, ++ V9fsFidOpenState *fs, struct stat *stbuf) + { +- return fstat(fs->fd, stbuf); ++ int fd; ++ ++ if (fid_type == P9_FID_DIR) { ++ fd = dirfd(fs->dir); ++ } else { ++ fd = fs->fd; ++ } ++ return fstat(fd, stbuf); + } + + static int handle_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name, +@@ -395,12 +402,21 @@ static int handle_remove(FsContext *ctx, const char *path) + return -1; + } + +-static int handle_fsync(FsContext *ctx, V9fsFidOpenState *fs, int datasync) ++static int handle_fsync(FsContext *ctx, int fid_type, ++ V9fsFidOpenState *fs, int datasync) + { ++ int fd; ++ ++ if (fid_type == P9_FID_DIR) { ++ fd = dirfd(fs->dir); ++ } else { ++ fd = fs->fd; ++ } ++ + if (datasync) { +- return qemu_fdatasync(fs->fd); ++ return qemu_fdatasync(fd); + } else { +- return fsync(fs->fd); ++ return fsync(fd); + } + } + +diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c +index 99ef0cd..371a94d 100644 +--- a/hw/9pfs/virtio-9p-local.c ++++ b/hw/9pfs/virtio-9p-local.c +@@ -366,11 +366,18 @@ out: + return err; + } + +-static int local_fstat(FsContext *fs_ctx, ++static int local_fstat(FsContext *fs_ctx, int fid_type, + V9fsFidOpenState *fs, struct stat *stbuf) + { +- int err; +- err = fstat(fs->fd, stbuf); ++ int err, fd; ++ ++ if (fid_type == P9_FID_DIR) { ++ fd = dirfd(fs->dir); ++ } else { ++ fd = fs->fd; ++ } ++ ++ err = fstat(fd, stbuf); + if (err) { + return err; + } +@@ -381,19 +388,19 @@ static int local_fstat(FsContext *fs_ctx, + mode_t tmp_mode; + dev_t tmp_dev; + +- if (fgetxattr(fs->fd, "user.virtfs.uid", ++ if (fgetxattr(fd, "user.virtfs.uid", + &tmp_uid, sizeof(uid_t)) > 0) { + stbuf->st_uid = tmp_uid; + } +- if (fgetxattr(fs->fd, "user.virtfs.gid", ++ if (fgetxattr(fd, "user.virtfs.gid", + &tmp_gid, sizeof(gid_t)) > 0) { + stbuf->st_gid = tmp_gid; + } +- if (fgetxattr(fs->fd, "user.virtfs.mode", ++ if (fgetxattr(fd, "user.virtfs.mode", + &tmp_mode, sizeof(mode_t)) > 0) { + stbuf->st_mode = tmp_mode; + } +- if (fgetxattr(fs->fd, "user.virtfs.rdev", ++ if (fgetxattr(fd, "user.virtfs.rdev", + &tmp_dev, sizeof(dev_t)) > 0) { + stbuf->st_rdev = tmp_dev; + } +@@ -592,12 +599,21 @@ static int local_remove(FsContext *ctx, const char *path) + return remove(rpath(ctx, path, buffer)); + } + +-static int local_fsync(FsContext *ctx, V9fsFidOpenState *fs, int datasync) ++static int local_fsync(FsContext *ctx, int fid_type, ++ V9fsFidOpenState *fs, int datasync) + { ++ int fd; ++ ++ if (fid_type == P9_FID_DIR) { ++ fd = dirfd(fs->dir); ++ } else { ++ fd = fs->fd; ++ } ++ + if (datasync) { +- return qemu_fdatasync(fs->fd); ++ return qemu_fdatasync(fd); + } else { +- return fsync(fs->fd); ++ return fsync(fd); + } + } + +diff --git a/hw/9pfs/virtio-9p-synth.c b/hw/9pfs/virtio-9p-synth.c +index f573616..92e0b09 100644 +--- a/hw/9pfs/virtio-9p-synth.c ++++ b/hw/9pfs/virtio-9p-synth.c +@@ -166,7 +166,7 @@ static int v9fs_synth_lstat(FsContext *fs_ctx, + return 0; + } + +-static int v9fs_synth_fstat(FsContext *fs_ctx, ++static int v9fs_synth_fstat(FsContext *fs_ctx, int fid_type, + V9fsFidOpenState *fs, struct stat *stbuf) + { + V9fsSynthOpenState *synth_open = fs->private; +@@ -414,7 +414,8 @@ static int v9fs_synth_remove(FsContext *ctx, const char *path) + return -1; + } + +-static int v9fs_synth_fsync(FsContext *ctx, V9fsFidOpenState *fs, int datasync) ++static int v9fs_synth_fsync(FsContext *ctx, int fid_type, ++ V9fsFidOpenState *fs, int datasync) + { + errno = ENOSYS; + return 0; +-- +1.7.7.5 + diff --git a/0008-hw-9pfs-replace-iovec-manipulation-with-QEMUIOVector.patch b/0008-hw-9pfs-replace-iovec-manipulation-with-QEMUIOVector.patch new file mode 100644 index 0000000..95c3f05 --- /dev/null +++ b/0008-hw-9pfs-replace-iovec-manipulation-with-QEMUIOVector.patch @@ -0,0 +1,305 @@ +From 45d6cdff48356dc8974497ec0524f971b646dd70 Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Wed, 21 Dec 2011 12:37:22 +0530 +Subject: [PATCH 08/25] hw/9pfs: replace iovec manipulation with QEMUIOVector + +The v9fs_read() and v9fs_write() functions rely on iovec[] manipulation +code should be replaced with QEMUIOVector to avoid duplicating code. +In the future it may be possible to make the code even more concise by +using QEMUIOVector consistently across virtio and 9pfs. + +The "v" format specifier for pdu_marshal() and pdu_unmarshal() is +dropped since it does not actually pack/unpack anything. The specifier +was also not implemented to update the offset variable and could only be +used at the end of a format string, another sign that this shouldn't +really be a format specifier. Instead, see the new +v9fs_init_qiov_from_pdu() function. + +This change avoids a possible iovec[] buffer overflow when indirect +vrings are used since the number of vectors is now limited by the +underlying VirtQueueElement and cannot be out-of-bounds. + +Signed-off-by: Stefan Hajnoczi +Signed-off-by: Aneesh Kumar K.V +--- + hw/9pfs/virtio-9p.c | 162 +++++++++++++++++++-------------------------------- + 1 files changed, 60 insertions(+), 102 deletions(-) + +diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c +index dd43209..c018916 100644 +--- a/hw/9pfs/virtio-9p.c ++++ b/hw/9pfs/virtio-9p.c +@@ -674,40 +674,6 @@ static size_t pdu_pack(V9fsPDU *pdu, size_t offset, const void *src, + offset, size, 1); + } + +-static int pdu_copy_sg(V9fsPDU *pdu, size_t offset, int rx, struct iovec *sg) +-{ +- size_t pos = 0; +- int i, j; +- struct iovec *src_sg; +- unsigned int num; +- +- if (rx) { +- src_sg = pdu->elem.in_sg; +- num = pdu->elem.in_num; +- } else { +- src_sg = pdu->elem.out_sg; +- num = pdu->elem.out_num; +- } +- +- j = 0; +- for (i = 0; i < num; i++) { +- if (offset <= pos) { +- sg[j].iov_base = src_sg[i].iov_base; +- sg[j].iov_len = src_sg[i].iov_len; +- j++; +- } else if (offset < (src_sg[i].iov_len + pos)) { +- sg[j].iov_base = src_sg[i].iov_base; +- sg[j].iov_len = src_sg[i].iov_len; +- sg[j].iov_base += (offset - pos); +- sg[j].iov_len -= (offset - pos); +- j++; +- } +- pos += src_sg[i].iov_len; +- } +- +- return j; +-} +- + static size_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...) + { + size_t old_offset = offset; +@@ -743,12 +709,6 @@ static size_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...) + *valp = le64_to_cpu(val); + break; + } +- case 'v': { +- struct iovec *iov = va_arg(ap, struct iovec *); +- int *iovcnt = va_arg(ap, int *); +- *iovcnt = pdu_copy_sg(pdu, offset, 0, iov); +- break; +- } + case 's': { + V9fsString *str = va_arg(ap, V9fsString *); + offset += pdu_unmarshal(pdu, offset, "w", &str->size); +@@ -827,12 +787,6 @@ static size_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...) + offset += pdu_pack(pdu, offset, &val, sizeof(val)); + break; + } +- case 'v': { +- struct iovec *iov = va_arg(ap, struct iovec *); +- int *iovcnt = va_arg(ap, int *); +- *iovcnt = pdu_copy_sg(pdu, offset, 1, iov); +- break; +- } + case 's': { + V9fsString *str = va_arg(ap, V9fsString *); + offset += pdu_marshal(pdu, offset, "w", str->size); +@@ -1143,42 +1097,6 @@ static void stat_to_v9stat_dotl(V9fsState *s, const struct stat *stbuf, + stat_to_qid(stbuf, &v9lstat->qid); + } + +-static struct iovec *adjust_sg(struct iovec *sg, int len, int *iovcnt) +-{ +- while (len && *iovcnt) { +- if (len < sg->iov_len) { +- sg->iov_len -= len; +- sg->iov_base += len; +- len = 0; +- } else { +- len -= sg->iov_len; +- sg++; +- *iovcnt -= 1; +- } +- } +- +- return sg; +-} +- +-static struct iovec *cap_sg(struct iovec *sg, int cap, int *cnt) +-{ +- int i; +- int total = 0; +- +- for (i = 0; i < *cnt; i++) { +- if ((total + sg[i].iov_len) > cap) { +- sg[i].iov_len -= ((total + sg[i].iov_len) - cap); +- i++; +- break; +- } +- total += sg[i].iov_len; +- } +- +- *cnt = i; +- +- return sg; +-} +- + static void print_sg(struct iovec *sg, int cnt) + { + int i; +@@ -1861,6 +1779,38 @@ out: + return count; + } + ++/* ++ * Create a QEMUIOVector for a sub-region of PDU iovecs ++ * ++ * @qiov: uninitialized QEMUIOVector ++ * @skip: number of bytes to skip from beginning of PDU ++ * @size: number of bytes to include ++ * @is_write: true - write, false - read ++ * ++ * The resulting QEMUIOVector has heap-allocated iovecs and must be cleaned up ++ * with qemu_iovec_destroy(). ++ */ ++static void v9fs_init_qiov_from_pdu(QEMUIOVector *qiov, V9fsPDU *pdu, ++ uint64_t skip, size_t size, ++ bool is_write) ++{ ++ QEMUIOVector elem; ++ struct iovec *iov; ++ unsigned int niov; ++ ++ if (is_write) { ++ iov = pdu->elem.out_sg; ++ niov = pdu->elem.out_num; ++ } else { ++ iov = pdu->elem.in_sg; ++ niov = pdu->elem.in_num; ++ } ++ ++ qemu_iovec_init_external(&elem, iov, niov); ++ qemu_iovec_init(qiov, niov); ++ qemu_iovec_copy(qiov, &elem, skip, size); ++} ++ + static void v9fs_read(void *opaque) + { + int32_t fid; +@@ -1895,21 +1845,21 @@ static void v9fs_read(void *opaque) + err += pdu_marshal(pdu, offset, "d", count); + err += count; + } else if (fidp->fid_type == P9_FID_FILE) { +- int32_t cnt; ++ QEMUIOVector qiov_full; ++ QEMUIOVector qiov; + int32_t len; +- struct iovec *sg; +- struct iovec iov[128]; /* FIXME: bad, bad, bad */ + +- sg = iov; +- pdu_marshal(pdu, offset + 4, "v", sg, &cnt); +- sg = cap_sg(sg, max_count, &cnt); ++ v9fs_init_qiov_from_pdu(&qiov_full, pdu, offset + 4, max_count, false); ++ qemu_iovec_init(&qiov, qiov_full.niov); + do { ++ qemu_iovec_reset(&qiov); ++ qemu_iovec_copy(&qiov, &qiov_full, count, qiov_full.size - count); + if (0) { +- print_sg(sg, cnt); ++ print_sg(qiov.iov, qiov.niov); + } + /* Loop in case of EINTR */ + do { +- len = v9fs_co_preadv(pdu, fidp, sg, cnt, off); ++ len = v9fs_co_preadv(pdu, fidp, qiov.iov, qiov.niov, off); + if (len >= 0) { + off += len; + count += len; +@@ -1920,11 +1870,12 @@ static void v9fs_read(void *opaque) + err = len; + goto out; + } +- sg = adjust_sg(sg, len, &cnt); + } while (count < max_count && len > 0); + err = offset; + err += pdu_marshal(pdu, offset, "d", count); + err += count; ++ qemu_iovec_destroy(&qiov); ++ qemu_iovec_destroy(&qiov_full); + } else if (fidp->fid_type == P9_FID_XATTR) { + err = v9fs_xattr_read(s, pdu, fidp, off, max_count); + } else { +@@ -2095,7 +2046,6 @@ out: + + static void v9fs_write(void *opaque) + { +- int cnt; + ssize_t err; + int32_t fid; + int64_t off; +@@ -2104,13 +2054,14 @@ static void v9fs_write(void *opaque) + int32_t total = 0; + size_t offset = 7; + V9fsFidState *fidp; +- struct iovec iov[128]; /* FIXME: bad, bad, bad */ +- struct iovec *sg = iov; + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; ++ QEMUIOVector qiov_full; ++ QEMUIOVector qiov; + +- pdu_unmarshal(pdu, offset, "dqdv", &fid, &off, &count, sg, &cnt); +- trace_v9fs_write(pdu->tag, pdu->id, fid, off, count, cnt); ++ offset += pdu_unmarshal(pdu, offset, "dqd", &fid, &off, &count); ++ v9fs_init_qiov_from_pdu(&qiov_full, pdu, offset, count, true); ++ trace_v9fs_write(pdu->tag, pdu->id, fid, off, count, qiov_full.niov); + + fidp = get_fid(pdu, fid); + if (fidp == NULL) { +@@ -2126,20 +2077,23 @@ static void v9fs_write(void *opaque) + /* + * setxattr operation + */ +- err = v9fs_xattr_write(s, pdu, fidp, off, count, sg, cnt); ++ err = v9fs_xattr_write(s, pdu, fidp, off, count, ++ qiov_full.iov, qiov_full.niov); + goto out; + } else { + err = -EINVAL; + goto out; + } +- sg = cap_sg(sg, count, &cnt); ++ qemu_iovec_init(&qiov, qiov_full.niov); + do { ++ qemu_iovec_reset(&qiov); ++ qemu_iovec_copy(&qiov, &qiov_full, total, qiov_full.size - total); + if (0) { +- print_sg(sg, cnt); ++ print_sg(qiov.iov, qiov.niov); + } + /* Loop in case of EINTR */ + do { +- len = v9fs_co_pwritev(pdu, fidp, sg, cnt, off); ++ len = v9fs_co_pwritev(pdu, fidp, qiov.iov, qiov.niov, off); + if (len >= 0) { + off += len; + total += len; +@@ -2148,16 +2102,20 @@ static void v9fs_write(void *opaque) + if (len < 0) { + /* IO error return the error */ + err = len; +- goto out; ++ goto out_qiov; + } +- sg = adjust_sg(sg, len, &cnt); + } while (total < count && len > 0); ++ ++ offset = 7; + offset += pdu_marshal(pdu, offset, "d", total); + err = offset; + trace_v9fs_write_return(pdu->tag, pdu->id, total, err); ++out_qiov: ++ qemu_iovec_destroy(&qiov); + out: + put_fid(pdu, fidp); + out_nofid: ++ qemu_iovec_destroy(&qiov_full); + complete_pdu(s, pdu, err); + } + +-- +1.7.7.5 + diff --git a/0008-virtio-console-Enable-port-throttling-when-chardev-i.patch b/0008-virtio-console-Enable-port-throttling-when-chardev-i.patch deleted file mode 100644 index 740e25d..0000000 --- a/0008-virtio-console-Enable-port-throttling-when-chardev-i.patch +++ /dev/null @@ -1,49 +0,0 @@ ->From 8750ea70a68e74ca3ecea6149d1d5289cc77dae3 Mon Sep 17 00:00:00 2001 -From: Amit Shah -Date: Mon, 21 Mar 2011 22:06:41 +0100 -Subject: [PATCH 08/28] virtio-console: Enable port throttling when chardev is - slow to consume data - -When a chardev indicates it can't accept more data, we tell the -virtio-serial code to stop sending us any more data till we tell -otherwise. This helps in guests continuing to run normally while the vq -keeps getting full and eventually the guest stops queueing more data. -As soon as the chardev indicates it can accept more data, start pushing! - -Signed-off-by: Amit Shah ---- - hw/virtio-console.c | 11 +++++++++++ - 1 files changed, 11 insertions(+), 0 deletions(-) - -diff --git a/hw/virtio-console.c b/hw/virtio-console.c -index cfc3087..b91f46e 100644 ---- a/hw/virtio-console.c -+++ b/hw/virtio-console.c -@@ -20,6 +20,16 @@ typedef struct VirtConsole { - CharDriverState *chr; - } VirtConsole; - -+/* -+ * Callback function that's called from chardevs when backend becomes -+ * writable. -+ */ -+static void chr_write_unblocked(void *opaque) -+{ -+ VirtConsole *vcon = opaque; -+ -+ virtio_serial_throttle_port(&vcon->port, false); -+} - - /* Callback function that's called when the guest sends us data */ - static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len) -@@ -99,6 +109,7 @@ static const QemuChrHandlers chr_handlers = { - .fd_can_read = chr_can_read, - .fd_read = chr_read, - .fd_event = chr_event, -+ .fd_write_unblocked = chr_write_unblocked, - }; - - static int virtconsole_initfn(VirtIOSerialPort *port) --- -1.7.5.1 - diff --git a/0009-hw-9pfs-Use-the-correct-signed-type-for-different-va.patch b/0009-hw-9pfs-Use-the-correct-signed-type-for-different-va.patch new file mode 100644 index 0000000..c0b02f2 --- /dev/null +++ b/0009-hw-9pfs-Use-the-correct-signed-type-for-different-va.patch @@ -0,0 +1,133 @@ +From 3d3ec7b809b91f2a71fb78fc6b5b079963383243 Mon Sep 17 00:00:00 2001 +From: "Aneesh Kumar K.V" +Date: Wed, 21 Dec 2011 12:37:23 +0530 +Subject: [PATCH 09/25] hw/9pfs: Use the correct signed type for different + variables + +Signed-off-by: Aneesh Kumar K.V +--- + fsdev/file-op-9p.h | 2 +- + hw/9pfs/virtio-9p.c | 21 +++++++++++---------- + hw/9pfs/virtio-9p.h | 2 +- + trace-events | 8 ++++---- + 4 files changed, 17 insertions(+), 16 deletions(-) + +diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h +index a85ecd3..c823fe0 100644 +--- a/fsdev/file-op-9p.h ++++ b/fsdev/file-op-9p.h +@@ -74,7 +74,7 @@ typedef struct FsContext + } FsContext; + + typedef struct V9fsPath { +- int16_t size; ++ uint16_t size; + char *data; + } V9fsPath; + +diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c +index c018916..b3fc3d0 100644 +--- a/hw/9pfs/virtio-9p.c ++++ b/hw/9pfs/virtio-9p.c +@@ -1694,8 +1694,8 @@ out_nofid: + complete_pdu(s, pdu, err); + } + +-static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, +- V9fsFidState *fidp, int64_t off, int32_t max_count) ++static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp, ++ uint64_t off, uint32_t max_count) + { + size_t offset = 7; + int read_count; +@@ -1719,7 +1719,7 @@ static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, + } + + static int v9fs_do_readdir_with_stat(V9fsPDU *pdu, +- V9fsFidState *fidp, int32_t max_count) ++ V9fsFidState *fidp, uint32_t max_count) + { + V9fsPath path; + V9fsStat v9stat; +@@ -1814,11 +1814,11 @@ static void v9fs_init_qiov_from_pdu(QEMUIOVector *qiov, V9fsPDU *pdu, + static void v9fs_read(void *opaque) + { + int32_t fid; +- int64_t off; ++ uint64_t off; + ssize_t err = 0; + int32_t count = 0; + size_t offset = 7; +- int32_t max_count; ++ uint32_t max_count; + V9fsFidState *fidp; + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; +@@ -1962,8 +1962,9 @@ static void v9fs_readdir(void *opaque) + V9fsFidState *fidp; + ssize_t retval = 0; + size_t offset = 7; +- int64_t initial_offset; +- int32_t count, max_count; ++ uint64_t initial_offset; ++ int32_t count; ++ uint32_t max_count; + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; + +@@ -2001,7 +2002,7 @@ out_nofid: + } + + static int v9fs_xattr_write(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp, +- int64_t off, int32_t count, ++ uint64_t off, uint32_t count, + struct iovec *sg, int cnt) + { + int i, to_copy; +@@ -2048,8 +2049,8 @@ static void v9fs_write(void *opaque) + { + ssize_t err; + int32_t fid; +- int64_t off; +- int32_t count; ++ uint64_t off; ++ uint32_t count; + int32_t len = 0; + int32_t total = 0; + size_t offset = 7; +diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h +index 8b612da..19a797b 100644 +--- a/hw/9pfs/virtio-9p.h ++++ b/hw/9pfs/virtio-9p.h +@@ -156,7 +156,7 @@ typedef struct V9fsFidState V9fsFidState; + + typedef struct V9fsString + { +- int16_t size; ++ uint16_t size; + char *data; + } V9fsString; + +diff --git a/trace-events b/trace-events +index 962caca..e417897 100644 +--- a/trace-events ++++ b/trace-events +@@ -579,11 +579,11 @@ v9fs_lcreate(uint16_t tag, uint8_t id, int32_t dfid, int32_t flags, int32_t mode + v9fs_lcreate_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path, int32_t iounit) "tag %d id %d qid={type %d version %d path %"PRId64"} iounit %d" + v9fs_fsync(uint16_t tag, uint8_t id, int32_t fid, int datasync) "tag %d id %d fid %d datasync %d" + v9fs_clunk(uint16_t tag, uint8_t id, int32_t fid) "tag %d id %d fid %d" +-v9fs_read(uint16_t tag, uint8_t id, int32_t fid, int64_t off, int32_t max_count) "tag %d id %d fid %d off %"PRId64" max_count %d" ++v9fs_read(uint16_t tag, uint8_t id, int32_t fid, uint64_t off, uint32_t max_count) "tag %d id %d fid %d off %"PRIu64" max_count %u" + v9fs_read_return(uint16_t tag, uint8_t id, int32_t count, ssize_t err) "tag %d id %d count %d err %zd" +-v9fs_readdir(uint16_t tag, uint8_t id, int32_t fid, int64_t offset, int32_t max_count) "tag %d id %d fid %d offset %"PRId64" max_count %d" +-v9fs_readdir_return(uint16_t tag, uint8_t id, int32_t count, ssize_t retval) "tag %d id %d count %d retval %zd" +-v9fs_write(uint16_t tag, uint8_t id, int32_t fid, int64_t off, int32_t count, int cnt) "tag %d id %d fid %d off %"PRId64" count %d cnt %d" ++v9fs_readdir(uint16_t tag, uint8_t id, int32_t fid, uint64_t offset, uint32_t max_count) "tag %d id %d fid %d offset %"PRIu64" max_count %u" ++v9fs_readdir_return(uint16_t tag, uint8_t id, uint32_t count, ssize_t retval) "tag %d id %d count %u retval %zd" ++v9fs_write(uint16_t tag, uint8_t id, int32_t fid, uint64_t off, uint32_t count, int cnt) "tag %d id %d fid %d off %"PRIu64" count %u cnt %d" + v9fs_write_return(uint16_t tag, uint8_t id, int32_t total, ssize_t err) "tag %d id %d total %d err %zd" + v9fs_create(uint16_t tag, uint8_t id, int32_t fid, char* name, int32_t perm, int8_t mode) "tag %d id %d fid %d name %s perm %d mode %d" + v9fs_create_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path, int iounit) "tag %d id %d qid={type %d version %d path %"PRId64"} iounit %d" +-- +1.7.7.5 + diff --git a/0009-spice-qemu-char.c-add-throttling.patch b/0009-spice-qemu-char.c-add-throttling.patch deleted file mode 100644 index 17bebaa..0000000 --- a/0009-spice-qemu-char.c-add-throttling.patch +++ /dev/null @@ -1,133 +0,0 @@ ->From a649fba41737329ae13a5b0b4f20798ddf97e2a2 Mon Sep 17 00:00:00 2001 -From: Alon Levy -Date: Tue, 22 Mar 2011 12:27:59 +0200 -Subject: [PATCH 09/28] spice-qemu-char.c: add throttling - -BZ: 672191 - -upstream: not submitted (explained below) - -Adds throttling support to spicevmc chardev. Uses a timer to avoid recursing: -1. spice-server: reds.c: read_from_vdi_port -2. qemu: spice-qemu-char.c: vmc_read -3. chr_write_unblocked - (calls virtio_serial_throttle_port(port, false)) -4. qemu: virtio ... -5. qemu: spice-qemu-char.c: spice_chr_write -6. qemu: spice-qemu-char.c: wakeup (calls into spice-server) -7. spice-server: ... -8. qemu: spice-qemu-char.c: vmc_read - -Instead, in vmc_read if we were throttled and we are just about to return -all the bytes we will set a timer to be triggered immediately to call -chr_write_unblocked. Then we return after 2 above, and 3 is called from the -timer callback. This also means we can later remove some ugly recursion protection -from spice-server. - -The other tricky point in this patch is not returning the leftover chunk twice. -When we throttle, by definition we have data that spice server didn't consume. -It is being kept by virtio-serial, and by us. The next vmc_read callback needs -to not return it, but just do unthrottling. Then virtio will give us the remaining -chunk as usual in spice_chr_write, and we will pass it to spice server in the -next vmc_read. - -This patch relies on Amit's series to expose throttling to chardev's, which -was not accepted upstream, and will not be accepted upstream until the mainloop -is reworked to use glib. ---- - spice-qemu-char.c | 39 +++++++++++++++++++++++++++++++++++---- - 1 files changed, 35 insertions(+), 4 deletions(-) - -diff --git a/spice-qemu-char.c b/spice-qemu-char.c -index 95bf6b6..0f72e91 100644 ---- a/spice-qemu-char.c -+++ b/spice-qemu-char.c -@@ -1,4 +1,6 @@ - #include "config-host.h" -+#include "qemu-common.h" -+#include "qemu-timer.h" - #include "trace.h" - #include "ui/qemu-spice.h" - #include -@@ -25,6 +27,7 @@ typedef struct SpiceCharDriver { - uint8_t *datapos; - ssize_t bufsize, datalen; - uint32_t debug; -+ QEMUTimer *unblock_timer; - } SpiceCharDriver; - - static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len) -@@ -50,6 +53,17 @@ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len) - return out; - } - -+static void spice_chr_unblock(void *opaque) -+{ -+ SpiceCharDriver *scd = opaque; -+ -+ if (scd->chr->chr_write_unblocked == NULL) { -+ dprintf(scd, 1, "%s: backend doesn't support unthrottling.\n", __func__); -+ return; -+ } -+ scd->chr->chr_write_unblocked(scd->chr->handler_opaque); -+} -+ - static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len) - { - SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin); -@@ -61,9 +75,16 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len) - scd->datapos += bytes; - scd->datalen -= bytes; - assert(scd->datalen >= 0); -- if (scd->datalen == 0) { -- scd->datapos = 0; -- } -+ } -+ if (scd->datalen == 0 && scd->chr->write_blocked) { -+ dprintf(scd, 1, "%s: unthrottling (%d)\n", __func__, bytes); -+ scd->chr->write_blocked = false; -+ /* -+ * set a timer instead of calling scd->chr->chr_write_unblocked directly, -+ * because that will call back into spice_chr_write (see -+ * virtio-console.c:chr_write_unblocked), which is unwanted. -+ */ -+ qemu_mod_timer(scd->unblock_timer, 0); - } - trace_spice_vmc_read(bytes, len); - return bytes; -@@ -106,6 +127,7 @@ static void vmc_unregister_interface(SpiceCharDriver *scd) - static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len) - { - SpiceCharDriver *s = chr->opaque; -+ int read_bytes; - - dprintf(s, 2, "%s: %d\n", __func__, len); - vmc_register_interface(s); -@@ -118,7 +140,15 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len) - s->datapos = s->buffer; - s->datalen = len; - spice_server_char_device_wakeup(&s->sin); -- return len; -+ read_bytes = len - s->datalen; -+ if (read_bytes != len) { -+ dprintf(s, 1, "%s: throttling: %d < %d (%zd)\n", __func__, -+ read_bytes, len, s->bufsize); -+ s->chr->write_blocked = true; -+ /* We'll get passed in the unconsumed data with the next call */ -+ s->datalen = 0; -+ } -+ return read_bytes; - } - - static void spice_chr_close(struct CharDriverState *chr) -@@ -196,6 +226,7 @@ int qemu_chr_open_spice(QemuOpts *opts, CharDriverState **_chr) - chr->chr_close = spice_chr_close; - chr->chr_guest_open = spice_chr_guest_open; - chr->chr_guest_close = spice_chr_guest_close; -+ s->unblock_timer = qemu_new_timer_ms(vm_clock, spice_chr_unblock, s); - - qemu_chr_generic_open(chr); - --- -1.7.5.1 - diff --git a/0010-spice-qemu-char.c-remove-intermediate-buffer.patch b/0010-spice-qemu-char.c-remove-intermediate-buffer.patch deleted file mode 100644 index ca23ed9..0000000 --- a/0010-spice-qemu-char.c-remove-intermediate-buffer.patch +++ /dev/null @@ -1,71 +0,0 @@ ->From 63350d37305a8fc5b6a8fb2fbacfb8a6a91956fd Mon Sep 17 00:00:00 2001 -From: Alon Levy -Date: Tue, 22 Mar 2011 12:28:00 +0200 -Subject: [PATCH 10/28] spice-qemu-char.c: remove intermediate buffer - -BZ: 672191 -upstream: not submitted (explained below) - -virtio-serial's buffer is valid when it calls us, and we don't -access it otherwise: vmc_read is only called in response to wakeup, -or else we set datalen=0 and throttle. Then vmc_read is called back, -we return 0 (not accessing the buffer) and set the timer to unthrottle. - -Also make datalen int and not ssize_t (to fit spice_chr_write signature). - -This relied on the previous patch that introduces throttling, which -can't go upstream right now as explained in that patch. ---- - spice-qemu-char.c | 18 ++++++------------ - 1 files changed, 6 insertions(+), 12 deletions(-) - -diff --git a/spice-qemu-char.c b/spice-qemu-char.c -index 0f72e91..2b8aec4 100644 ---- a/spice-qemu-char.c -+++ b/spice-qemu-char.c -@@ -23,9 +23,8 @@ typedef struct SpiceCharDriver { - SpiceCharDeviceInstance sin; - char *subtype; - bool active; -- uint8_t *buffer; -- uint8_t *datapos; -- ssize_t bufsize, datalen; -+ const uint8_t *datapos; -+ int datalen; - uint32_t debug; - QEMUTimer *unblock_timer; - } SpiceCharDriver; -@@ -69,7 +68,7 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len) - SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin); - int bytes = MIN(len, scd->datalen); - -- dprintf(scd, 2, "%s: %p %d/%d/%zd\n", __func__, scd->datapos, len, bytes, scd->datalen); -+ dprintf(scd, 2, "%s: %p %d/%d/%d\n", __func__, scd->datapos, len, bytes, scd->datalen); - if (bytes > 0) { - memcpy(buf, scd->datapos, bytes); - scd->datapos += bytes; -@@ -132,18 +131,13 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len) - dprintf(s, 2, "%s: %d\n", __func__, len); - vmc_register_interface(s); - assert(s->datalen == 0); -- if (s->bufsize < len) { -- s->bufsize = len; -- s->buffer = qemu_realloc(s->buffer, s->bufsize); -- } -- memcpy(s->buffer, buf, len); -- s->datapos = s->buffer; -+ s->datapos = buf; - s->datalen = len; - spice_server_char_device_wakeup(&s->sin); - read_bytes = len - s->datalen; - if (read_bytes != len) { -- dprintf(s, 1, "%s: throttling: %d < %d (%zd)\n", __func__, -- read_bytes, len, s->bufsize); -+ dprintf(s, 1, "%s: throttling: %d < %d\n", __func__, -+ read_bytes, len); - s->chr->write_blocked = true; - /* We'll get passed in the unconsumed data with the next call */ - s->datalen = 0; --- -1.7.5.1 - diff --git a/0010-target-i386-fix-cmpxchg-instruction-emulation.patch b/0010-target-i386-fix-cmpxchg-instruction-emulation.patch new file mode 100644 index 0000000..a7276e2 --- /dev/null +++ b/0010-target-i386-fix-cmpxchg-instruction-emulation.patch @@ -0,0 +1,54 @@ +From abf80f880410ebbdd01a289c41c87153802fe900 Mon Sep 17 00:00:00 2001 +From: Andreas Gustafsson +Date: Mon, 12 Dec 2011 00:46:32 +0400 +Subject: [PATCH 10/25] target-i386: fix cmpxchg instruction emulation + +When the i386 cmpxchg instruction is executed with a memory operand +and the comparison result is "unequal", do the memory write before +changing the accumulator instead of the other way around, because +otherwise the new accumulator value will incorrectly be used in the +comparison when the instruction is restarted after a page fault. + +This bug was originally reported on 2010-04-25 as +https://bugs.launchpad.net/qemu/+bug/569760 + +Signed-off-by: Andreas Gustafsson +--- + target-i386/translate.c | 11 +++++++---- + 1 files changed, 7 insertions(+), 4 deletions(-) + +diff --git a/target-i386/translate.c b/target-i386/translate.c +index 1ef8d16..8321bf3 100644 +--- a/target-i386/translate.c ++++ b/target-i386/translate.c +@@ -4870,20 +4870,23 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) + tcg_gen_sub_tl(t2, cpu_regs[R_EAX], t0); + gen_extu(ot, t2); + tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, label1); ++ label2 = gen_new_label(); + if (mod == 3) { +- label2 = gen_new_label(); + gen_op_mov_reg_v(ot, R_EAX, t0); + tcg_gen_br(label2); + gen_set_label(label1); + gen_op_mov_reg_v(ot, rm, t1); +- gen_set_label(label2); + } else { +- tcg_gen_mov_tl(t1, t0); ++ /* perform no-op store cycle like physical cpu; must be ++ before changing accumulator to ensure idempotency if ++ the store faults and the instruction is restarted */ ++ gen_op_st_v(ot + s->mem_index, t0, a0); + gen_op_mov_reg_v(ot, R_EAX, t0); ++ tcg_gen_br(label2); + gen_set_label(label1); +- /* always store */ + gen_op_st_v(ot + s->mem_index, t1, a0); + } ++ gen_set_label(label2); + tcg_gen_mov_tl(cpu_cc_src, t0); + tcg_gen_mov_tl(cpu_cc_dst, t2); + s->cc_op = CC_OP_SUBB + ot; +-- +1.7.7.5 + diff --git a/0011-configure-Enable-build-by-default-PIE-read-only-relo.patch b/0011-configure-Enable-build-by-default-PIE-read-only-relo.patch new file mode 100644 index 0000000..bd592c7 --- /dev/null +++ b/0011-configure-Enable-build-by-default-PIE-read-only-relo.patch @@ -0,0 +1,31 @@ +From 6d450bfbc862d0dab0e8da10ae15698612800726 Mon Sep 17 00:00:00 2001 +From: Brad +Date: Mon, 28 Nov 2011 19:53:49 -0500 +Subject: [PATCH 11/25] configure: Enable build by default PIE / read-only + relocation sections on OpenBSD amd64/i386. + +Enable build by default PIE / read-only relocation sections for the QEMU +binaries on OpenBSD amd64/i386. + +Signed-off-by: Brad Smith +Signed-off-by: Blue Swirl +--- + configure | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/configure b/configure +index ac4840d..b113f60 100755 +--- a/configure ++++ b/configure +@@ -1116,7 +1116,7 @@ fi + + if test "$pie" = ""; then + case "$cpu-$targetos" in +- i386-Linux|x86_64-Linux) ++ i386-Linux|x86_64-Linux|i386-OpenBSD|x86_64-OpenBSD) + ;; + *) + pie="no" +-- +1.7.7.5 + diff --git a/0011-usb-redir-Add-flow-control-support.patch b/0011-usb-redir-Add-flow-control-support.patch deleted file mode 100644 index ab8de4f..0000000 --- a/0011-usb-redir-Add-flow-control-support.patch +++ /dev/null @@ -1,64 +0,0 @@ ->From e7903f889f3105efe7e3876925926e8e91919b0f Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Tue, 19 Jul 2011 10:56:19 +0200 -Subject: [PATCH 11/28] usb-redir: Add flow control support - -Signed-off-by: Hans de Goede ---- - usb-redir.c | 28 +++++++++++++++++++++++++++- - 1 files changed, 27 insertions(+), 1 deletions(-) - -diff --git a/usb-redir.c b/usb-redir.c -index e2b5a2c..6932beb 100644 ---- a/usb-redir.c -+++ b/usb-redir.c -@@ -224,8 +224,22 @@ static int usbredir_read(void *priv, uint8_t *data, int count) - static int usbredir_write(void *priv, uint8_t *data, int count) - { - USBRedirDevice *dev = priv; -+ int r; - -- return qemu_chr_write(dev->cs, data, count); -+ if (dev->cs->write_blocked) { -+ return 0; -+ } -+ -+ r = qemu_chr_write(dev->cs, data, count); -+ -+ if (r < 0) { -+ if (dev->cs->write_blocked) { -+ return 0; -+ } -+ return -1; -+ } -+ -+ return r; - } - - /* -@@ -782,10 +796,22 @@ static void usbredir_chardev_event(void *opaque, int event) - } - } - -+static void usbredir_chardev_write_unblocked(void *opaque) -+{ -+ USBRedirDevice *dev = opaque; -+ -+ if (dev->parser == NULL) { -+ /* usbredir_open_close_bh hasn't handled the open event yet */ -+ return; -+ } -+ usbredirparser_do_write(dev->parser); -+} -+ - static const QemuChrHandlers usbredir_chr_handlers = { - .fd_can_read = usbredir_chardev_can_read, - .fd_read = usbredir_chardev_read, - .fd_event = usbredir_chardev_event, -+ .fd_write_unblocked = usbredir_chardev_write_unblocked, - }; - - /* --- -1.7.5.1 - diff --git a/0012-cris-Handle-conditional-stores-on-CRISv10.patch b/0012-cris-Handle-conditional-stores-on-CRISv10.patch new file mode 100644 index 0000000..c824a09 --- /dev/null +++ b/0012-cris-Handle-conditional-stores-on-CRISv10.patch @@ -0,0 +1,155 @@ +From 3e8088148bb56b84a739c2ef3c63d89188a1ad8f Mon Sep 17 00:00:00 2001 +From: Stefan Sandstrom +Date: Mon, 12 Dec 2011 11:38:31 +0100 +Subject: [PATCH 12/25] cris: Handle conditional stores on CRISv10 + +Signed-off-by: Stefan Sandstrom +Signed-off-by: Edgar E. Iglesias +--- + target-cris/cpu.h | 2 + + target-cris/helper.c | 1 + + target-cris/translate_v10.c | 72 +++++++++++++++++++++++++++++++++++++++--- + 3 files changed, 69 insertions(+), 6 deletions(-) + +diff --git a/target-cris/cpu.h b/target-cris/cpu.h +index 8ae0ce3..453afbb 100644 +--- a/target-cris/cpu.h ++++ b/target-cris/cpu.h +@@ -67,6 +67,8 @@ + #define Q_FLAG 0x80000000 + #define M_FLAG 0x40000000 + #define PFIX_FLAG 0x800 /* CRISv10 Only. */ ++#define F_FLAG_V10 0x400 ++#define P_FLAG_V10 0x200 + #define S_FLAG 0x200 + #define R_FLAG 0x100 + #define P_FLAG 0x80 +diff --git a/target-cris/helper.c b/target-cris/helper.c +index 75f0035..5bc6d81 100644 +--- a/target-cris/helper.c ++++ b/target-cris/helper.c +@@ -157,6 +157,7 @@ static void do_interruptv10(CPUState *env) + /* Now that we are in kernel mode, load the handlers address. */ + env->pc = ldl_code(env->pregs[PR_EBP] + ex_vec * 4); + env->locked_irq = 1; ++ env->pregs[PR_CCS] |= F_FLAG_V10; /* set F. */ + + qemu_log_mask(CPU_LOG_INT, "%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n", + __func__, env->pc, ex_vec, +diff --git a/target-cris/translate_v10.c b/target-cris/translate_v10.c +index 637ac20..95053b6 100644 +--- a/target-cris/translate_v10.c ++++ b/target-cris/translate_v10.c +@@ -62,6 +62,65 @@ static inline void cris_illegal_insn(DisasContext *dc) + t_gen_raise_exception(EXCP_BREAK); + } + ++static void gen_store_v10_conditional(DisasContext *dc, TCGv addr, TCGv val, ++ unsigned int size, int mem_index) ++{ ++ int l1 = gen_new_label(); ++ TCGv taddr = tcg_temp_local_new(); ++ TCGv tval = tcg_temp_local_new(); ++ TCGv t1 = tcg_temp_local_new(); ++ dc->postinc = 0; ++ cris_evaluate_flags(dc); ++ ++ tcg_gen_mov_tl(taddr, addr); ++ tcg_gen_mov_tl(tval, val); ++ ++ /* Store only if F flag isn't set */ ++ tcg_gen_andi_tl(t1, cpu_PR[PR_CCS], F_FLAG_V10); ++ tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1); ++ if (size == 1) { ++ tcg_gen_qemu_st8(tval, taddr, mem_index); ++ } else if (size == 2) { ++ tcg_gen_qemu_st16(tval, taddr, mem_index); ++ } else { ++ tcg_gen_qemu_st32(tval, taddr, mem_index); ++ } ++ gen_set_label(l1); ++ tcg_gen_shri_tl(t1, t1, 1); /* shift F to P position */ ++ tcg_gen_or_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], t1); /*P=F*/ ++ tcg_temp_free(t1); ++ tcg_temp_free(tval); ++ tcg_temp_free(taddr); ++} ++ ++static void gen_store_v10(DisasContext *dc, TCGv addr, TCGv val, ++ unsigned int size) ++{ ++ int mem_index = cpu_mmu_index(dc->env); ++ ++ /* If we get a fault on a delayslot we must keep the jmp state in ++ the cpu-state to be able to re-execute the jmp. */ ++ if (dc->delayed_branch == 1) { ++ cris_store_direct_jmp(dc); ++ } ++ ++ /* Conditional writes. We only support the kind were X is known ++ at translation time. */ ++ if (dc->flagx_known && dc->flags_x) { ++ gen_store_v10_conditional(dc, addr, val, size, mem_index); ++ return; ++ } ++ ++ if (size == 1) { ++ tcg_gen_qemu_st8(val, addr, mem_index); ++ } else if (size == 2) { ++ tcg_gen_qemu_st16(val, addr, mem_index); ++ } else { ++ tcg_gen_qemu_st32(val, addr, mem_index); ++ } ++} ++ ++ + /* Prefix flag and register are used to handle the more complex + addressing modes. */ + static void cris_set_prefix(DisasContext *dc) +@@ -313,7 +372,8 @@ static unsigned int dec10_setclrf(DisasContext *dc) + if (set) { + tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], flags); + } else { +- tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~flags); ++ tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ++ ~(flags|F_FLAG_V10|P_FLAG_V10)); + } + + dc->flags_uptodate = 1; +@@ -723,7 +783,7 @@ static unsigned int dec10_ind_move_r_m(DisasContext *dc, unsigned int size) + LOG_DIS("move.%d $r%d, [$r%d]\n", dc->size, dc->src, dc->dst); + addr = tcg_temp_new(); + crisv10_prepare_memaddr(dc, addr, size); +- gen_store(dc, addr, cpu_R[dc->dst], size); ++ gen_store_v10(dc, addr, cpu_R[dc->dst], size); + insn_len += crisv10_post_memaddr(dc, size); + + return insn_len; +@@ -767,10 +827,10 @@ static unsigned int dec10_ind_move_pr_m(DisasContext *dc) + t0 = tcg_temp_new(); + cris_evaluate_flags(dc); + tcg_gen_andi_tl(t0, cpu_PR[PR_CCS], ~PFIX_FLAG); +- gen_store(dc, addr, t0, size); ++ gen_store_v10(dc, addr, t0, size); + tcg_temp_free(t0); + } else { +- gen_store(dc, addr, cpu_PR[dc->dst], size); ++ gen_store_v10(dc, addr, cpu_PR[dc->dst], size); + } + t0 = tcg_temp_new(); + insn_len += crisv10_post_memaddr(dc, size); +@@ -793,9 +853,9 @@ static void dec10_movem_r_m(DisasContext *dc) + tcg_gen_mov_tl(t0, addr); + for (i = dc->dst; i >= 0; i--) { + if ((pfix && dc->mode == CRISV10_MODE_AUTOINC) && dc->src == i) { +- gen_store(dc, addr, t0, 4); ++ gen_store_v10(dc, addr, t0, 4); + } else { +- gen_store(dc, addr, cpu_R[i], 4); ++ gen_store_v10(dc, addr, cpu_R[i], 4); + } + tcg_gen_addi_tl(addr, addr, 4); + } +-- +1.7.7.5 + diff --git a/0012-spice-add-worker-wrapper-functions.patch b/0012-spice-add-worker-wrapper-functions.patch deleted file mode 100644 index a750ca6..0000000 --- a/0012-spice-add-worker-wrapper-functions.patch +++ /dev/null @@ -1,323 +0,0 @@ ->From 67d29af45ebb1539eaaa2bfb599350c790306111 Mon Sep 17 00:00:00 2001 -From: Gerd Hoffmann -Date: Fri, 17 Jun 2011 10:34:25 +0200 -Subject: [PATCH 12/28] spice: add worker wrapper functions. - -Add wrapper functions for all spice worker calls. - -Signed-off-by: Gerd Hoffmann ---- - hw/qxl-render.c | 4 +- - hw/qxl.c | 32 +++++++++--------- - ui/spice-display.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++--- - ui/spice-display.h | 22 ++++++++++++ - 4 files changed, 129 insertions(+), 24 deletions(-) - -diff --git a/hw/qxl-render.c b/hw/qxl-render.c -index 1316066..bef5f14 100644 ---- a/hw/qxl-render.c -+++ b/hw/qxl-render.c -@@ -124,8 +124,8 @@ void qxl_render_update(PCIQXLDevice *qxl) - update.bottom = qxl->guest_primary.surface.height; - - memset(dirty, 0, sizeof(dirty)); -- qxl->ssd.worker->update_area(qxl->ssd.worker, 0, &update, -- dirty, ARRAY_SIZE(dirty), 1); -+ qemu_spice_update_area(&qxl->ssd, 0, &update, -+ dirty, ARRAY_SIZE(dirty), 1); - - for (i = 0; i < ARRAY_SIZE(dirty); i++) { - if (qemu_spice_rect_is_empty(dirty+i)) { -diff --git a/hw/qxl.c b/hw/qxl.c -index a6fb7f0..5deb776 100644 ---- a/hw/qxl.c -+++ b/hw/qxl.c -@@ -684,8 +684,8 @@ static void qxl_hard_reset(PCIQXLDevice *d, int loadvm) - dprint(d, 1, "%s: start%s\n", __FUNCTION__, - loadvm ? " (loadvm)" : ""); - -- d->ssd.worker->reset_cursor(d->ssd.worker); -- d->ssd.worker->reset_image_cache(d->ssd.worker); -+ qemu_spice_reset_cursor(&d->ssd); -+ qemu_spice_reset_image_cache(&d->ssd); - qxl_reset_surfaces(d); - qxl_reset_memslots(d); - -@@ -790,7 +790,7 @@ static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta) - __FUNCTION__, memslot.slot_id, - memslot.virt_start, memslot.virt_end); - -- d->ssd.worker->add_memslot(d->ssd.worker, &memslot); -+ qemu_spice_add_memslot(&d->ssd, &memslot); - d->guest_slots[slot_id].ptr = (void*)memslot.virt_start; - d->guest_slots[slot_id].size = memslot.virt_end - memslot.virt_start; - d->guest_slots[slot_id].delta = delta; -@@ -800,14 +800,14 @@ static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta) - static void qxl_del_memslot(PCIQXLDevice *d, uint32_t slot_id) - { - dprint(d, 1, "%s: slot %d\n", __FUNCTION__, slot_id); -- d->ssd.worker->del_memslot(d->ssd.worker, MEMSLOT_GROUP_HOST, slot_id); -+ qemu_spice_del_memslot(&d->ssd, MEMSLOT_GROUP_HOST, slot_id); - d->guest_slots[slot_id].active = 0; - } - - static void qxl_reset_memslots(PCIQXLDevice *d) - { - dprint(d, 1, "%s:\n", __FUNCTION__); -- d->ssd.worker->reset_memslots(d->ssd.worker); -+ qemu_spice_reset_memslots(&d->ssd); - memset(&d->guest_slots, 0, sizeof(d->guest_slots)); - } - -@@ -815,7 +815,7 @@ static void qxl_reset_surfaces(PCIQXLDevice *d) - { - dprint(d, 1, "%s:\n", __FUNCTION__); - d->mode = QXL_MODE_UNDEFINED; -- d->ssd.worker->destroy_surfaces(d->ssd.worker); -+ qemu_spice_destroy_surfaces(&d->ssd); - memset(&d->guest_surfaces.cmds, 0, sizeof(d->guest_surfaces.cmds)); - } - -@@ -869,7 +869,7 @@ static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm) - - qxl->mode = QXL_MODE_NATIVE; - qxl->cmdflags = 0; -- qxl->ssd.worker->create_primary_surface(qxl->ssd.worker, 0, &surface); -+ qemu_spice_create_primary_surface(&qxl->ssd, 0, &surface); - - /* for local rendering */ - qxl_render_resize(qxl); -@@ -884,7 +884,7 @@ static void qxl_destroy_primary(PCIQXLDevice *d) - dprint(d, 1, "%s\n", __FUNCTION__); - - d->mode = QXL_MODE_UNDEFINED; -- d->ssd.worker->destroy_primary_surface(d->ssd.worker, 0); -+ qemu_spice_destroy_primary_surface(&d->ssd, 0); - } - - static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm) -@@ -956,15 +956,15 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) - case QXL_IO_UPDATE_AREA: - { - QXLRect update = d->ram->update_area; -- d->ssd.worker->update_area(d->ssd.worker, d->ram->update_surface, -- &update, NULL, 0, 0); -+ qemu_spice_update_area(&d->ssd, d->ram->update_surface, -+ &update, NULL, 0, 0); - break; - } - case QXL_IO_NOTIFY_CMD: -- d->ssd.worker->wakeup(d->ssd.worker); -+ qemu_spice_wakeup(&d->ssd); - break; - case QXL_IO_NOTIFY_CURSOR: -- d->ssd.worker->wakeup(d->ssd.worker); -+ qemu_spice_wakeup(&d->ssd); - break; - case QXL_IO_UPDATE_IRQ: - qxl_set_irq(d); -@@ -978,7 +978,7 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) - break; - } - d->oom_running = 1; -- d->ssd.worker->oom(d->ssd.worker); -+ qemu_spice_oom(&d->ssd); - d->oom_running = 0; - break; - case QXL_IO_SET_MODE: -@@ -1016,10 +1016,10 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) - qxl_destroy_primary(d); - break; - case QXL_IO_DESTROY_SURFACE_WAIT: -- d->ssd.worker->destroy_surface_wait(d->ssd.worker, val); -+ qemu_spice_destroy_surface_wait(&d->ssd, val); - break; - case QXL_IO_DESTROY_ALL_SURFACES: -- d->ssd.worker->destroy_surfaces(d->ssd.worker); -+ qemu_spice_destroy_surfaces(&d->ssd); - break; - default: - fprintf(stderr, "%s: ioport=0x%x, abort()\n", __FUNCTION__, io_port); -@@ -1424,7 +1424,7 @@ static int qxl_post_load(void *opaque, int version) - cmds[out].cmd.type = QXL_CMD_CURSOR; - cmds[out].group_id = MEMSLOT_GROUP_GUEST; - out++; -- d->ssd.worker->loadvm_commands(d->ssd.worker, cmds, out); -+ qemu_spice_loadvm_commands(&d->ssd, cmds, out); - qemu_free(cmds); - - break; -diff --git a/ui/spice-display.c b/ui/spice-display.c -index feeee73..1e6a38f 100644 ---- a/ui/spice-display.c -+++ b/ui/spice-display.c -@@ -62,6 +62,89 @@ void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r) - dest->right = MAX(dest->right, r->right); - } - -+ -+void qemu_spice_update_area(SimpleSpiceDisplay *ssd, uint32_t surface_id, -+ struct QXLRect *area, struct QXLRect *dirty_rects, -+ uint32_t num_dirty_rects, -+ uint32_t clear_dirty_region) -+{ -+ ssd->worker->update_area(ssd->worker, surface_id, area, dirty_rects, -+ num_dirty_rects, clear_dirty_region); -+} -+ -+void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot) -+{ -+ ssd->worker->add_memslot(ssd->worker, memslot); -+} -+ -+void qemu_spice_del_memslot(SimpleSpiceDisplay *ssd, uint32_t gid, uint32_t sid) -+{ -+ ssd->worker->del_memslot(ssd->worker, gid, sid); -+} -+ -+void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id, -+ QXLDevSurfaceCreate *surface) -+{ -+ ssd->worker->create_primary_surface(ssd->worker, id, surface); -+} -+ -+void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id) -+{ -+ ssd->worker->destroy_primary_surface(ssd->worker, id); -+} -+ -+void qemu_spice_destroy_surface_wait(SimpleSpiceDisplay *ssd, uint32_t id) -+{ -+ ssd->worker->destroy_surface_wait(ssd->worker, id); -+} -+ -+void qemu_spice_loadvm_commands(SimpleSpiceDisplay *ssd, -+ struct QXLCommandExt *ext, uint32_t count) -+{ -+ ssd->worker->loadvm_commands(ssd->worker, ext, count); -+} -+ -+void qemu_spice_wakeup(SimpleSpiceDisplay *ssd) -+{ -+ ssd->worker->wakeup(ssd->worker); -+} -+ -+void qemu_spice_oom(SimpleSpiceDisplay *ssd) -+{ -+ ssd->worker->oom(ssd->worker); -+} -+ -+void qemu_spice_start(SimpleSpiceDisplay *ssd) -+{ -+ ssd->worker->start(ssd->worker); -+} -+ -+void qemu_spice_stop(SimpleSpiceDisplay *ssd) -+{ -+ ssd->worker->stop(ssd->worker); -+} -+ -+void qemu_spice_reset_memslots(SimpleSpiceDisplay *ssd) -+{ -+ ssd->worker->reset_memslots(ssd->worker); -+} -+ -+void qemu_spice_destroy_surfaces(SimpleSpiceDisplay *ssd) -+{ -+ ssd->worker->destroy_surfaces(ssd->worker); -+} -+ -+void qemu_spice_reset_image_cache(SimpleSpiceDisplay *ssd) -+{ -+ ssd->worker->reset_image_cache(ssd->worker); -+} -+ -+void qemu_spice_reset_cursor(SimpleSpiceDisplay *ssd) -+{ -+ ssd->worker->reset_cursor(ssd->worker); -+} -+ -+ - static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd) - { - SimpleSpiceUpdate *update; -@@ -161,7 +244,7 @@ void qemu_spice_create_host_memslot(SimpleSpiceDisplay *ssd) - memset(&memslot, 0, sizeof(memslot)); - memslot.slot_group_id = MEMSLOT_GROUP_HOST; - memslot.virt_end = ~0; -- ssd->worker->add_memslot(ssd->worker, &memslot); -+ qemu_spice_add_memslot(ssd, &memslot); - } - - void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd) -@@ -181,14 +264,14 @@ void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd) - surface.mem = (intptr_t)ssd->buf; - surface.group_id = MEMSLOT_GROUP_HOST; - -- ssd->worker->create_primary_surface(ssd->worker, 0, &surface); -+ qemu_spice_create_primary_surface(ssd, 0, &surface); - } - - void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd) - { - dprint(1, "%s:\n", __FUNCTION__); - -- ssd->worker->destroy_primary_surface(ssd->worker, 0); -+ qemu_spice_destroy_primary_surface(ssd, 0); - } - - void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason) -@@ -196,9 +279,9 @@ void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason) - SimpleSpiceDisplay *ssd = opaque; - - if (running) { -- ssd->worker->start(ssd->worker); -+ qemu_spice_start(ssd); - } else { -- ssd->worker->stop(ssd->worker); -+ qemu_spice_stop(ssd); - } - ssd->running = running; - } -@@ -267,7 +350,7 @@ void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd) - - if (ssd->notify) { - ssd->notify = 0; -- ssd->worker->wakeup(ssd->worker); -+ qemu_spice_wakeup(ssd); - dprint(2, "%s: notify\n", __FUNCTION__); - } - } -diff --git a/ui/spice-display.h b/ui/spice-display.h -index 2f95f68..5b06b11 100644 ---- a/ui/spice-display.h -+++ b/ui/spice-display.h -@@ -80,3 +80,25 @@ void qemu_spice_display_update(SimpleSpiceDisplay *ssd, - int x, int y, int w, int h); - void qemu_spice_display_resize(SimpleSpiceDisplay *ssd); - void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd); -+ -+void qemu_spice_update_area(SimpleSpiceDisplay *ssd, uint32_t surface_id, -+ struct QXLRect *area, struct QXLRect *dirty_rects, -+ uint32_t num_dirty_rects, -+ uint32_t clear_dirty_region); -+void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot); -+void qemu_spice_del_memslot(SimpleSpiceDisplay *ssd, uint32_t gid, -+ uint32_t sid); -+void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id, -+ QXLDevSurfaceCreate *surface); -+void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id); -+void qemu_spice_destroy_surface_wait(SimpleSpiceDisplay *ssd, uint32_t id); -+void qemu_spice_loadvm_commands(SimpleSpiceDisplay *ssd, -+ struct QXLCommandExt *ext, uint32_t count); -+void qemu_spice_wakeup(SimpleSpiceDisplay *ssd); -+void qemu_spice_oom(SimpleSpiceDisplay *ssd); -+void qemu_spice_start(SimpleSpiceDisplay *ssd); -+void qemu_spice_stop(SimpleSpiceDisplay *ssd); -+void qemu_spice_reset_memslots(SimpleSpiceDisplay *ssd); -+void qemu_spice_destroy_surfaces(SimpleSpiceDisplay *ssd); -+void qemu_spice_reset_image_cache(SimpleSpiceDisplay *ssd); -+void qemu_spice_reset_cursor(SimpleSpiceDisplay *ssd); --- -1.7.5.1 - diff --git a/0013-pc-add-pc-0.15.patch b/0013-pc-add-pc-0.15.patch new file mode 100644 index 0000000..f85b065 --- /dev/null +++ b/0013-pc-add-pc-0.15.patch @@ -0,0 +1,40 @@ +From a25808dc5baee83f36e0cdab998eb6c0024156fa Mon Sep 17 00:00:00 2001 +From: Anthony Liguori +Date: Sun, 18 Dec 2011 12:59:12 -0600 +Subject: [PATCH 13/25] pc: add pc-0.15 + +Signed-off-by: Anthony Liguori +--- + hw/pc_piix.c | 9 +++++++++ + 1 files changed, 9 insertions(+), 0 deletions(-) + +diff --git a/hw/pc_piix.c b/hw/pc_piix.c +index 970f43c..9093a28 100644 +--- a/hw/pc_piix.c ++++ b/hw/pc_piix.c +@@ -306,6 +306,14 @@ static QEMUMachine pc_machine_v1_0 = { + .is_default = 1, + }; + ++static QEMUMachine pc_machine_v0_15 = { ++ .name = "pc-0.15", ++ .desc = "Standard PC", ++ .init = pc_init_pci, ++ .max_cpus = 255, ++ .is_default = 1, ++}; ++ + static QEMUMachine pc_machine_v0_14 = { + .name = "pc-0.14", + .desc = "Standard PC", +@@ -557,6 +565,7 @@ static QEMUMachine xenfv_machine = { + static void pc_machine_init(void) + { + qemu_register_machine(&pc_machine_v1_0); ++ qemu_register_machine(&pc_machine_v0_15); + qemu_register_machine(&pc_machine_v0_14); + qemu_register_machine(&pc_machine_v0_13); + qemu_register_machine(&pc_machine_v0_12); +-- +1.7.7.5 + diff --git a/0013-spice-add-qemu_spice_display_init_common.patch b/0013-spice-add-qemu_spice_display_init_common.patch deleted file mode 100644 index d40d24e..0000000 --- a/0013-spice-add-qemu_spice_display_init_common.patch +++ /dev/null @@ -1,84 +0,0 @@ ->From c28ee0e7c851fc58ac6ef8f5137fc35cc55b607c Mon Sep 17 00:00:00 2001 -From: Gerd Hoffmann -Date: Fri, 17 Jun 2011 10:42:25 +0200 -Subject: [PATCH 13/28] spice: add qemu_spice_display_init_common - -Factor out SimpleSpiceDisplay initialization into -qemu_spice_display_init_common() and call it from -both qxl.c (for vga mode) and spice-display.c - -Signed-off-by: Gerd Hoffmann ---- - hw/qxl.c | 7 +------ - ui/spice-display.c | 17 +++++++++++------ - ui/spice-display.h | 1 + - 3 files changed, 13 insertions(+), 12 deletions(-) - -diff --git a/hw/qxl.c b/hw/qxl.c -index 5deb776..2127fa3 100644 ---- a/hw/qxl.c -+++ b/hw/qxl.c -@@ -1315,12 +1315,7 @@ static int qxl_init_primary(PCIDevice *dev) - - vga->ds = graphic_console_init(qxl_hw_update, qxl_hw_invalidate, - qxl_hw_screen_dump, qxl_hw_text_update, qxl); -- qxl->ssd.ds = vga->ds; -- qemu_mutex_init(&qxl->ssd.lock); -- qxl->ssd.mouse_x = -1; -- qxl->ssd.mouse_y = -1; -- qxl->ssd.bufsize = (16 * 1024 * 1024); -- qxl->ssd.buf = qemu_malloc(qxl->ssd.bufsize); -+ qemu_spice_display_init_common(&qxl->ssd, vga->ds); - - qxl0 = qxl; - register_displaychangelistener(vga->ds, &display_listener); -diff --git a/ui/spice-display.c b/ui/spice-display.c -index 1e6a38f..93e25bf 100644 ---- a/ui/spice-display.c -+++ b/ui/spice-display.c -@@ -286,6 +286,16 @@ void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason) - ssd->running = running; - } - -+void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd, DisplayState *ds) -+{ -+ ssd->ds = ds; -+ qemu_mutex_init(&ssd->lock); -+ ssd->mouse_x = -1; -+ ssd->mouse_y = -1; -+ ssd->bufsize = (16 * 1024 * 1024); -+ ssd->buf = qemu_malloc(ssd->bufsize); -+} -+ - /* display listener callbacks */ - - void qemu_spice_display_update(SimpleSpiceDisplay *ssd, -@@ -499,12 +509,7 @@ static DisplayChangeListener display_listener = { - void qemu_spice_display_init(DisplayState *ds) - { - assert(sdpy.ds == NULL); -- sdpy.ds = ds; -- qemu_mutex_init(&sdpy.lock); -- sdpy.mouse_x = -1; -- sdpy.mouse_y = -1; -- sdpy.bufsize = (16 * 1024 * 1024); -- sdpy.buf = qemu_malloc(sdpy.bufsize); -+ qemu_spice_display_init_common(&sdpy, ds); - register_displaychangelistener(ds, &display_listener); - - sdpy.qxl.base.sif = &dpy_interface.base; -diff --git a/ui/spice-display.h b/ui/spice-display.h -index 5b06b11..eb7a573 100644 ---- a/ui/spice-display.h -+++ b/ui/spice-display.h -@@ -75,6 +75,7 @@ void qemu_spice_create_host_memslot(SimpleSpiceDisplay *ssd); - void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd); - void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd); - void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason); -+void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd, DisplayState *ds); - - void qemu_spice_display_update(SimpleSpiceDisplay *ssd, - int x, int y, int w, int h); --- -1.7.5.1 - diff --git a/0014-pc-fix-event_idx-compatibility-for-virtio-devices.patch b/0014-pc-fix-event_idx-compatibility-for-virtio-devices.patch new file mode 100644 index 0000000..121ec6c --- /dev/null +++ b/0014-pc-fix-event_idx-compatibility-for-virtio-devices.patch @@ -0,0 +1,87 @@ +From 7e2191ae9898cc957a3d1991aff0e40f2e0f44a4 Mon Sep 17 00:00:00 2001 +From: Anthony Liguori +Date: Sun, 18 Dec 2011 13:07:03 -0600 +Subject: [PATCH 14/25] pc: fix event_idx compatibility for virtio devices + +event_idx was introduced in 0.15 and must be disabled for all virtio-pci devices +(including virtio-balloon-pci). + +Signed-off-by: Anthony Liguori +--- + hw/pc_piix.c | 32 ++++++++++++++++++++++++++++++++ + 1 files changed, 32 insertions(+), 0 deletions(-) + +diff --git a/hw/pc_piix.c b/hw/pc_piix.c +index 9093a28..05000e3 100644 +--- a/hw/pc_piix.c ++++ b/hw/pc_piix.c +@@ -328,6 +328,22 @@ static QEMUMachine pc_machine_v0_14 = { + .driver = "qxl-vga", + .property = "revision", + .value = stringify(2), ++ },{ ++ .driver = "virtio-blk-pci", ++ .property = "event_idx", ++ .value = "off", ++ },{ ++ .driver = "virtio-serial-pci", ++ .property = "event_idx", ++ .value = "off", ++ },{ ++ .driver = "virtio-net-pci", ++ .property = "event_idx", ++ .value = "off", ++ },{ ++ .driver = "virtio-balloon-pci", ++ .property = "event_idx", ++ .value = "off", + }, + { /* end of list */ } + }, +@@ -368,6 +384,10 @@ static QEMUMachine pc_machine_v0_13 = { + .property = "event_idx", + .value = "off", + },{ ++ .driver = "virtio-balloon-pci", ++ .property = "event_idx", ++ .value = "off", ++ },{ + .driver = "AC97", + .property = "use_broken_id", + .value = stringify(1), +@@ -415,6 +435,10 @@ static QEMUMachine pc_machine_v0_12 = { + .property = "event_idx", + .value = "off", + },{ ++ .driver = "virtio-balloon-pci", ++ .property = "event_idx", ++ .value = "off", ++ },{ + .driver = "AC97", + .property = "use_broken_id", + .value = stringify(1), +@@ -470,6 +494,10 @@ static QEMUMachine pc_machine_v0_11 = { + .property = "event_idx", + .value = "off", + },{ ++ .driver = "virtio-balloon-pci", ++ .property = "event_idx", ++ .value = "off", ++ },{ + .driver = "AC97", + .property = "use_broken_id", + .value = stringify(1), +@@ -537,6 +565,10 @@ static QEMUMachine pc_machine_v0_10 = { + .property = "event_idx", + .value = "off", + },{ ++ .driver = "virtio-balloon-pci", ++ .property = "event_idx", ++ .value = "off", ++ },{ + .driver = "AC97", + .property = "use_broken_id", + .value = stringify(1), +-- +1.7.7.5 + diff --git a/0014-spice-qxl-move-worker-wrappers.patch b/0014-spice-qxl-move-worker-wrappers.patch deleted file mode 100644 index ef804d6..0000000 --- a/0014-spice-qxl-move-worker-wrappers.patch +++ /dev/null @@ -1,294 +0,0 @@ ->From 60257c766e7a39134a9db9f4d1111f2b9fea2f86 Mon Sep 17 00:00:00 2001 -From: Gerd Hoffmann -Date: Wed, 29 Jun 2011 10:07:52 +0200 -Subject: [PATCH 14/28] spice/qxl: move worker wrappers - -Move the wrapper functions which are used by qxl only to qxl.c. -Rename them from qemu_spice_* to qxl_spice_*. Also pass in a -qxl state pointer instead of a SimpleSpiceDisplay pointer. - -Signed-off-by: Gerd Hoffmann ---- - hw/qxl-render.c | 4 +- - hw/qxl.c | 67 ++++++++++++++++++++++++++++++++++++++++++++------- - hw/qxl.h | 13 ++++++++++ - ui/spice-display.c | 46 ----------------------------------- - ui/spice-display.h | 12 --------- - 5 files changed, 72 insertions(+), 70 deletions(-) - -diff --git a/hw/qxl-render.c b/hw/qxl-render.c -index bef5f14..60b822d 100644 ---- a/hw/qxl-render.c -+++ b/hw/qxl-render.c -@@ -124,8 +124,8 @@ void qxl_render_update(PCIQXLDevice *qxl) - update.bottom = qxl->guest_primary.surface.height; - - memset(dirty, 0, sizeof(dirty)); -- qemu_spice_update_area(&qxl->ssd, 0, &update, -- dirty, ARRAY_SIZE(dirty), 1); -+ qxl_spice_update_area(qxl, 0, &update, -+ dirty, ARRAY_SIZE(dirty), 1); - - for (i = 0; i < ARRAY_SIZE(dirty); i++) { - if (qemu_spice_rect_is_empty(dirty+i)) { -diff --git a/hw/qxl.c b/hw/qxl.c -index 2127fa3..803a364 100644 ---- a/hw/qxl.c -+++ b/hw/qxl.c -@@ -125,6 +125,53 @@ static void qxl_reset_memslots(PCIQXLDevice *d); - static void qxl_reset_surfaces(PCIQXLDevice *d); - static void qxl_ring_set_dirty(PCIQXLDevice *qxl); - -+ -+void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id, -+ struct QXLRect *area, struct QXLRect *dirty_rects, -+ uint32_t num_dirty_rects, -+ uint32_t clear_dirty_region) -+{ -+ qxl->ssd.worker->update_area(qxl->ssd.worker, surface_id, area, dirty_rects, -+ num_dirty_rects, clear_dirty_region); -+} -+ -+void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id) -+{ -+ qxl->ssd.worker->destroy_surface_wait(qxl->ssd.worker, id); -+} -+ -+void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext, -+ uint32_t count) -+{ -+ qxl->ssd.worker->loadvm_commands(qxl->ssd.worker, ext, count); -+} -+ -+void qxl_spice_oom(PCIQXLDevice *qxl) -+{ -+ qxl->ssd.worker->oom(qxl->ssd.worker); -+} -+ -+void qxl_spice_reset_memslots(PCIQXLDevice *qxl) -+{ -+ qxl->ssd.worker->reset_memslots(qxl->ssd.worker); -+} -+ -+void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl) -+{ -+ qxl->ssd.worker->destroy_surfaces(qxl->ssd.worker); -+} -+ -+void qxl_spice_reset_image_cache(PCIQXLDevice *qxl) -+{ -+ qxl->ssd.worker->reset_image_cache(qxl->ssd.worker); -+} -+ -+void qxl_spice_reset_cursor(PCIQXLDevice *qxl) -+{ -+ qxl->ssd.worker->reset_cursor(qxl->ssd.worker); -+} -+ -+ - static inline uint32_t msb_mask(uint32_t val) - { - uint32_t mask; -@@ -684,8 +731,8 @@ static void qxl_hard_reset(PCIQXLDevice *d, int loadvm) - dprint(d, 1, "%s: start%s\n", __FUNCTION__, - loadvm ? " (loadvm)" : ""); - -- qemu_spice_reset_cursor(&d->ssd); -- qemu_spice_reset_image_cache(&d->ssd); -+ qxl_spice_reset_cursor(d); -+ qxl_spice_reset_image_cache(d); - qxl_reset_surfaces(d); - qxl_reset_memslots(d); - -@@ -807,7 +854,7 @@ static void qxl_del_memslot(PCIQXLDevice *d, uint32_t slot_id) - static void qxl_reset_memslots(PCIQXLDevice *d) - { - dprint(d, 1, "%s:\n", __FUNCTION__); -- qemu_spice_reset_memslots(&d->ssd); -+ qxl_spice_reset_memslots(d); - memset(&d->guest_slots, 0, sizeof(d->guest_slots)); - } - -@@ -815,7 +862,7 @@ static void qxl_reset_surfaces(PCIQXLDevice *d) - { - dprint(d, 1, "%s:\n", __FUNCTION__); - d->mode = QXL_MODE_UNDEFINED; -- qemu_spice_destroy_surfaces(&d->ssd); -+ qxl_spice_destroy_surfaces(d); - memset(&d->guest_surfaces.cmds, 0, sizeof(d->guest_surfaces.cmds)); - } - -@@ -956,8 +1003,8 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) - case QXL_IO_UPDATE_AREA: - { - QXLRect update = d->ram->update_area; -- qemu_spice_update_area(&d->ssd, d->ram->update_surface, -- &update, NULL, 0, 0); -+ qxl_spice_update_area(d, d->ram->update_surface, -+ &update, NULL, 0, 0); - break; - } - case QXL_IO_NOTIFY_CMD: -@@ -978,7 +1025,7 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) - break; - } - d->oom_running = 1; -- qemu_spice_oom(&d->ssd); -+ qxl_spice_oom(d); - d->oom_running = 0; - break; - case QXL_IO_SET_MODE: -@@ -1016,10 +1063,10 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) - qxl_destroy_primary(d); - break; - case QXL_IO_DESTROY_SURFACE_WAIT: -- qemu_spice_destroy_surface_wait(&d->ssd, val); -+ qxl_spice_destroy_surface_wait(d, val); - break; - case QXL_IO_DESTROY_ALL_SURFACES: -- qemu_spice_destroy_surfaces(&d->ssd); -+ qxl_spice_destroy_surfaces(d); - break; - default: - fprintf(stderr, "%s: ioport=0x%x, abort()\n", __FUNCTION__, io_port); -@@ -1419,7 +1466,7 @@ static int qxl_post_load(void *opaque, int version) - cmds[out].cmd.type = QXL_CMD_CURSOR; - cmds[out].group_id = MEMSLOT_GROUP_GUEST; - out++; -- qemu_spice_loadvm_commands(&d->ssd, cmds, out); -+ qxl_spice_loadvm_commands(d, cmds, out); - qemu_free(cmds); - - break; -diff --git a/hw/qxl.h b/hw/qxl.h -index f6c450d..e62b9d0 100644 ---- a/hw/qxl.h -+++ b/hw/qxl.h -@@ -98,6 +98,19 @@ typedef struct PCIQXLDevice { - /* qxl.c */ - void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id); - -+void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id, -+ struct QXLRect *area, struct QXLRect *dirty_rects, -+ uint32_t num_dirty_rects, -+ uint32_t clear_dirty_region); -+void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id); -+void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext, -+ uint32_t count); -+void qxl_spice_oom(PCIQXLDevice *qxl); -+void qxl_spice_reset_memslots(PCIQXLDevice *qxl); -+void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl); -+void qxl_spice_reset_image_cache(PCIQXLDevice *qxl); -+void qxl_spice_reset_cursor(PCIQXLDevice *qxl); -+ - /* qxl-logger.c */ - void qxl_log_cmd_cursor(PCIQXLDevice *qxl, QXLCursorCmd *cmd, int group_id); - void qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext); -diff --git a/ui/spice-display.c b/ui/spice-display.c -index 93e25bf..af10ae8 100644 ---- a/ui/spice-display.c -+++ b/ui/spice-display.c -@@ -63,15 +63,6 @@ void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r) - } - - --void qemu_spice_update_area(SimpleSpiceDisplay *ssd, uint32_t surface_id, -- struct QXLRect *area, struct QXLRect *dirty_rects, -- uint32_t num_dirty_rects, -- uint32_t clear_dirty_region) --{ -- ssd->worker->update_area(ssd->worker, surface_id, area, dirty_rects, -- num_dirty_rects, clear_dirty_region); --} -- - void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot) - { - ssd->worker->add_memslot(ssd->worker, memslot); -@@ -93,27 +84,11 @@ void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id) - ssd->worker->destroy_primary_surface(ssd->worker, id); - } - --void qemu_spice_destroy_surface_wait(SimpleSpiceDisplay *ssd, uint32_t id) --{ -- ssd->worker->destroy_surface_wait(ssd->worker, id); --} -- --void qemu_spice_loadvm_commands(SimpleSpiceDisplay *ssd, -- struct QXLCommandExt *ext, uint32_t count) --{ -- ssd->worker->loadvm_commands(ssd->worker, ext, count); --} -- - void qemu_spice_wakeup(SimpleSpiceDisplay *ssd) - { - ssd->worker->wakeup(ssd->worker); - } - --void qemu_spice_oom(SimpleSpiceDisplay *ssd) --{ -- ssd->worker->oom(ssd->worker); --} -- - void qemu_spice_start(SimpleSpiceDisplay *ssd) - { - ssd->worker->start(ssd->worker); -@@ -124,27 +99,6 @@ void qemu_spice_stop(SimpleSpiceDisplay *ssd) - ssd->worker->stop(ssd->worker); - } - --void qemu_spice_reset_memslots(SimpleSpiceDisplay *ssd) --{ -- ssd->worker->reset_memslots(ssd->worker); --} -- --void qemu_spice_destroy_surfaces(SimpleSpiceDisplay *ssd) --{ -- ssd->worker->destroy_surfaces(ssd->worker); --} -- --void qemu_spice_reset_image_cache(SimpleSpiceDisplay *ssd) --{ -- ssd->worker->reset_image_cache(ssd->worker); --} -- --void qemu_spice_reset_cursor(SimpleSpiceDisplay *ssd) --{ -- ssd->worker->reset_cursor(ssd->worker); --} -- -- - static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd) - { - SimpleSpiceUpdate *update; -diff --git a/ui/spice-display.h b/ui/spice-display.h -index eb7a573..abe99c7 100644 ---- a/ui/spice-display.h -+++ b/ui/spice-display.h -@@ -82,24 +82,12 @@ void qemu_spice_display_update(SimpleSpiceDisplay *ssd, - void qemu_spice_display_resize(SimpleSpiceDisplay *ssd); - void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd); - --void qemu_spice_update_area(SimpleSpiceDisplay *ssd, uint32_t surface_id, -- struct QXLRect *area, struct QXLRect *dirty_rects, -- uint32_t num_dirty_rects, -- uint32_t clear_dirty_region); - void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot); - void qemu_spice_del_memslot(SimpleSpiceDisplay *ssd, uint32_t gid, - uint32_t sid); - void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id, - QXLDevSurfaceCreate *surface); - void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id); --void qemu_spice_destroy_surface_wait(SimpleSpiceDisplay *ssd, uint32_t id); --void qemu_spice_loadvm_commands(SimpleSpiceDisplay *ssd, -- struct QXLCommandExt *ext, uint32_t count); - void qemu_spice_wakeup(SimpleSpiceDisplay *ssd); --void qemu_spice_oom(SimpleSpiceDisplay *ssd); - void qemu_spice_start(SimpleSpiceDisplay *ssd); - void qemu_spice_stop(SimpleSpiceDisplay *ssd); --void qemu_spice_reset_memslots(SimpleSpiceDisplay *ssd); --void qemu_spice_destroy_surfaces(SimpleSpiceDisplay *ssd); --void qemu_spice_reset_image_cache(SimpleSpiceDisplay *ssd); --void qemu_spice_reset_cursor(SimpleSpiceDisplay *ssd); --- -1.7.5.1 - diff --git a/0015-Fix-parse-of-usb-device-description-with-multiple-co.patch b/0015-Fix-parse-of-usb-device-description-with-multiple-co.patch new file mode 100644 index 0000000..efc5119 --- /dev/null +++ b/0015-Fix-parse-of-usb-device-description-with-multiple-co.patch @@ -0,0 +1,56 @@ +From 9b81fbdbb0cc930aacec343c6ab37adfd60c9e76 Mon Sep 17 00:00:00 2001 +From: "Cao,Bing Bu" +Date: Tue, 13 Dec 2011 09:22:20 +0800 +Subject: [PATCH 15/25] Fix parse of usb device description with multiple + configurations + +Changed From V1: +Use DPRINTF instead of fprintf,because it is not an error. + +When testing ipod on QEMU by He Jie Xu,qemu made a assertion. +We found that the ipod with 2 configurations,and the usb-linux did not parse the descriptor correctly. +The descr_len returned is the total length of the all configurations,not one configuration. +The older version will through the other configurations instead of skip,continue parsing the descriptor of interfaces/endpoints in other configurations,then went wrong. + +This patch will put the configuration descriptor parse in loop outside and dispel the other configurations not requested. + +Signed-off-by: Cao,Bing Bu +Signed-off-by: Gerd Hoffmann +--- + usb-linux.c | 19 +++++++++++-------- + 1 files changed, 11 insertions(+), 8 deletions(-) + +diff --git a/usb-linux.c b/usb-linux.c +index ab4c693..ed14bb1 100644 +--- a/usb-linux.c ++++ b/usb-linux.c +@@ -1141,15 +1141,18 @@ static int usb_linux_update_endp_table(USBHostDevice *s) + length = s->descr_len - 18; + i = 0; + +- if (descriptors[i + 1] != USB_DT_CONFIG || +- descriptors[i + 5] != s->configuration) { +- fprintf(stderr, "invalid descriptor data - configuration %d\n", +- s->configuration); +- return 1; +- } +- i += descriptors[i]; +- + while (i < length) { ++ if (descriptors[i + 1] != USB_DT_CONFIG) { ++ fprintf(stderr, "invalid descriptor data\n"); ++ return 1; ++ } else if (descriptors[i + 5] != s->configuration) { ++ DPRINTF("not requested configuration %d\n", s->configuration); ++ i += (descriptors[i + 3] << 8) + descriptors[i + 2]; ++ continue; ++ } ++ ++ i += descriptors[i]; ++ + if (descriptors[i + 1] != USB_DT_INTERFACE || + (descriptors[i + 1] == USB_DT_INTERFACE && + descriptors[i + 4] == 0)) { +-- +1.7.7.5 + diff --git a/0015-qxl-fix-surface-tracking-locking.patch b/0015-qxl-fix-surface-tracking-locking.patch deleted file mode 100644 index c5bd1ee..0000000 --- a/0015-qxl-fix-surface-tracking-locking.patch +++ /dev/null @@ -1,92 +0,0 @@ ->From b2b956cfda5fb144d9faa10b7c5894833feb7d30 Mon Sep 17 00:00:00 2001 -From: Gerd Hoffmann -Date: Wed, 29 Jun 2011 10:24:05 +0200 -Subject: [PATCH 15/28] qxl: fix surface tracking & locking - -Surface tracking needs proper locking since it is used from vcpu and spice -worker threads, add it. Also reset the surface counter when zapping all -surfaces. - -Signed-off-by: Gerd Hoffmann ---- - hw/qxl.c | 13 ++++++++++++- - hw/qxl.h | 2 ++ - 2 files changed, 14 insertions(+), 1 deletions(-) - -diff --git a/hw/qxl.c b/hw/qxl.c -index 803a364..416bd48 100644 ---- a/hw/qxl.c -+++ b/hw/qxl.c -@@ -137,7 +137,12 @@ void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id, - - void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id) - { -+ qemu_mutex_lock(&qxl->track_lock); -+ PANIC_ON(id >= NUM_SURFACES); - qxl->ssd.worker->destroy_surface_wait(qxl->ssd.worker, id); -+ qxl->guest_surfaces.cmds[id] = 0; -+ qxl->guest_surfaces.count--; -+ qemu_mutex_unlock(&qxl->track_lock); - } - - void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext, -@@ -158,7 +163,11 @@ void qxl_spice_reset_memslots(PCIQXLDevice *qxl) - - void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl) - { -+ qemu_mutex_lock(&qxl->track_lock); - qxl->ssd.worker->destroy_surfaces(qxl->ssd.worker); -+ memset(&qxl->guest_surfaces.cmds, 0, sizeof(qxl->guest_surfaces.cmds)); -+ qxl->guest_surfaces.count = 0; -+ qemu_mutex_unlock(&qxl->track_lock); - } - - void qxl_spice_reset_image_cache(PCIQXLDevice *qxl) -@@ -317,6 +326,7 @@ static void qxl_track_command(PCIQXLDevice *qxl, struct QXLCommandExt *ext) - QXLSurfaceCmd *cmd = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id); - uint32_t id = le32_to_cpu(cmd->surface_id); - PANIC_ON(id >= NUM_SURFACES); -+ qemu_mutex_lock(&qxl->track_lock); - if (cmd->type == QXL_SURFACE_CMD_CREATE) { - qxl->guest_surfaces.cmds[id] = ext->cmd.data; - qxl->guest_surfaces.count++; -@@ -327,6 +337,7 @@ static void qxl_track_command(PCIQXLDevice *qxl, struct QXLCommandExt *ext) - qxl->guest_surfaces.cmds[id] = 0; - qxl->guest_surfaces.count--; - } -+ qemu_mutex_unlock(&qxl->track_lock); - break; - } - case QXL_CMD_CURSOR: -@@ -863,7 +874,6 @@ static void qxl_reset_surfaces(PCIQXLDevice *d) - dprint(d, 1, "%s:\n", __FUNCTION__); - d->mode = QXL_MODE_UNDEFINED; - qxl_spice_destroy_surfaces(d); -- memset(&d->guest_surfaces.cmds, 0, sizeof(d->guest_surfaces.cmds)); - } - - /* called from spice server thread context only */ -@@ -1283,6 +1293,7 @@ static int qxl_init_common(PCIQXLDevice *qxl) - qxl->generation = 1; - qxl->num_memslots = NUM_MEMSLOTS; - qxl->num_surfaces = NUM_SURFACES; -+ qemu_mutex_init(&qxl->track_lock); - - switch (qxl->revision) { - case 1: /* spice 0.4 -- qxl-1 */ -diff --git a/hw/qxl.h b/hw/qxl.h -index e62b9d0..5d0e85e 100644 ---- a/hw/qxl.h -+++ b/hw/qxl.h -@@ -55,6 +55,8 @@ typedef struct PCIQXLDevice { - } guest_surfaces; - QXLPHYSICAL guest_cursor; - -+ QemuMutex track_lock; -+ - /* thread signaling */ - pthread_t main; - int pipe[2]; --- -1.7.5.1 - diff --git a/0016-qxl-add-io_port_to_string.patch b/0016-qxl-add-io_port_to_string.patch deleted file mode 100644 index a47328c..0000000 --- a/0016-qxl-add-io_port_to_string.patch +++ /dev/null @@ -1,71 +0,0 @@ ->From 31c995f6ee18ff2e2b45dbdcf1d57f777d1e0ef9 Mon Sep 17 00:00:00 2001 -From: Alon Levy -Date: Fri, 17 Jun 2011 14:42:09 +0200 -Subject: [PATCH 16/28] qxl: add io_port_to_string - -Signed-off-by: Alon Levy ---- - hw/qxl.c | 40 +++++++++++++++++++++++++++++++++++++++- - 1 files changed, 39 insertions(+), 1 deletions(-) - -diff --git a/hw/qxl.c b/hw/qxl.c -index 416bd48..6e66021 100644 ---- a/hw/qxl.c -+++ b/hw/qxl.c -@@ -409,6 +409,43 @@ static const char *qxl_mode_to_string(int mode) - return "INVALID"; - } - -+static const char *io_port_to_string(uint32_t io_port) -+{ -+ if (io_port >= QXL_IO_RANGE_SIZE) { -+ return "out of range"; -+ } -+ static const char *io_port_to_string[QXL_IO_RANGE_SIZE + 1] = { -+ [QXL_IO_NOTIFY_CMD] = "QXL_IO_NOTIFY_CMD", -+ [QXL_IO_NOTIFY_CURSOR] = "QXL_IO_NOTIFY_CURSOR", -+ [QXL_IO_UPDATE_AREA] = "QXL_IO_UPDATE_AREA", -+ [QXL_IO_UPDATE_IRQ] = "QXL_IO_UPDATE_IRQ", -+ [QXL_IO_NOTIFY_OOM] = "QXL_IO_NOTIFY_OOM", -+ [QXL_IO_RESET] = "QXL_IO_RESET", -+ [QXL_IO_SET_MODE] = "QXL_IO_SET_MODE", -+ [QXL_IO_LOG] = "QXL_IO_LOG", -+ [QXL_IO_MEMSLOT_ADD] = "QXL_IO_MEMSLOT_ADD", -+ [QXL_IO_MEMSLOT_DEL] = "QXL_IO_MEMSLOT_DEL", -+ [QXL_IO_DETACH_PRIMARY] = "QXL_IO_DETACH_PRIMARY", -+ [QXL_IO_ATTACH_PRIMARY] = "QXL_IO_ATTACH_PRIMARY", -+ [QXL_IO_CREATE_PRIMARY] = "QXL_IO_CREATE_PRIMARY", -+ [QXL_IO_DESTROY_PRIMARY] = "QXL_IO_DESTROY_PRIMARY", -+ [QXL_IO_DESTROY_SURFACE_WAIT] = "QXL_IO_DESTROY_SURFACE_WAIT", -+ [QXL_IO_DESTROY_ALL_SURFACES] = "QXL_IO_DESTROY_ALL_SURFACES", -+#if SPICE_INTERFACE_QXL_MINOR >= 1 -+ [QXL_IO_UPDATE_AREA_ASYNC] = "QXL_IO_UPDATE_AREA_ASYNC", -+ [QXL_IO_MEMSLOT_ADD_ASYNC] = "QXL_IO_MEMSLOT_ADD_ASYNC", -+ [QXL_IO_CREATE_PRIMARY_ASYNC] = "QXL_IO_CREATE_PRIMARY_ASYNC", -+ [QXL_IO_DESTROY_PRIMARY_ASYNC] = "QXL_IO_DESTROY_PRIMARY_ASYNC", -+ [QXL_IO_DESTROY_SURFACE_ASYNC] = "QXL_IO_DESTROY_SURFACE_ASYNC", -+ [QXL_IO_DESTROY_ALL_SURFACES_ASYNC] -+ = "QXL_IO_DESTROY_ALL_SURFACES_ASYNC", -+ [QXL_IO_FLUSH_SURFACES_ASYNC] = "QXL_IO_FLUSH_SURFACES_ASYNC", -+ [QXL_IO_FLUSH_RELEASE] = "QXL_IO_FLUSH_RELEASE", -+#endif -+ }; -+ return io_port_to_string[io_port]; -+} -+ - /* called from spice server thread context only */ - static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext) - { -@@ -1005,7 +1042,8 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) - default: - if (d->mode == QXL_MODE_NATIVE || d->mode == QXL_MODE_COMPAT) - break; -- dprint(d, 1, "%s: unexpected port 0x%x in vga mode\n", __FUNCTION__, io_port); -+ dprint(d, 1, "%s: unexpected port 0x%x (%s) in vga mode\n", -+ __func__, io_port, io_port_to_string(io_port)); - return; - } - --- -1.7.5.1 - diff --git a/0016-usb-storage-cancel-I-O-on-reset.patch b/0016-usb-storage-cancel-I-O-on-reset.patch new file mode 100644 index 0000000..5fdd63d --- /dev/null +++ b/0016-usb-storage-cancel-I-O-on-reset.patch @@ -0,0 +1,40 @@ +From f63d074313c5df917535587b50802ece7beb6e45 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 4 Jan 2012 18:13:54 +0100 +Subject: [PATCH 16/25] usb-storage: cancel I/O on reset + +When resetting the usb-storage device we'll have to carefully cancel +and clear any requests which might be in flight, otherwise we'll confuse +the state machine. + +Signed-off-by: Gerd Hoffmann +--- + hw/usb-msd.c | 12 ++++++++++++ + 1 files changed, 12 insertions(+), 0 deletions(-) + +diff --git a/hw/usb-msd.c b/hw/usb-msd.c +index 4c06950..3147131 100644 +--- a/hw/usb-msd.c ++++ b/hw/usb-msd.c +@@ -278,6 +278,18 @@ static void usb_msd_handle_reset(USBDevice *dev) + MSDState *s = (MSDState *)dev; + + DPRINTF("Reset\n"); ++ if (s->req) { ++ scsi_req_cancel(s->req); ++ } ++ assert(s->req == NULL); ++ ++ if (s->packet) { ++ USBPacket *p = s->packet; ++ s->packet = NULL; ++ p->result = USB_RET_STALL; ++ usb_packet_complete(dev, p); ++ } ++ + s->mode = USB_MSDM_CBW; + } + +-- +1.7.7.5 + diff --git a/0017-qxl-error-handling-fixes-and-cleanups.patch b/0017-qxl-error-handling-fixes-and-cleanups.patch deleted file mode 100644 index 39a81b7..0000000 --- a/0017-qxl-error-handling-fixes-and-cleanups.patch +++ /dev/null @@ -1,110 +0,0 @@ ->From 4b61f7ca2ed63deb1d35c17150b53a1661f395f7 Mon Sep 17 00:00:00 2001 -From: Gerd Hoffmann -Date: Thu, 30 Jun 2011 10:41:36 +0200 -Subject: [PATCH 17/28] qxl: error handling fixes and cleanups. - -Add qxl_guest_bug() function which is supposed to be called in case -sanity checks of guest requests fail. It raises an error IRQ and -logs a message in case guest debugging is enabled. - -Make PANIC_ON() abort instead of exit. That macro should be used -for qemu bugs only, any guest-triggerable stuff should use the new -qxl_guest_bug() function instead. - -Convert a few easy cases from PANIC_ON() to qxl_guest_bug() to -show intended usage. - -Signed-off-by: Gerd Hoffmann ---- - hw/qxl.c | 34 ++++++++++++++++++++++++++++++---- - hw/qxl.h | 3 ++- - 2 files changed, 32 insertions(+), 5 deletions(-) - -diff --git a/hw/qxl.c b/hw/qxl.c -index 6e66021..28c8b5d 100644 ---- a/hw/qxl.c -+++ b/hw/qxl.c -@@ -125,6 +125,16 @@ static void qxl_reset_memslots(PCIQXLDevice *d); - static void qxl_reset_surfaces(PCIQXLDevice *d); - static void qxl_ring_set_dirty(PCIQXLDevice *qxl); - -+void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg) -+{ -+#if SPICE_INTERFACE_QXL_MINOR >= 1 -+ qxl_send_events(qxl, QXL_INTERRUPT_ERROR); -+#endif -+ if (qxl->guestdebug) { -+ fprintf(stderr, "qxl-%d: guest bug: %s\n", qxl->id, msg); -+ } -+} -+ - - void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id, - struct QXLRect *area, struct QXLRect *dirty_rects, -@@ -1091,22 +1101,38 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) - qxl_hard_reset(d, 0); - break; - case QXL_IO_MEMSLOT_ADD: -- PANIC_ON(val >= NUM_MEMSLOTS); -- PANIC_ON(d->guest_slots[val].active); -+ if (val >= NUM_MEMSLOTS) { -+ qxl_guest_bug(d, "QXL_IO_MEMSLOT_ADD: val out of range"); -+ break; -+ } -+ if (d->guest_slots[val].active) { -+ qxl_guest_bug(d, "QXL_IO_MEMSLOT_ADD: memory slot already active"); -+ break; -+ } - d->guest_slots[val].slot = d->ram->mem_slot; - qxl_add_memslot(d, val, 0); - break; - case QXL_IO_MEMSLOT_DEL: -+ if (val >= NUM_MEMSLOTS) { -+ qxl_guest_bug(d, "QXL_IO_MEMSLOT_DEL: val out of range"); -+ break; -+ } - qxl_del_memslot(d, val); - break; - case QXL_IO_CREATE_PRIMARY: -- PANIC_ON(val != 0); -+ if (val != 0) { -+ qxl_guest_bug(d, "QXL_IO_CREATE_PRIMARY: val != 0"); -+ break; -+ } - dprint(d, 1, "QXL_IO_CREATE_PRIMARY\n"); - d->guest_primary.surface = d->ram->create_surface; - qxl_create_guest_primary(d, 0); - break; - case QXL_IO_DESTROY_PRIMARY: -- PANIC_ON(val != 0); -+ if (val != 0) { -+ qxl_guest_bug(d, "QXL_IO_DESTROY_PRIMARY: val != 0"); -+ break; -+ } - dprint(d, 1, "QXL_IO_DESTROY_PRIMARY (%s)\n", qxl_mode_to_string(d->mode)); - qxl_destroy_primary(d); - break; -diff --git a/hw/qxl.h b/hw/qxl.h -index 5d0e85e..5db9aae 100644 ---- a/hw/qxl.h -+++ b/hw/qxl.h -@@ -86,7 +86,7 @@ typedef struct PCIQXLDevice { - - #define PANIC_ON(x) if ((x)) { \ - printf("%s: PANIC %s failed\n", __FUNCTION__, #x); \ -- exit(-1); \ -+ abort(); \ - } - - #define dprint(_qxl, _level, _fmt, ...) \ -@@ -99,6 +99,7 @@ typedef struct PCIQXLDevice { - - /* qxl.c */ - void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id); -+void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg); - - void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id, - struct QXLRect *area, struct QXLRect *dirty_rects, --- -1.7.5.1 - diff --git a/0017-usb-host-properly-release-port-on-unplug-exit.patch b/0017-usb-host-properly-release-port-on-unplug-exit.patch new file mode 100644 index 0000000..5804510 --- /dev/null +++ b/0017-usb-host-properly-release-port-on-unplug-exit.patch @@ -0,0 +1,111 @@ +From c936f649d4a6b87cabe809170874f6b560cc0524 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Thu, 5 Jan 2012 15:49:18 +0100 +Subject: [PATCH 17/25] usb-host: properly release port on unplug & exit + +Factor out port release into a separate function. Call release function +in exit notifier too. Add explicit call the USBDEVFS_RELEASE_PORT +ioctl, just closing the hub file handle seems not to be enougth. Make +sure we release the port before resetting the device, otherwise host +drivers will not re-attach. + +Signed-off-by: Gerd Hoffmann +--- + usb-linux.c | 28 ++++++++++++++++++++-------- + 1 files changed, 20 insertions(+), 8 deletions(-) + +diff --git a/usb-linux.c b/usb-linux.c +index ed14bb1..749ce71 100644 +--- a/usb-linux.c ++++ b/usb-linux.c +@@ -116,6 +116,7 @@ typedef struct USBHostDevice { + USBDevice dev; + int fd; + int hub_fd; ++ int hub_port; + + uint8_t descr[8192]; + int descr_len; +@@ -434,7 +435,7 @@ static int usb_host_claim_port(USBHostDevice *s) + { + #ifdef USBDEVFS_CLAIM_PORT + char *h, hub_name[64], line[1024]; +- int hub_addr, portnr, ret; ++ int hub_addr, ret; + + snprintf(hub_name, sizeof(hub_name), "%d-%s", + s->match.bus_num, s->match.port); +@@ -442,13 +443,13 @@ static int usb_host_claim_port(USBHostDevice *s) + /* try strip off last ".$portnr" to get hub */ + h = strrchr(hub_name, '.'); + if (h != NULL) { +- portnr = atoi(h+1); ++ s->hub_port = atoi(h+1); + *h = '\0'; + } else { + /* no dot in there -> it is the root hub */ + snprintf(hub_name, sizeof(hub_name), "usb%d", + s->match.bus_num); +- portnr = atoi(s->match.port); ++ s->hub_port = atoi(s->match.port); + } + + if (!usb_host_read_file(line, sizeof(line), "devnum", +@@ -469,20 +470,32 @@ static int usb_host_claim_port(USBHostDevice *s) + return -1; + } + +- ret = ioctl(s->hub_fd, USBDEVFS_CLAIM_PORT, &portnr); ++ ret = ioctl(s->hub_fd, USBDEVFS_CLAIM_PORT, &s->hub_port); + if (ret < 0) { + close(s->hub_fd); + s->hub_fd = -1; + return -1; + } + +- trace_usb_host_claim_port(s->match.bus_num, hub_addr, portnr); ++ trace_usb_host_claim_port(s->match.bus_num, hub_addr, s->hub_port); + return 0; + #else + return -1; + #endif + } + ++static void usb_host_release_port(USBHostDevice *s) ++{ ++ if (s->hub_fd == -1) { ++ return; ++ } ++#ifdef USBDEVFS_RELEASE_PORT ++ ioctl(s->hub_fd, USBDEVFS_RELEASE_PORT, &s->hub_port); ++#endif ++ close(s->hub_fd); ++ s->hub_fd = -1; ++} ++ + static int usb_host_disconnect_ifaces(USBHostDevice *dev, int nb_interfaces) + { + /* earlier Linux 2.4 do not support that */ +@@ -635,10 +648,8 @@ static void usb_host_handle_destroy(USBDevice *dev) + { + USBHostDevice *s = (USBHostDevice *)dev; + ++ usb_host_release_port(s); + usb_host_close(s); +- if (s->hub_fd != -1) { +- close(s->hub_fd); +- } + QTAILQ_REMOVE(&hostdevs, s, next); + qemu_remove_exit_notifier(&s->exit); + } +@@ -1402,6 +1413,7 @@ static void usb_host_exit_notifier(struct Notifier *n, void *data) + { + USBHostDevice *s = container_of(n, USBHostDevice, exit); + ++ usb_host_release_port(s); + if (s->fd != -1) { + usb_host_do_reset(s);; + } +-- +1.7.7.5 + diff --git a/0018-qxl-make-qxl_guest_bug-take-variable-arguments.patch b/0018-qxl-make-qxl_guest_bug-take-variable-arguments.patch deleted file mode 100644 index b7b311f..0000000 --- a/0018-qxl-make-qxl_guest_bug-take-variable-arguments.patch +++ /dev/null @@ -1,52 +0,0 @@ ->From 5c0219c6cef769a5748705d489376ea618486a17 Mon Sep 17 00:00:00 2001 -From: Alon Levy -Date: Wed, 6 Jul 2011 13:40:29 +0200 -Subject: [PATCH 18/28] qxl: make qxl_guest_bug take variable arguments - -Signed-off-by: Alon Levy ---- - hw/qxl.c | 9 +++++++-- - hw/qxl.h | 2 +- - 2 files changed, 8 insertions(+), 3 deletions(-) - -diff --git a/hw/qxl.c b/hw/qxl.c -index 28c8b5d..c50eaf9 100644 ---- a/hw/qxl.c -+++ b/hw/qxl.c -@@ -125,13 +125,18 @@ static void qxl_reset_memslots(PCIQXLDevice *d); - static void qxl_reset_surfaces(PCIQXLDevice *d); - static void qxl_ring_set_dirty(PCIQXLDevice *qxl); - --void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg) -+void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg, ...) - { - #if SPICE_INTERFACE_QXL_MINOR >= 1 - qxl_send_events(qxl, QXL_INTERRUPT_ERROR); - #endif - if (qxl->guestdebug) { -- fprintf(stderr, "qxl-%d: guest bug: %s\n", qxl->id, msg); -+ va_list ap; -+ va_start(ap, msg); -+ fprintf(stderr, "qxl-%d: guest bug: ", qxl->id); -+ vfprintf(stderr, msg, ap); -+ fprintf(stderr, "\n"); -+ va_end(ap); - } - } - -diff --git a/hw/qxl.h b/hw/qxl.h -index 5db9aae..32ca5a0 100644 ---- a/hw/qxl.h -+++ b/hw/qxl.h -@@ -99,7 +99,7 @@ typedef struct PCIQXLDevice { - - /* qxl.c */ - void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id); --void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg); -+void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg, ...); - - void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id, - struct QXLRect *area, struct QXLRect *dirty_rects, --- -1.7.5.1 - diff --git a/0018-usb-ohci-td.cbp-incorrectly-updated-near-page-end.patch b/0018-usb-ohci-td.cbp-incorrectly-updated-near-page-end.patch new file mode 100644 index 0000000..bba083e --- /dev/null +++ b/0018-usb-ohci-td.cbp-incorrectly-updated-near-page-end.patch @@ -0,0 +1,40 @@ +From 23201c64a789cf948fedcea221a4b6e197fcd628 Mon Sep 17 00:00:00 2001 +From: Andriy Gapon +Date: Thu, 22 Dec 2011 11:34:30 +0200 +Subject: [PATCH 18/25] usb-ohci: td.cbp incorrectly updated near page end + +The current code that updates the cbp value after a transfer looks like this: +td.cbp += ret; +if ((td.cbp & 0xfff) + ret > 0xfff) { + +because the 'ret' value is effectively added twice the check may fire too early +when the overflow hasn't happened yet. + +Below is one of the possible changes that correct the behavior: + +Signed-off-by: Gerd Hoffmann +--- + hw/usb-ohci.c | 6 +++--- + 1 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c +index c2981c5..c27014a 100644 +--- a/hw/usb-ohci.c ++++ b/hw/usb-ohci.c +@@ -1025,10 +1025,10 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) + if (ret == len) { + td.cbp = 0; + } else { +- td.cbp += ret; + if ((td.cbp & 0xfff) + ret > 0xfff) { +- td.cbp &= 0xfff; +- td.cbp |= td.be & ~0xfff; ++ td.cbp = (td.be & ~0xfff) + ((td.cbp + ret) & 0xfff); ++ } else { ++ td.cbp += ret; + } + } + td.flags |= OHCI_TD_T1; +-- +1.7.7.5 + diff --git a/0019-qxl-only-disallow-specific-io-s-in-vga-mode.patch b/0019-qxl-only-disallow-specific-io-s-in-vga-mode.patch deleted file mode 100644 index 258a7c3..0000000 --- a/0019-qxl-only-disallow-specific-io-s-in-vga-mode.patch +++ /dev/null @@ -1,31 +0,0 @@ ->From e8f481961a5fd3ad92a55dbabcccf09b037d86c9 Mon Sep 17 00:00:00 2001 -From: Alon Levy -Date: Wed, 29 Jun 2011 11:53:21 +0200 -Subject: [PATCH 19/28] qxl: only disallow specific io's in vga mode - -Since the driver is still in operation even after moving to UNDEFINED, i.e. -by destroying primary in any way. - -Signed-off-by: Alon Levy ---- - hw/qxl.c | 3 ++- - 1 files changed, 2 insertions(+), 1 deletions(-) - -diff --git a/hw/qxl.c b/hw/qxl.c -index c50eaf9..23e3240 100644 ---- a/hw/qxl.c -+++ b/hw/qxl.c -@@ -1055,8 +1055,9 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) - case QXL_IO_LOG: - break; - default: -- if (d->mode == QXL_MODE_NATIVE || d->mode == QXL_MODE_COMPAT) -+ if (d->mode != QXL_MODE_VGA) { - break; -+ } - dprint(d, 1, "%s: unexpected port 0x%x (%s) in vga mode\n", - __func__, io_port, io_port_to_string(io_port)); - return; --- -1.7.5.1 - diff --git a/0019-target-sh4-ignore-ocbp-and-ocbwb-instructions.patch b/0019-target-sh4-ignore-ocbp-and-ocbwb-instructions.patch new file mode 100644 index 0000000..d3a4197 --- /dev/null +++ b/0019-target-sh4-ignore-ocbp-and-ocbwb-instructions.patch @@ -0,0 +1,47 @@ +From 37769d27270eff15d878a1c7df23407fc5f09b7f Mon Sep 17 00:00:00 2001 +From: Aurelien Jarno +Date: Sat, 7 Jan 2012 15:20:12 +0100 +Subject: [PATCH 19/25] target-sh4: ignore ocbp and ocbwb instructions + +ocbp and ocbwb controls the writeback of a cache line to memory. They +are supposed to do nothing in case of a cache miss. Given QEMU only +partially emulate caches, it is safe to ignore these instructions. + +This fixes a kernel oops when trying to access an rtl8139 NIC with +recent versions. + +Signed-off-by: Aurelien Jarno +(cherry picked from commit 0cdb95549fedc73e13c147ab9dcabcc303426a07) +--- + target-sh4/translate.c | 14 +++----------- + 1 files changed, 3 insertions(+), 11 deletions(-) + +diff --git a/target-sh4/translate.c b/target-sh4/translate.c +index bad3577..e04a6e0 100644 +--- a/target-sh4/translate.c ++++ b/target-sh4/translate.c +@@ -1652,18 +1652,10 @@ static void _decode_opc(DisasContext * ctx) + } + return; + case 0x00a3: /* ocbp @Rn */ +- { +- TCGv dummy = tcg_temp_new(); +- tcg_gen_qemu_ld32s(dummy, REG(B11_8), ctx->memidx); +- tcg_temp_free(dummy); +- } +- return; + case 0x00b3: /* ocbwb @Rn */ +- { +- TCGv dummy = tcg_temp_new(); +- tcg_gen_qemu_ld32s(dummy, REG(B11_8), ctx->memidx); +- tcg_temp_free(dummy); +- } ++ /* These instructions are supposed to do nothing in case of ++ a cache miss. Given that we only partially emulate caches ++ it is safe to simply ignore them. */ + return; + case 0x0083: /* pref @Rn */ + return; +-- +1.7.7.5 + diff --git a/0020-PPC-Fix-linker-scripts-on-ppc-hosts.patch b/0020-PPC-Fix-linker-scripts-on-ppc-hosts.patch new file mode 100644 index 0000000..f6ce35a --- /dev/null +++ b/0020-PPC-Fix-linker-scripts-on-ppc-hosts.patch @@ -0,0 +1,74 @@ +From fbcf305e5adc310e6383d4ec5e844f3f8d072116 Mon Sep 17 00:00:00 2001 +From: Alexander Graf +Date: Mon, 12 Dec 2011 22:36:01 +0100 +Subject: [PATCH 20/25] PPC: Fix linker scripts on ppc hosts + +When compiling qemu statically with multilib on PPC, we hit the +same issue that commit 845f2c2812d9ed24b36c02a3d06ee83aeafe8b49 +is fixing. Do the same here. + +Signed-off-by: Alexander Graf +Signed-off-by: Aurelien Jarno +(cherry picked from commit 665a04ae1cbfa8004a38cf0fe99ba799c978a1fe) +--- + ppc.ld | 16 ++++++++++++++-- + ppc64.ld | 16 ++++++++++++++-- + 2 files changed, 28 insertions(+), 4 deletions(-) + +diff --git a/ppc.ld b/ppc.ld +index 69aa3f2..2a0dcad 100644 +--- a/ppc.ld ++++ b/ppc.ld +@@ -49,8 +49,20 @@ SECTIONS + .rela.sbss2 : { *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) } + .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) } + .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) } +- .rel.plt : { *(.rel.plt) } +- .rela.plt : { *(.rela.plt) } ++ .rel.plt : ++ { ++ *(.rel.plt) ++ PROVIDE (__rel_iplt_start = .); ++ *(.rel.iplt) ++ PROVIDE (__rel_iplt_end = .); ++ } ++ .rela.plt : ++ { ++ *(.rela.plt) ++ PROVIDE (__rela_iplt_start = .); ++ *(.rela.iplt) ++ PROVIDE (__rela_iplt_end = .); ++ } + .init : + { + KEEP (*(.init)) +diff --git a/ppc64.ld b/ppc64.ld +index 0a7c0dd..e2dafa0 100644 +--- a/ppc64.ld ++++ b/ppc64.ld +@@ -54,8 +54,20 @@ SECTIONS + *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + } +- .rel.plt : { *(.rel.plt) } +- .rela.plt : { *(.rela.plt) } ++ .rel.plt : ++ { ++ *(.rel.plt) ++ PROVIDE (__rel_iplt_start = .); ++ *(.rel.iplt) ++ PROVIDE (__rel_iplt_end = .); ++ } ++ .rela.plt : ++ { ++ *(.rela.plt) ++ PROVIDE (__rela_iplt_start = .); ++ *(.rela.iplt) ++ PROVIDE (__rela_iplt_end = .); ++ } + .rela.tocbss : { *(.rela.tocbss) } + .init : + { +-- +1.7.7.5 + diff --git a/0020-qxl-async-io-support-using-new-spice-api.patch b/0020-qxl-async-io-support-using-new-spice-api.patch deleted file mode 100644 index 68ed72c..0000000 --- a/0020-qxl-async-io-support-using-new-spice-api.patch +++ /dev/null @@ -1,659 +0,0 @@ ->From a1950cb3afb36a78df3ac9a545d99baf7cc93ca2 Mon Sep 17 00:00:00 2001 -From: Alon Levy -Date: Thu, 23 Jun 2011 20:02:18 +0200 -Subject: [PATCH 20/28] qxl: async io support using new spice api - -Some of the QXL port i/o commands are waiting for the spice server to -complete certain actions. Add async versions for these commands, so we -don't block the vcpu while the spice server processses the command. -Instead the qxl device will raise an IRQ when done. - -The async command processing relies on an added QXLInterface::async_complete -and added QXLWorker::*_async additions, in spice server qxl >= 3.1 - -Signed-off-by: Gerd Hoffmann -Signed-off-by: Alon Levy ---- - hw/qxl-render.c | 2 +- - hw/qxl.c | 240 ++++++++++++++++++++++++++++++++++++++++++++-------- - hw/qxl.h | 16 +++- - ui/spice-display.c | 47 ++++++++-- - ui/spice-display.h | 23 +++++- - 5 files changed, 274 insertions(+), 54 deletions(-) - -diff --git a/hw/qxl-render.c b/hw/qxl-render.c -index 60b822d..643ff2d 100644 ---- a/hw/qxl-render.c -+++ b/hw/qxl-render.c -@@ -125,7 +125,7 @@ void qxl_render_update(PCIQXLDevice *qxl) - - memset(dirty, 0, sizeof(dirty)); - qxl_spice_update_area(qxl, 0, &update, -- dirty, ARRAY_SIZE(dirty), 1); -+ dirty, ARRAY_SIZE(dirty), 1, QXL_SYNC); - - for (i = 0; i < ARRAY_SIZE(dirty); i++) { - if (qemu_spice_rect_is_empty(dirty+i)) { -diff --git a/hw/qxl.c b/hw/qxl.c -index 23e3240..d3109e4 100644 ---- a/hw/qxl.c -+++ b/hw/qxl.c -@@ -120,7 +120,7 @@ static QXLMode qxl_modes[] = { - static PCIQXLDevice *qxl0; - - static void qxl_send_events(PCIQXLDevice *d, uint32_t events); --static void qxl_destroy_primary(PCIQXLDevice *d); -+static int qxl_destroy_primary(PCIQXLDevice *d, qxl_async_io async); - static void qxl_reset_memslots(PCIQXLDevice *d); - static void qxl_reset_surfaces(PCIQXLDevice *d); - static void qxl_ring_set_dirty(PCIQXLDevice *qxl); -@@ -144,22 +144,47 @@ void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg, ...) - void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id, - struct QXLRect *area, struct QXLRect *dirty_rects, - uint32_t num_dirty_rects, -- uint32_t clear_dirty_region) -+ uint32_t clear_dirty_region, -+ qxl_async_io async) - { -- qxl->ssd.worker->update_area(qxl->ssd.worker, surface_id, area, dirty_rects, -- num_dirty_rects, clear_dirty_region); -+ if (async == QXL_SYNC) { -+ qxl->ssd.worker->update_area(qxl->ssd.worker, surface_id, area, -+ dirty_rects, num_dirty_rects, clear_dirty_region); -+ } else { -+#if SPICE_INTERFACE_QXL_MINOR >= 1 -+ spice_qxl_update_area_async(&qxl->ssd.qxl, surface_id, area, -+ clear_dirty_region, 0); -+#else -+ abort(); -+#endif -+ } - } - --void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id) -+static void qxl_spice_destroy_surface_wait_complete(PCIQXLDevice *qxl, -+ uint32_t id) - { - qemu_mutex_lock(&qxl->track_lock); -- PANIC_ON(id >= NUM_SURFACES); -- qxl->ssd.worker->destroy_surface_wait(qxl->ssd.worker, id); - qxl->guest_surfaces.cmds[id] = 0; - qxl->guest_surfaces.count--; - qemu_mutex_unlock(&qxl->track_lock); - } - -+static void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id, -+ qxl_async_io async) -+{ -+ if (async) { -+#if SPICE_INTERFACE_QXL_MINOR < 1 -+ abort(); -+#else -+ spice_qxl_destroy_surface_async(&qxl->ssd.qxl, id, -+ (uint64_t)id); -+#endif -+ } else { -+ qxl->ssd.worker->destroy_surface_wait(qxl->ssd.worker, id); -+ qxl_spice_destroy_surface_wait_complete(qxl, id); -+ } -+} -+ - void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext, - uint32_t count) - { -@@ -176,15 +201,28 @@ void qxl_spice_reset_memslots(PCIQXLDevice *qxl) - qxl->ssd.worker->reset_memslots(qxl->ssd.worker); - } - --void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl) -+static void qxl_spice_destroy_surfaces_complete(PCIQXLDevice *qxl) - { - qemu_mutex_lock(&qxl->track_lock); -- qxl->ssd.worker->destroy_surfaces(qxl->ssd.worker); - memset(&qxl->guest_surfaces.cmds, 0, sizeof(qxl->guest_surfaces.cmds)); - qxl->guest_surfaces.count = 0; - qemu_mutex_unlock(&qxl->track_lock); - } - -+static void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl, qxl_async_io async) -+{ -+ if (async) { -+#if SPICE_INTERFACE_QXL_MINOR < 1 -+ abort(); -+#else -+ spice_qxl_destroy_surfaces_async(&qxl->ssd.qxl, 0); -+#endif -+ } else { -+ qxl->ssd.worker->destroy_surfaces(qxl->ssd.worker); -+ qxl_spice_destroy_surfaces_complete(qxl); -+ } -+} -+ - void qxl_spice_reset_image_cache(PCIQXLDevice *qxl) - { - qxl->ssd.worker->reset_image_cache(qxl->ssd.worker); -@@ -689,6 +727,38 @@ static int interface_flush_resources(QXLInstance *sin) - return ret; - } - -+static void qxl_create_guest_primary_complete(PCIQXLDevice *d); -+ -+#if SPICE_INTERFACE_QXL_MINOR >= 1 -+ -+/* called from spice server thread context only */ -+static void interface_async_complete(QXLInstance *sin, uint64_t cookie) -+{ -+ PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); -+ uint32_t current_async; -+ -+ qemu_mutex_lock(&qxl->async_lock); -+ current_async = qxl->current_async; -+ qxl->current_async = QXL_UNDEFINED_IO; -+ qemu_mutex_unlock(&qxl->async_lock); -+ -+ dprint(qxl, 2, "async_complete: %d (%ld) done\n", current_async, cookie); -+ switch (current_async) { -+ case QXL_IO_CREATE_PRIMARY_ASYNC: -+ qxl_create_guest_primary_complete(qxl); -+ break; -+ case QXL_IO_DESTROY_ALL_SURFACES_ASYNC: -+ qxl_spice_destroy_surfaces_complete(qxl); -+ break; -+ case QXL_IO_DESTROY_SURFACE_ASYNC: -+ qxl_spice_destroy_surface_wait_complete(qxl, (uint32_t)cookie); -+ break; -+ } -+ qxl_send_events(qxl, QXL_INTERRUPT_IO_CMD); -+} -+ -+#endif -+ - static const QXLInterface qxl_interface = { - .base.type = SPICE_INTERFACE_QXL, - .base.description = "qxl gpu", -@@ -708,6 +778,9 @@ static const QXLInterface qxl_interface = { - .req_cursor_notification = interface_req_cursor_notification, - .notify_update = interface_notify_update, - .flush_resources = interface_flush_resources, -+#if SPICE_INTERFACE_QXL_MINOR >= 1 -+ .async_complete = interface_async_complete, -+#endif - }; - - static void qxl_enter_vga_mode(PCIQXLDevice *d) -@@ -727,7 +800,7 @@ static void qxl_exit_vga_mode(PCIQXLDevice *d) - return; - } - dprint(d, 1, "%s\n", __FUNCTION__); -- qxl_destroy_primary(d); -+ qxl_destroy_primary(d, QXL_SYNC); - } - - static void qxl_set_irq(PCIQXLDevice *d) -@@ -824,13 +897,14 @@ static void qxl_vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) - - if (qxl->mode != QXL_MODE_VGA) { - dprint(qxl, 1, "%s\n", __FUNCTION__); -- qxl_destroy_primary(qxl); -+ qxl_destroy_primary(qxl, QXL_SYNC); - qxl_soft_reset(qxl); - } - vga_ioport_write(opaque, addr, val); - } - --static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta) -+static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta, -+ qxl_async_io async) - { - static const int regions[] = { - QXL_RAM_RANGE_INDEX, -@@ -900,7 +974,7 @@ static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta) - __FUNCTION__, memslot.slot_id, - memslot.virt_start, memslot.virt_end); - -- qemu_spice_add_memslot(&d->ssd, &memslot); -+ qemu_spice_add_memslot(&d->ssd, &memslot, async); - d->guest_slots[slot_id].ptr = (void*)memslot.virt_start; - d->guest_slots[slot_id].size = memslot.virt_end - memslot.virt_start; - d->guest_slots[slot_id].delta = delta; -@@ -925,7 +999,7 @@ static void qxl_reset_surfaces(PCIQXLDevice *d) - { - dprint(d, 1, "%s:\n", __FUNCTION__); - d->mode = QXL_MODE_UNDEFINED; -- qxl_spice_destroy_surfaces(d); -+ qxl_spice_destroy_surfaces(d, QXL_SYNC); - } - - /* called from spice server thread context only */ -@@ -950,7 +1024,14 @@ void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id) - } - } - --static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm) -+static void qxl_create_guest_primary_complete(PCIQXLDevice *qxl) -+{ -+ /* for local rendering */ -+ qxl_render_resize(qxl); -+} -+ -+static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm, -+ qxl_async_io async) - { - QXLDevSurfaceCreate surface; - QXLSurfaceCreate *sc = &qxl->guest_primary.surface; -@@ -978,22 +1059,26 @@ static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm) - - qxl->mode = QXL_MODE_NATIVE; - qxl->cmdflags = 0; -- qemu_spice_create_primary_surface(&qxl->ssd, 0, &surface); -+ qemu_spice_create_primary_surface(&qxl->ssd, 0, &surface, async); - -- /* for local rendering */ -- qxl_render_resize(qxl); -+ if (async == QXL_SYNC) { -+ qxl_create_guest_primary_complete(qxl); -+ } - } - --static void qxl_destroy_primary(PCIQXLDevice *d) -+/* return 1 if surface destoy was initiated (in QXL_ASYNC case) or -+ * done (in QXL_SYNC case), 0 otherwise. */ -+static int qxl_destroy_primary(PCIQXLDevice *d, qxl_async_io async) - { - if (d->mode == QXL_MODE_UNDEFINED) { -- return; -+ return 0; - } - - dprint(d, 1, "%s\n", __FUNCTION__); - - d->mode = QXL_MODE_UNDEFINED; -- qemu_spice_destroy_primary_surface(&d->ssd, 0); -+ qemu_spice_destroy_primary_surface(&d->ssd, 0, async); -+ return 1; - } - - static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm) -@@ -1023,10 +1108,10 @@ static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm) - } - - d->guest_slots[0].slot = slot; -- qxl_add_memslot(d, 0, devmem); -+ qxl_add_memslot(d, 0, devmem, QXL_SYNC); - - d->guest_primary.surface = surface; -- qxl_create_guest_primary(d, 0); -+ qxl_create_guest_primary(d, 0, QXL_SYNC); - - d->mode = QXL_MODE_COMPAT; - d->cmdflags = QXL_COMMAND_FLAG_COMPAT; -@@ -1044,6 +1129,10 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) - { - PCIQXLDevice *d = opaque; - uint32_t io_port = addr - d->io_base; -+ qxl_async_io async = QXL_SYNC; -+#if SPICE_INTERFACE_QXL_MINOR >= 1 -+ uint32_t orig_io_port = io_port; -+#endif - - switch (io_port) { - case QXL_IO_RESET: -@@ -1053,6 +1142,10 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) - case QXL_IO_CREATE_PRIMARY: - case QXL_IO_UPDATE_IRQ: - case QXL_IO_LOG: -+#if SPICE_INTERFACE_QXL_MINOR >= 1 -+ case QXL_IO_MEMSLOT_ADD_ASYNC: -+ case QXL_IO_CREATE_PRIMARY_ASYNC: -+#endif - break; - default: - if (d->mode != QXL_MODE_VGA) { -@@ -1060,15 +1153,61 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) - } - dprint(d, 1, "%s: unexpected port 0x%x (%s) in vga mode\n", - __func__, io_port, io_port_to_string(io_port)); -+#if SPICE_INTERFACE_QXL_MINOR >= 1 -+ /* be nice to buggy guest drivers */ -+ if (io_port >= QXL_IO_UPDATE_AREA_ASYNC && -+ io_port <= QXL_IO_DESTROY_ALL_SURFACES_ASYNC) { -+ qxl_send_events(d, QXL_INTERRUPT_IO_CMD); -+ } -+#endif - return; - } - -+#if SPICE_INTERFACE_QXL_MINOR >= 1 -+ /* we change the io_port to avoid ifdeffery in the main switch */ -+ orig_io_port = io_port; -+ switch (io_port) { -+ case QXL_IO_UPDATE_AREA_ASYNC: -+ io_port = QXL_IO_UPDATE_AREA; -+ goto async_common; -+ case QXL_IO_MEMSLOT_ADD_ASYNC: -+ io_port = QXL_IO_MEMSLOT_ADD; -+ goto async_common; -+ case QXL_IO_CREATE_PRIMARY_ASYNC: -+ io_port = QXL_IO_CREATE_PRIMARY; -+ goto async_common; -+ case QXL_IO_DESTROY_PRIMARY_ASYNC: -+ io_port = QXL_IO_DESTROY_PRIMARY; -+ goto async_common; -+ case QXL_IO_DESTROY_SURFACE_ASYNC: -+ io_port = QXL_IO_DESTROY_SURFACE_WAIT; -+ goto async_common; -+ case QXL_IO_DESTROY_ALL_SURFACES_ASYNC: -+ io_port = QXL_IO_DESTROY_ALL_SURFACES; -+async_common: -+ async = QXL_ASYNC; -+ qemu_mutex_lock(&d->async_lock); -+ if (d->current_async != QXL_UNDEFINED_IO) { -+ qxl_guest_bug(d, "%d async started before last (%d) complete", -+ io_port, d->current_async); -+ qemu_mutex_unlock(&d->async_lock); -+ return; -+ } -+ d->current_async = orig_io_port; -+ qemu_mutex_unlock(&d->async_lock); -+ dprint(d, 2, "start async %d (%d)\n", io_port, val); -+ break; -+ default: -+ break; -+ } -+#endif -+ - switch (io_port) { - case QXL_IO_UPDATE_AREA: - { - QXLRect update = d->ram->update_area; - qxl_spice_update_area(d, d->ram->update_surface, -- &update, NULL, 0, 0); -+ &update, NULL, 0, 0, async); - break; - } - case QXL_IO_NOTIFY_CMD: -@@ -1116,7 +1255,7 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) - break; - } - d->guest_slots[val].slot = d->ram->mem_slot; -- qxl_add_memslot(d, val, 0); -+ qxl_add_memslot(d, val, 0, async); - break; - case QXL_IO_MEMSLOT_DEL: - if (val >= NUM_MEMSLOTS) { -@@ -1127,31 +1266,56 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) - break; - case QXL_IO_CREATE_PRIMARY: - if (val != 0) { -- qxl_guest_bug(d, "QXL_IO_CREATE_PRIMARY: val != 0"); -- break; -+ qxl_guest_bug(d, "QXL_IO_CREATE_PRIMARY (async=%d): val != 0", -+ async); -+ goto cancel_async; - } -- dprint(d, 1, "QXL_IO_CREATE_PRIMARY\n"); -+ dprint(d, 1, "QXL_IO_CREATE_PRIMARY async=%d\n", async); - d->guest_primary.surface = d->ram->create_surface; -- qxl_create_guest_primary(d, 0); -+ qxl_create_guest_primary(d, 0, async); - break; - case QXL_IO_DESTROY_PRIMARY: - if (val != 0) { -- qxl_guest_bug(d, "QXL_IO_DESTROY_PRIMARY: val != 0"); -- break; -+ qxl_guest_bug(d, "QXL_IO_DESTROY_PRIMARY (async=%d): val != 0", -+ async); -+ goto cancel_async; -+ } -+ dprint(d, 1, "QXL_IO_DESTROY_PRIMARY (async=%d) (%s)\n", async, -+ qxl_mode_to_string(d->mode)); -+ if (!qxl_destroy_primary(d, async)) { -+ dprint(d, 1, "QXL_IO_DESTROY_PRIMARY_ASYNC in %s, ignored\n", -+ qxl_mode_to_string(d->mode)); -+ goto cancel_async; - } -- dprint(d, 1, "QXL_IO_DESTROY_PRIMARY (%s)\n", qxl_mode_to_string(d->mode)); -- qxl_destroy_primary(d); - break; - case QXL_IO_DESTROY_SURFACE_WAIT: -- qxl_spice_destroy_surface_wait(d, val); -+ if (val >= NUM_SURFACES) { -+ qxl_guest_bug(d, "QXL_IO_DESTROY_SURFACE (async=%d):" -+ "%d >= NUM_SURFACES", async, val); -+ goto cancel_async; -+ } -+ qxl_spice_destroy_surface_wait(d, val, async); - break; - case QXL_IO_DESTROY_ALL_SURFACES: -- qxl_spice_destroy_surfaces(d); -+ d->mode = QXL_MODE_UNDEFINED; -+ qxl_spice_destroy_surfaces(d, async); - break; - default: - fprintf(stderr, "%s: ioport=0x%x, abort()\n", __FUNCTION__, io_port); - abort(); - } -+ return; -+cancel_async: -+#if SPICE_INTERFACE_QXL_MINOR >= 1 -+ if (async) { -+ qxl_send_events(d, QXL_INTERRUPT_IO_CMD); -+ qemu_mutex_lock(&d->async_lock); -+ d->current_async = QXL_UNDEFINED_IO; -+ qemu_mutex_unlock(&d->async_lock); -+ } -+#else -+ return; -+#endif - } - - static uint32_t ioport_read(void *opaque, uint32_t addr) -@@ -1364,6 +1528,8 @@ static int qxl_init_common(PCIQXLDevice *qxl) - qxl->num_memslots = NUM_MEMSLOTS; - qxl->num_surfaces = NUM_SURFACES; - qemu_mutex_init(&qxl->track_lock); -+ qemu_mutex_init(&qxl->async_lock); -+ qxl->current_async = QXL_UNDEFINED_IO; - - switch (qxl->revision) { - case 1: /* spice 0.4 -- qxl-1 */ -@@ -1528,9 +1694,9 @@ static int qxl_post_load(void *opaque, int version) - if (!d->guest_slots[i].active) { - continue; - } -- qxl_add_memslot(d, i, 0); -+ qxl_add_memslot(d, i, 0, QXL_SYNC); - } -- qxl_create_guest_primary(d, 1); -+ qxl_create_guest_primary(d, 1, QXL_SYNC); - - /* replay surface-create and cursor-set commands */ - cmds = qemu_mallocz(sizeof(QXLCommandExt) * (NUM_SURFACES + 1)); -diff --git a/hw/qxl.h b/hw/qxl.h -index 32ca5a0..1046205 100644 ---- a/hw/qxl.h -+++ b/hw/qxl.h -@@ -15,6 +15,8 @@ enum qxl_mode { - QXL_MODE_NATIVE, - }; - -+#define QXL_UNDEFINED_IO UINT32_MAX -+ - typedef struct PCIQXLDevice { - PCIDevice pci; - SimpleSpiceDisplay ssd; -@@ -30,6 +32,9 @@ typedef struct PCIQXLDevice { - int32_t num_memslots; - int32_t num_surfaces; - -+ uint32_t current_async; -+ QemuMutex async_lock; -+ - struct guest_slots { - QXLMemSlot slot; - void *ptr; -@@ -104,13 +109,12 @@ void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg, ...); - void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id, - struct QXLRect *area, struct QXLRect *dirty_rects, - uint32_t num_dirty_rects, -- uint32_t clear_dirty_region); --void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id); -+ uint32_t clear_dirty_region, -+ qxl_async_io async); - void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext, - uint32_t count); - void qxl_spice_oom(PCIQXLDevice *qxl); - void qxl_spice_reset_memslots(PCIQXLDevice *qxl); --void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl); - void qxl_spice_reset_image_cache(PCIQXLDevice *qxl); - void qxl_spice_reset_cursor(PCIQXLDevice *qxl); - -@@ -122,3 +126,9 @@ void qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext); - void qxl_render_resize(PCIQXLDevice *qxl); - void qxl_render_update(PCIQXLDevice *qxl); - void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext); -+#if SPICE_INTERFACE_QXL_MINOR >= 1 -+void qxl_spice_update_area_async(PCIQXLDevice *qxl, uint32_t surface_id, -+ struct QXLRect *area, -+ uint32_t clear_dirty_region, -+ int is_vga); -+#endif -diff --git a/ui/spice-display.c b/ui/spice-display.c -index af10ae8..683d454 100644 ---- a/ui/spice-display.c -+++ b/ui/spice-display.c -@@ -62,10 +62,18 @@ void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r) - dest->right = MAX(dest->right, r->right); - } - -- --void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot) --{ -- ssd->worker->add_memslot(ssd->worker, memslot); -+void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot, -+ qxl_async_io async) -+{ -+ if (async != QXL_SYNC) { -+#if SPICE_INTERFACE_QXL_MINOR >= 1 -+ spice_qxl_add_memslot_async(&ssd->qxl, memslot, 0); -+#else -+ abort(); -+#endif -+ } else { -+ ssd->worker->add_memslot(ssd->worker, memslot); -+ } - } - - void qemu_spice_del_memslot(SimpleSpiceDisplay *ssd, uint32_t gid, uint32_t sid) -@@ -74,14 +82,33 @@ void qemu_spice_del_memslot(SimpleSpiceDisplay *ssd, uint32_t gid, uint32_t sid) - } - - void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id, -- QXLDevSurfaceCreate *surface) --{ -- ssd->worker->create_primary_surface(ssd->worker, id, surface); -+ QXLDevSurfaceCreate *surface, -+ qxl_async_io async) -+{ -+ if (async != QXL_SYNC) { -+#if SPICE_INTERFACE_QXL_MINOR >= 1 -+ spice_qxl_create_primary_surface_async(&ssd->qxl, id, surface, 0); -+#else -+ abort(); -+#endif -+ } else { -+ ssd->worker->create_primary_surface(ssd->worker, id, surface); -+ } - } - --void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id) -+ -+void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd, -+ uint32_t id, qxl_async_io async) - { -- ssd->worker->destroy_primary_surface(ssd->worker, id); -+ if (async != QXL_SYNC) { -+#if SPICE_INTERFACE_QXL_MINOR >= 1 -+ spice_qxl_destroy_primary_surface_async(&ssd->qxl, id, 0); -+#else -+ abort(); -+#endif -+ } else { -+ ssd->worker->destroy_primary_surface(ssd->worker, id); -+ } - } - - void qemu_spice_wakeup(SimpleSpiceDisplay *ssd) -@@ -198,7 +225,7 @@ void qemu_spice_create_host_memslot(SimpleSpiceDisplay *ssd) - memset(&memslot, 0, sizeof(memslot)); - memslot.slot_group_id = MEMSLOT_GROUP_HOST; - memslot.virt_end = ~0; -- qemu_spice_add_memslot(ssd, &memslot); -+ qemu_spice_add_memslot(ssd, &memslot, QXL_SYNC); - } - - void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd) -@@ -218,14 +245,14 @@ void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd) - surface.mem = (intptr_t)ssd->buf; - surface.group_id = MEMSLOT_GROUP_HOST; - -- qemu_spice_create_primary_surface(ssd, 0, &surface); -+ qemu_spice_create_primary_surface(ssd, 0, &surface, QXL_SYNC); - } - - void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd) - { - dprint(1, "%s:\n", __FUNCTION__); - -- qemu_spice_destroy_primary_surface(ssd, 0); -+ qemu_spice_destroy_primary_surface(ssd, 0, QXL_SYNC); - } - - void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason) -diff --git a/ui/spice-display.h b/ui/spice-display.h -index abe99c7..1388641 100644 ---- a/ui/spice-display.h -+++ b/ui/spice-display.h -@@ -33,6 +33,20 @@ - - #define NUM_SURFACES 1024 - -+/* -+ * Internal enum to differenciate between options for -+ * io calls that have a sync (old) version and an _async (new) -+ * version: -+ * QXL_SYNC: use the old version -+ * QXL_ASYNC: use the new version and make sure there are no two -+ * happening at the same time. This is used for guest initiated -+ * calls -+ */ -+typedef enum qxl_async_io { -+ QXL_SYNC, -+ QXL_ASYNC, -+} qxl_async_io; -+ - typedef struct SimpleSpiceDisplay SimpleSpiceDisplay; - typedef struct SimpleSpiceUpdate SimpleSpiceUpdate; - -@@ -82,12 +96,15 @@ void qemu_spice_display_update(SimpleSpiceDisplay *ssd, - void qemu_spice_display_resize(SimpleSpiceDisplay *ssd); - void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd); - --void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot); -+void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot, -+ qxl_async_io async); - void qemu_spice_del_memslot(SimpleSpiceDisplay *ssd, uint32_t gid, - uint32_t sid); - void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id, -- QXLDevSurfaceCreate *surface); --void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id); -+ QXLDevSurfaceCreate *surface, -+ qxl_async_io async); -+void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd, -+ uint32_t id, qxl_async_io async); - void qemu_spice_wakeup(SimpleSpiceDisplay *ssd); - void qemu_spice_start(SimpleSpiceDisplay *ssd); - void qemu_spice_stop(SimpleSpiceDisplay *ssd); --- -1.7.5.1 - diff --git a/0021-qiov-prevent-double-free-or-use-after-free.patch b/0021-qiov-prevent-double-free-or-use-after-free.patch new file mode 100644 index 0000000..08e0e84 --- /dev/null +++ b/0021-qiov-prevent-double-free-or-use-after-free.patch @@ -0,0 +1,34 @@ +From 6061f16a8a119a46e61f2ddbabdb58f83e8857f7 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 25 Nov 2011 12:06:22 +0100 +Subject: [PATCH 21/25] qiov: prevent double free or use-after-free + +qemu_iovec_destroy does not clear the QEMUIOVector fully, and the data +could thus be used after free or freed again. While I do not know any +example in the tree, I observed this using virtio-scsi (and SCSI +scatter/gather) when canceling DMA requests. + +Signed-off-by: Paolo Bonzini +Signed-off-by: Kevin Wolf +--- + cutils.c | 3 +++ + 1 files changed, 3 insertions(+), 0 deletions(-) + +diff --git a/cutils.c b/cutils.c +index 6db6304..24b3fe3 100644 +--- a/cutils.c ++++ b/cutils.c +@@ -217,7 +217,10 @@ void qemu_iovec_destroy(QEMUIOVector *qiov) + { + assert(qiov->nalloc != -1); + ++ qemu_iovec_reset(qiov); + g_free(qiov->iov); ++ qiov->nalloc = 0; ++ qiov->iov = NULL; + } + + void qemu_iovec_reset(QEMUIOVector *qiov) +-- +1.7.7.5 + diff --git a/0021-qxl-add-QXL_IO_FLUSH_-SURFACES-RELEASE-for-guest-S3-.patch b/0021-qxl-add-QXL_IO_FLUSH_-SURFACES-RELEASE-for-guest-S3-.patch deleted file mode 100644 index 41b88a3..0000000 --- a/0021-qxl-add-QXL_IO_FLUSH_-SURFACES-RELEASE-for-guest-S3-.patch +++ /dev/null @@ -1,77 +0,0 @@ ->From fed782e33714e6a44bca9a8c3ab8b017393e8089 Mon Sep 17 00:00:00 2001 -From: Alon Levy -Date: Sun, 5 Jun 2011 11:01:48 +0300 -Subject: [PATCH 21/28] qxl: add QXL_IO_FLUSH_{SURFACES,RELEASE} for guest - S3&S4 support - -Add two new IOs. - QXL_IO_FLUSH_SURFACES - equivalent to update area for all surfaces, used - to reduce vmexits from NumSurfaces to 1 on guest S3, S4 and resolution change (windows - driver implementation is such that this is done on each of those occasions). - QXL_IO_FLUSH_RELEASE - used to ensure anything on last_release is put on the release ring - for the client to free. - -Signed-off-by: Yonit Halperin -Signed-off-by: Alon Levy ---- - hw/qxl.c | 30 ++++++++++++++++++++++++++++++ - 1 files changed, 30 insertions(+), 0 deletions(-) - -diff --git a/hw/qxl.c b/hw/qxl.c -index d3109e4..847a9b8 100644 ---- a/hw/qxl.c -+++ b/hw/qxl.c -@@ -185,6 +185,13 @@ static void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id, - } - } - -+#if SPICE_INTERFACE_QXL_MINOR >= 1 -+static void qxl_spice_flush_surfaces_async(PCIQXLDevice *qxl) -+{ -+ spice_qxl_flush_surfaces_async(&qxl->ssd.qxl, 0); -+} -+#endif -+ - void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext, - uint32_t count) - { -@@ -1184,6 +1191,8 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) - goto async_common; - case QXL_IO_DESTROY_ALL_SURFACES_ASYNC: - io_port = QXL_IO_DESTROY_ALL_SURFACES; -+ goto async_common; -+ case QXL_IO_FLUSH_SURFACES_ASYNC: - async_common: - async = QXL_ASYNC; - qemu_mutex_lock(&d->async_lock); -@@ -1296,6 +1305,27 @@ async_common: - } - qxl_spice_destroy_surface_wait(d, val, async); - break; -+#if SPICE_INTERFACE_QXL_MINOR >= 1 -+ case QXL_IO_FLUSH_RELEASE: { -+ QXLReleaseRing *ring = &d->ram->release_ring; -+ if (ring->prod - ring->cons + 1 == ring->num_items) { -+ fprintf(stderr, -+ "ERROR: no flush, full release ring [p%d,%dc]\n", -+ ring->prod, ring->cons); -+ } -+ qxl_push_free_res(d, 1 /* flush */); -+ dprint(d, 1, "QXL_IO_FLUSH_RELEASE exit (%s, s#=%d, res#=%d,%p)\n", -+ qxl_mode_to_string(d->mode), d->guest_surfaces.count, -+ d->num_free_res, d->last_release); -+ break; -+ } -+ case QXL_IO_FLUSH_SURFACES_ASYNC: -+ dprint(d, 1, "QXL_IO_FLUSH_SURFACES_ASYNC (%d) (%s, s#=%d, res#=%d)\n", -+ val, qxl_mode_to_string(d->mode), d->guest_surfaces.count, -+ d->num_free_res); -+ qxl_spice_flush_surfaces_async(d); -+ break; -+#endif - case QXL_IO_DESTROY_ALL_SURFACES: - d->mode = QXL_MODE_UNDEFINED; - qxl_spice_destroy_surfaces(d, async); --- -1.7.5.1 - diff --git a/0022-coroutine-switch-per-thread-free-pool-to-a-global-po.patch b/0022-coroutine-switch-per-thread-free-pool-to-a-global-po.patch new file mode 100644 index 0000000..eebdfaa --- /dev/null +++ b/0022-coroutine-switch-per-thread-free-pool-to-a-global-po.patch @@ -0,0 +1,115 @@ +From fe5c13ebf1161d0f324229cfb36cb5fb87ec6248 Mon Sep 17 00:00:00 2001 +From: Avi Kivity +Date: Mon, 5 Dec 2011 19:20:12 +0200 +Subject: [PATCH 22/25] coroutine: switch per-thread free pool to a global + pool + +ucontext-based coroutines use a free pool to reduce allocations and +deallocations of coroutine objects. The pool is per-thread, presumably +to improve locality. However, as coroutines are usually allocated in +a vcpu thread and freed in the I/O thread, the pool accounting gets +screwed up and we end allocating and freeing a coroutine for every I/O +request. This is expensive since large objects are allocated via the +kernel, and are not cached by the C runtime. + +Fix by switching to a global pool. This is safe since we're protected +by the global mutex. + +Signed-off-by: Avi Kivity +Signed-off-by: Kevin Wolf +--- + coroutine-ucontext.c | 30 ++++++++++++++++-------------- + 1 files changed, 16 insertions(+), 14 deletions(-) + +diff --git a/coroutine-ucontext.c b/coroutine-ucontext.c +index 2b8d3e9..3d01075 100644 +--- a/coroutine-ucontext.c ++++ b/coroutine-ucontext.c +@@ -35,6 +35,10 @@ enum { + POOL_MAX_SIZE = 64, + }; + ++/** Free list to speed up creation */ ++static QLIST_HEAD(, Coroutine) pool = QLIST_HEAD_INITIALIZER(pool); ++static unsigned int pool_size; ++ + typedef struct { + Coroutine base; + void *stack; +@@ -48,10 +52,6 @@ typedef struct { + /** Currently executing coroutine */ + Coroutine *current; + +- /** Free list to speed up creation */ +- QLIST_HEAD(, Coroutine) pool; +- unsigned int pool_size; +- + /** The default coroutine */ + CoroutineUContext leader; + } CoroutineThreadState; +@@ -75,7 +75,6 @@ static CoroutineThreadState *coroutine_get_thread_state(void) + if (!s) { + s = g_malloc0(sizeof(*s)); + s->current = &s->leader.base; +- QLIST_INIT(&s->pool); + pthread_setspecific(thread_state_key, s); + } + return s; +@@ -84,14 +83,19 @@ static CoroutineThreadState *coroutine_get_thread_state(void) + static void qemu_coroutine_thread_cleanup(void *opaque) + { + CoroutineThreadState *s = opaque; ++ ++ g_free(s); ++} ++ ++static void __attribute__((destructor)) coroutine_cleanup(void) ++{ + Coroutine *co; + Coroutine *tmp; + +- QLIST_FOREACH_SAFE(co, &s->pool, pool_next, tmp) { ++ QLIST_FOREACH_SAFE(co, &pool, pool_next, tmp) { + g_free(DO_UPCAST(CoroutineUContext, base, co)->stack); + g_free(co); + } +- g_free(s); + } + + static void __attribute__((constructor)) coroutine_init(void) +@@ -169,13 +173,12 @@ static Coroutine *coroutine_new(void) + + Coroutine *qemu_coroutine_new(void) + { +- CoroutineThreadState *s = coroutine_get_thread_state(); + Coroutine *co; + +- co = QLIST_FIRST(&s->pool); ++ co = QLIST_FIRST(&pool); + if (co) { + QLIST_REMOVE(co, pool_next); +- s->pool_size--; ++ pool_size--; + } else { + co = coroutine_new(); + } +@@ -184,13 +187,12 @@ Coroutine *qemu_coroutine_new(void) + + void qemu_coroutine_delete(Coroutine *co_) + { +- CoroutineThreadState *s = coroutine_get_thread_state(); + CoroutineUContext *co = DO_UPCAST(CoroutineUContext, base, co_); + +- if (s->pool_size < POOL_MAX_SIZE) { +- QLIST_INSERT_HEAD(&s->pool, &co->base, pool_next); ++ if (pool_size < POOL_MAX_SIZE) { ++ QLIST_INSERT_HEAD(&pool, &co->base, pool_next); + co->base.caller = NULL; +- s->pool_size++; ++ pool_size++; + return; + } + +-- +1.7.7.5 + diff --git a/0022-qxl-bump-pci-rev.patch b/0022-qxl-bump-pci-rev.patch deleted file mode 100644 index 17ebfc1..0000000 --- a/0022-qxl-bump-pci-rev.patch +++ /dev/null @@ -1,90 +0,0 @@ ->From 81c99528614b45f2b8407418f7e2b5742559ac19 Mon Sep 17 00:00:00 2001 -From: Gerd Hoffmann -Date: Wed, 29 Jun 2011 15:51:24 +0200 -Subject: [PATCH 22/28] qxl: bump pci rev - -Inform guest drivers about the new features I/O commands we have -now (async commands, S3 support) if building with newer spice, i.e. -if SPICE_INTERFACE_QXL_MINOR >= 1. - -sneaked in some 81+ column line spliting. - -Signed-off-by: Gerd Hoffmann -Signed-off-by: Alon Levy ---- - hw/qxl.c | 25 ++++++++++++++++++------- - hw/qxl.h | 6 ++++++ - 2 files changed, 24 insertions(+), 7 deletions(-) - -diff --git a/hw/qxl.c b/hw/qxl.c -index 847a9b8..b684608 100644 ---- a/hw/qxl.c -+++ b/hw/qxl.c -@@ -1566,9 +1566,14 @@ static int qxl_init_common(PCIQXLDevice *qxl) - pci_device_rev = QXL_REVISION_STABLE_V04; - break; - case 2: /* spice 0.6 -- qxl-2 */ -- default: - pci_device_rev = QXL_REVISION_STABLE_V06; - break; -+#if SPICE_INTERFACE_QXL_MINOR >= 1 -+ case 3: /* qxl-3 */ -+#endif -+ default: -+ pci_device_rev = QXL_DEFAULT_REVISION; -+ break; - } - - pci_set_byte(&config[PCI_REVISION_ID], pci_device_rev); -@@ -1830,9 +1835,12 @@ static PCIDeviceInfo qxl_info_primary = { - .device_id = QXL_DEVICE_ID_STABLE, - .class_id = PCI_CLASS_DISPLAY_VGA, - .qdev.props = (Property[]) { -- DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size, 64 * 1024 * 1024), -- DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram_size, 64 * 1024 * 1024), -- DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision, 2), -+ DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size, -+ 64 * 1024 * 1024), -+ DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram_size, -+ 64 * 1024 * 1024), -+ DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision, -+ QXL_DEFAULT_REVISION), - DEFINE_PROP_UINT32("debug", PCIQXLDevice, debug, 0), - DEFINE_PROP_UINT32("guestdebug", PCIQXLDevice, guestdebug, 0), - DEFINE_PROP_UINT32("cmdlog", PCIQXLDevice, cmdlog, 0), -@@ -1851,9 +1859,12 @@ static PCIDeviceInfo qxl_info_secondary = { - .device_id = QXL_DEVICE_ID_STABLE, - .class_id = PCI_CLASS_DISPLAY_OTHER, - .qdev.props = (Property[]) { -- DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size, 64 * 1024 * 1024), -- DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram_size, 64 * 1024 * 1024), -- DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision, 2), -+ DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size, -+ 64 * 1024 * 1024), -+ DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram_size, -+ 64 * 1024 * 1024), -+ DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision, -+ QXL_DEFAULT_REVISION), - DEFINE_PROP_UINT32("debug", PCIQXLDevice, debug, 0), - DEFINE_PROP_UINT32("guestdebug", PCIQXLDevice, guestdebug, 0), - DEFINE_PROP_UINT32("cmdlog", PCIQXLDevice, cmdlog, 0), -diff --git a/hw/qxl.h b/hw/qxl.h -index 1046205..4bcf7e1 100644 ---- a/hw/qxl.h -+++ b/hw/qxl.h -@@ -102,6 +102,12 @@ typedef struct PCIQXLDevice { - } \ - } while (0) - -+#if SPICE_INTERFACE_QXL_MINOR >= 1 -+#define QXL_DEFAULT_REVISION QXL_REVISION_STABLE_V10 -+#else -+#define QXL_DEFAULT_REVISION QXL_REVISION_STABLE_V06 -+#endif -+ - /* qxl.c */ - void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id); - void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg, ...); --- -1.7.5.1 - diff --git a/0023-qemu-img-rebase-Fix-for-undersized-backing-files.patch b/0023-qemu-img-rebase-Fix-for-undersized-backing-files.patch new file mode 100644 index 0000000..413ebd0 --- /dev/null +++ b/0023-qemu-img-rebase-Fix-for-undersized-backing-files.patch @@ -0,0 +1,86 @@ +From 5bb37d151b026759ee35f04212b11b4d625c7431 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 7 Dec 2011 12:42:10 +0100 +Subject: [PATCH 23/25] qemu-img rebase: Fix for undersized backing files + +Backing files may be smaller than the corresponding COW file. When +reading directly from the backing file, qemu-img rebase must consider +this and assume zero sectors after the end of backing files. + +Signed-off-by: Kevin Wolf +Reviewed-by: Stefan Hajnoczi +--- + qemu-img.c | 42 +++++++++++++++++++++++++++++++++--------- + 1 files changed, 33 insertions(+), 9 deletions(-) + +diff --git a/qemu-img.c b/qemu-img.c +index 8bdae66..01cc0d3 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -1420,6 +1420,8 @@ static int img_rebase(int argc, char **argv) + */ + if (!unsafe) { + uint64_t num_sectors; ++ uint64_t old_backing_num_sectors; ++ uint64_t new_backing_num_sectors; + uint64_t sector; + int n; + uint8_t * buf_old; +@@ -1430,6 +1432,8 @@ static int img_rebase(int argc, char **argv) + buf_new = qemu_blockalign(bs, IO_BUF_SIZE); + + bdrv_get_geometry(bs, &num_sectors); ++ bdrv_get_geometry(bs_old_backing, &old_backing_num_sectors); ++ bdrv_get_geometry(bs_new_backing, &new_backing_num_sectors); + + local_progress = (float)100 / + (num_sectors / MIN(num_sectors, IO_BUF_SIZE / 512)); +@@ -1448,16 +1452,36 @@ static int img_rebase(int argc, char **argv) + continue; + } + +- /* Read old and new backing file */ +- ret = bdrv_read(bs_old_backing, sector, buf_old, n); +- if (ret < 0) { +- error_report("error while reading from old backing file"); +- goto out; ++ /* ++ * Read old and new backing file and take into consideration that ++ * backing files may be smaller than the COW image. ++ */ ++ if (sector >= old_backing_num_sectors) { ++ memset(buf_old, 0, n * BDRV_SECTOR_SIZE); ++ } else { ++ if (sector + n > old_backing_num_sectors) { ++ n = old_backing_num_sectors - sector; ++ } ++ ++ ret = bdrv_read(bs_old_backing, sector, buf_old, n); ++ if (ret < 0) { ++ error_report("error while reading from old backing file"); ++ goto out; ++ } + } +- ret = bdrv_read(bs_new_backing, sector, buf_new, n); +- if (ret < 0) { +- error_report("error while reading from new backing file"); +- goto out; ++ ++ if (sector >= new_backing_num_sectors) { ++ memset(buf_new, 0, n * BDRV_SECTOR_SIZE); ++ } else { ++ if (sector + n > new_backing_num_sectors) { ++ n = new_backing_num_sectors - sector; ++ } ++ ++ ret = bdrv_read(bs_new_backing, sector, buf_new, n); ++ if (ret < 0) { ++ error_report("error while reading from new backing file"); ++ goto out; ++ } + } + + /* If they differ, we need to write to the COW file */ +-- +1.7.7.5 + diff --git a/0023-virtio-serial-bus-replay-guest_open-on-migration.patch b/0023-virtio-serial-bus-replay-guest_open-on-migration.patch deleted file mode 100644 index 5abb114..0000000 --- a/0023-virtio-serial-bus-replay-guest_open-on-migration.patch +++ /dev/null @@ -1,50 +0,0 @@ ->From ab57ac80b3e681a61ed34c84c36df673e6f9be33 Mon Sep 17 00:00:00 2001 -From: Alon Levy -Date: Thu, 28 Jul 2011 15:08:48 +0300 -Subject: [PATCH 23/28] virtio-serial-bus: replay guest_open on migration - -When migrating a host with with a spice agent running the mouse becomes -non operational after the migration. This is rhbz #725965. - -The problem is that after migration spice doesn't know the guest agent is open. -Spice is just a char dev here. And a chardev cannot query it's device, the -device has to let the chardev know when it is open. Right now after migration -the chardev which is recreated is in it's default state, which assumes the -guest is disconnected. - -Char devices carry no information across migration, but the virtio-serial does -already carry the guest_connected state. This patch passes that bit to the -chardev. - -Signed-off-by: Alon Levy ---- - hw/virtio-serial-bus.c | 6 ++++++ - 1 files changed, 6 insertions(+), 0 deletions(-) - -diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c -index c5eb931..4a6d932 100644 ---- a/hw/virtio-serial-bus.c -+++ b/hw/virtio-serial-bus.c -@@ -618,6 +618,7 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id) - for (i = 0; i < nr_active_ports; i++) { - uint32_t id; - bool host_connected; -+ VirtIOSerialPortInfo *info; - - id = qemu_get_be32(f); - port = find_port_by_id(s, id); -@@ -626,6 +627,11 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id) - } - - port->guest_connected = qemu_get_byte(f); -+ info = DO_UPCAST(VirtIOSerialPortInfo, qdev, port->dev.info); -+ if (port->guest_connected && info->guest_open) { -+ /* replay guest open */ -+ info->guest_open(port); -+ } - host_connected = qemu_get_byte(f); - if (host_connected != port->host_connected) { - /* --- -1.7.5.1 - diff --git a/0024-Documentation-Add-qemu-img-t-parameter-in-man-page.patch b/0024-Documentation-Add-qemu-img-t-parameter-in-man-page.patch new file mode 100644 index 0000000..6df771d --- /dev/null +++ b/0024-Documentation-Add-qemu-img-t-parameter-in-man-page.patch @@ -0,0 +1,82 @@ +From 8afe984ef7aa25cb2f8af51da021fdc8a242884d Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 7 Dec 2011 13:57:13 +0100 +Subject: [PATCH 24/25] Documentation: Add qemu-img -t parameter in man page + +Signed-off-by: Kevin Wolf +Reviewed-by: Stefan Hajnoczi +--- + qemu-img-cmds.hx | 6 +++--- + qemu-img.texi | 10 +++++++--- + 2 files changed, 10 insertions(+), 6 deletions(-) + +diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx +index 4be00a5..49dce7c 100644 +--- a/qemu-img-cmds.hx ++++ b/qemu-img-cmds.hx +@@ -24,13 +24,13 @@ ETEXI + DEF("commit", img_commit, + "commit [-f fmt] [-t cache] filename") + STEXI +-@item commit [-f @var{fmt}] @var{filename} ++@item commit [-f @var{fmt}] [-t @var{cache}] @var{filename} + ETEXI + + DEF("convert", img_convert, + "convert [-c] [-p] [-f fmt] [-t cache] [-O output_fmt] [-o options] [-s snapshot_name] [-S sparse_size] filename [filename2 [...]] output_filename") + STEXI +-@item convert [-c] [-p] [-f @var{fmt}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename} ++@item convert [-c] [-p] [-f @var{fmt}] [-t @var{cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename} + ETEXI + + DEF("info", img_info, +@@ -48,7 +48,7 @@ ETEXI + DEF("rebase", img_rebase, + "rebase [-f fmt] [-t cache] [-p] [-u] -b backing_file [-F backing_fmt] filename") + STEXI +-@item rebase [-f @var{fmt}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename} ++@item rebase [-f @var{fmt}] [-t @var{cache}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename} + ETEXI + + DEF("resize", img_resize, +diff --git a/qemu-img.texi b/qemu-img.texi +index 70fa321..b2ca3a5 100644 +--- a/qemu-img.texi ++++ b/qemu-img.texi +@@ -45,6 +45,10 @@ indicates the consecutive number of bytes that must contain only zeros + for qemu-img to create a sparse image during conversion. This value is rounded + down to the nearest 512 bytes. You may use the common size suffixes like + @code{k} for kilobytes. ++@item -t @var{cache} ++specifies the cache mode that should be used with the (destination) file. See ++the documentation of the emulator's @code{-drive cache=...} option for allowed ++values. + @end table + + Parameters to snapshot subcommand: +@@ -87,11 +91,11 @@ this case. @var{backing_file} will never be modified unless you use the + The size can also be specified using the @var{size} option with @code{-o}, + it doesn't need to be specified separately in this case. + +-@item commit [-f @var{fmt}] @var{filename} ++@item commit [-f @var{fmt}] [-t @var{cache}] @var{filename} + + Commit the changes recorded in @var{filename} in its base image. + +-@item convert [-c] [-p] [-f @var{fmt}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename} ++@item convert [-c] [-p] [-f @var{fmt}] [-t @var{cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename} + + Convert the disk image @var{filename} or a snapshot @var{snapshot_name} to disk image @var{output_filename} + using format @var{output_fmt}. It can be optionally compressed (@code{-c} +@@ -121,7 +125,7 @@ they are displayed too. + + List, apply, create or delete snapshots in image @var{filename}. + +-@item rebase [-f @var{fmt}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename} ++@item rebase [-f @var{fmt}] [-t @var{cache}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename} + + Changes the backing file of an image. Only the formats @code{qcow2} and + @code{qed} support changing the backing file. +-- +1.7.7.5 + diff --git a/0024-qemu-char-make-qemu_chr_event-public.patch b/0024-qemu-char-make-qemu_chr_event-public.patch deleted file mode 100644 index 2294597..0000000 --- a/0024-qemu-char-make-qemu_chr_event-public.patch +++ /dev/null @@ -1,42 +0,0 @@ ->From c86147be45fe6cc38efa932f9587774d626a881b Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Thu, 11 Aug 2011 12:16:11 +0200 -Subject: [PATCH 24/28] qemu-char: make qemu_chr_event public - -Make qemu_chr_event public so that it can be used by chardev code -which lives outside of qemu-char.c - -Signed-off-by: Hans de Goede ---- - qemu-char.c | 2 +- - qemu-char.h | 1 + - 2 files changed, 2 insertions(+), 1 deletions(-) - -diff --git a/qemu-char.c b/qemu-char.c -index 8d39500..5d5a6d5 100644 ---- a/qemu-char.c -+++ b/qemu-char.c -@@ -119,7 +119,7 @@ static void char_write_unblocked(void *opaque) - chr->chr_write_unblocked(chr->handler_opaque); - } - --static void qemu_chr_event(CharDriverState *s, int event) -+void qemu_chr_event(CharDriverState *s, int event) - { - /* Keep track if the char device is open */ - switch (event) { -diff --git a/qemu-char.h b/qemu-char.h -index 68e7b5b..77ad62d 100644 ---- a/qemu-char.h -+++ b/qemu-char.h -@@ -107,6 +107,7 @@ int qemu_chr_ioctl(CharDriverState *s, int cmd, void *arg); - void qemu_chr_generic_open(CharDriverState *s); - int qemu_chr_can_read(CharDriverState *s); - void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len); -+void qemu_chr_event(CharDriverState *s, int event); - int qemu_chr_get_msgfd(CharDriverState *s); - void qemu_chr_accept_input(CharDriverState *s); - int qemu_chr_add_client(CharDriverState *s, int fd); --- -1.7.5.1 - diff --git a/0025-rbd-always-set-out-parameter-in-qemu_rbd_snap_list.patch b/0025-rbd-always-set-out-parameter-in-qemu_rbd_snap_list.patch new file mode 100644 index 0000000..fb7010d --- /dev/null +++ b/0025-rbd-always-set-out-parameter-in-qemu_rbd_snap_list.patch @@ -0,0 +1,39 @@ +From e47c212cb5af148ab6d9dcf49bc0e054fe9c2e1d Mon Sep 17 00:00:00 2001 +From: Josh Durgin +Date: Tue, 6 Dec 2011 17:05:10 -0800 +Subject: [PATCH 25/25] rbd: always set out parameter in qemu_rbd_snap_list + +The caller expects psn_tab to be NULL when there are no snapshots or +an error occurs. This results in calling g_free on an invalid address. + +Reported-by: Oliver Francke +Signed-off-by: Josh Durgin +Signed-off-by: Kevin Wolf +--- + block/rbd.c | 3 ++- + 1 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/block/rbd.c b/block/rbd.c +index 9088c52..54a6961 100644 +--- a/block/rbd.c ++++ b/block/rbd.c +@@ -808,7 +808,7 @@ static int qemu_rbd_snap_list(BlockDriverState *bs, + } while (snap_count == -ERANGE); + + if (snap_count <= 0) { +- return snap_count; ++ goto done; + } + + sn_tab = g_malloc0(snap_count * sizeof(QEMUSnapshotInfo)); +@@ -827,6 +827,7 @@ static int qemu_rbd_snap_list(BlockDriverState *bs, + } + rbd_snap_list_end(snaps); + ++ done: + *psn_tab = sn_tab; + return snap_count; + } +-- +1.7.7.5 + diff --git a/0025-spice-qemu-char-Generate-chardev-open-close-events.patch b/0025-spice-qemu-char-Generate-chardev-open-close-events.patch deleted file mode 100644 index 7b4b41b..0000000 --- a/0025-spice-qemu-char-Generate-chardev-open-close-events.patch +++ /dev/null @@ -1,79 +0,0 @@ ->From d98187ff877341b5db5ca7f9d50b238d5936052b Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Thu, 21 Jul 2011 15:36:40 +0200 -Subject: [PATCH 25/28] spice-qemu-char: Generate chardev open/close events - -Define a state callback and make that generate chardev open/close events when -called by the spice-server. - -Note that for all but the newest spice-server versions (which have a fix for -this) the code ignores these events for a spicevmc with a subtype of vdagent, -this subtype specific knowledge is undesirable, but unavoidable for now, see: -http://lists.freedesktop.org/archives/spice-devel/2011-July/004837.html - -Signed-off-by: Hans de Goede ---- - spice-qemu-char.c | 35 ++++++++++++++++++++++++++++++++++- - 1 files changed, 34 insertions(+), 1 deletions(-) - -diff --git a/spice-qemu-char.c b/spice-qemu-char.c -index 2b8aec4..d55e74a 100644 ---- a/spice-qemu-char.c -+++ b/spice-qemu-char.c -@@ -89,11 +89,39 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len) - return bytes; - } - -+static void vmc_state(SpiceCharDeviceInstance *sin, int connected) -+{ -+ SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin); -+ -+#if SPICE_SERVER_VERSION < 0x000901 -+ /* -+ * spice-server calls the state callback for the agent channel when the -+ * spice client connects / disconnects. Given that not the client but -+ * the server is doing the parsing of the messages this is wrong as the -+ * server is still listening. Worse, this causes the parser in the server -+ * to go out of sync, so we ignore state calls for subtype vdagent -+ * spicevmc chardevs. For the full story see: -+ * http://lists.freedesktop.org/archives/spice-devel/2011-July/004837.html -+ */ -+ if (strcmp(sin->subtype, "vdagent") == 0) { -+ return; -+ } -+#endif -+ -+ if ((scd->chr->opened && connected) || -+ (!scd->chr->opened && !connected)) { -+ return; -+ } -+ -+ qemu_chr_event(scd->chr, connected ? CHR_EVENT_OPENED : CHR_EVENT_CLOSED); -+} -+ - static SpiceCharDeviceInterface vmc_interface = { - .base.type = SPICE_INTERFACE_CHAR_DEVICE, - .base.description = "spice virtual channel char device", - .base.major_version = SPICE_INTERFACE_CHAR_DEVICE_MAJOR, - .base.minor_version = SPICE_INTERFACE_CHAR_DEVICE_MINOR, -+ .state = vmc_state, - .write = vmc_write, - .read = vmc_read, - }; -@@ -222,7 +250,12 @@ int qemu_chr_open_spice(QemuOpts *opts, CharDriverState **_chr) - chr->chr_guest_close = spice_chr_guest_close; - s->unblock_timer = qemu_new_timer_ms(vm_clock, spice_chr_unblock, s); - -- qemu_chr_generic_open(chr); -+#if SPICE_SERVER_VERSION < 0x000901 -+ /* See comment in vmc_state() */ -+ if (strcmp(subtype, "vdagent") == 0) { -+ qemu_chr_generic_open(chr); -+ } -+#endif - - *_chr = chr; - return 0; --- -1.7.5.1 - diff --git a/0026-usb-redir-Call-qemu_chr_guest_open-close.patch b/0026-usb-redir-Call-qemu_chr_guest_open-close.patch deleted file mode 100644 index 8bb4dbf..0000000 --- a/0026-usb-redir-Call-qemu_chr_guest_open-close.patch +++ /dev/null @@ -1,37 +0,0 @@ ->From c8a865625b713ffc1cff6ff97fc3e4c01aeeb0f7 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Thu, 21 Jul 2011 16:28:06 +0200 -Subject: [PATCH 26/28] usb-redir: Call qemu_chr_guest_open/close - -To let the chardev now we're ready start receiving data. This is necessary -with the spicevmc chardev to get it registered with the spice-server. - -Signed-off-by: Hans de Goede ---- - usb-redir.c | 3 +++ - 1 files changed, 3 insertions(+), 0 deletions(-) - -diff --git a/usb-redir.c b/usb-redir.c -index 6932beb..9ce2c8b 100644 ---- a/usb-redir.c -+++ b/usb-redir.c -@@ -839,6 +839,8 @@ static int usbredir_initfn(USBDevice *udev) - /* We'll do the attach once we receive the speed from the usb-host */ - udev->auto_attach = 0; - -+ /* Let the other side know we are ready */ -+ qemu_chr_guest_open(dev->cs); - qemu_chr_add_handlers(dev->cs, &usbredir_chr_handlers, dev); - - return 0; -@@ -861,6 +863,7 @@ static void usbredir_handle_destroy(USBDevice *udev) - { - USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); - -+ qemu_chr_guest_close(dev->cs); - qemu_chr_close(dev->cs); - /* Note must be done after qemu_chr_close, as that causes a close event */ - qemu_bh_delete(dev->open_close_bh); --- -1.7.5.1 - diff --git a/0027-usb-redir-Device-disconnect-re-connect-robustness-fi.patch b/0027-usb-redir-Device-disconnect-re-connect-robustness-fi.patch deleted file mode 100644 index baf9f81..0000000 --- a/0027-usb-redir-Device-disconnect-re-connect-robustness-fi.patch +++ /dev/null @@ -1,88 +0,0 @@ ->From a6fba82709859fc91e676ce53079eb250bb55750 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Thu, 4 Aug 2011 14:41:07 +0200 -Subject: [PATCH 27/28] usb-redir: Device disconnect + re-connect robustness - fixes - -These fixes mainly target the other side sending some (error status) -packets after a disconnect packet. In some cases these would get queued -up and then reported to the controller when a new device gets connected. - -* Fully reset device state on disconnect -* Don't allow a connect message when already connected -* Ignore iso and interrupt status messages when disconnected - -Signed-off-by: Hans de Goede ---- - usb-redir.c | 22 +++++++++++++++++++++- - 1 files changed, 21 insertions(+), 1 deletions(-) - -diff --git a/usb-redir.c b/usb-redir.c -index 9ce2c8b..6d8f986 100644 ---- a/usb-redir.c -+++ b/usb-redir.c -@@ -905,6 +905,11 @@ static void usbredir_device_connect(void *priv, - { - USBRedirDevice *dev = priv; - -+ if (qemu_timer_pending(dev->attach_timer) || dev->dev.attached) { -+ ERROR("Received device connect while already connected\n"); -+ return; -+ } -+ - switch (device_connect->speed) { - case usb_redir_speed_low: - DPRINTF("attaching low speed device\n"); -@@ -933,19 +938,26 @@ static void usbredir_device_connect(void *priv, - static void usbredir_device_disconnect(void *priv) - { - USBRedirDevice *dev = priv; -+ int i; - - /* Stop any pending attaches */ - qemu_del_timer(dev->attach_timer); - - if (dev->dev.attached) { - usb_device_detach(&dev->dev); -- usbredir_cleanup_device_queues(dev); - /* - * Delay next usb device attach to give the guest a chance to see - * see the detach / attach in case of quick close / open succession - */ - dev->next_attach_time = qemu_get_clock_ms(vm_clock) + 200; - } -+ -+ /* Reset state so that the next dev connected starts with a clean slate */ -+ usbredir_cleanup_device_queues(dev); -+ memset(dev->endpoint, 0, sizeof(dev->endpoint)); -+ for (i = 0; i < MAX_ENDPOINTS; i++) { -+ QTAILQ_INIT(&dev->endpoint[i].bufpq); -+ } - } - - static void usbredir_interface_info(void *priv, -@@ -1037,6 +1049,10 @@ static void usbredir_iso_stream_status(void *priv, uint32_t id, - DPRINTF("iso status %d ep %02X id %u\n", iso_stream_status->status, - ep, id); - -+ if (!dev->dev.attached) { -+ return; -+ } -+ - dev->endpoint[EP2I(ep)].iso_error = iso_stream_status->status; - if (iso_stream_status->status == usb_redir_stall) { - DPRINTF("iso stream stopped by peer ep %02X\n", ep); -@@ -1054,6 +1070,10 @@ static void usbredir_interrupt_receiving_status(void *priv, uint32_t id, - DPRINTF("interrupt recv status %d ep %02X id %u\n", - interrupt_receiving_status->status, ep, id); - -+ if (!dev->dev.attached) { -+ return; -+ } -+ - dev->endpoint[EP2I(ep)].interrupt_error = - interrupt_receiving_status->status; - if (interrupt_receiving_status->status == usb_redir_stall) { --- -1.7.5.1 - diff --git a/0028-usb-redir-Don-t-try-to-write-to-the-chardev-after-a-.patch b/0028-usb-redir-Don-t-try-to-write-to-the-chardev-after-a-.patch deleted file mode 100644 index 18e5064..0000000 --- a/0028-usb-redir-Don-t-try-to-write-to-the-chardev-after-a-.patch +++ /dev/null @@ -1,32 +0,0 @@ ->From 7e49ff036892fade86c7734118ee0c6da5cbad09 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Thu, 11 Aug 2011 12:11:16 +0200 -Subject: [PATCH 28/28] usb-redir: Don't try to write to the chardev after a - close event - -Sicne we handle close async in a bh, do_write and thus write can get -called after receiving a close event. This patch adds a check to -the usb-redir write callback to not do a qemu_chr_write on a closed -chardev. - -Signed-off-by: Hans de Goede ---- - usb-redir.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/usb-redir.c b/usb-redir.c -index 6d8f986..732ddab 100644 ---- a/usb-redir.c -+++ b/usb-redir.c -@@ -226,7 +226,7 @@ static int usbredir_write(void *priv, uint8_t *data, int count) - USBRedirDevice *dev = priv; - int r; - -- if (dev->cs->write_blocked) { -+ if (!dev->cs->opened || dev->cs->write_blocked) { - return 0; - } - --- -1.7.5.1 - diff --git a/Fix_save-restore_of_in-kernel_i8259.patch b/Fix_save-restore_of_in-kernel_i8259.patch new file mode 100644 index 0000000..15c772f --- /dev/null +++ b/Fix_save-restore_of_in-kernel_i8259.patch @@ -0,0 +1,87 @@ +As the qemu-kvm version of the i8259 contains KVM bits, it still has to +be compiled per target. This unbreaks migration of the i8259. + +Signed-off-by: Jan Kiszka +--- + +Not sure if anyone bothers (no one should actually use qemu-kvm for +targets != x86), but let's avoid needless breakages of other targets +requiring the i8259. + + Makefile.objs | 2 +- + Makefile.target | 8 ++++---- + hw/i8259.c | 2 -- + 3 files changed, 5 insertions(+), 7 deletions(-) + +diff --git a/Makefile.objs b/Makefile.objs +index 13afd19..77237e1 100644 +--- a/Makefile.objs ++++ b/Makefile.objs +@@ -223,7 +223,7 @@ hw-obj-$(CONFIG_APPLESMC) += applesmc.o + hw-obj-$(CONFIG_SMARTCARD) += usb-ccid.o ccid-card-passthru.o + hw-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o + hw-obj-$(CONFIG_USB_REDIR) += usb-redir.o +-hw-obj-$(CONFIG_I8259) += i8259.o ++# hw-obj-$(CONFIG_I8259) += i8259.o + + # PPC devices + hw-obj-$(CONFIG_PREP_PCI) += prep_pci.o +diff --git a/Makefile.target b/Makefile.target +index 0b610ad..29eaa68 100644 +--- a/Makefile.target ++++ b/Makefile.target +@@ -236,7 +236,7 @@ obj-$(CONFIG_IVSHMEM) += ivshmem.o + + # Hardware support + obj-i386-y += vga.o +-obj-i386-y += mc146818rtc.o pc.o ++obj-i386-y += mc146818rtc.o pc.o i8259.o + obj-i386-y += cirrus_vga.o sga.o apic.o ioapic.o piix_pci.o + obj-i386-y += vmport.o + obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o +@@ -255,7 +255,7 @@ obj-i386-$(CONFIG_KVM_DEVICE_ASSIGNMENT) += device-assignment.o + obj-ppc-y = ppc.o ppc_booke.o + obj-ppc-y += vga.o + # PREP target +-obj-ppc-y += mc146818rtc.o ++obj-ppc-y += mc146818rtc.o i8259.o + obj-ppc-y += ppc_prep.o + # OldWorld PowerMac + obj-ppc-y += ppc_oldworld.o +@@ -311,7 +311,7 @@ obj-mips-y += acpi.o acpi_piix4.o + obj-mips-y += mips_addr.o mips_timer.o mips_int.o + obj-mips-y += vga.o + obj-mips-y += jazz_led.o +-obj-mips-y += gt64xxx.o mc146818rtc.o ++obj-mips-y += gt64xxx.o mc146818rtc.o i8259.o + obj-mips-y += cirrus_vga.o + obj-mips-$(CONFIG_FULONG) += bonito.o vt82c686.o mips_fulong2e.o + +@@ -392,7 +392,7 @@ obj-m68k-y += m68k-semi.o dummy_m68k.o + + obj-s390x-y = s390-virtio-bus.o s390-virtio.o + +-obj-alpha-y = mc146818rtc.o ++obj-alpha-y = mc146818rtc.o i8259.o + obj-alpha-y += vga.o cirrus_vga.o + obj-alpha-y += alpha_pci.o alpha_dp264.o alpha_typhoon.o + +diff --git a/hw/i8259.c b/hw/i8259.c +index fa63e83..a9ea9c9 100644 +--- a/hw/i8259.c ++++ b/hw/i8259.c +@@ -697,8 +697,6 @@ static int kvm_kernel_pic_load_from_user(PicState *s) + return 0; + } + +-extern void apic_set_irq_delivered(void); +- + static void kvm_i8259_set_irq(void *opaque, int irq, int level) + { + int pic_ret; +-- +1.7.3.4 +-- +To unsubscribe from this list: send the line "unsubscribe kvm" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/sources b/sources index fcf95cc..c8f2676 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -8800a7d6b3aa4a168ea7f78dc66c0320 qemu-kvm-0.15.1.tar.gz +00a825db46a70ba8ef9fc95da9cc7c1e qemu-kvm-1.0.tar.gz diff --git a/virtio-blk_refuse_SG_IO_requests_with_scsi_off.patch b/virtio-blk_refuse_SG_IO_requests_with_scsi_off.patch new file mode 100644 index 0000000..277e740 --- /dev/null +++ b/virtio-blk_refuse_SG_IO_requests_with_scsi_off.patch @@ -0,0 +1,111 @@ +From qemu-stable-bounces+jmforbes=linuxtx.org@nongnu.org Wed Jan 11 03:51:20 2012 +Return-Path: +Received: from citysiren.linuxtx.org (localhost [127.0.0.1]) + by citysiren.linuxtx.org (8.14.4/8.14.4) with ESMTP id q0B9pIjw017454 + for ; Wed, 11 Jan 2012 03:51:20 -0600 +Delivered-To: jmforbes@linuxtx.org +Received: from gmail-pop.l.google.com [74.125.81.108] + by citysiren.linuxtx.org with POP3 (fetchmail-6.3.20) + for (single-drop); Wed, 11 Jan 2012 03:51:20 -0600 (CST) +Received: by 10.180.102.100 with SMTP id fn4cs34060wib; + Wed, 11 Jan 2012 01:48:56 -0800 (PST) +Received: by 10.224.182.2 with SMTP id ca2mr28967033qab.57.1326275334564; + Wed, 11 Jan 2012 01:48:54 -0800 (PST) +Received: from lists.gnu.org (lists.gnu.org. [140.186.70.17]) + by mx.google.com with ESMTPS id gc3si782557qab.44.2012.01.11.01.48.54 + (version=TLSv1/SSLv3 cipher=OTHER); + Wed, 11 Jan 2012 01:48:54 -0800 (PST) +Received-SPF: pass (google.com: domain of qemu-stable-bounces+jmforbes=linuxtx.org@nongnu.org designates 140.186.70.17 as permitted sender) client-ip=140.186.70.17; +Authentication-Results: mx.google.com; spf=pass (google.com: domain of qemu-stable-bounces+jmforbes=linuxtx.org@nongnu.org designates 140.186.70.17 as permitted sender) smtp.mail=qemu-stable-bounces+jmforbes=linuxtx.org@nongnu.org +Received: from localhost ([::1]:48473 helo=lists.gnu.org) + by lists.gnu.org with esmtp (Exim 4.71) + (envelope-from ) + id 1Rkund-0003iT-UQ + for jmforbes@linuxtx.org; Wed, 11 Jan 2012 04:48:53 -0500 +Received: from eggs.gnu.org ([140.186.70.92]:40037) + by lists.gnu.org with esmtp (Exim 4.71) + (envelope-from ) id 1RkunV-0003fY-Vl + for qemu-stable@nongnu.org; Wed, 11 Jan 2012 04:48:53 -0500 +Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) + (envelope-from ) id 1RkunQ-0004zL-Nl + for qemu-stable@nongnu.org; Wed, 11 Jan 2012 04:48:45 -0500 +Received: from mx1.redhat.com ([209.132.183.28]:23781) + by eggs.gnu.org with esmtp (Exim 4.71) + (envelope-from ) id 1RkunQ-0004vY-3c + for qemu-stable@nongnu.org; Wed, 11 Jan 2012 04:48:40 -0500 +Received: from int-mx11.intmail.prod.int.phx2.redhat.com + (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) + by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q0B9mcYI005348 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) + for ; Wed, 11 Jan 2012 04:48:38 -0500 +Received: from yakj.usersys.redhat.com (ovpn-112-23.ams2.redhat.com + [10.36.112.23]) + by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP + id q0B9magG031084 + for ; Wed, 11 Jan 2012 04:48:37 -0500 +From: Paolo Bonzini +To: qemu-stable@nongnu.org +Date: Wed, 11 Jan 2012 10:48:33 +0100 +Message-Id: <1326275313-15635-1-git-send-email-pbonzini@redhat.com> +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 +X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) +X-Received-From: 209.132.183.28 +Subject: [Qemu-stable] [PATCH] virtio-blk: refuse SG_IO requests with + scsi=off +X-BeenThere: qemu-stable@nongnu.org +X-Mailman-Version: 2.1.14 +Precedence: list +List-Id: +List-Unsubscribe: , + +List-Archive: +List-Post: +List-Help: +List-Subscribe: , + +Errors-To: qemu-stable-bounces+jmforbes=linuxtx.org@nongnu.org +Sender: qemu-stable-bounces+jmforbes=linuxtx.org@nongnu.org +X-UID: 32 +Status: RO +Content-Length: 1003 +Lines: 38 + +QEMU does have a "scsi" option (to be used like -device +virtio-blk-pci,drive=foo,scsi=off). However, it only +masks the feature bit, and does not reject the command +if a malicious guest disregards the feature bits and +issues a request. + +Without this patch, using scsi=off does not protect you +from CVE-2011-4127. + +Signed-off-by: Paolo Bonzini +--- + hw/virtio-blk.c | 6 ++++++ + 1 files changed, 6 insertions(+), 0 deletions(-) + +diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c +index b70d116..6cd3164 100644 +--- a/hw/virtio-blk.c ++++ b/hw/virtio-blk.c +@@ -153,6 +153,12 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req) + int status; + int i; + ++ if ((req->dev->vdev.guest_features & (1 << VIRTIO_BLK_F_SCSI)) == 0) { ++ virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP); ++ g_free(req); ++ return; ++ } ++ + /* + * We require at least one output segment each for the virtio_blk_outhdr + * and the SCSI command block. +-- +1.7.7.1 + + + + + +