diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2017-01-30 10:23:20 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2017-01-30 10:23:20 +0000 |
commit | a0def594286d9110a6035e02eef558cf3cf5d847 (patch) | |
tree | 32275a1bfdd6c17682788f2b2e018a15c3b30214 /hw | |
parent | 3aca12f841fcd6f3a7477076dad0d564360500de (diff) | |
parent | 6da67de6803e93cbb7e93ac3497865832f8c00ea (diff) |
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
* SCSI max_transfer support for scsi-generic (Eric)
* x86 SMI broadcast (Laszlo)
* Character device QOMification (Marc-André)
* Record/replay improvements (Pavel)
* iscsi fixes (Peter L.)
* "info mtree -f" command (Peter Xu)
* TSC clock rate reporting (Phil)
* DEVICE_CATEGORY_CPU (Thomas)
* Memory sign-extension fix (Ladi)
# gpg: Signature made Fri 27 Jan 2017 17:08:51 GMT
# gpg: using RSA key 0xBFFBD25F78C7AE83
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>"
# gpg: aka "Paolo Bonzini <pbonzini@redhat.com>"
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1
# Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83
* remotes/bonzini/tags/for-upstream: (41 commits)
memory: don't sign-extend 32-bit writes
chardev: qom-ify
vc: use a common prefix for chr callbacks
baum: use a common prefix for chr callbacks
gtk: overwrite the console.c char driver
char: use error_report()
spice-char: improve error reporting
char: rename TCPChardev and NetChardev
char: rename CharDriverState Chardev
bt: use qemu_chr_alloc()
char: allocate CharDriverState as a single object
char: use a feature bit for replay
char: introduce generic qemu_chr_get_kind()
char: fold single-user functions in caller
char: move callbacks in CharDriver
char: use a static array for backends
char: use a const CharDriver
doc: fix spelling
char: add qemu_chr_fe_add_watch() Returns description
qemu-options: stdio is available on win32
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
38 files changed, 240 insertions, 64 deletions
diff --git a/hw/arm/fsl-imx25.c b/hw/arm/fsl-imx25.c index 7bb7be76b6..2126f73ca0 100644 --- a/hw/arm/fsl-imx25.c +++ b/hw/arm/fsl-imx25.c @@ -118,7 +118,7 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp) }; if (i < MAX_SERIAL_PORTS) { - CharDriverState *chr; + Chardev *chr; chr = serial_hds[i]; diff --git a/hw/arm/fsl-imx31.c b/hw/arm/fsl-imx31.c index f23672b222..dd1c713ae3 100644 --- a/hw/arm/fsl-imx31.c +++ b/hw/arm/fsl-imx31.c @@ -107,7 +107,7 @@ static void fsl_imx31_realize(DeviceState *dev, Error **errp) }; if (i < MAX_SERIAL_PORTS) { - CharDriverState *chr; + Chardev *chr; chr = serial_hds[i]; diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c index e93532fb57..76dd8a48ca 100644 --- a/hw/arm/fsl-imx6.c +++ b/hw/arm/fsl-imx6.c @@ -187,7 +187,7 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp) }; if (i < MAX_SERIAL_PORTS) { - CharDriverState *chr; + Chardev *chr; chr = serial_hds[i]; diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c index c86cf80514..503a3b6d24 100644 --- a/hw/arm/nseries.c +++ b/hw/arm/nseries.c @@ -786,7 +786,7 @@ static void n8x0_cbus_setup(struct n800_s *s) static void n8x0_uart_setup(struct n800_s *s) { - CharDriverState *radio = uart_hci_init(); + Chardev *radio = uart_hci_init(); qdev_connect_gpio_out(s->mpu->gpio, N8X0_BT_RESET_GPIO, csrhci_pins_get(radio)[csrhci_pin_reset]); diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c index 6f05c98d3e..cf1b4ba58f 100644 --- a/hw/arm/omap2.c +++ b/hw/arm/omap2.c @@ -792,7 +792,7 @@ static const MemoryRegionOps omap_sti_fifo_ops = { static struct omap_sti_s *omap_sti_init(struct omap_target_agent_s *ta, MemoryRegion *sysmem, hwaddr channel_base, qemu_irq irq, omap_clk clk, - CharDriverState *chr) + Chardev *chr) { struct omap_sti_s *s = g_new0(struct omap_sti_s, 1); diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c index d31b4577f0..cfee3929d9 100644 --- a/hw/arm/pxa2xx.c +++ b/hw/arm/pxa2xx.c @@ -2024,7 +2024,7 @@ static PXA2xxFIrState *pxa2xx_fir_init(MemoryRegion *sysmem, hwaddr base, qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma, - CharDriverState *chr) + Chardev *chr) { DeviceState *dev; SysBusDevice *sbd; diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 6c9e8985bf..1f216cf3b1 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -613,7 +613,7 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic) } static void create_uart(const VirtMachineState *vms, qemu_irq *pic, int uart, - MemoryRegion *mem, CharDriverState *chr) + MemoryRegion *mem, Chardev *chr) { char *nodename; hwaddr base = vms->memmap[uart].base; diff --git a/hw/bt/hci-csr.c b/hw/bt/hci-csr.c index fbb3109cc1..3c193848fc 100644 --- a/hw/bt/hci-csr.c +++ b/hw/bt/hci-csr.c @@ -26,13 +26,14 @@ #include "hw/irq.h" #include "sysemu/bt.h" #include "hw/bt.h" +#include "qapi/error.h" struct csrhci_s { + Chardev parent; int enable; qemu_irq *pins; int pin_state; int modem_state; - CharDriverState chr; #define FIFO_LEN 4096 int out_start; int out_len; @@ -54,6 +55,9 @@ struct csrhci_s { struct HCIInfo *hci; }; +#define TYPE_CHARDEV_HCI "chardev-hci" +#define HCI_CHARDEV(obj) OBJECT_CHECK(struct csrhci_s, (obj), TYPE_CHARDEV_HCI) + /* H4+ packet types */ enum { H4_CMD_PKT = 1, @@ -78,7 +82,8 @@ enum { static inline void csrhci_fifo_wake(struct csrhci_s *s) { - CharBackend *be = s->chr.be; + Chardev *chr = (Chardev *)s; + CharBackend *be = chr->be; if (!s->enable || !s->out_len) return; @@ -311,10 +316,10 @@ static void csrhci_ready_for_next_inpkt(struct csrhci_s *s) s->in_hdr = INT_MAX; } -static int csrhci_write(struct CharDriverState *chr, +static int csrhci_write(struct Chardev *chr, const uint8_t *buf, int len) { - struct csrhci_s *s = (struct csrhci_s *) chr->opaque; + struct csrhci_s *s = (struct csrhci_s *)chr; int total = 0; if (!s->enable) @@ -384,10 +389,10 @@ static void csrhci_out_hci_packet_acl(void *opaque, csrhci_fifo_wake(s); } -static int csrhci_ioctl(struct CharDriverState *chr, int cmd, void *arg) +static int csrhci_ioctl(struct Chardev *chr, int cmd, void *arg) { QEMUSerialSetParams *ssp; - struct csrhci_s *s = (struct csrhci_s *) chr->opaque; + struct csrhci_s *s = (struct csrhci_s *) chr; int prev_state = s->modem_state; switch (cmd) { @@ -453,21 +458,19 @@ static void csrhci_pins(void *opaque, int line, int level) } } -qemu_irq *csrhci_pins_get(CharDriverState *chr) +qemu_irq *csrhci_pins_get(Chardev *chr) { - struct csrhci_s *s = (struct csrhci_s *) chr->opaque; + struct csrhci_s *s = (struct csrhci_s *) chr; return s->pins; } -CharDriverState *uart_hci_init(void) +static void csrhci_open(Chardev *chr, + ChardevBackend *backend, + bool *be_opened, + Error **errp) { - struct csrhci_s *s = (struct csrhci_s *) - g_malloc0(sizeof(struct csrhci_s)); - - s->chr.opaque = s; - s->chr.chr_write = csrhci_write; - s->chr.chr_ioctl = csrhci_ioctl; + struct csrhci_s *s = HCI_CHARDEV(chr); s->hci = qemu_next_hci(); s->hci->opaque = s; @@ -477,6 +480,35 @@ CharDriverState *uart_hci_init(void) s->out_tm = timer_new_ns(QEMU_CLOCK_VIRTUAL, csrhci_out_tick, s); s->pins = qemu_allocate_irqs(csrhci_pins, s, __csrhci_pins); csrhci_reset(s); + *be_opened = false; +} + +static void char_hci_class_init(ObjectClass *oc, void *data) +{ + ChardevClass *cc = CHARDEV_CLASS(oc); + + cc->internal = true; + cc->open = csrhci_open; + cc->chr_write = csrhci_write; + cc->chr_ioctl = csrhci_ioctl; +} - return &s->chr; +static const TypeInfo char_hci_type_info = { + .name = TYPE_CHARDEV_HCI, + .parent = TYPE_CHARDEV, + .instance_size = sizeof(struct csrhci_s), + .class_init = char_hci_class_init, +}; + +Chardev *uart_hci_init(void) +{ + return qemu_chardev_new(NULL, TYPE_CHARDEV_HCI, + NULL, &error_abort); } + +static void register_types(void) +{ + type_register_static(&char_hci_type_info); +} + +type_init(register_types); diff --git a/hw/char/escc.c b/hw/char/escc.c index d6662dc77d..9228091cec 100644 --- a/hw/char/escc.c +++ b/hw/char/escc.c @@ -689,7 +689,7 @@ static const VMStateDescription vmstate_escc = { }; MemoryRegion *escc_init(hwaddr base, qemu_irq irqA, qemu_irq irqB, - CharDriverState *chrA, CharDriverState *chrB, + Chardev *chrA, Chardev *chrB, int clock, int it_shift) { DeviceState *dev; diff --git a/hw/char/exynos4210_uart.c b/hw/char/exynos4210_uart.c index 0cd3dd3958..7c16e894e2 100644 --- a/hw/char/exynos4210_uart.c +++ b/hw/char/exynos4210_uart.c @@ -582,7 +582,7 @@ static const VMStateDescription vmstate_exynos4210_uart = { DeviceState *exynos4210_uart_create(hwaddr addr, int fifo_size, int channel, - CharDriverState *chr, + Chardev *chr, qemu_irq irq) { DeviceState *dev; diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c index 99545fc359..52e67f8dc9 100644 --- a/hw/char/imx_serial.c +++ b/hw/char/imx_serial.c @@ -170,7 +170,7 @@ static void imx_serial_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { IMXSerialState *s = (IMXSerialState *)opaque; - CharDriverState *chr = qemu_chr_fe_get_driver(&s->chr); + Chardev *chr = qemu_chr_fe_get_driver(&s->chr); unsigned char ch; DPRINTF("write(offset=0x%" HWADDR_PRIx ", value = 0x%x) to %s\n", diff --git a/hw/char/mcf_uart.c b/hw/char/mcf_uart.c index ecaa091190..80c380e077 100644 --- a/hw/char/mcf_uart.c +++ b/hw/char/mcf_uart.c @@ -275,7 +275,7 @@ static void mcf_uart_receive(void *opaque, const uint8_t *buf, int size) mcf_uart_push_byte(s, buf[0]); } -void *mcf_uart_init(qemu_irq irq, CharDriverState *chr) +void *mcf_uart_init(qemu_irq irq, Chardev *chr) { mcf_uart_state *s; @@ -300,7 +300,7 @@ static const MemoryRegionOps mcf_uart_ops = { void mcf_uart_mm_init(MemoryRegion *sysmem, hwaddr base, qemu_irq irq, - CharDriverState *chr) + Chardev *chr) { mcf_uart_state *s; diff --git a/hw/char/omap_uart.c b/hw/char/omap_uart.c index 893ab108bc..31ebb1592c 100644 --- a/hw/char/omap_uart.c +++ b/hw/char/omap_uart.c @@ -54,7 +54,7 @@ void omap_uart_reset(struct omap_uart_s *s) struct omap_uart_s *omap_uart_init(hwaddr base, qemu_irq irq, omap_clk fclk, omap_clk iclk, qemu_irq txdma, qemu_irq rxdma, - const char *label, CharDriverState *chr) + const char *label, Chardev *chr) { struct omap_uart_s *s = g_new0(struct omap_uart_s, 1); @@ -163,7 +163,7 @@ struct omap_uart_s *omap2_uart_init(MemoryRegion *sysmem, struct omap_target_agent_s *ta, qemu_irq irq, omap_clk fclk, omap_clk iclk, qemu_irq txdma, qemu_irq rxdma, - const char *label, CharDriverState *chr) + const char *label, Chardev *chr) { hwaddr base = omap_l4_attach(ta, 0, NULL); struct omap_uart_s *s = omap_uart_init(base, irq, @@ -178,7 +178,7 @@ struct omap_uart_s *omap2_uart_init(MemoryRegion *sysmem, return s; } -void omap_uart_attach(struct omap_uart_s *s, CharDriverState *chr) +void omap_uart_attach(struct omap_uart_s *s, Chardev *chr) { /* TODO: Should reuse or destroy current s->serial */ s->serial = serial_mm_init(get_system_memory(), s->base, 2, s->irq, diff --git a/hw/char/parallel.c b/hw/char/parallel.c index f2d56666b7..c71a4a0f4f 100644 --- a/hw/char/parallel.c +++ b/hw/char/parallel.c @@ -603,7 +603,7 @@ static const MemoryRegionOps parallel_mm_ops = { /* If fd is zero, it means that the parallel device uses the console */ bool parallel_mm_init(MemoryRegion *address_space, hwaddr base, int it_shift, qemu_irq irq, - CharDriverState *chr) + Chardev *chr) { ParallelState *s; diff --git a/hw/char/serial-isa.c b/hw/char/serial-isa.c index 54d3a12f51..d7c5cc11fe 100644 --- a/hw/char/serial-isa.c +++ b/hw/char/serial-isa.c @@ -121,7 +121,7 @@ static void serial_register_types(void) type_init(serial_register_types) -static void serial_isa_init(ISABus *bus, int index, CharDriverState *chr) +static void serial_isa_init(ISABus *bus, int index, Chardev *chr) { DeviceState *dev; ISADevice *isadev; diff --git a/hw/char/serial.c b/hw/char/serial.c index 67b18eda12..03d890ca24 100644 --- a/hw/char/serial.c +++ b/hw/char/serial.c @@ -937,7 +937,7 @@ const MemoryRegionOps serial_io_ops = { }; SerialState *serial_init(int base, qemu_irq irq, int baudbase, - CharDriverState *chr, MemoryRegion *system_io) + Chardev *chr, MemoryRegion *system_io) { SerialState *s; @@ -993,7 +993,7 @@ static const MemoryRegionOps serial_mm_ops[3] = { SerialState *serial_mm_init(MemoryRegion *address_space, hwaddr base, int it_shift, qemu_irq irq, int baudbase, - CharDriverState *chr, enum device_endian end) + Chardev *chr, enum device_endian end) { SerialState *s; diff --git a/hw/char/sh_serial.c b/hw/char/sh_serial.c index 9d35564bcf..303eb0a678 100644 --- a/hw/char/sh_serial.c +++ b/hw/char/sh_serial.c @@ -356,7 +356,7 @@ static const MemoryRegionOps sh_serial_ops = { void sh_serial_init(MemoryRegion *sysmem, hwaddr base, int feat, - uint32_t freq, CharDriverState *chr, + uint32_t freq, Chardev *chr, qemu_irq eri_source, qemu_irq rxi_source, qemu_irq txi_source, diff --git a/hw/char/spapr_vty.c b/hw/char/spapr_vty.c index 7c22b8bd0e..e30c8da57c 100644 --- a/hw/char/spapr_vty.c +++ b/hw/char/spapr_vty.c @@ -141,7 +141,7 @@ static target_ulong h_get_term_char(PowerPCCPU *cpu, sPAPRMachineState *spapr, return H_SUCCESS; } -void spapr_vty_create(VIOsPAPRBus *bus, CharDriverState *chardev) +void spapr_vty_create(VIOsPAPRBus *bus, Chardev *chardev) { DeviceState *dev; diff --git a/hw/char/virtio-console.c b/hw/char/virtio-console.c index 776205b4a9..798d9b69fd 100644 --- a/hw/char/virtio-console.c +++ b/hw/char/virtio-console.c @@ -168,7 +168,7 @@ static void virtconsole_realize(DeviceState *dev, Error **errp) VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev); VirtConsole *vcon = VIRTIO_CONSOLE(dev); VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(dev); - CharDriverState *chr = qemu_chr_fe_get_driver(&vcon->chr); + Chardev *chr = qemu_chr_fe_get_driver(&vcon->chr); if (port->id == 0 && !k->is_console) { error_setg(errp, "Port number 0 on virtio-serial devices reserved " diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index 1b7ea50e9f..94f4d8bde4 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -179,7 +179,7 @@ static void set_chr(Object *obj, Visitor *v, const char *name, void *opaque, Error *local_err = NULL; Property *prop = opaque; CharBackend *be = qdev_get_prop_ptr(dev, prop); - CharDriverState *s; + Chardev *s; char *str; if (dev->realized) { @@ -411,7 +411,7 @@ void qdev_prop_set_drive(DeviceState *dev, const char *name, } void qdev_prop_set_chr(DeviceState *dev, const char *name, - CharDriverState *value) + Chardev *value) { assert(!value || value->label); object_property_set_str(OBJECT(dev), diff --git a/hw/cpu/core.c b/hw/cpu/core.c index eff90c12be..2bf960d6a8 100644 --- a/hw/cpu/core.c +++ b/hw/cpu/core.c @@ -72,10 +72,18 @@ static void cpu_core_instance_init(Object *obj) core->nr_threads = smp_threads; } +static void cpu_core_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + set_bit(DEVICE_CATEGORY_CPU, dc->categories); +} + static const TypeInfo cpu_core_type_info = { .name = TYPE_CPU_CORE, .parent = TYPE_DEVICE, .abstract = true, + .class_init = cpu_core_class_init, .instance_size = sizeof(CPUCore), .instance_init = cpu_core_instance_init, }; diff --git a/hw/display/milkymist-tmu2.c b/hw/display/milkymist-tmu2.c index 920374b985..7528665510 100644 --- a/hw/display/milkymist-tmu2.c +++ b/hw/display/milkymist-tmu2.c @@ -85,7 +85,7 @@ struct MilkymistTMU2State { SysBusDevice parent_obj; MemoryRegion regs_region; - CharDriverState *chr; + Chardev *chr; qemu_irq irq; uint32_t regs[R_MAX]; diff --git a/hw/display/sm501.c b/hw/display/sm501.c index 5f71012108..040a0b93f2 100644 --- a/hw/display/sm501.c +++ b/hw/display/sm501.c @@ -1392,7 +1392,7 @@ static const GraphicHwOps sm501_ops = { }; void sm501_init(MemoryRegion *address_space_mem, uint32_t base, - uint32_t local_mem_bytes, qemu_irq irq, CharDriverState *chr) + uint32_t local_mem_bytes, qemu_irq irq, Chardev *chr) { SM501State * s; DeviceState *dev; diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c index 702e281dc8..7135633863 100644 --- a/hw/i386/kvmvapic.c +++ b/hw/i386/kvmvapic.c @@ -413,6 +413,12 @@ static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip) if (!kvm_enabled()) { cpu_get_tb_cpu_state(env, ¤t_pc, ¤t_cs_base, ¤t_flags); + /* Account this instruction, because we will exit the tb. + This is the first instruction in the block. Therefore + there is no need in restoring CPU state. */ + if (use_icount) { + --cs->icount_decr.u16.low; + } } pause_all_vcpus(); diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c index 3945dfd7b9..17df24c9d0 100644 --- a/hw/intc/apic_common.c +++ b/hw/intc/apic_common.c @@ -385,6 +385,25 @@ static bool apic_common_sipi_needed(void *opaque) return s->wait_for_sipi != 0; } +static bool apic_irq_delivered_needed(void *opaque) +{ + APICCommonState *s = APIC_COMMON(opaque); + return s->cpu == X86_CPU(first_cpu) && apic_irq_delivered != 0; +} + +static void apic_irq_delivered_pre_save(void *opaque) +{ + APICCommonState *s = APIC_COMMON(opaque); + s->apic_irq_delivered = apic_irq_delivered; +} + +static int apic_irq_delivered_post_load(void *opaque, int version_id) +{ + APICCommonState *s = APIC_COMMON(opaque); + apic_irq_delivered = s->apic_irq_delivered; + return 0; +} + static const VMStateDescription vmstate_apic_common_sipi = { .name = "apic_sipi", .version_id = 1, @@ -397,6 +416,19 @@ static const VMStateDescription vmstate_apic_common_sipi = { } }; +static const VMStateDescription vmstate_apic_irq_delivered = { + .name = "apic_irq_delivered", + .version_id = 1, + .minimum_version_id = 1, + .needed = apic_irq_delivered_needed, + .pre_save = apic_irq_delivered_pre_save, + .post_load = apic_irq_delivered_post_load, + .fields = (VMStateField[]) { + VMSTATE_INT32(apic_irq_delivered, APICCommonState), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_apic_common = { .name = "apic", .version_id = 3, @@ -431,6 +463,7 @@ static const VMStateDescription vmstate_apic_common = { }, .subsections = (const VMStateDescription*[]) { &vmstate_apic_common_sipi, + &vmstate_apic_irq_delivered, NULL } }; diff --git a/hw/isa/isa-bus.c b/hw/isa/isa-bus.c index 0ffbc8dd28..348e0eab9d 100644 --- a/hw/isa/isa-bus.c +++ b/hw/isa/isa-bus.c @@ -288,7 +288,7 @@ MemoryRegion *isa_address_space_io(ISADevice *dev) type_init(isabus_register_types) -static void parallel_init(ISABus *bus, int index, CharDriverState *chr) +static void parallel_init(ISABus *bus, int index, Chardev *chr) { DeviceState *dev; ISADevice *isadev; diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c index 10d1ee8b93..59930dd9d0 100644 --- a/hw/isa/lpc_ich9.c +++ b/hw/isa/lpc_ich9.c @@ -48,6 +48,8 @@ #include "exec/address-spaces.h" #include "sysemu/sysemu.h" #include "qom/cpu.h" +#include "hw/nvram/fw_cfg.h" +#include "qemu/cutils.h" /*****************************************************************************/ /* ICH9 LPC PCI to ISA bridge */ @@ -360,13 +362,62 @@ static void ich9_set_sci(void *opaque, int irq_num, int level) } } +static void smi_features_ok_callback(void *opaque) +{ + ICH9LPCState *lpc = opaque; + uint64_t guest_features; + + if (lpc->smi_features_ok) { + /* negotiation already complete, features locked */ + return; + } + + memcpy(&guest_features, lpc->smi_guest_features_le, sizeof guest_features); + le64_to_cpus(&guest_features); + if (guest_features & ~lpc->smi_host_features) { + /* guest requests invalid features, leave @features_ok at zero */ + return; + } + + /* valid feature subset requested, lock it down, report success */ + lpc->smi_negotiated_features = guest_features; + lpc->smi_features_ok = 1; +} + void ich9_lpc_pm_init(PCIDevice *lpc_pci, bool smm_enabled) { ICH9LPCState *lpc = ICH9_LPC_DEVICE(lpc_pci); qemu_irq sci_irq; + FWCfgState *fw_cfg = fw_cfg_find(); sci_irq = qemu_allocate_irq(ich9_set_sci, lpc, 0); ich9_pm_init(lpc_pci, &lpc->pm, smm_enabled, sci_irq); + + if (lpc->smi_host_features && fw_cfg) { + uint64_t host_features_le; + + host_features_le = cpu_to_le64(lpc->smi_host_features); + memcpy(lpc->smi_host_features_le, &host_features_le, + sizeof host_features_le); + fw_cfg_add_file(fw_cfg, "etc/smi/supported-features", + lpc->smi_host_features_le, + sizeof lpc->smi_host_features_le); + + /* The other two guest-visible fields are cleared on device reset, we + * just link them into fw_cfg here. + */ + fw_cfg_add_file_callback(fw_cfg, "etc/smi/requested-features", + NULL, NULL, + lpc->smi_guest_features_le, + sizeof lpc->smi_guest_features_le, + false); + fw_cfg_add_file_callback(fw_cfg, "etc/smi/features-ok", + smi_features_ok_callback, lpc, + &lpc->smi_features_ok, + sizeof lpc->smi_features_ok, + true); + } + ich9_lpc_reset(&lpc->d.qdev); } @@ -386,7 +437,15 @@ static void ich9_apm_ctrl_changed(uint32_t val, void *arg) /* SMI_EN = PMBASE + 30. SMI control and enable register */ if (lpc->pm.smi_en & ICH9_PMIO_SMI_EN_APMC_EN) { - cpu_interrupt(current_cpu, CPU_INTERRUPT_SMI); + if (lpc->smi_negotiated_features & + (UINT64_C(1) << ICH9_LPC_SMI_F_BROADCAST_BIT)) { + CPUState *cs; + CPU_FOREACH(cs) { + cpu_interrupt(cs, CPU_INTERRUPT_SMI); + } + } else { + cpu_interrupt(current_cpu, CPU_INTERRUPT_SMI); + } } } @@ -507,6 +566,10 @@ static void ich9_lpc_reset(DeviceState *qdev) lpc->sci_level = 0; lpc->rst_cnt = 0; + + memset(lpc->smi_guest_features_le, 0, sizeof lpc->smi_guest_features_le); + lpc->smi_features_ok = 0; + lpc->smi_negotiated_features = 0; } /* root complex register block is mapped into memory space */ @@ -668,6 +731,29 @@ static const VMStateDescription vmstate_ich9_rst_cnt = { } }; +static bool ich9_smi_feat_needed(void *opaque) +{ + ICH9LPCState *lpc = opaque; + + return !buffer_is_zero(lpc->smi_guest_features_le, + sizeof lpc->smi_guest_features_le) || + lpc->smi_features_ok; +} + +static const VMStateDescription vmstate_ich9_smi_feat = { + .name = "ICH9LPC/smi_feat", + .version_id = 1, + .minimum_version_id = 1, + .needed = ich9_smi_feat_needed, + .fields = (VMStateField[]) { + VMSTATE_UINT8_ARRAY(smi_guest_features_le, ICH9LPCState, + sizeof(uint64_t)), + VMSTATE_UINT8(smi_features_ok, ICH9LPCState), + VMSTATE_UINT64(smi_negotiated_features, ICH9LPCState), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_ich9_lpc = { .name = "ICH9LPC", .version_id = 1, @@ -683,12 +769,15 @@ static const VMStateDescription vmstate_ich9_lpc = { }, .subsections = (const VMStateDescription*[]) { &vmstate_ich9_rst_cnt, + &vmstate_ich9_smi_feat, NULL } }; static Property ich9_lpc_properties[] = { DEFINE_PROP_BOOL("noreboot", ICH9LPCState, pin_strap.spkr_hi, true), + DEFINE_PROP_BIT64("x-smi-broadcast", ICH9LPCState, smi_host_features, + ICH9_LPC_SMI_F_BROADCAST_BIT, true), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/isa/pc87312.c b/hw/isa/pc87312.c index b1c1a0acb1..c707d24db4 100644 --- a/hw/isa/pc87312.c +++ b/hw/isa/pc87312.c @@ -268,7 +268,7 @@ static void pc87312_realize(DeviceState *dev, Error **errp) DeviceState *d; ISADevice *isa; ISABus *bus; - CharDriverState *chr; + Chardev *chr; DriveInfo *drive; char name[5]; int i; diff --git a/hw/lm32/lm32.h b/hw/lm32/lm32.h index db9eb29ea4..d1514a61b3 100644 --- a/hw/lm32/lm32.h +++ b/hw/lm32/lm32.h @@ -16,7 +16,7 @@ static inline DeviceState *lm32_pic_init(qemu_irq cpu_irq) return dev; } -static inline DeviceState *lm32_juart_init(CharDriverState *chr) +static inline DeviceState *lm32_juart_init(Chardev *chr) { DeviceState *dev; @@ -29,7 +29,7 @@ static inline DeviceState *lm32_juart_init(CharDriverState *chr) static inline DeviceState *lm32_uart_create(hwaddr addr, qemu_irq irq, - CharDriverState *chr) + Chardev *chr) { DeviceState *dev; SysBusDevice *s; diff --git a/hw/lm32/milkymist-hw.h b/hw/lm32/milkymist-hw.h index 4418b44ca9..d3be0cfb3a 100644 --- a/hw/lm32/milkymist-hw.h +++ b/hw/lm32/milkymist-hw.h @@ -6,7 +6,7 @@ static inline DeviceState *milkymist_uart_create(hwaddr base, qemu_irq irq, - CharDriverState *chr) + Chardev *chr) { DeviceState *dev; diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index cf48f420cc..75877de11c 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -551,10 +551,10 @@ static void malta_fgpa_display_event(void *opaque, int event) } static MaltaFPGAState *malta_fpga_init(MemoryRegion *address_space, - hwaddr base, qemu_irq uart_irq, CharDriverState *uart_chr) + hwaddr base, qemu_irq uart_irq, Chardev *uart_chr) { MaltaFPGAState *s; - CharDriverState *chr; + Chardev *chr; s = (MaltaFPGAState *)g_malloc0(sizeof(MaltaFPGAState)); diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c index fd14d7a07e..846e903eb2 100644 --- a/hw/misc/ivshmem.c +++ b/hw/misc/ivshmem.c @@ -869,7 +869,7 @@ static void ivshmem_common_realize(PCIDevice *dev, Error **errp) s->ivshmem_bar2 = host_memory_backend_get_memory(s->hostmem, &error_abort); } else { - CharDriverState *chr = qemu_chr_fe_get_driver(&s->server_chr); + Chardev *chr = qemu_chr_fe_get_driver(&s->server_chr); assert(chr); IVSHMEM_DPRINTF("using shared memory server (socket = %s)\n", diff --git a/hw/misc/milkymist-pfpu.c b/hw/misc/milkymist-pfpu.c index 3ca25894f1..86f5e383b0 100644 --- a/hw/misc/milkymist-pfpu.c +++ b/hw/misc/milkymist-pfpu.c @@ -125,7 +125,7 @@ struct MilkymistPFPUState { SysBusDevice parent_obj; MemoryRegion regs_region; - CharDriverState *chr; + Chardev *chr; qemu_irq irq; uint32_t regs[R_MAX]; diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c index 7a588a7ad4..92f091a613 100644 --- a/hw/scsi/scsi-generic.c +++ b/hw/scsi/scsi-generic.c @@ -246,7 +246,7 @@ static void scsi_read_data(SCSIRequest *req) SCSIDevice *s = r->req.dev; int ret; - DPRINTF("scsi_read_data 0x%x\n", req->tag); + DPRINTF("scsi_read_data tag=0x%x\n", req->tag); /* The request is used as the AIO opaque value, so add a ref. */ scsi_req_ref(&r->req); @@ -294,7 +294,7 @@ static void scsi_write_data(SCSIRequest *req) SCSIDevice *s = r->req.dev; int ret; - DPRINTF("scsi_write_data 0x%x\n", req->tag); + DPRINTF("scsi_write_data tag=0x%x\n", req->tag); if (r->len == 0) { r->len = r->buflen; scsi_req_data(&r->req, r->len); @@ -329,6 +329,7 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd) int ret; #ifdef DEBUG_SCSI + DPRINTF("Command: data=0x%02x", cmd[0]); { int i; for (i = 1; i < r->req.cmd.len; i++) { diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c index 637f8722a7..4165450250 100644 --- a/hw/timer/mc146818rtc.c +++ b/hw/timer/mc146818rtc.c @@ -27,6 +27,7 @@ #include "hw/hw.h" #include "qemu/timer.h" #include "sysemu/sysemu.h" +#include "sysemu/replay.h" #include "hw/timer/mc146818rtc.h" #include "qapi/visitor.h" #include "qapi-event.h" @@ -734,10 +735,16 @@ static int rtc_post_load(void *opaque, int version_id) check_update_timer(s); } - uint64_t now = qemu_clock_get_ns(rtc_clock); - if (now < s->next_periodic_time || - now > (s->next_periodic_time + get_max_clock_jump())) { - periodic_timer_update(s, qemu_clock_get_ns(rtc_clock)); + /* The periodic timer is deterministic in record/replay mode, + * so there is no need to update it after loading the vmstate. + * Reading RTC here would misalign record and replay. + */ + if (replay_mode == REPLAY_MODE_NONE) { + uint64_t now = qemu_clock_get_ns(rtc_clock); + if (now < s->next_periodic_time || + now > (s->next_periodic_time + get_max_clock_jump())) { + periodic_timer_update(s, qemu_clock_get_ns(rtc_clock)); + } } #ifdef TARGET_I386 diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c index 88cb6d8978..daab0d56cf 100644 --- a/hw/usb/ccid-card-passthru.c +++ b/hw/usb/ccid-card-passthru.c @@ -264,7 +264,7 @@ static void ccid_card_vscard_handle_message(PassthruState *card, static void ccid_card_vscard_drop_connection(PassthruState *card) { - CharDriverState *chr = qemu_chr_fe_get_driver(&card->cs); + Chardev *chr = qemu_chr_fe_get_driver(&card->cs); qemu_chr_fe_deinit(&card->cs); qemu_chr_delete(chr); diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c index 6066d9b0f7..6d5137383b 100644 --- a/hw/usb/dev-serial.c +++ b/hw/usb/dev-serial.c @@ -483,7 +483,7 @@ static void usb_serial_realize(USBDevice *dev, Error **errp) { USBSerialState *s = USB_SERIAL_DEV(dev); Error *local_err = NULL; - CharDriverState *chr = qemu_chr_fe_get_driver(&s->cs); + Chardev *chr = qemu_chr_fe_get_driver(&s->cs); usb_desc_create_serial(dev); usb_desc_init(dev); @@ -512,7 +512,7 @@ static void usb_serial_realize(USBDevice *dev, Error **errp) static USBDevice *usb_serial_init(USBBus *bus, const char *filename) { USBDevice *dev; - CharDriverState *cdrv; + Chardev *cdrv; uint32_t vendorid = 0, productid = 0; char label[32]; static int index; @@ -564,7 +564,7 @@ static USBDevice *usb_serial_init(USBBus *bus, const char *filename) static USBDevice *usb_braille_init(USBBus *bus, const char *unused) { USBDevice *dev; - CharDriverState *cdrv; + Chardev *cdrv; cdrv = qemu_chr_new("braille", "braille"); if (!cdrv) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 4a0ebbfb32..860f5c35eb 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -284,7 +284,7 @@ static gboolean usbredir_write_unblocked(GIOChannel *chan, GIOCondition cond, static int usbredir_write(void *priv, uint8_t *data, int count) { USBRedirDevice *dev = priv; - CharDriverState *chr = qemu_chr_fe_get_driver(&dev->cs); + Chardev *chr = qemu_chr_fe_get_driver(&dev->cs); int r; if (!chr->be_open) { @@ -1430,7 +1430,7 @@ static void usbredir_cleanup_device_queues(USBRedirDevice *dev) static void usbredir_handle_destroy(USBDevice *udev) { USBRedirDevice *dev = USB_REDIRECT(udev); - CharDriverState *chr = qemu_chr_fe_get_driver(&dev->cs); + Chardev *chr = qemu_chr_fe_get_driver(&dev->cs); qemu_chr_fe_deinit(&dev->cs); qemu_chr_delete(chr); |