diff options
Diffstat (limited to 'include/hw')
50 files changed, 814 insertions, 125 deletions
diff --git a/include/hw/acpi/cpu_hotplug.h b/include/hw/acpi/cpu_hotplug.h index 9e5d30c9d..f6d358def 100644 --- a/include/hw/acpi/cpu_hotplug.h +++ b/include/hw/acpi/cpu_hotplug.h @@ -20,8 +20,9 @@ typedef struct AcpiCpuHotplug { uint8_t sts[ACPI_GPE_PROC_LEN]; } AcpiCpuHotplug; -void AcpiCpuHotplug_add(ACPIGPE *gpe, AcpiCpuHotplug *g, CPUState *cpu); +void acpi_cpu_plug_cb(ACPIREGS *ar, qemu_irq irq, + AcpiCpuHotplug *g, DeviceState *dev, Error **errp); -void AcpiCpuHotplug_init(MemoryRegion *parent, Object *owner, - AcpiCpuHotplug *gpe_cpu, uint16_t base); +void acpi_cpu_hotplug_init(MemoryRegion *parent, Object *owner, + AcpiCpuHotplug *gpe_cpu, uint16_t base); #endif diff --git a/include/hw/acpi/ich9.h b/include/hw/acpi/ich9.h index 7e42448ef..fe975e662 100644 --- a/include/hw/acpi/ich9.h +++ b/include/hw/acpi/ich9.h @@ -47,7 +47,6 @@ typedef struct ICH9LPCPMRegs { Notifier powerdown_notifier; AcpiCpuHotplug gpe_cpu; - Notifier cpu_added_notifier; MemHotplugState acpi_memory_hotplug; } ICH9LPCPMRegs; diff --git a/include/hw/acpi/pc-hotplug.h b/include/hw/acpi/pc-hotplug.h index bf5157d7c..b9db29576 100644 --- a/include/hw/acpi/pc-hotplug.h +++ b/include/hw/acpi/pc-hotplug.h @@ -32,7 +32,7 @@ #define ACPI_MEMORY_HOTPLUG_IO_LEN 24 #define ACPI_MEMORY_HOTPLUG_BASE 0x0a00 -#define MEMORY_HOPTLUG_DEVICE MHPD +#define MEMORY_HOTPLUG_DEVICE MHPD #define MEMORY_SLOTS_NUMBER MDNR #define MEMORY_HOTPLUG_IO_REGION HPMR #define MEMORY_SLOT_ADDR_LOW MRBL diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h new file mode 100644 index 000000000..792fcbf5b --- /dev/null +++ b/include/hw/acpi/tpm.h @@ -0,0 +1,29 @@ +/* + * tpm.h - TPM ACPI definitions + * + * Copyright (C) 2014 IBM Corporation + * + * Authors: + * Stefan Berger <stefanb@us.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + * Implementation of the TIS interface according to specs found at + * http://www.trustedcomputinggroup.org + * + */ +#ifndef HW_ACPI_TPM_H +#define HW_ACPI_TPM_H + +#define TPM_TIS_ADDR_BASE 0xFED40000 +#define TPM_TIS_ADDR_SIZE 0x5000 + +#define TPM_TIS_IRQ 5 + +#define TPM_LOG_AREA_MINIMUM_SIZE (64 * 1024) + +#define TPM_TCPA_ACPI_CLASS_CLIENT 0 +#define TPM_TCPA_ACPI_CLASS_SERVER 1 + +#endif /* HW_ACPI_TPM_H */ diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h index cbbf4ca4c..cefc9e698 100644 --- a/include/hw/arm/arm.h +++ b/include/hw/arm/arm.h @@ -15,7 +15,7 @@ #include "hw/irq.h" /* armv7m.c */ -qemu_irq *armv7m_init(MemoryRegion *address_space_mem, +qemu_irq *armv7m_init(MemoryRegion *system_memory, int flash_size, int sram_size, const char *kernel_filename, const char *cpu_model); diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h index b9655ee39..0ad5fb883 100644 --- a/include/hw/arm/omap.h +++ b/include/hw/arm/omap.h @@ -755,10 +755,10 @@ void omap_rfbi_attach(struct omap_dss_s *s, int cs, struct rfbi_chip_s *chip); struct omap_mmc_s; struct omap_mmc_s *omap_mmc_init(hwaddr base, MemoryRegion *sysmem, - BlockDriverState *bd, + BlockBackend *blk, qemu_irq irq, qemu_irq dma[], omap_clk clk); struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta, - BlockDriverState *bd, qemu_irq irq, qemu_irq dma[], + BlockBackend *blk, qemu_irq irq, qemu_irq dma[], omap_clk fclk, omap_clk iclk); void omap_mmc_reset(struct omap_mmc_s *s); void omap_mmc_handlers(struct omap_mmc_s *s, qemu_irq ro, qemu_irq cover); diff --git a/include/hw/arm/pxa.h b/include/hw/arm/pxa.h index c5079067b..259b85249 100644 --- a/include/hw/arm/pxa.h +++ b/include/hw/arm/pxa.h @@ -87,7 +87,7 @@ void pxa2xx_lcdc_oritentation(void *opaque, int angle); typedef struct PXA2xxMMCIState PXA2xxMMCIState; PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem, hwaddr base, - BlockDriverState *bd, qemu_irq irq, + BlockBackend *blk, qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma); void pxa2xx_mmci_handlers(PXA2xxMMCIState *s, qemu_irq readonly, qemu_irq coverswitch); diff --git a/include/hw/block/block.h b/include/hw/block/block.h index 7c3d6c817..0d0ce9a46 100644 --- a/include/hw/block/block.h +++ b/include/hw/block/block.h @@ -12,11 +12,12 @@ #define HW_BLOCK_COMMON_H #include "qemu-common.h" +#include "qapi/error.h" /* Configuration */ typedef struct BlockConf { - BlockDriverState *bs; + BlockBackend *blk; uint16_t physical_block_size; uint16_t logical_block_size; uint16_t min_io_size; @@ -41,14 +42,13 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf) } #define DEFINE_BLOCK_PROPERTIES(_state, _conf) \ - DEFINE_PROP_DRIVE("drive", _state, _conf.bs), \ + DEFINE_PROP_DRIVE("drive", _state, _conf.blk), \ DEFINE_PROP_BLOCKSIZE("logical_block_size", _state, \ _conf.logical_block_size, 512), \ DEFINE_PROP_BLOCKSIZE("physical_block_size", _state, \ _conf.physical_block_size, 512), \ DEFINE_PROP_UINT16("min_io_size", _state, _conf.min_io_size, 0), \ DEFINE_PROP_UINT32("opt_io_size", _state, _conf.opt_io_size, 0), \ - DEFINE_PROP_INT32("bootindex", _state, _conf.bootindex, -1), \ DEFINE_PROP_UINT32("discard_granularity", _state, \ _conf.discard_granularity, -1) @@ -60,12 +60,13 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf) /* Configuration helpers */ void blkconf_serial(BlockConf *conf, char **serial); -int blkconf_geometry(BlockConf *conf, int *trans, - unsigned cyls_max, unsigned heads_max, unsigned secs_max); +void blkconf_geometry(BlockConf *conf, int *trans, + unsigned cyls_max, unsigned heads_max, unsigned secs_max, + Error **errp); /* Hard disk geometry */ -void hd_geometry_guess(BlockDriverState *bs, +void hd_geometry_guess(BlockBackend *blk, uint32_t *pcyls, uint32_t *pheads, uint32_t *psecs, int *ptrans); int hd_bios_chs_auto_trans(uint32_t cyls, uint32_t heads, uint32_t secs); diff --git a/include/hw/block/flash.h b/include/hw/block/flash.h index 920d7596e..50ccbbcf1 100644 --- a/include/hw/block/flash.h +++ b/include/hw/block/flash.h @@ -11,7 +11,7 @@ typedef struct pflash_t pflash_t; pflash_t *pflash_cfi01_register(hwaddr base, DeviceState *qdev, const char *name, hwaddr size, - BlockDriverState *bs, + BlockBackend *blk, uint32_t sector_len, int nb_blocs, int width, uint16_t id0, uint16_t id1, uint16_t id2, uint16_t id3, int be); @@ -20,7 +20,7 @@ pflash_t *pflash_cfi01_register(hwaddr base, pflash_t *pflash_cfi02_register(hwaddr base, DeviceState *qdev, const char *name, hwaddr size, - BlockDriverState *bs, uint32_t sector_len, + BlockBackend *blk, uint32_t sector_len, int nb_blocs, int nb_mappings, int width, uint16_t id0, uint16_t id1, uint16_t id2, uint16_t id3, @@ -30,7 +30,7 @@ pflash_t *pflash_cfi02_register(hwaddr base, MemoryRegion *pflash_cfi01_get_memory(pflash_t *fl); /* nand.c */ -DeviceState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id); +DeviceState *nand_init(BlockBackend *blk, int manf_id, int chip_id); void nand_setpins(DeviceState *dev, uint8_t cle, uint8_t ale, uint8_t ce, uint8_t wp, uint8_t gnd); void nand_getpins(DeviceState *dev, int *rb); diff --git a/include/hw/boards.h b/include/hw/boards.h index 605a97093..e0a67903e 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -5,12 +5,11 @@ #include "qemu/typedefs.h" #include "sysemu/blockdev.h" +#include "sysemu/accel.h" #include "hw/qdev.h" #include "qom/object.h" -typedef struct MachineState MachineState; - typedef void QEMUMachineInitFunc(MachineState *ms); typedef void QEMUMachineResetFunc(void); @@ -20,6 +19,7 @@ typedef void QEMUMachineHotAddCPUFunc(const int64_t id, Error **errp); typedef int QEMUMachineGetKvmtypeFunc(const char *arg); struct QEMUMachine { + const char *family; /* NULL iff @name identifies a standalone machtype */ const char *name; const char *alias; const char *desc; @@ -28,6 +28,7 @@ struct QEMUMachine { QEMUMachineHotAddCPUFunc *hot_add_cpu; QEMUMachineGetKvmtypeFunc *kvm_type; BlockInterfaceType block_default_type; + int units_per_default_bus; int max_cpus; unsigned int no_serial:1, no_parallel:1, @@ -35,10 +36,12 @@ struct QEMUMachine { use_sclp:1, no_floppy:1, no_cdrom:1, - no_sdcard:1; + no_sdcard:1, + has_dynamic_sysbus:1; int is_default; const char *default_machine_opts; const char *default_boot_order; + const char *default_display; GlobalProperty *compat_props; const char *hw_version; }; @@ -76,6 +79,7 @@ struct MachineClass { ObjectClass parent_class; /*< public >*/ + const char *family; /* NULL iff @name identifies a standalone machtype */ const char *name; const char *alias; const char *desc; @@ -86,6 +90,7 @@ struct MachineClass { int (*kvm_type)(const char *arg); BlockInterfaceType block_default_type; + int units_per_default_bus; int max_cpus; unsigned int no_serial:1, no_parallel:1, @@ -93,10 +98,12 @@ struct MachineClass { use_sclp:1, no_floppy:1, no_cdrom:1, - no_sdcard:1; + no_sdcard:1, + has_dynamic_sysbus:1; int is_default; const char *default_machine_opts; const char *default_boot_order; + const char *default_display; GlobalProperty *compat_props; const char *hw_version; @@ -110,6 +117,8 @@ struct MachineClass { struct MachineState { /*< private >*/ Object parent_obj; + Notifier sysbus_notifier; + /*< public >*/ char *accel; @@ -123,6 +132,7 @@ struct MachineState { bool mem_merge; bool usb; char *firmware; + bool iommu; ram_addr_t ram_size; ram_addr_t maxram_size; @@ -132,6 +142,7 @@ struct MachineState { char *kernel_cmdline; char *initrd_filename; const char *cpu_model; + AccelState *accelerator; }; #endif diff --git a/include/hw/compat.h b/include/hw/compat.h new file mode 100644 index 000000000..313682a70 --- /dev/null +++ b/include/hw/compat.h @@ -0,0 +1,35 @@ +#ifndef HW_COMPAT_H +#define HW_COMPAT_H + +#define HW_COMPAT_2_1 \ + {\ + .driver = "intel-hda",\ + .property = "old_msi_addr",\ + .value = "on",\ + },{\ + .driver = "VGA",\ + .property = "qemu-extended-regs",\ + .value = "off",\ + },{\ + .driver = "secondary-vga",\ + .property = "qemu-extended-regs",\ + .value = "off",\ + },{\ + .driver = "virtio-scsi-pci",\ + .property = "any_layout",\ + .value = "off",\ + },{\ + .driver = "usb-mouse",\ + .property = "usb_version",\ + .value = stringify(1),\ + },{\ + .driver = "usb-kbd",\ + .property = "usb_version",\ + .value = stringify(1),\ + },{\ + .driver = "virtio-pci",\ + .property = "virtio-pci-bus-master-bug-migration",\ + .value = "on",\ + } + +#endif /* HW_COMPAT_H */ diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h index c6b5129ba..a517753a6 100644 --- a/include/hw/elf_ops.h +++ b/include/hw/elf_ops.h @@ -147,18 +147,13 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab, } i++; } - if (nsyms) { - syms = g_realloc(syms, nsyms * sizeof(*syms)); + syms = g_realloc(syms, nsyms * sizeof(*syms)); - qsort(syms, nsyms, sizeof(*syms), glue(symcmp, SZ)); - for (i = 0; i < nsyms - 1; i++) { - if (syms[i].st_size == 0) { - syms[i].st_size = syms[i + 1].st_value - syms[i].st_value; - } + qsort(syms, nsyms, sizeof(*syms), glue(symcmp, SZ)); + for (i = 0; i < nsyms - 1; i++) { + if (syms[i].st_size == 0) { + syms[i].st_size = syms[i + 1].st_value - syms[i].st_value; } - } else { - g_free(syms); - syms = NULL; } /* String table */ diff --git a/include/hw/hotplug.h b/include/hw/hotplug.h index a6533cb0b..050d2f053 100644 --- a/include/hw/hotplug.h +++ b/include/hw/hotplug.h @@ -47,7 +47,12 @@ typedef void (*hotplug_fn)(HotplugHandler *plug_handler, * * @parent: Opaque parent interface. * @plug: plug callback. + * @unplug_request: unplug request callback. + * Used as a means to initiate device unplug for devices that + * require asynchronous unplug handling. * @unplug: unplug callback. + * Used for device removal with devices that implement + * asynchronous and synchronous (suprise) removal. */ typedef struct HotplugHandlerClass { /* <private> */ @@ -55,6 +60,7 @@ typedef struct HotplugHandlerClass { /* <public> */ hotplug_fn plug; + hotplug_fn unplug_request; hotplug_fn unplug; } HotplugHandlerClass; @@ -68,9 +74,17 @@ void hotplug_handler_plug(HotplugHandler *plug_handler, Error **errp); /** + * hotplug_handler_unplug_request: + * + * Calls #HotplugHandlerClass.unplug_request callback of @plug_handler. + */ +void hotplug_handler_unplug_request(HotplugHandler *plug_handler, + DeviceState *plugged_dev, + Error **errp); +/** * hotplug_handler_unplug: * - * Call #HotplugHandlerClass.unplug callback of @plug_handler. + * Calls #HotplugHandlerClass.unplug callback of @plug_handler. */ void hotplug_handler_unplug(HotplugHandler *plug_handler, DeviceState *plugged_dev, diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h new file mode 100644 index 000000000..e321ee4fb --- /dev/null +++ b/include/hw/i386/intel_iommu.h @@ -0,0 +1,120 @@ +/* + * QEMU emulation of an Intel IOMMU (VT-d) + * (DMA Remapping device) + * + * Copyright (C) 2013 Knut Omang, Oracle <knut.omang@oracle.com> + * Copyright (C) 2014 Le Tan, <tamlokveer@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef INTEL_IOMMU_H +#define INTEL_IOMMU_H +#include "hw/qdev.h" +#include "sysemu/dma.h" + +#define TYPE_INTEL_IOMMU_DEVICE "intel-iommu" +#define INTEL_IOMMU_DEVICE(obj) \ + OBJECT_CHECK(IntelIOMMUState, (obj), TYPE_INTEL_IOMMU_DEVICE) + +/* DMAR Hardware Unit Definition address (IOMMU unit) */ +#define Q35_HOST_BRIDGE_IOMMU_ADDR 0xfed90000ULL + +#define VTD_PCI_BUS_MAX 256 +#define VTD_PCI_SLOT_MAX 32 +#define VTD_PCI_FUNC_MAX 8 +#define VTD_PCI_DEVFN_MAX 256 +#define VTD_PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f) +#define VTD_PCI_FUNC(devfn) ((devfn) & 0x07) +#define VTD_SID_TO_BUS(sid) (((sid) >> 8) & 0xff) +#define VTD_SID_TO_DEVFN(sid) ((sid) & 0xff) + +#define DMAR_REG_SIZE 0x230 +#define VTD_HOST_ADDRESS_WIDTH 39 +#define VTD_HAW_MASK ((1ULL << VTD_HOST_ADDRESS_WIDTH) - 1) + +typedef struct VTDContextEntry VTDContextEntry; +typedef struct VTDContextCacheEntry VTDContextCacheEntry; +typedef struct IntelIOMMUState IntelIOMMUState; +typedef struct VTDAddressSpace VTDAddressSpace; +typedef struct VTDIOTLBEntry VTDIOTLBEntry; + +/* Context-Entry */ +struct VTDContextEntry { + uint64_t lo; + uint64_t hi; +}; + +struct VTDContextCacheEntry { + /* The cache entry is obsolete if + * context_cache_gen!=IntelIOMMUState.context_cache_gen + */ + uint32_t context_cache_gen; + struct VTDContextEntry context_entry; +}; + +struct VTDAddressSpace { + uint8_t bus_num; + uint8_t devfn; + AddressSpace as; + MemoryRegion iommu; + IntelIOMMUState *iommu_state; + VTDContextCacheEntry context_cache_entry; +}; + +struct VTDIOTLBEntry { + uint64_t gfn; + uint16_t domain_id; + uint64_t slpte; + bool read_flags; + bool write_flags; +}; + +/* The iommu (DMAR) device state struct */ +struct IntelIOMMUState { + SysBusDevice busdev; + MemoryRegion csrmem; + uint8_t csr[DMAR_REG_SIZE]; /* register values */ + uint8_t wmask[DMAR_REG_SIZE]; /* R/W bytes */ + uint8_t w1cmask[DMAR_REG_SIZE]; /* RW1C(Write 1 to Clear) bytes */ + uint8_t womask[DMAR_REG_SIZE]; /* WO (write only - read returns 0) */ + uint32_t version; + + dma_addr_t root; /* Current root table pointer */ + bool root_extended; /* Type of root table (extended or not) */ + bool dmar_enabled; /* Set if DMA remapping is enabled */ + + uint16_t iq_head; /* Current invalidation queue head */ + uint16_t iq_tail; /* Current invalidation queue tail */ + dma_addr_t iq; /* Current invalidation queue pointer */ + uint16_t iq_size; /* IQ Size in number of entries */ + bool qi_enabled; /* Set if the QI is enabled */ + uint8_t iq_last_desc_type; /* The type of last completed descriptor */ + + /* The index of the Fault Recording Register to be used next. + * Wraps around from N-1 to 0, where N is the number of FRCD_REG. + */ + uint16_t next_frcd_reg; + + uint64_t cap; /* The value of capability reg */ + uint64_t ecap; /* The value of extended capability reg */ + + uint32_t context_cache_gen; /* Should be in [1,MAX] */ + GHashTable *iotlb; /* IOTLB */ + + MemoryRegionIOMMUOps iommu_ops; + VTDAddressSpace **address_spaces[VTD_PCI_BUS_MAX]; +}; + +#endif diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index f4b9b2bb7..69d9cf8e6 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -14,6 +14,7 @@ #include "sysemu/sysemu.h" #include "hw/pci/pci.h" #include "hw/boards.h" +#include "hw/compat.h" #define HPET_INTCAP "hpet-intcap" @@ -23,6 +24,8 @@ * address space begins. * @hotplug_memory: hotplug memory addess space container * @acpi_dev: link to ACPI PM device that performs ACPI hotplug handling + * @enforce_aligned_dimm: check that DIMM's address/size is aligned by + * backend's alignment value if provided */ struct PCMachineState { /*< private >*/ @@ -33,13 +36,18 @@ struct PCMachineState { MemoryRegion hotplug_memory; HotplugHandler *acpi_dev; + ISADevice *rtc; uint64_t max_ram_below_4g; + OnOffAuto vmport; + bool enforce_aligned_dimm; }; #define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device" #define PC_MACHINE_MEMHP_REGION_SIZE "hotplug-memory-region-size" #define PC_MACHINE_MAX_RAM_BELOW_4G "max-ram-below-4g" +#define PC_MACHINE_VMPORT "vmport" +#define PC_MACHINE_ENFORCE_ALIGNED_DIMM "enforce-aligned-dimm" /** * PCMachineClass: @@ -85,7 +93,6 @@ typedef struct PcPciInfo { #define ACPI_PM_PROP_GPE0_BLK_LEN "gpe0_blk_len" struct PcGuestInfo { - bool has_pci_info; bool isapc_ram_fw; hwaddr ram_size, ram_size_below_4g; unsigned apic_id_limit; @@ -177,6 +184,8 @@ void pc_acpi_init(const char *default_dsdt); PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size, ram_addr_t above_4g_mem_size); +void pc_set_legacy_acpi_data_size(void); + #define PCI_HOST_PROP_PCI_HOLE_START "pci-hole-start" #define PCI_HOST_PROP_PCI_HOLE_END "pci-hole-end" #define PCI_HOST_PROP_PCI_HOLE64_START "pci-hole64-start" @@ -188,6 +197,11 @@ PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size, void pc_pci_as_mapping_init(Object *owner, MemoryRegion *system_memory, MemoryRegion *pci_address_space); +FWCfgState *xen_load_linux(const char *kernel_filename, + const char *kernel_cmdline, + const char *initrd_filename, + ram_addr_t below_4g_mem_size, + PcGuestInfo *guest_info); FWCfgState *pc_memory_init(MachineState *machine, MemoryRegion *system_memory, ram_addr_t below_4g_mem_size, @@ -204,7 +218,7 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi, uint32 hpet_irqs); void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd); void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size, - const char *boot_device, + const char *boot_device, MachineState *machine, ISADevice *floppy, BusState *ide0, BusState *ide1, ISADevice *s); void pc_nic_init(ISABus *isa_bus, PCIBus *pci_bus); @@ -296,6 +310,7 @@ int e820_get_num_entries(void); bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); #define PC_COMPAT_2_0 \ + HW_COMPAT_2_1, \ {\ .driver = "virtio-scsi-pci",\ .property = "any_layout",\ @@ -316,6 +331,11 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); .value = "off",\ },\ {\ + .driver = "nec-usb-xhci",\ + .property = "force-pcie-endcap",\ + .value = "on",\ + },\ + {\ .driver = "pci-serial",\ .property = "prog_if",\ .value = stringify(0),\ diff --git a/include/hw/i386/smbios.h b/include/hw/i386/smbios.h index a3f4d88bf..d2850bed2 100644 --- a/include/hw/i386/smbios.h +++ b/include/hw/i386/smbios.h @@ -20,7 +20,8 @@ void smbios_entry_add(QemuOpts *opts); void smbios_set_cpuid(uint32_t version, uint32_t features); void smbios_set_defaults(const char *manufacturer, const char *product, - const char *version, bool legacy_mode); + const char *version, bool legacy_mode, + bool uuid_encoded); uint8_t *smbios_get_table_legacy(size_t *length); void smbios_get_tables(uint8_t **tables, size_t *tables_len, uint8_t **anchor, size_t *anchor_len); @@ -72,6 +73,18 @@ struct smbios_type_0 { uint8_t embedded_controller_minor_release; } QEMU_PACKED; +/* UUID encoding. The time_* fields are little-endian, as specified by SMBIOS + * version 2.6. + */ +struct smbios_uuid { + uint32_t time_low; + uint16_t time_mid; + uint16_t time_hi_and_version; + uint8_t clock_seq_hi_and_reserved; + uint8_t clock_seq_low; + uint8_t node[6]; +} QEMU_PACKED; + /* SMBIOS type 1 - System Information */ struct smbios_type_1 { struct smbios_structure_header header; @@ -79,7 +92,7 @@ struct smbios_type_1 { uint8_t product_name_str; uint8_t version_str; uint8_t serial_number_str; - uint8_t uuid[16]; + struct smbios_uuid uuid; uint8_t wake_up_type; uint8_t sku_number_str; uint8_t family_str; diff --git a/include/hw/irq.h b/include/hw/irq.h index 6f874f5ac..4c4c2eaf9 100644 --- a/include/hw/irq.h +++ b/include/hw/irq.h @@ -61,6 +61,5 @@ qemu_irq *qemu_irq_proxy(qemu_irq **target, int n); /* For internal use in qtest. Similar to qemu_irq_split, but operating on an existing vector of qemu_irq. */ void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n); -void qemu_irq_intercept_out(qemu_irq **gpio_out, qemu_irq_handler handler, int n); #endif diff --git a/include/hw/isa/pc87312.h b/include/hw/isa/pc87312.h index befc8bdc6..bf74470d4 100644 --- a/include/hw/isa/pc87312.h +++ b/include/hw/isa/pc87312.h @@ -47,13 +47,10 @@ typedef struct PC87312State { struct { ISADevice *dev; - BlockDriverState *drive[2]; - uint32_t base; } fdc; struct { ISADevice *dev; - uint32_t base; } ide; MemoryRegion io; diff --git a/include/hw/loader.h b/include/hw/loader.h index 796cbf9b3..64816395d 100644 --- a/include/hw/loader.h +++ b/include/hw/loader.h @@ -13,8 +13,10 @@ */ int get_image_size(const char *filename); int load_image(const char *filename, uint8_t *addr); /* deprecated */ +ssize_t load_image_size(const char *filename, void *addr, size_t size); int load_image_targphys(const char *filename, hwaddr, uint64_t max_sz); +int load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz); #define ELF_LOAD_FAILED -1 #define ELF_LOAD_NOT_ELF -2 @@ -28,7 +30,9 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t), int load_aout(const char *filename, hwaddr addr, int max_sz, int bswap_needed, hwaddr target_page_size); int load_uimage(const char *filename, hwaddr *ep, - hwaddr *loadaddr, int *is_linux); + hwaddr *loadaddr, int *is_linux, + uint64_t (*translate_fn)(void *, uint64_t), + void *translate_opaque); /** * load_ramdisk: @@ -55,7 +59,7 @@ extern bool rom_file_has_mr; int rom_add_file(const char *file, const char *fw_dir, hwaddr addr, int32_t bootindex, bool option_rom); -void *rom_add_blob(const char *name, const void *blob, size_t len, +ram_addr_t rom_add_blob(const char *name, const void *blob, size_t len, hwaddr addr, const char *fw_file_name, FWCfgReadCallback fw_callback, void *callback_opaque); int rom_add_elf_program(const char *name, void *data, size_t datasize, diff --git a/include/hw/mem/pc-dimm.h b/include/hw/mem/pc-dimm.h index 761eeef80..e1dcbbcd5 100644 --- a/include/hw/mem/pc-dimm.h +++ b/include/hw/mem/pc-dimm.h @@ -72,7 +72,7 @@ typedef struct PCDIMMDeviceClass { uint64_t pc_dimm_get_free_addr(uint64_t address_space_start, uint64_t address_space_size, - uint64_t *hint, uint64_t size, + uint64_t *hint, uint64_t align, uint64_t size, Error **errp); int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp); diff --git a/include/hw/nmi.h b/include/hw/nmi.h new file mode 100644 index 000000000..b541772e1 --- /dev/null +++ b/include/hw/nmi.h @@ -0,0 +1,49 @@ +/* + * NMI monitor handler class and helpers definitions. + * + * Copyright IBM Corp., 2014 + * + * Author: Alexey Kardashevskiy <aik@ozlabs.ru> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef NMI_H +#define NMI_H 1 + +#include "qemu-common.h" +#include "qom/object.h" + +#define TYPE_NMI "nmi" + +#define NMI_CLASS(klass) \ + OBJECT_CLASS_CHECK(NMIClass, (klass), TYPE_NMI) +#define NMI_GET_CLASS(obj) \ + OBJECT_GET_CLASS(NMIClass, (obj), TYPE_NMI) +#define NMI(obj) \ + INTERFACE_CHECK(NMI, (obj), TYPE_NMI) + +typedef struct NMIState { + Object parent_obj; +} NMIState; + +typedef struct NMIClass { + InterfaceClass parent_class; + + void (*nmi_monitor_handler)(NMIState *n, int cpu_index, Error **errp); +} NMIClass; + +void nmi_monitor_handle(int cpu_index, Error **errp); + +#endif /* NMI_H */ diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h index 72b1549dc..56e1ed712 100644 --- a/include/hw/nvram/fw_cfg.h +++ b/include/hw/nvram/fw_cfg.h @@ -76,6 +76,8 @@ void fw_cfg_add_file(FWCfgState *s, const char *filename, void *data, void fw_cfg_add_file_callback(FWCfgState *s, const char *filename, FWCfgReadCallback callback, void *callback_opaque, void *data, size_t len); +void *fw_cfg_modify_file(FWCfgState *s, const char *filename, void *data, + size_t len); FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port, hwaddr crl_addr, hwaddr data_addr); diff --git a/include/hw/pci-host/pam.h b/include/hw/pci-host/pam.h index a8b87b89a..4d03e4bf1 100644 --- a/include/hw/pci-host/pam.h +++ b/include/hw/pci-host/pam.h @@ -7,7 +7,7 @@ * VA Linux Systems Japan K.K. * Copyright (c) 2012 Jason Baron <jbaron@redhat.com> * - * Split out from piix_pci.c + * Split out from piix.c * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/include/hw/pci-host/q35.h b/include/hw/pci-host/q35.h index d9ee97845..025d6e69a 100644 --- a/include/hw/pci-host/q35.h +++ b/include/hw/pci-host/q35.h @@ -33,6 +33,7 @@ #include "hw/acpi/acpi.h" #include "hw/acpi/ich9.h" #include "hw/pci-host/pam.h" +#include "hw/i386/intel_iommu.h" #define TYPE_Q35_HOST_DEVICE "q35-pcihost" #define Q35_HOST_DEVICE(obj) \ @@ -60,6 +61,7 @@ typedef struct MCHPCIState { uint64_t pci_hole64_size; PcGuestInfo *guest_info; uint32_t short_root_bus; + IntelIOMMUState *iommu; } MCHPCIState; typedef struct Q35PCIHost { diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h index 32f0aa7d1..4ea2a0d14 100644 --- a/include/hw/pci-host/spapr.h +++ b/include/hw/pci-host/spapr.h @@ -70,7 +70,7 @@ struct sPAPRPHBState { MemoryRegion memspace, iospace; hwaddr mem_win_addr, mem_win_size, io_win_addr, io_win_size; - MemoryRegion memwindow, iowindow; + MemoryRegion memwindow, iowindow, msiwindow; uint32_t dma_liobn; AddressSpace iommu_as; diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h index e597070ab..321d622b7 100644 --- a/include/hw/pci/pci_ids.h +++ b/include/hw/pci/pci_ids.h @@ -56,6 +56,7 @@ #define PCI_DEVICE_ID_LSI_53C810 0x0001 #define PCI_DEVICE_ID_LSI_53C895A 0x0012 #define PCI_DEVICE_ID_LSI_SAS1078 0x0060 +#define PCI_DEVICE_ID_LSI_SAS0079 0x0079 #define PCI_VENDOR_ID_DEC 0x1011 #define PCI_DEVICE_ID_DEC_21154 0x0026 diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h index 7fe81f31e..b48a7a2c5 100644 --- a/include/hw/pci/pcie.h +++ b/include/hw/pci/pcie.h @@ -103,9 +103,10 @@ void pcie_cap_flr_init(PCIDevice *dev); void pcie_cap_flr_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int len); -void pcie_cap_ari_init(PCIDevice *dev); -void pcie_cap_ari_reset(PCIDevice *dev); -bool pcie_cap_is_ari_enabled(const PCIDevice *dev); +/* ARI forwarding capability and control */ +void pcie_cap_arifwd_init(PCIDevice *dev); +void pcie_cap_arifwd_reset(PCIDevice *dev); +bool pcie_cap_is_arifwd_enabled(const PCIDevice *dev); /* PCI express extended capability helper functions */ uint16_t pcie_find_capability(PCIDevice *dev, uint16_t cap_id); @@ -127,6 +128,6 @@ extern const VMStateDescription vmstate_pcie_device; void pcie_cap_slot_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp); -void pcie_cap_slot_hot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, - Error **errp); +void pcie_cap_slot_hot_unplug_request_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp); #endif /* QEMU_PCIE_H */ diff --git a/include/hw/pci/shpc.h b/include/hw/pci/shpc.h index eef1a1ad6..025bc5b26 100644 --- a/include/hw/pci/shpc.h +++ b/include/hw/pci/shpc.h @@ -46,8 +46,8 @@ void shpc_cap_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int len); void shpc_device_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp); -void shpc_device_hot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, - Error **errp); +void shpc_device_hot_unplug_request_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp); extern VMStateInfo shpc_vmstate_info; #define SHPC_VMSTATE(_field, _type) \ diff --git a/include/hw/pcmcia.h b/include/hw/pcmcia.h index 2695d3cba..98406ffbc 100644 --- a/include/hw/pcmcia.h +++ b/include/hw/pcmcia.h @@ -8,14 +8,8 @@ typedef struct PCMCIASocket { qemu_irq irq; bool attached; - const char *slot_string; - const char *card_string; } PCMCIASocket; -void pcmcia_socket_register(PCMCIASocket *socket); -void pcmcia_socket_unregister(PCMCIASocket *socket); -void pcmcia_info(Monitor *mon, const QDict *qdict); - #define TYPE_PCMCIA_CARD "pcmcia-card" #define PCMCIA_CARD(obj) \ OBJECT_CHECK(PCMCIACardState, (obj), TYPE_PCMCIA_CARD) diff --git a/include/hw/platform-bus.h b/include/hw/platform-bus.h new file mode 100644 index 000000000..bd42b8380 --- /dev/null +++ b/include/hw/platform-bus.h @@ -0,0 +1,57 @@ +#ifndef HW_PLATFORM_BUS_H +#define HW_PLATFORM_BUS_H 1 + +/* + * Platform Bus device to support dynamic Sysbus devices + * + * Copyright (C) 2014 Freescale Semiconductor, Inc. All rights reserved. + * + * Author: Alexander Graf, <agraf@suse.de> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "hw/sysbus.h" + +typedef struct PlatformBusDevice PlatformBusDevice; + +#define TYPE_PLATFORM_BUS_DEVICE "platform-bus-device" +#define PLATFORM_BUS_DEVICE(obj) \ + OBJECT_CHECK(PlatformBusDevice, (obj), TYPE_PLATFORM_BUS_DEVICE) +#define PLATFORM_BUS_DEVICE_CLASS(klass) \ + OBJECT_CLASS_CHECK(PlatformBusDeviceClass, (klass), TYPE_PLATFORM_BUS_DEVICE) +#define PLATFORM_BUS_DEVICE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(PlatformBusDeviceClass, (obj), TYPE_PLATFORM_BUS_DEVICE) + +struct PlatformBusDevice { + /*< private >*/ + SysBusDevice parent_obj; + Notifier notifier; + bool done_gathering; + + /*< public >*/ + uint32_t mmio_size; + MemoryRegion mmio; + + uint32_t num_irqs; + qemu_irq *irqs; + unsigned long *used_irqs; +}; + +int platform_bus_get_irqn(PlatformBusDevice *platform_bus, SysBusDevice *sbdev, + int n); +hwaddr platform_bus_get_mmio_addr(PlatformBusDevice *pbus, SysBusDevice *sbdev, + int n); + +#endif /* !HW_PLATFORM_BUS_H */ diff --git a/include/hw/ppc/ppc.h b/include/hw/ppc/ppc.h index 7e16e2e06..14efd0ca3 100644 --- a/include/hw/ppc/ppc.h +++ b/include/hw/ppc/ppc.h @@ -92,7 +92,7 @@ enum { #define FW_CFG_PPC_IS_KVM (FW_CFG_ARCH_LOCAL + 0x05) #define FW_CFG_PPC_KVM_HC (FW_CFG_ARCH_LOCAL + 0x06) #define FW_CFG_PPC_KVM_PID (FW_CFG_ARCH_LOCAL + 0x07) -/* OpenBIOS has FW_CFG_PPC_NVRAM_ADDR as +0x08 */ +#define FW_CFG_PPC_NVRAM_ADDR (FW_CFG_ARCH_LOCAL + 0x08) #define FW_CFG_PPC_BUSFREQ (FW_CFG_ARCH_LOCAL + 0x09) #define PPC_SERIAL_MM_BAUDBASE 399193 diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index bbba51a70..749daf4dd 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -13,8 +13,6 @@ struct sPAPRNVRAM; typedef struct sPAPREnvironment { struct VIOsPAPRBus *vio_bus; QLIST_HEAD(, sPAPRPHBState) phbs; - hwaddr msi_win_addr; - MemoryRegion msiwindow; struct sPAPRNVRAM *nvram; XICSState *icp; @@ -24,7 +22,8 @@ typedef struct sPAPREnvironment { hwaddr rma_size; int vrma_adjust; hwaddr fdt_addr, rtas_addr; - long rtas_size; + ssize_t rtas_size; + void *rtas_blob; void *fdt_skel; target_ulong entry_point; uint64_t rtc_offset; @@ -382,9 +381,8 @@ int spapr_allocate_irq_block(int num, bool lsi, bool msi); #define RTAS_GET_SENSOR_STATE (RTAS_TOKEN_BASE + 0x1D) #define RTAS_IBM_CONFIGURE_CONNECTOR (RTAS_TOKEN_BASE + 0x1E) #define RTAS_IBM_OS_TERM (RTAS_TOKEN_BASE + 0x1F) -#define RTAS_IBM_EXTENDED_OS_TERM (RTAS_TOKEN_BASE + 0x20) -#define RTAS_TOKEN_MAX (RTAS_TOKEN_BASE + 0x21) +#define RTAS_TOKEN_MAX (RTAS_TOKEN_BASE + 0x20) /* RTAS ibm,get-system-parameter token values */ #define RTAS_SYSPARM_SPLPAR_CHARACTERISTICS 20 diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 0799ff29b..589bbe736 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -126,7 +126,6 @@ typedef struct DeviceClass { /* Private to qdev / bus. */ qdev_initfn init; /* TODO remove, once users are converted to realize */ - qdev_event unplug; qdev_event exit; /* TODO remove, once users are converted to unrealize */ const char *bus_type; } DeviceClass; @@ -137,7 +136,6 @@ struct NamedGPIOList { char *name; qemu_irq *in; int num_in; - qemu_irq *out; int num_out; QLIST_ENTRY(NamedGPIOList) node; }; @@ -210,7 +208,6 @@ struct BusState { Object obj; DeviceState *parent; const char *name; - int allow_hotplug; HotplugHandler *hotplug_handler; int max_index; bool realized; @@ -232,7 +229,7 @@ struct Property { struct PropertyInfo { const char *name; - const char *legacy_name; + const char *description; const char **enum_table; int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len); ObjectPropertyAccessor *get; @@ -242,16 +239,16 @@ struct PropertyInfo { /** * GlobalProperty: - * @not_used: Track use of a global property. Defaults to false in all C99 - * struct initializations. - * - * This prevents reports of .compat_props when they are not used. + * @user_provided: Set to true if property comes from user-provided config + * (command-line or config file). + * @used: Set to true if property was used when initializing a device. */ typedef struct GlobalProperty { const char *driver; const char *property; const char *value; - bool not_used; + bool user_provided; + bool used; QTAILQ_ENTRY(GlobalProperty) next; } GlobalProperty; @@ -264,7 +261,8 @@ void qdev_init_nofail(DeviceState *dev); void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id, int required_for_version); void qdev_unplug(DeviceState *dev, Error **errp); -int qdev_simple_unplug_cb(DeviceState *dev); +void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp); void qdev_machine_creation_done(void); bool qdev_machine_modified(void); @@ -274,6 +272,9 @@ qemu_irq qdev_get_gpio_in_named(DeviceState *dev, const char *name, int n); void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin); void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n, qemu_irq pin); +qemu_irq qdev_get_gpio_out_connector(DeviceState *dev, const char *name, int n); +qemu_irq qdev_intercept_gpio_out(DeviceState *dev, qemu_irq icpt, + const char *name, int n); BusState *qdev_get_child_bus(DeviceState *dev, const char *name); @@ -288,6 +289,9 @@ void qdev_init_gpio_in_named(DeviceState *dev, qemu_irq_handler handler, void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins, const char *name, int n); +void qdev_pass_gpios(DeviceState *dev, DeviceState *container, + const char *name); + BusState *qdev_get_parent_bus(DeviceState *dev); /*** BUS API. ***/ @@ -361,11 +365,15 @@ extern int qdev_hotplug; char *qdev_get_dev_path(DeviceState *dev); -static inline void qbus_set_hotplug_handler(BusState *bus, DeviceState *handler, - Error **errp) +GSList *qdev_build_hotpluggable_device_list(Object *peripheral); + +void qbus_set_hotplug_handler(BusState *bus, DeviceState *handler, + Error **errp); + +void qbus_set_bus_hotplug_handler(BusState *bus, Error **errp); + +static inline bool qbus_is_hotpluggable(BusState *bus) { - object_property_set_link(OBJECT(bus), OBJECT(handler), - QDEV_HOTPLUG_HANDLER_PROPERTY, errp); - bus->allow_hotplug = 1; + return bus->hotplug_handler; } #endif diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h index 77fe3a12b..070006c71 100644 --- a/include/hw/qdev-properties.h +++ b/include/hw/qdev-properties.h @@ -141,7 +141,7 @@ extern PropertyInfo qdev_prop_arraylen; #define DEFINE_PROP_VLAN(_n, _s, _f) \ DEFINE_PROP(_n, _s, _f, qdev_prop_vlan, NICPeers) #define DEFINE_PROP_DRIVE(_n, _s, _f) \ - DEFINE_PROP(_n, _s, _f, qdev_prop_drive, BlockDriverState *) + DEFINE_PROP(_n, _s, _f, qdev_prop_drive, BlockBackend *) #define DEFINE_PROP_MACADDR(_n, _s, _f) \ DEFINE_PROP(_n, _s, _f, qdev_prop_macaddr, MACAddr) #define DEFINE_PROP_LOSTTICKPOLICY(_n, _s, _f, _d) \ @@ -168,8 +168,10 @@ void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value); void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value); void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value); void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value); -int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value) QEMU_WARN_UNUSED_RESULT; -void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value); +int qdev_prop_set_drive(DeviceState *dev, const char *name, + BlockBackend *value) QEMU_WARN_UNUSED_RESULT; +void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, + BlockBackend *value); void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value); void qdev_prop_set_enum(DeviceState *dev, const char *name, int value); /* FIXME: Remove opaque pointer properties. */ @@ -177,7 +179,7 @@ void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value); void qdev_prop_register_global(GlobalProperty *prop); void qdev_prop_register_global_list(GlobalProperty *props); -int qdev_prop_check_global(void); +int qdev_prop_check_globals(void); void qdev_prop_set_globals(DeviceState *dev, Error **errp); void qdev_prop_set_globals_for_type(DeviceState *dev, const char *typename, Error **errp); diff --git a/include/hw/s390x/sclp.h b/include/hw/s390x/sclp.h index 7ef16226d..ec07a118f 100644 --- a/include/hw/s390x/sclp.h +++ b/include/hw/s390x/sclp.h @@ -28,8 +28,6 @@ #define SCLP_UNASSIGN_STORAGE 0x000C0001 #define SCLP_CMD_READ_EVENT_DATA 0x00770005 #define SCLP_CMD_WRITE_EVENT_DATA 0x00760005 -#define SCLP_CMD_READ_EVENT_DATA 0x00770005 -#define SCLP_CMD_WRITE_EVENT_DATA 0x00760005 #define SCLP_CMD_WRITE_EVENT_MASK 0x00780005 /* SCLP Memory hotplug codes */ @@ -37,6 +35,7 @@ #define SCLP_STARTING_SUBINCREMENT_ID 0x10001 #define SCLP_INCREMENT_UNIT 0x10000 #define MAX_AVAIL_SLOTS 32 +#define MAX_STORAGE_INCREMENTS 1020 /* CPU hotplug SCLP codes */ #define SCLP_HAS_CPU_INFO 0x0C00000000000000ULL @@ -156,6 +155,23 @@ typedef struct SCCB { char data[SCCB_DATA_LEN]; } QEMU_PACKED SCCB; +typedef struct sclpMemoryHotplugDev sclpMemoryHotplugDev; + +#define TYPE_SCLP_MEMORY_HOTPLUG_DEV "sclp-memory-hotplug-dev" +#define SCLP_MEMORY_HOTPLUG_DEV(obj) \ + OBJECT_CHECK(sclpMemoryHotplugDev, (obj), TYPE_SCLP_MEMORY_HOTPLUG_DEV) + +struct sclpMemoryHotplugDev { + SysBusDevice parent; + ram_addr_t standby_mem_size; + ram_addr_t padded_ram_size; + ram_addr_t pad_size; + ram_addr_t standby_subregion_size; + ram_addr_t rzm; + int increment_size; + char *standby_state_map; +}; + static inline int sccb_data_len(SCCB *sccb) { return be16_to_cpu(sccb->h.length) - sizeof(sccb->h); @@ -163,6 +179,8 @@ static inline int sccb_data_len(SCCB *sccb) void s390_sclp_init(void); +sclpMemoryHotplugDev *init_sclp_memory_hotplug_dev(void); +sclpMemoryHotplugDev *get_sclp_memory_hotplug_dev(void); void sclp_service_interrupt(uint32_t sccb); void raise_irq_cpu_hotplug(void); diff --git a/include/hw/scsi/esp.h b/include/hw/scsi/esp.h index e079fb8d1..6c795276c 100644 --- a/include/hw/scsi/esp.h +++ b/include/hw/scsi/esp.h @@ -22,6 +22,7 @@ struct ESPState { uint8_t wregs[ESP_REGS]; qemu_irq irq; uint8_t chip_id; + bool tchi_written; int32_t ti_size; uint32_t ti_rptr, ti_wptr; uint32_t status; diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h index 1adb54906..cdaf0f8eb 100644 --- a/include/hw/scsi/scsi.h +++ b/include/hw/scsi/scsi.h @@ -2,9 +2,10 @@ #define QEMU_HW_SCSI_H #include "hw/qdev.h" -#include "block/block.h" +#include "qemu/typedefs.h" #include "hw/block/block.h" #include "sysemu/sysemu.h" +#include "qemu/notify.h" #define MAX_SCSI_DEVS 255 @@ -50,17 +51,25 @@ struct SCSIRequest { uint32_t tag; uint32_t lun; uint32_t status; + void *hba_private; size_t resid; SCSICommand cmd; - BlockDriverAIOCB *aiocb; - QEMUSGList *sg; + NotifierList cancel_notifiers; + + /* Note: + * - fields before sense are initialized by scsi_req_alloc; + * - sense[] is uninitialized; + * - fields after sense are memset to 0 by scsi_req_alloc. + * */ + + uint8_t sense[SCSI_SENSE_BUF_SIZE]; + uint32_t sense_len; + bool enqueued; + bool io_canceled; + bool retry; bool dma_started; - uint8_t sense[SCSI_SENSE_BUF_SIZE]; - uint32_t sense_len; - bool enqueued; - bool io_canceled; - bool retry; - void *hba_private; + BlockAIOCB *aiocb; + QEMUSGList *sg; QTAILQ_ENTRY(SCSIRequest) next; }; @@ -74,8 +83,9 @@ struct SCSIRequest { typedef struct SCSIDeviceClass { DeviceClass parent_class; - int (*init)(SCSIDevice *dev); - void (*destroy)(SCSIDevice *s); + void (*realize)(SCSIDevice *dev, Error **errp); + int (*parse_cdb)(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf, + void *hba_private); SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun, uint8_t *buf, void *hba_private); void (*unit_attention_reported)(SCSIDevice *s); @@ -121,7 +131,6 @@ struct SCSIReqOps { int32_t (*send_command)(SCSIRequest *req, uint8_t *buf); void (*read_data)(SCSIRequest *req); void (*write_data)(SCSIRequest *req); - void (*cancel_io)(SCSIRequest *req); uint8_t *(*get_buf)(SCSIRequest *req); void (*save_request)(QEMUFile *f, SCSIRequest *req); @@ -131,11 +140,11 @@ struct SCSIReqOps { struct SCSIBusInfo { int tcq; int max_channel, max_target, max_lun; + int (*parse_cdb)(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf, + void *hba_private); void (*transfer_data)(SCSIRequest *req, uint32_t arg); void (*complete)(SCSIRequest *req, uint32_t arg, size_t resid); void (*cancel)(SCSIRequest *req); - void (*hotplug)(SCSIBus *bus, SCSIDevice *dev); - void (*hot_unplug)(SCSIBus *bus, SCSIDevice *dev); void (*change)(SCSIBus *bus, SCSIDevice *dev, SCSISense sense); QEMUSGList *(*get_sg_list)(SCSIRequest *req); @@ -163,7 +172,7 @@ static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d) return DO_UPCAST(SCSIBus, qbus, d->qdev.parent_bus); } -SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, +SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk, int unit, bool removable, int bootindex, const char *serial, Error **errp); void scsi_bus_legacy_handle_cmdline(SCSIBus *bus, Error **errp); @@ -229,8 +238,9 @@ extern const struct SCSISense sense_code_SPACE_ALLOC_FAILED; #define SENSE_CODE(x) sense_code_ ## x -uint32_t scsi_data_cdb_length(uint8_t *buf); -uint32_t scsi_cdb_length(uint8_t *buf); +uint32_t scsi_data_cdb_xfer(uint8_t *buf); +uint32_t scsi_cdb_xfer(uint8_t *buf); +int scsi_cdb_length(uint8_t *buf); int scsi_sense_valid(SCSISense sense); int scsi_build_sense(uint8_t *in_buf, int in_len, uint8_t *buf, int len, bool fixed); @@ -244,6 +254,9 @@ void scsi_req_free(SCSIRequest *req); SCSIRequest *scsi_req_ref(SCSIRequest *req); void scsi_req_unref(SCSIRequest *req); +int scsi_bus_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf, + void *hba_private); +int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf); void scsi_req_build_sense(SCSIRequest *req, SCSISense sense); void scsi_req_print(SCSIRequest *req); void scsi_req_continue(SCSIRequest *req); @@ -251,12 +264,14 @@ void scsi_req_data(SCSIRequest *req, int len); void scsi_req_complete(SCSIRequest *req, int status); uint8_t *scsi_req_get_buf(SCSIRequest *req); int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len); -void scsi_req_abort(SCSIRequest *req, int status); +void scsi_req_cancel_complete(SCSIRequest *req); void scsi_req_cancel(SCSIRequest *req); +void scsi_req_cancel_async(SCSIRequest *req, Notifier *notifier); void scsi_req_retry(SCSIRequest *req); void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense); void scsi_device_set_ua(SCSIDevice *sdev, SCSISense sense); void scsi_device_report_change(SCSIDevice *dev, SCSISense sense); +void scsi_device_unit_attention_reported(SCSIDevice *dev); int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed); SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int target, int lun); diff --git a/include/hw/sd.h b/include/hw/sd.h index d9b97e446..79adb5bb4 100644 --- a/include/hw/sd.h +++ b/include/hw/sd.h @@ -68,7 +68,7 @@ typedef struct { typedef struct SDState SDState; -SDState *sd_init(BlockDriverState *bs, bool is_spi); +SDState *sd_init(BlockBackend *bs, bool is_spi); int sd_do_command(SDState *sd, SDRequest *req, uint8_t *response); void sd_write_data(SDState *sd, uint8_t value); diff --git a/include/hw/sysbus.h b/include/hw/sysbus.h index f5aaa05ee..d1f3f000f 100644 --- a/include/hw/sysbus.h +++ b/include/hw/sysbus.h @@ -8,10 +8,9 @@ #define QDEV_MAX_MMIO 32 #define QDEV_MAX_PIO 32 -#define QDEV_MAX_IRQ 512 #define TYPE_SYSTEM_BUS "System" -#define SYSTEM_BUS(obj) OBJECT_CHECK(IDEBus, (obj), TYPE_IDE_BUS) +#define SYSTEM_BUS(obj) OBJECT_CHECK(BusState, (obj), TYPE_SYSTEM_BUS) typedef struct SysBusDevice SysBusDevice; @@ -33,6 +32,9 @@ typedef struct SysBusDevice SysBusDevice; * SysBusDeviceClass is not overriding #DeviceClass.realize, so derived * classes overriding it are not required to invoke its implementation. */ + +#define SYSBUS_DEVICE_GPIO_IRQ "sysbus-irq" + typedef struct SysBusDeviceClass { /*< private >*/ DeviceClass parent_class; @@ -46,9 +48,6 @@ struct SysBusDevice { DeviceState parent_obj; /*< public >*/ - int num_irq; - qemu_irq irqs[QDEV_MAX_IRQ]; - qemu_irq *irqp[QDEV_MAX_IRQ]; int num_mmio; struct { hwaddr addr; @@ -58,6 +57,8 @@ struct SysBusDevice { pio_addr_t pio[QDEV_MAX_PIO]; }; +typedef int FindSysbusDeviceFunc(SysBusDevice *sbdev, void *opaque); + void sysbus_init_mmio(SysBusDevice *dev, MemoryRegion *memory); MemoryRegion *sysbus_mmio_get_region(SysBusDevice *dev, int n); void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p); @@ -65,15 +66,21 @@ void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target); void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size); +bool sysbus_has_irq(SysBusDevice *dev, int n); +bool sysbus_has_mmio(SysBusDevice *dev, unsigned int n); void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq); +bool sysbus_is_irq_connected(SysBusDevice *dev, int n); +qemu_irq sysbus_get_connected_irq(SysBusDevice *dev, int n); void sysbus_mmio_map(SysBusDevice *dev, int n, hwaddr addr); void sysbus_mmio_map_overlap(SysBusDevice *dev, int n, hwaddr addr, int priority); void sysbus_add_io(SysBusDevice *dev, hwaddr addr, MemoryRegion *mem); -void sysbus_del_io(SysBusDevice *dev, MemoryRegion *mem); MemoryRegion *sysbus_address_space(SysBusDevice *dev); +/* Call func for every dynamically created sysbus device in the system */ +void foreach_dynamic_sysbus_device(FindSysbusDeviceFunc *func, void *opaque); + /* Legacy helper function for creating devices. */ DeviceState *sysbus_create_varargs(const char *name, hwaddr addr, ...); diff --git a/include/hw/tricore/tricore.h b/include/hw/tricore/tricore.h new file mode 100644 index 000000000..5f1325278 --- /dev/null +++ b/include/hw/tricore/tricore.h @@ -0,0 +1,11 @@ +#ifndef TRICORE_MISC_H +#define TRICORE_MISC_H 1 + +#include "exec/memory.h" +#include "hw/irq.h" + +struct tricore_boot_info { + uint64_t ram_size; + const char *kernel_filename; +}; +#endif diff --git a/include/hw/usb.h b/include/hw/usb.h index 8bcab48d2..b20b95912 100644 --- a/include/hw/usb.h +++ b/include/hw/usb.h @@ -267,10 +267,14 @@ struct USBDevice { #define USB_DEVICE_GET_CLASS(obj) \ OBJECT_GET_CLASS(USBDeviceClass, (obj), TYPE_USB_DEVICE) +typedef void (*USBDeviceRealize)(USBDevice *dev, Error **errp); +typedef void (*USBDeviceUnrealize)(USBDevice *dev, Error **errp); + typedef struct USBDeviceClass { DeviceClass parent_class; - int (*init)(USBDevice *dev); + USBDeviceRealize realize; + USBDeviceUnrealize unrealize; /* * Walk (enabled) downstream ports, check for a matching device. @@ -475,7 +479,8 @@ void usb_host_info(Monitor *mon, const QDict *qdict); #define VM_USB_HUB_SIZE 8 -/* usb-musb.c */ +/* hw/usb/hdc-musb.c */ + enum musb_irq_source_e { musb_irq_suspend = 0, musb_irq_resume, @@ -494,6 +499,10 @@ enum musb_irq_source_e { }; typedef struct MUSBState MUSBState; + +extern CPUReadMemoryFunc * const musb_read[]; +extern CPUWriteMemoryFunc * const musb_write[]; + MUSBState *musb_init(DeviceState *parent_device, int gpio_base); void musb_reset(MUSBState *s); uint32_t musb_core_intr_get(MUSBState *s); @@ -524,6 +533,7 @@ struct USBBusOps { void usb_bus_new(USBBus *bus, size_t bus_size, USBBusOps *ops, DeviceState *host); +void usb_bus_release(USBBus *bus); USBBus *usb_bus_find(int busnr); void usb_legacy_register(const char *typename, const char *usbdevice_name, USBDevice *(*usbdevice_init)(USBBus *bus, @@ -538,11 +548,12 @@ int usb_register_companion(const char *masterbus, USBPort *ports[], void *opaque, USBPortOps *ops, int speedmask); void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr); void usb_unregister_port(USBBus *bus, USBPort *port); -int usb_claim_port(USBDevice *dev); +void usb_claim_port(USBDevice *dev, Error **errp); void usb_release_port(USBDevice *dev); -int usb_device_attach(USBDevice *dev); +void usb_device_attach(USBDevice *dev, Error **errp); int usb_device_detach(USBDevice *dev); int usb_device_delete_addr(int busnr, int addr); +void usb_check_attach(USBDevice *dev, Error **errp); static inline USBBus *usb_bus_from_device(USBDevice *d) { diff --git a/include/hw/virtio/dataplane/vring.h b/include/hw/virtio/dataplane/vring.h index af73ee2ae..d3e086aef 100644 --- a/include/hw/virtio/dataplane/vring.h +++ b/include/hw/virtio/dataplane/vring.h @@ -17,8 +17,8 @@ #ifndef VRING_H #define VRING_H -#include <linux/virtio_ring.h> #include "qemu-common.h" +#include "hw/virtio/virtio_ring.h" #include "hw/virtio/virtio.h" typedef struct { diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h index d31768a1d..e472f2971 100644 --- a/include/hw/virtio/vhost-backend.h +++ b/include/hw/virtio/vhost-backend.h @@ -32,6 +32,8 @@ typedef struct VhostOps { vhost_backend_cleanup vhost_backend_cleanup; } VhostOps; +extern const VhostOps user_ops; + int vhost_set_backend_type(struct vhost_dev *dev, VhostBackendType backend_type); diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h index afb7b8db3..3979dc41a 100644 --- a/include/hw/virtio/virtio-blk.h +++ b/include/hw/virtio/virtio-blk.h @@ -17,7 +17,7 @@ #include "hw/virtio/virtio.h" #include "hw/block/block.h" #include "sysemu/iothread.h" -#include "block/block.h" +#include "sysemu/block-backend.h" #define TYPE_VIRTIO_BLK "virtio-blk-device" #define VIRTIO_BLK(obj) \ @@ -120,21 +120,18 @@ struct VirtIOBlockDataPlane; struct VirtIOBlockReq; typedef struct VirtIOBlock { VirtIODevice parent_obj; - BlockDriverState *bs; + BlockBackend *blk; VirtQueue *vq; void *rq; QEMUBH *bh; - BlockConf *conf; - VirtIOBlkConf blk; + VirtIOBlkConf conf; unsigned short sector_mask; bool original_wce; VMChangeStateEntry *change; /* Function to push to vq and notify guest */ void (*complete_request)(struct VirtIOBlockReq *req, unsigned char status); -#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE Notifier migration_state_notifier; struct VirtIOBlockDataPlane *dataplane; -#endif } VirtIOBlock; typedef struct MultiReqBuffer { @@ -161,6 +158,6 @@ int virtio_blk_handle_scsi_req(VirtIOBlock *blk, void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb); -void virtio_submit_multiwrite(BlockDriverState *bs, MultiReqBuffer *mrb); +void virtio_submit_multiwrite(BlockBackend *blk, MultiReqBuffer *mrb); #endif diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h index 188a2d914..bf17cc9ea 100644 --- a/include/hw/virtio/virtio-scsi.h +++ b/include/hw/virtio/virtio-scsi.h @@ -17,6 +17,8 @@ #include "hw/virtio/virtio.h" #include "hw/pci/pci.h" #include "hw/scsi/scsi.h" +#include "sysemu/iothread.h" +#include "hw/virtio/dataplane/vring.h" #define TYPE_VIRTIO_SCSI_COMMON "virtio-scsi-common" #define VIRTIO_SCSI_COMMON(obj) \ @@ -151,8 +153,18 @@ struct VirtIOSCSIConf { uint32_t cmd_per_lun; char *vhostfd; char *wwpn; + IOThread *iothread; }; +struct VirtIOSCSI; + +typedef struct { + struct VirtIOSCSI *parent; + Vring vring; + EventNotifier host_notifier; + EventNotifier guest_notifier; +} VirtIOSCSIVring; + typedef struct VirtIOSCSICommon { VirtIODevice parent_obj; VirtIOSCSIConf conf; @@ -164,14 +176,77 @@ typedef struct VirtIOSCSICommon { VirtQueue **cmd_vqs; } VirtIOSCSICommon; -typedef struct { +typedef struct VirtIOSCSI { VirtIOSCSICommon parent_obj; SCSIBus bus; int resetting; bool events_dropped; + + /* Fields for dataplane below */ + AioContext *ctx; /* one iothread per virtio-scsi-pci for now */ + + /* Vring is used instead of vq in dataplane code, because of the underlying + * memory layer thread safety */ + VirtIOSCSIVring *ctrl_vring; + VirtIOSCSIVring *event_vring; + VirtIOSCSIVring **cmd_vrings; + bool dataplane_started; + bool dataplane_starting; + bool dataplane_stopping; + bool dataplane_disabled; + bool dataplane_fenced; + Error *blocker; + Notifier migration_state_notifier; } VirtIOSCSI; +typedef struct VirtIOSCSIReq { + VirtIOSCSI *dev; + VirtQueue *vq; + QEMUSGList qsgl; + QEMUIOVector resp_iov; + + /* Note: + * - fields before elem are initialized by virtio_scsi_init_req; + * - elem is uninitialized at the time of allocation. + * - fields after elem (except the ending cdb[]) are zeroed by + * virtio_scsi_init_req. + * */ + + VirtQueueElement elem; + /* Set by dataplane code. */ + VirtIOSCSIVring *vring; + + union { + /* Used for two-stage request submission */ + QTAILQ_ENTRY(VirtIOSCSIReq) next; + + /* Used for cancellation of request during TMFs */ + int remaining; + }; + + SCSIRequest *sreq; + size_t resp_size; + enum SCSIXferMode mode; + union { + VirtIOSCSICmdResp cmd; + VirtIOSCSICtrlTMFResp tmf; + VirtIOSCSICtrlANResp an; + VirtIOSCSIEvent event; + } resp; + union { + struct { + VirtIOSCSICmdReq cmd; + uint8_t cdb[]; + } QEMU_PACKED; + VirtIOSCSICtrlTMFReq tmf; + VirtIOSCSICtrlANReq an; + } req; +} VirtIOSCSIReq; + +QEMU_BUILD_BUG_ON(offsetof(VirtIOSCSIReq, req.cdb) != + offsetof(VirtIOSCSIReq, req.cmd) + sizeof(VirtIOSCSICmdReq)); + #define DEFINE_VIRTIO_SCSI_PROPERTIES(_state, _conf_field) \ DEFINE_PROP_UINT32("num_queues", _state, _conf_field.num_queues, 1), \ DEFINE_PROP_UINT32("max_sectors", _state, _conf_field.max_sectors, 0xFFFF),\ @@ -192,5 +267,19 @@ void virtio_scsi_common_realize(DeviceState *dev, Error **errp, HandleOutput cmd); void virtio_scsi_common_unrealize(DeviceState *dev, Error **errp); +void virtio_scsi_handle_ctrl_req(VirtIOSCSI *s, VirtIOSCSIReq *req); +bool virtio_scsi_handle_cmd_req_prepare(VirtIOSCSI *s, VirtIOSCSIReq *req); +void virtio_scsi_handle_cmd_req_submit(VirtIOSCSI *s, VirtIOSCSIReq *req); +VirtIOSCSIReq *virtio_scsi_init_req(VirtIOSCSI *s, VirtQueue *vq); +void virtio_scsi_free_req(VirtIOSCSIReq *req); +void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev, + uint32_t event, uint32_t reason); + +void virtio_scsi_set_iothread(VirtIOSCSI *s, IOThread *iothread); +void virtio_scsi_dataplane_start(VirtIOSCSI *s); +void virtio_scsi_dataplane_stop(VirtIOSCSI *s); +void virtio_scsi_vring_push_notify(VirtIOSCSIReq *req); +VirtIOSCSIReq *virtio_scsi_pop_req_vring(VirtIOSCSI *s, + VirtIOSCSIVring *vring); #endif /* _QEMU_VIRTIO_SCSI_H */ diff --git a/include/hw/virtio/virtio-serial.h b/include/hw/virtio/virtio-serial.h index 4746312a8..a679e54aa 100644 --- a/include/hw/virtio/virtio-serial.h +++ b/include/hw/virtio/virtio-serial.h @@ -202,6 +202,8 @@ struct VirtIOSerial { QTAILQ_HEAD(, VirtIOSerialPort) ports; + QLIST_ENTRY(VirtIOSerial) next; + /* bitmap for identifying active ports */ uint32_t *ports_map; diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index a60104ca2..0726d76f4 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -161,6 +161,9 @@ typedef struct VirtioDeviceClass { int (*load)(VirtIODevice *vdev, QEMUFile *f, int version_id); } VirtioDeviceClass; +void virtio_instance_init_common(Object *proxy_obj, void *data, + size_t vdev_size, const char *vdev_name); + void virtio_init(VirtIODevice *vdev, const char *name, uint16_t device_id, size_t config_size); void virtio_cleanup(VirtIODevice *vdev); diff --git a/include/hw/virtio/virtio_ring.h b/include/hw/virtio/virtio_ring.h new file mode 100644 index 000000000..0b42e6eae --- /dev/null +++ b/include/hw/virtio/virtio_ring.h @@ -0,0 +1,167 @@ +#ifndef _LINUX_VIRTIO_RING_H +#define _LINUX_VIRTIO_RING_H +/* + * This file is copied from /usr/include/linux while converting __uNN types + * to uXX_t, __inline__ to inline, and tab to spaces. + * */ + +/* An interface for efficient virtio implementation, currently for use by KVM + * and lguest, but hopefully others soon. Do NOT change this since it will + * break existing servers and clients. + * + * This header is BSD licensed so anyone can use the definitions to implement + * compatible drivers/servers. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of IBM nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Copyright Rusty Russell IBM Corporation 2007. */ + +/* This marks a buffer as continuing via the next field. */ +#define VRING_DESC_F_NEXT 1 +/* This marks a buffer as write-only (otherwise read-only). */ +#define VRING_DESC_F_WRITE 2 +/* This means the buffer contains a list of buffer descriptors. */ +#define VRING_DESC_F_INDIRECT 4 + +/* The Host uses this in used->flags to advise the Guest: don't kick me when + * you add a buffer. It's unreliable, so it's simply an optimization. Guest + * will still kick if it's out of buffers. */ +#define VRING_USED_F_NO_NOTIFY 1 +/* The Guest uses this in avail->flags to advise the Host: don't interrupt me + * when you consume a buffer. It's unreliable, so it's simply an + * optimization. */ +#define VRING_AVAIL_F_NO_INTERRUPT 1 + +/* We support indirect buffer descriptors */ +#define VIRTIO_RING_F_INDIRECT_DESC 28 + +/* The Guest publishes the used index for which it expects an interrupt + * at the end of the avail ring. Host should ignore the avail->flags field. */ +/* The Host publishes the avail index for which it expects a kick + * at the end of the used ring. Guest should ignore the used->flags field. */ +#define VIRTIO_RING_F_EVENT_IDX 29 + +/* Virtio ring descriptors: 16 bytes. These can chain together via "next". */ +struct vring_desc { + /* Address (guest-physical). */ + uint64_t addr; + /* Length. */ + uint32_t len; + /* The flags as indicated above. */ + uint16_t flags; + /* We chain unused descriptors via this, too */ + uint16_t next; +}; + +struct vring_avail { + uint16_t flags; + uint16_t idx; + uint16_t ring[]; +}; + +/* u32 is used here for ids for padding reasons. */ +struct vring_used_elem { + /* Index of start of used descriptor chain. */ + uint32_t id; + /* Total length of the descriptor chain which was used (written to) */ + uint32_t len; +}; + +struct vring_used { + uint16_t flags; + uint16_t idx; + struct vring_used_elem ring[]; +}; + +struct vring { + unsigned int num; + + struct vring_desc *desc; + + struct vring_avail *avail; + + struct vring_used *used; +}; + +/* The standard layout for the ring is a continuous chunk of memory which looks + * like this. We assume num is a power of 2. + * + * struct vring + * { + * // The actual descriptors (16 bytes each) + * struct vring_desc desc[num]; + * + * // A ring of available descriptor heads with free-running index. + * uint16_t avail_flags; + * uint16_t avail_idx; + * uint16_t available[num]; + * uint16_t used_event_idx; + * + * // Padding to the next align boundary. + * char pad[]; + * + * // A ring of used descriptor heads with free-running index. + * uint16_t used_flags; + * uint16_t used_idx; + * struct vring_used_elem used[num]; + * uint16_t avail_event_idx; + * }; + */ +/* We publish the used event index at the end of the available ring, and vice + * versa. They are at the end for backwards compatibility. */ +#define vring_used_event(vr) ((vr)->avail->ring[(vr)->num]) +#define vring_avail_event(vr) (*(uint16_t *)&(vr)->used->ring[(vr)->num]) + +static inline void vring_init(struct vring *vr, unsigned int num, void *p, + unsigned long align) +{ + vr->num = num; + vr->desc = p; + vr->avail = p + num*sizeof(struct vring_desc); + vr->used = (void *)(((uintptr_t)&vr->avail->ring[num] + sizeof(uint16_t) + + align - 1) & ~(align - 1)); +} + +static inline unsigned vring_size(unsigned int num, unsigned long align) +{ + return ((sizeof(struct vring_desc) * num + sizeof(uint16_t) * (3 + num) + + align - 1) & ~(align - 1)) + + sizeof(uint16_t) * 3 + sizeof(struct vring_used_elem) * num; +} + +/* The following is used with USED_EVENT_IDX and AVAIL_EVENT_IDX */ +/* Assuming a given event_idx value from the other size, if + * we have just incremented index from old to new_idx, + * should we trigger an event? */ +static inline int vring_need_event(uint16_t event_idx, uint16_t new_idx, uint16_t old) +{ + /* Note: Xen has similar logic for notification hold-off + * in include/xen/interface/io/ring.h with req_event and req_prod + * corresponding to event_idx + 1 and new_idx respectively. + * Note also that req_event and req_prod in Xen start at 1, + * event indexes in virtio start at 0. */ + return (uint16_t)(new_idx - event_idx - 1) < (uint16_t)(new_idx - old); +} + +#endif /* _LINUX_VIRTIO_RING_H */ diff --git a/include/hw/xen/xen.h b/include/hw/xen/xen.h index f71f2d896..b0ed04caa 100644 --- a/include/hw/xen/xen.h +++ b/include/hw/xen/xen.h @@ -36,7 +36,6 @@ void xen_cmos_set_s3_resume(void *opaque, int irq, int level); qemu_irq *xen_interrupt_controller_init(void); -int xen_init(MachineClass *mc); void xenstore_store_pv_console_info(int i, struct CharDriverState *chr); #if defined(NEED_CPU_H) && !defined(CONFIG_USER_ONLY) diff --git a/include/hw/xen/xen_common.h b/include/hw/xen/xen_common.h index 07731b928..95612a40c 100644 --- a/include/hw/xen/xen_common.h +++ b/include/hw/xen/xen_common.h @@ -164,4 +164,19 @@ void destroy_hvm_domain(bool reboot); /* shutdown/destroy current domain because of an error */ void xen_shutdown_fatal_error(const char *fmt, ...) GCC_FMT_ATTR(1, 2); +#ifdef HVM_PARAM_VMPORT_REGS_PFN +static inline int xen_get_vmport_regs_pfn(XenXC xc, domid_t dom, + unsigned long *vmport_regs_pfn) +{ + return xc_get_hvm_param(xc, dom, HVM_PARAM_VMPORT_REGS_PFN, + vmport_regs_pfn); +} +#else +static inline int xen_get_vmport_regs_pfn(XenXC xc, domid_t dom, + unsigned long *vmport_regs_pfn) +{ + return -ENOSYS; +} +#endif + #endif /* QEMU_HW_XEN_COMMON_H */ |