diff options
Diffstat (limited to 'include/hw')
96 files changed, 4036 insertions, 1792 deletions
diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h new file mode 100644 index 0000000000..2b431e6242 --- /dev/null +++ b/include/hw/acpi/acpi-defs.h @@ -0,0 +1,564 @@ +/* + * 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 QEMU_ACPI_DEFS_H +#define QEMU_ACPI_DEFS_H + +enum { + ACPI_FADT_F_WBINVD, + ACPI_FADT_F_WBINVD_FLUSH, + ACPI_FADT_F_PROC_C1, + ACPI_FADT_F_P_LVL2_UP, + ACPI_FADT_F_PWR_BUTTON, + ACPI_FADT_F_SLP_BUTTON, + ACPI_FADT_F_FIX_RTC, + ACPI_FADT_F_RTC_S4, + ACPI_FADT_F_TMR_VAL_EXT, + ACPI_FADT_F_DCK_CAP, + ACPI_FADT_F_RESET_REG_SUP, + ACPI_FADT_F_SEALED_CASE, + ACPI_FADT_F_HEADLESS, + ACPI_FADT_F_CPU_SW_SLP, + ACPI_FADT_F_PCI_EXP_WAK, + ACPI_FADT_F_USE_PLATFORM_CLOCK, + ACPI_FADT_F_S4_RTC_STS_VALID, + ACPI_FADT_F_REMOTE_POWER_ON_CAPABLE, + ACPI_FADT_F_FORCE_APIC_CLUSTER_MODEL, + ACPI_FADT_F_FORCE_APIC_PHYSICAL_DESTINATION_MODE, + ACPI_FADT_F_HW_REDUCED_ACPI, + ACPI_FADT_F_LOW_POWER_S0_IDLE_CAPABLE, +}; + +/* + * ACPI 2.0 Generic Address Space definition. + */ +struct Acpi20GenericAddress { + uint8_t address_space_id; + uint8_t register_bit_width; + uint8_t register_bit_offset; + uint8_t reserved; + uint64_t address; +} QEMU_PACKED; +typedef struct Acpi20GenericAddress Acpi20GenericAddress; + +struct AcpiRsdpDescriptor { /* Root System Descriptor Pointer */ + uint64_t signature; /* ACPI signature, contains "RSD PTR " */ + uint8_t checksum; /* To make sum of struct == 0 */ + uint8_t oem_id [6]; /* OEM identification */ + uint8_t revision; /* Must be 0 for 1.0, 2 for 2.0 */ + uint32_t rsdt_physical_address; /* 32-bit physical address of RSDT */ + uint32_t length; /* XSDT Length in bytes including hdr */ + uint64_t xsdt_physical_address; /* 64-bit physical address of XSDT */ + uint8_t extended_checksum; /* Checksum of entire table */ + uint8_t reserved [3]; /* Reserved field must be 0 */ +} QEMU_PACKED; +typedef struct AcpiRsdpDescriptor AcpiRsdpDescriptor; + +/* Table structure from Linux kernel (the ACPI tables are under the + BSD license) */ + + +#define ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \ + uint32_t signature; /* ACPI signature (4 ASCII characters) */ \ + uint32_t length; /* Length of table, in bytes, including header */ \ + uint8_t revision; /* ACPI Specification minor version # */ \ + uint8_t checksum; /* To make sum of entire table == 0 */ \ + uint8_t oem_id [6]; /* OEM identification */ \ + uint8_t oem_table_id [8]; /* OEM table identification */ \ + uint32_t oem_revision; /* OEM revision number */ \ + uint8_t asl_compiler_id [4]; /* ASL compiler vendor ID */ \ + uint32_t asl_compiler_revision; /* ASL compiler revision number */ + + +struct AcpiTableHeader /* ACPI common table header */ +{ + ACPI_TABLE_HEADER_DEF +} QEMU_PACKED; +typedef struct AcpiTableHeader AcpiTableHeader; + +/* + * ACPI Fixed ACPI Description Table (FADT) + */ +#define ACPI_FADT_COMMON_DEF /* FADT common definition */ \ + ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \ + uint32_t firmware_ctrl; /* Physical address of FACS */ \ + uint32_t dsdt; /* Physical address of DSDT */ \ + uint8_t model; /* System Interrupt Model */ \ + uint8_t reserved1; /* Reserved */ \ + uint16_t sci_int; /* System vector of SCI interrupt */ \ + uint32_t smi_cmd; /* Port address of SMI command port */ \ + uint8_t acpi_enable; /* Value to write to smi_cmd to enable ACPI */ \ + uint8_t acpi_disable; /* Value to write to smi_cmd to disable ACPI */ \ + /* Value to write to SMI CMD to enter S4BIOS state */ \ + uint8_t S4bios_req; \ + uint8_t reserved2; /* Reserved - must be zero */ \ + /* Port address of Power Mgt 1a acpi_event Reg Blk */ \ + uint32_t pm1a_evt_blk; \ + /* Port address of Power Mgt 1b acpi_event Reg Blk */ \ + uint32_t pm1b_evt_blk; \ + uint32_t pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */ \ + uint32_t pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */ \ + uint32_t pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */ \ + uint32_t pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */ \ + /* Port addr of General Purpose acpi_event 0 Reg Blk */ \ + uint32_t gpe0_blk; \ + /* Port addr of General Purpose acpi_event 1 Reg Blk */ \ + uint32_t gpe1_blk; \ + uint8_t pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */ \ + uint8_t pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */ \ + uint8_t pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */ \ + uint8_t pm_tmr_len; /* Byte Length of ports at pm_tm_blk */ \ + uint8_t gpe0_blk_len; /* Byte Length of ports at gpe0_blk */ \ + uint8_t gpe1_blk_len; /* Byte Length of ports at gpe1_blk */ \ + uint8_t gpe1_base; /* Offset in gpe model where gpe1 events start */ \ + uint8_t reserved3; /* Reserved */ \ + uint16_t plvl2_lat; /* Worst case HW latency to enter/exit C2 state */ \ + uint16_t plvl3_lat; /* Worst case HW latency to enter/exit C3 state */ \ + uint16_t flush_size; /* Size of area read to flush caches */ \ + uint16_t flush_stride; /* Stride used in flushing caches */ \ + uint8_t duty_offset; /* Bit location of duty cycle field in p_cnt reg */ \ + uint8_t duty_width; /* Bit width of duty cycle field in p_cnt reg */ \ + uint8_t day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */ \ + uint8_t mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */ \ + uint8_t century; /* Index to century in RTC CMOS RAM */ + +struct AcpiFadtDescriptorRev1 +{ + ACPI_FADT_COMMON_DEF + uint8_t reserved4; /* Reserved */ + uint8_t reserved4a; /* Reserved */ + uint8_t reserved4b; /* Reserved */ + uint32_t flags; +} QEMU_PACKED; +typedef struct AcpiFadtDescriptorRev1 AcpiFadtDescriptorRev1; + +struct AcpiGenericAddress { + uint8_t space_id; /* Address space where struct or register exists */ + uint8_t bit_width; /* Size in bits of given register */ + uint8_t bit_offset; /* Bit offset within the register */ + uint8_t access_width; /* Minimum Access size (ACPI 3.0) */ + uint64_t address; /* 64-bit address of struct or register */ +} QEMU_PACKED; + +struct AcpiFadtDescriptorRev5_1 { + ACPI_FADT_COMMON_DEF + /* IA-PC Boot Architecture Flags (see below for individual flags) */ + uint16_t boot_flags; + uint8_t reserved; /* Reserved, must be zero */ + /* Miscellaneous flag bits (see below for individual flags) */ + uint32_t flags; + /* 64-bit address of the Reset register */ + struct AcpiGenericAddress reset_register; + /* Value to write to the reset_register port to reset the system */ + uint8_t reset_value; + /* ARM-Specific Boot Flags (see below for individual flags) (ACPI 5.1) */ + uint16_t arm_boot_flags; + uint8_t minor_revision; /* FADT Minor Revision (ACPI 5.1) */ + uint64_t Xfacs; /* 64-bit physical address of FACS */ + uint64_t Xdsdt; /* 64-bit physical address of DSDT */ + /* 64-bit Extended Power Mgt 1a Event Reg Blk address */ + struct AcpiGenericAddress xpm1a_event_block; + /* 64-bit Extended Power Mgt 1b Event Reg Blk address */ + struct AcpiGenericAddress xpm1b_event_block; + /* 64-bit Extended Power Mgt 1a Control Reg Blk address */ + struct AcpiGenericAddress xpm1a_control_block; + /* 64-bit Extended Power Mgt 1b Control Reg Blk address */ + struct AcpiGenericAddress xpm1b_control_block; + /* 64-bit Extended Power Mgt 2 Control Reg Blk address */ + struct AcpiGenericAddress xpm2_control_block; + /* 64-bit Extended Power Mgt Timer Ctrl Reg Blk address */ + struct AcpiGenericAddress xpm_timer_block; + /* 64-bit Extended General Purpose Event 0 Reg Blk address */ + struct AcpiGenericAddress xgpe0_block; + /* 64-bit Extended General Purpose Event 1 Reg Blk address */ + struct AcpiGenericAddress xgpe1_block; + /* 64-bit Sleep Control register (ACPI 5.0) */ + struct AcpiGenericAddress sleep_control; + /* 64-bit Sleep Status register (ACPI 5.0) */ + struct AcpiGenericAddress sleep_status; +} QEMU_PACKED; + +typedef struct AcpiFadtDescriptorRev5_1 AcpiFadtDescriptorRev5_1; + +enum { + ACPI_FADT_ARM_USE_PSCI_G_0_2 = 0, + ACPI_FADT_ARM_PSCI_USE_HVC = 1, +}; + +/* + * Serial Port Console Redirection Table (SPCR), Rev. 1.02 + * + * For .interface_type see Debug Port Table 2 (DBG2) serial port + * subtypes in Table 3, Rev. May 22, 2012 + */ +struct AcpiSerialPortConsoleRedirection { + ACPI_TABLE_HEADER_DEF + uint8_t interface_type; + uint8_t reserved1[3]; + struct AcpiGenericAddress base_address; + uint8_t interrupt_types; + uint8_t irq; + uint32_t gsi; + uint8_t baud; + uint8_t parity; + uint8_t stopbits; + uint8_t flowctrl; + uint8_t term_type; + uint8_t reserved2; + uint16_t pci_device_id; + uint16_t pci_vendor_id; + uint8_t pci_bus; + uint8_t pci_slot; + uint8_t pci_func; + uint32_t pci_flags; + uint8_t pci_seg; + uint32_t reserved3; +} QEMU_PACKED; +typedef struct AcpiSerialPortConsoleRedirection + AcpiSerialPortConsoleRedirection; + +/* + * ACPI 1.0 Root System Description Table (RSDT) + */ +struct AcpiRsdtDescriptorRev1 +{ + ACPI_TABLE_HEADER_DEF /* ACPI common table header */ + uint32_t table_offset_entry[0]; /* Array of pointers to other */ + /* ACPI tables */ +} QEMU_PACKED; +typedef struct AcpiRsdtDescriptorRev1 AcpiRsdtDescriptorRev1; + +/* + * ACPI 1.0 Firmware ACPI Control Structure (FACS) + */ +struct AcpiFacsDescriptorRev1 +{ + uint32_t signature; /* ACPI Signature */ + uint32_t length; /* Length of structure, in bytes */ + uint32_t hardware_signature; /* Hardware configuration signature */ + uint32_t firmware_waking_vector; /* ACPI OS waking vector */ + uint32_t global_lock; /* Global Lock */ + uint32_t flags; + uint8_t resverved3 [40]; /* Reserved - must be zero */ +} QEMU_PACKED; +typedef struct AcpiFacsDescriptorRev1 AcpiFacsDescriptorRev1; + +/* + * Differentiated System Description Table (DSDT) + */ + +/* + * MADT values and structures + */ + +/* Values for MADT PCATCompat */ + +#define ACPI_DUAL_PIC 0 +#define ACPI_MULTIPLE_APIC 1 + +/* Master MADT */ + +struct AcpiMultipleApicTable +{ + ACPI_TABLE_HEADER_DEF /* ACPI common table header */ + uint32_t local_apic_address; /* Physical address of local APIC */ + uint32_t flags; +} QEMU_PACKED; +typedef struct AcpiMultipleApicTable AcpiMultipleApicTable; + +/* Values for Type in APIC sub-headers */ + +#define ACPI_APIC_PROCESSOR 0 +#define ACPI_APIC_IO 1 +#define ACPI_APIC_XRUPT_OVERRIDE 2 +#define ACPI_APIC_NMI 3 +#define ACPI_APIC_LOCAL_NMI 4 +#define ACPI_APIC_ADDRESS_OVERRIDE 5 +#define ACPI_APIC_IO_SAPIC 6 +#define ACPI_APIC_LOCAL_SAPIC 7 +#define ACPI_APIC_XRUPT_SOURCE 8 +#define ACPI_APIC_LOCAL_X2APIC 9 +#define ACPI_APIC_LOCAL_X2APIC_NMI 10 +#define ACPI_APIC_GENERIC_INTERRUPT 11 +#define ACPI_APIC_GENERIC_DISTRIBUTOR 12 +#define ACPI_APIC_GENERIC_MSI_FRAME 13 +#define ACPI_APIC_GENERIC_REDISTRIBUTOR 14 +#define ACPI_APIC_RESERVED 15 /* 15 and greater are reserved */ + +/* + * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE) + */ +#define ACPI_SUB_HEADER_DEF /* Common ACPI sub-structure header */\ + uint8_t type; \ + uint8_t length; + +/* Sub-structures for MADT */ + +struct AcpiMadtProcessorApic +{ + ACPI_SUB_HEADER_DEF + uint8_t processor_id; /* ACPI processor id */ + uint8_t local_apic_id; /* Processor's local APIC id */ + uint32_t flags; +} QEMU_PACKED; +typedef struct AcpiMadtProcessorApic AcpiMadtProcessorApic; + +struct AcpiMadtIoApic +{ + ACPI_SUB_HEADER_DEF + uint8_t io_apic_id; /* I/O APIC ID */ + uint8_t reserved; /* Reserved - must be zero */ + uint32_t address; /* APIC physical address */ + uint32_t interrupt; /* Global system interrupt where INTI + * lines start */ +} QEMU_PACKED; +typedef struct AcpiMadtIoApic AcpiMadtIoApic; + +struct AcpiMadtIntsrcovr { + ACPI_SUB_HEADER_DEF + uint8_t bus; + uint8_t source; + uint32_t gsi; + uint16_t flags; +} QEMU_PACKED; +typedef struct AcpiMadtIntsrcovr AcpiMadtIntsrcovr; + +struct AcpiMadtLocalNmi { + ACPI_SUB_HEADER_DEF + uint8_t processor_id; /* ACPI processor id */ + uint16_t flags; /* MPS INTI flags */ + uint8_t lint; /* Local APIC LINT# */ +} QEMU_PACKED; +typedef struct AcpiMadtLocalNmi AcpiMadtLocalNmi; + +struct AcpiMadtGenericInterrupt { + ACPI_SUB_HEADER_DEF + uint16_t reserved; + uint32_t cpu_interface_number; + uint32_t uid; + uint32_t flags; + uint32_t parking_version; + uint32_t performance_interrupt; + uint64_t parked_address; + uint64_t base_address; + uint64_t gicv_base_address; + uint64_t gich_base_address; + uint32_t vgic_interrupt; + uint64_t gicr_base_address; + uint64_t arm_mpidr; +} QEMU_PACKED; + +typedef struct AcpiMadtGenericInterrupt AcpiMadtGenericInterrupt; + +struct AcpiMadtGenericDistributor { + ACPI_SUB_HEADER_DEF + uint16_t reserved; + uint32_t gic_id; + uint64_t base_address; + uint32_t global_irq_base; + uint32_t reserved2; +} QEMU_PACKED; + +typedef struct AcpiMadtGenericDistributor AcpiMadtGenericDistributor; + +struct AcpiMadtGenericMsiFrame { + ACPI_SUB_HEADER_DEF + uint16_t reserved; + uint32_t gic_msi_frame_id; + uint64_t base_address; + uint32_t flags; + uint16_t spi_count; + uint16_t spi_base; +} QEMU_PACKED; + +typedef struct AcpiMadtGenericMsiFrame AcpiMadtGenericMsiFrame; + +/* + * Generic Timer Description Table (GTDT) + */ + +#define ACPI_GTDT_INTERRUPT_MODE (1 << 0) +#define ACPI_GTDT_INTERRUPT_POLARITY (1 << 1) +#define ACPI_GTDT_ALWAYS_ON (1 << 2) + +/* Triggering */ + +#define ACPI_LEVEL_SENSITIVE ((uint8_t) 0x00) +#define ACPI_EDGE_SENSITIVE ((uint8_t) 0x01) + +/* Polarity */ + +#define ACPI_ACTIVE_HIGH ((uint8_t) 0x00) +#define ACPI_ACTIVE_LOW ((uint8_t) 0x01) +#define ACPI_ACTIVE_BOTH ((uint8_t) 0x02) + +struct AcpiGenericTimerTable { + ACPI_TABLE_HEADER_DEF + uint64_t counter_block_addresss; + uint32_t reserved; + uint32_t secure_el1_interrupt; + uint32_t secure_el1_flags; + uint32_t non_secure_el1_interrupt; + uint32_t non_secure_el1_flags; + uint32_t virtual_timer_interrupt; + uint32_t virtual_timer_flags; + uint32_t non_secure_el2_interrupt; + uint32_t non_secure_el2_flags; + uint64_t counter_read_block_address; + uint32_t platform_timer_count; + uint32_t platform_timer_offset; +} QEMU_PACKED; +typedef struct AcpiGenericTimerTable AcpiGenericTimerTable; + +/* + * HPET Description Table + */ +struct Acpi20Hpet { + ACPI_TABLE_HEADER_DEF /* ACPI common table header */ + uint32_t timer_block_id; + Acpi20GenericAddress addr; + uint8_t hpet_number; + uint16_t min_tick; + uint8_t page_protect; +} QEMU_PACKED; +typedef struct Acpi20Hpet Acpi20Hpet; + +/* + * SRAT (NUMA topology description) table + */ + +struct AcpiSystemResourceAffinityTable +{ + ACPI_TABLE_HEADER_DEF + uint32_t reserved1; + uint32_t reserved2[2]; +} QEMU_PACKED; +typedef struct AcpiSystemResourceAffinityTable AcpiSystemResourceAffinityTable; + +#define ACPI_SRAT_PROCESSOR 0 +#define ACPI_SRAT_MEMORY 1 + +struct AcpiSratProcessorAffinity +{ + ACPI_SUB_HEADER_DEF + uint8_t proximity_lo; + uint8_t local_apic_id; + uint32_t flags; + uint8_t local_sapic_eid; + uint8_t proximity_hi[3]; + uint32_t reserved; +} QEMU_PACKED; +typedef struct AcpiSratProcessorAffinity AcpiSratProcessorAffinity; + +struct AcpiSratMemoryAffinity +{ + ACPI_SUB_HEADER_DEF + uint8_t proximity[4]; + uint16_t reserved1; + uint64_t base_addr; + uint64_t range_length; + uint32_t reserved2; + uint32_t flags; + uint32_t reserved3[2]; +} QEMU_PACKED; +typedef struct AcpiSratMemoryAffinity AcpiSratMemoryAffinity; + +/* PCI fw r3.0 MCFG table. */ +/* Subtable */ +struct AcpiMcfgAllocation { + uint64_t address; /* Base address, processor-relative */ + uint16_t pci_segment; /* PCI segment group number */ + uint8_t start_bus_number; /* Starting PCI Bus number */ + uint8_t end_bus_number; /* Final PCI Bus number */ + uint32_t reserved; +} QEMU_PACKED; +typedef struct AcpiMcfgAllocation AcpiMcfgAllocation; + +struct AcpiTableMcfg { + ACPI_TABLE_HEADER_DEF; + uint8_t reserved[8]; + AcpiMcfgAllocation allocation[0]; +} QEMU_PACKED; +typedef struct AcpiTableMcfg AcpiTableMcfg; + +/* + * TCPA Description Table + * + * Following Level 00, Rev 00.37 of specs: + * http://www.trustedcomputinggroup.org/resources/tcg_acpi_specification + */ +struct Acpi20Tcpa { + ACPI_TABLE_HEADER_DEF /* ACPI common table header */ + uint16_t platform_class; + uint32_t log_area_minimum_length; + uint64_t log_area_start_address; +} QEMU_PACKED; +typedef struct Acpi20Tcpa Acpi20Tcpa; + +/* + * TPM2 + * + * Following Level 00, Rev 00.37 of specs: + * http://www.trustedcomputinggroup.org/resources/tcg_acpi_specification + */ +struct Acpi20TPM2 { + ACPI_TABLE_HEADER_DEF + uint16_t platform_class; + uint16_t reserved; + uint64_t control_area_address; + uint32_t start_method; +} QEMU_PACKED; +typedef struct Acpi20TPM2 Acpi20TPM2; + +/* DMAR - DMA Remapping table r2.2 */ +struct AcpiTableDmar { + ACPI_TABLE_HEADER_DEF + uint8_t host_address_width; /* Maximum DMA physical addressability */ + uint8_t flags; + uint8_t reserved[10]; +} QEMU_PACKED; +typedef struct AcpiTableDmar AcpiTableDmar; + +/* Masks for Flags field above */ +#define ACPI_DMAR_INTR_REMAP 1 +#define ACPI_DMAR_X2APIC_OPT_OUT (1 << 1) + +/* Values for sub-structure type for DMAR */ +enum { + ACPI_DMAR_TYPE_HARDWARE_UNIT = 0, /* DRHD */ + ACPI_DMAR_TYPE_RESERVED_MEMORY = 1, /* RMRR */ + ACPI_DMAR_TYPE_ATSR = 2, /* ATSR */ + ACPI_DMAR_TYPE_HARDWARE_AFFINITY = 3, /* RHSR */ + ACPI_DMAR_TYPE_ANDD = 4, /* ANDD */ + ACPI_DMAR_TYPE_RESERVED = 5 /* Reserved for furture use */ +}; + +/* + * Sub-structures for DMAR + */ +/* Type 0: Hardware Unit Definition */ +struct AcpiDmarHardwareUnit { + uint16_t type; + uint16_t length; + uint8_t flags; + uint8_t reserved; + uint16_t pci_segment; /* The PCI Segment associated with this unit */ + uint64_t address; /* Base address of remapping hardware register-set */ +} QEMU_PACKED; +typedef struct AcpiDmarHardwareUnit AcpiDmarHardwareUnit; + +/* Masks for Flags field above */ +#define ACPI_DMAR_INCLUDE_PCI_ALL 1 + +#endif diff --git a/include/hw/acpi/acpi.h b/include/hw/acpi/acpi.h index 1f678b4bf2..b20bd55a67 100644 --- a/include/hw/acpi/acpi.h +++ b/include/hw/acpi/acpi.h @@ -91,6 +91,13 @@ /* PM2_CNT */ #define ACPI_BITMASK_ARB_DISABLE 0x0001 +/* These values are part of guest ABI, and can not be changed */ +typedef enum { + ACPI_PCI_HOTPLUG_STATUS = 2, + ACPI_CPU_HOTPLUG_STATUS = 4, + ACPI_MEMORY_HOTPLUG_STATUS = 8, +} AcpiGPEStatusBits; + /* structs */ typedef struct ACPIPMTimer ACPIPMTimer; typedef struct ACPIPM1EVT ACPIPM1EVT; @@ -160,7 +167,8 @@ void acpi_pm1_evt_init(ACPIREGS *ar, acpi_update_sci_fn update_sci, MemoryRegion *parent); /* PM1a_CNT: piix and ich9 don't implement PM1b CNT. */ -void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent, uint8_t s4_val); +void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent, + bool disable_s3, bool disable_s4, uint8_t s4_val); void acpi_pm1_cnt_update(ACPIREGS *ar, bool sci_enable, bool sci_disable); void acpi_pm1_cnt_reset(ACPIREGS *ar); @@ -172,6 +180,9 @@ void acpi_gpe_reset(ACPIREGS *ar); void acpi_gpe_ioport_writeb(ACPIREGS *ar, uint32_t addr, uint32_t val); uint32_t acpi_gpe_ioport_readb(ACPIREGS *ar, uint32_t addr); +void acpi_send_gpe_event(ACPIREGS *ar, qemu_irq irq, + AcpiGPEStatusBits status); + void acpi_update_sci(ACPIREGS *acpi_regs, qemu_irq irq); /* acpi.c */ diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h new file mode 100644 index 0000000000..e3afa13678 --- /dev/null +++ b/include/hw/acpi/aml-build.h @@ -0,0 +1,290 @@ +#ifndef HW_ACPI_GEN_UTILS_H +#define HW_ACPI_GEN_UTILS_H + +#include <stdint.h> +#include <glib.h> +#include "qemu/compiler.h" +#include "hw/acpi/acpi-defs.h" + +/* Reserve RAM space for tables: add another order of magnitude. */ +#define ACPI_BUILD_TABLE_MAX_SIZE 0x200000 + +#define ACPI_BUILD_APPNAME "Bochs" +#define ACPI_BUILD_APPNAME6 "BOCHS " +#define ACPI_BUILD_APPNAME4 "BXPC" + +#define ACPI_BUILD_TABLE_FILE "etc/acpi/tables" +#define ACPI_BUILD_RSDP_FILE "etc/acpi/rsdp" +#define ACPI_BUILD_TPMLOG_FILE "etc/tpm/log" + +typedef enum { + AML_NO_OPCODE = 0,/* has only data */ + AML_OPCODE, /* has opcode optionally followed by data */ + AML_PACKAGE, /* has opcode and uses PkgLength for its length */ + AML_EXT_PACKAGE, /* Same as AML_PACKAGE but also has 'ExOpPrefix' */ + AML_BUFFER, /* data encoded as 'DefBuffer' */ + AML_RES_TEMPLATE, /* encoded as ResourceTemplate macro */ +} AmlBlockFlags; + +struct Aml { + GArray *buf; + + /*< private >*/ + uint8_t op; + AmlBlockFlags block_flags; +}; +typedef struct Aml Aml; + +typedef enum { + AML_DECODE10 = 0, + AML_DECODE16 = 1, +} AmlIODecode; + +typedef enum { + AML_ANY_ACC = 0, + AML_BYTE_ACC = 1, + AML_WORD_ACC = 2, + AML_DWORD_ACC = 3, + AML_QWORD_ACC = 4, + AML_BUFFER_ACC = 5, +} AmlAccessType; + +typedef enum { + AML_PRESERVE = 0, + AML_WRITE_AS_ONES = 1, + AML_WRITE_AS_ZEROS = 2, +} AmlUpdateRule; + +typedef enum { + AML_SYSTEM_MEMORY = 0X00, + AML_SYSTEM_IO = 0X01, +} AmlRegionSpace; + +typedef enum { + AML_MEMORY_RANGE = 0, + AML_IO_RANGE = 1, + AML_BUS_NUMBER_RANGE = 2, +} AmlResourceType; + +typedef enum { + AML_SUB_DECODE = 1 << 1, + AML_POS_DECODE = 0 +} AmlDecode; + +typedef enum { + AML_MAX_FIXED = 1 << 3, + AML_MAX_NOT_FIXED = 0, +} AmlMaxFixed; + +typedef enum { + AML_MIN_FIXED = 1 << 2, + AML_MIN_NOT_FIXED = 0 +} AmlMinFixed; + +/* + * ACPI 1.0b: Table 6-26 I/O Resource Flag (Resource Type = 1) Definitions + * _RNG field definition + */ +typedef enum { + AML_ISA_ONLY = 1, + AML_NON_ISA_ONLY = 2, + AML_ENTIRE_RANGE = 3, +} AmlISARanges; + +/* + * ACPI 1.0b: Table 6-25 Memory Resource Flag (Resource Type = 0) Definitions + * _MEM field definition + */ +typedef enum { + AML_NON_CACHEABLE = 0, + AML_CACHEABLE = 1, + AML_WRITE_COMBINING = 2, + AML_PREFETCHABLE = 3, +} AmlCacheable; + +/* + * ACPI 1.0b: Table 6-25 Memory Resource Flag (Resource Type = 0) Definitions + * _RW field definition + */ +typedef enum { + AML_READ_ONLY = 0, + AML_READ_WRITE = 1, +} AmlReadAndWrite; + +/* + * ACPI 5.0: Table 6-187 Extended Interrupt Descriptor Definition + * Interrupt Vector Flags Bits[0] Consumer/Producer + */ +typedef enum { + AML_CONSUMER_PRODUCER = 0, + AML_CONSUMER = 1, +} AmlConsumerAndProducer; + +/* + * ACPI 5.0: Table 6-187 Extended Interrupt Descriptor Definition + * _HE field definition + */ +typedef enum { + AML_LEVEL = 0, + AML_EDGE = 1, +} AmlLevelAndEdge; + +/* + * ACPI 5.0: Table 6-187 Extended Interrupt Descriptor Definition + * _LL field definition + */ +typedef enum { + AML_ACTIVE_HIGH = 0, + AML_ACTIVE_LOW = 1, +} AmlActiveHighAndLow; + +/* + * ACPI 5.0: Table 6-187 Extended Interrupt Descriptor Definition + * _SHR field definition + */ +typedef enum { + AML_EXCLUSIVE = 0, + AML_SHARED = 1, + AML_EXCLUSIVE_AND_WAKE = 2, + AML_SHARED_AND_WAKE = 3, +} AmlShared; + +typedef +struct AcpiBuildTables { + GArray *table_data; + GArray *rsdp; + GArray *tcpalog; + GArray *linker; +} AcpiBuildTables; + +/** + * init_aml_allocator: + * + * Called for initializing API allocator which allow to use + * AML API. + * Returns: toplevel container which accumulates all other + * AML elements for a table. + */ +Aml *init_aml_allocator(void); + +/** + * free_aml_allocator: + * + * Releases all elements used by AML API, frees associated memory + * and invalidates AML allocator. After this call @init_aml_allocator + * should be called again if AML API is to be used again. + */ +void free_aml_allocator(void); + +/** + * aml_append: + * @parent_ctx: context to which @child element is added + * @child: element that is copied into @parent_ctx context + * + * Joins Aml elements together and helps to construct AML tables + * Examle of usage: + * Aml *table = aml_def_block("SSDT", ...); + * Aml *sb = aml_scope("\\_SB"); + * Aml *dev = aml_device("PCI0"); + * + * aml_append(dev, aml_name_decl("HID", aml_eisaid("PNP0A03"))); + * aml_append(sb, dev); + * aml_append(table, sb); + */ +void aml_append(Aml *parent_ctx, Aml *child); + +/* non block AML object primitives */ +Aml *aml_name(const char *name_format, ...) GCC_FMT_ATTR(1, 2); +Aml *aml_name_decl(const char *name, Aml *val); +Aml *aml_return(Aml *val); +Aml *aml_int(const uint64_t val); +Aml *aml_arg(int pos); +Aml *aml_store(Aml *val, Aml *target); +Aml *aml_and(Aml *arg1, Aml *arg2); +Aml *aml_or(Aml *arg1, Aml *arg2); +Aml *aml_shiftleft(Aml *arg1, Aml *count); +Aml *aml_shiftright(Aml *arg1, Aml *count); +Aml *aml_lless(Aml *arg1, Aml *arg2); +Aml *aml_add(Aml *arg1, Aml *arg2); +Aml *aml_increment(Aml *arg); +Aml *aml_index(Aml *arg1, Aml *idx); +Aml *aml_notify(Aml *arg1, Aml *arg2); +Aml *aml_call1(const char *method, Aml *arg1); +Aml *aml_call2(const char *method, Aml *arg1, Aml *arg2); +Aml *aml_call3(const char *method, Aml *arg1, Aml *arg2, Aml *arg3); +Aml *aml_call4(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4); +Aml *aml_memory32_fixed(uint32_t addr, uint32_t size, + AmlReadAndWrite read_and_write); +Aml *aml_interrupt(AmlConsumerAndProducer con_and_pro, + AmlLevelAndEdge level_and_edge, + AmlActiveHighAndLow high_and_low, AmlShared shared, + uint32_t irq); +Aml *aml_io(AmlIODecode dec, uint16_t min_base, uint16_t max_base, + uint8_t aln, uint8_t len); +Aml *aml_operation_region(const char *name, AmlRegionSpace rs, + uint32_t offset, uint32_t len); +Aml *aml_irq_no_flags(uint8_t irq); +Aml *aml_named_field(const char *name, unsigned length); +Aml *aml_reserved_field(unsigned length); +Aml *aml_local(int num); +Aml *aml_string(const char *name_format, ...) GCC_FMT_ATTR(1, 2); +Aml *aml_lnot(Aml *arg); +Aml *aml_equal(Aml *arg1, Aml *arg2); +Aml *aml_processor(uint8_t proc_id, uint32_t pblk_addr, uint8_t pblk_len, + const char *name_format, ...) GCC_FMT_ATTR(4, 5); +Aml *aml_eisaid(const char *str); +Aml *aml_word_bus_number(AmlMinFixed min_fixed, AmlMaxFixed max_fixed, + AmlDecode dec, uint16_t addr_gran, + uint16_t addr_min, uint16_t addr_max, + uint16_t addr_trans, uint16_t len); +Aml *aml_word_io(AmlMinFixed min_fixed, AmlMaxFixed max_fixed, + AmlDecode dec, AmlISARanges isa_ranges, + uint16_t addr_gran, uint16_t addr_min, + uint16_t addr_max, uint16_t addr_trans, + uint16_t len); +Aml *aml_dword_io(AmlMinFixed min_fixed, AmlMaxFixed max_fixed, + AmlDecode dec, AmlISARanges isa_ranges, + uint32_t addr_gran, uint32_t addr_min, + uint32_t addr_max, uint32_t addr_trans, + uint32_t len); +Aml *aml_dword_memory(AmlDecode dec, AmlMinFixed min_fixed, + AmlMaxFixed max_fixed, AmlCacheable cacheable, + AmlReadAndWrite read_and_write, + uint32_t addr_gran, uint32_t addr_min, + uint32_t addr_max, uint32_t addr_trans, + uint32_t len); +Aml *aml_qword_memory(AmlDecode dec, AmlMinFixed min_fixed, + AmlMaxFixed max_fixed, AmlCacheable cacheable, + AmlReadAndWrite read_and_write, + uint64_t addr_gran, uint64_t addr_min, + uint64_t addr_max, uint64_t addr_trans, + uint64_t len); + +/* Block AML object primitives */ +Aml *aml_scope(const char *name_format, ...) GCC_FMT_ATTR(1, 2); +Aml *aml_device(const char *name_format, ...) GCC_FMT_ATTR(1, 2); +Aml *aml_method(const char *name, int arg_count); +Aml *aml_if(Aml *predicate); +Aml *aml_else(void); +Aml *aml_while(Aml *predicate); +Aml *aml_package(uint8_t num_elements); +Aml *aml_buffer(int buffer_size, uint8_t *byte_list); +Aml *aml_resource_template(void); +Aml *aml_field(const char *name, AmlAccessType type, AmlUpdateRule rule); +Aml *aml_create_dword_field(Aml *srcbuf, Aml *index, const char *name); +Aml *aml_varpackage(uint32_t num_elements); +Aml *aml_touuid(const char *uuid); +Aml *aml_unicode(const char *str); + +void +build_header(GArray *linker, GArray *table_data, + AcpiTableHeader *h, const char *sig, int len, uint8_t rev); +void *acpi_data_push(GArray *table_data, unsigned size); +unsigned acpi_data_len(GArray *table); +void acpi_add_table(GArray *table_offsets, GArray *table_data); +void acpi_build_tables_init(AcpiBuildTables *tables); +void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre); +void +build_rsdt(GArray *table_data, GArray *linker, GArray *table_offsets); + +#endif diff --git a/include/hw/acpi/bios-linker-loader.h b/include/hw/acpi/bios-linker-loader.h new file mode 100644 index 0000000000..498c0af773 --- /dev/null +++ b/include/hw/acpi/bios-linker-loader.h @@ -0,0 +1,27 @@ +#ifndef BIOS_LINKER_LOADER_H +#define BIOS_LINKER_LOADER_H + +#include <glib.h> +#include <stdbool.h> +#include <inttypes.h> + +GArray *bios_linker_loader_init(void); + +void bios_linker_loader_alloc(GArray *linker, + const char *file, + uint32_t alloc_align, + bool alloc_fseg); + +void bios_linker_loader_add_checksum(GArray *linker, const char *file, + void *table, + void *start, unsigned size, + uint8_t *checksum); + +void bios_linker_loader_add_pointer(GArray *linker, + const char *dest_file, + const char *src_file, + GArray *table, void *pointer, + uint8_t pointer_size); + +void *bios_linker_loader_cleanup(GArray *linker); +#endif diff --git a/include/hw/acpi/ich9.h b/include/hw/acpi/ich9.h index fe975e6624..345fd8d92b 100644 --- a/include/hw/acpi/ich9.h +++ b/include/hw/acpi/ich9.h @@ -25,6 +25,7 @@ #include "hw/acpi/cpu_hotplug.h" #include "hw/acpi/memory_hotplug.h" #include "hw/acpi/acpi_dev_interface.h" +#include "hw/acpi/tco.h" typedef struct ICH9LPCPMRegs { /* @@ -39,6 +40,7 @@ typedef struct ICH9LPCPMRegs { MemoryRegion io_smi; uint32_t smi_en; + uint32_t smi_en_wmask; uint32_t smi_sts; qemu_irq irq; /* SCI */ @@ -49,16 +51,30 @@ typedef struct ICH9LPCPMRegs { AcpiCpuHotplug gpe_cpu; MemHotplugState acpi_memory_hotplug; + + uint8_t disable_s3; + uint8_t disable_s4; + uint8_t s4_val; + uint8_t smm_enabled; + bool enable_tco; + TCOIORegs tco_regs; } ICH9LPCPMRegs; void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm, + bool smm_enabled, + bool enable_tco, qemu_irq sci_irq); + void ich9_pm_iospace_update(ICH9LPCPMRegs *pm, uint32_t pm_io_base); extern const VMStateDescription vmstate_ich9_pm; void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp); void ich9_pm_device_plug_cb(ICH9LPCPMRegs *pm, DeviceState *dev, Error **errp); +void ich9_pm_device_unplug_request_cb(ICH9LPCPMRegs *pm, DeviceState *dev, + Error **errp); +void ich9_pm_device_unplug_cb(ICH9LPCPMRegs *pm, DeviceState *dev, + Error **errp); void ich9_pm_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list); #endif /* HW_ACPI_ICH9_H */ diff --git a/include/hw/acpi/memory_hotplug.h b/include/hw/acpi/memory_hotplug.h index 7bbf8a0064..1342adb08f 100644 --- a/include/hw/acpi/memory_hotplug.h +++ b/include/hw/acpi/memory_hotplug.h @@ -5,12 +5,17 @@ #include "hw/acpi/acpi.h" #include "migration/vmstate.h" -#define ACPI_MEMORY_HOTPLUG_STATUS 8 - +/** + * MemStatus: + * @is_removing: the memory device in slot has been requested to be ejected. + * + * This structure stores memory device's status. + */ typedef struct MemStatus { DeviceState *dimm; bool is_enabled; bool is_inserting; + bool is_removing; uint32_t ost_event; uint32_t ost_status; } MemStatus; @@ -28,6 +33,11 @@ void acpi_memory_hotplug_init(MemoryRegion *as, Object *owner, void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st, DeviceState *dev, Error **errp); +void acpi_memory_unplug_request_cb(ACPIREGS *ar, qemu_irq irq, + MemHotplugState *mem_st, + DeviceState *dev, Error **errp); +void acpi_memory_unplug_cb(MemHotplugState *mem_st, + DeviceState *dev, Error **errp); extern const VMStateDescription vmstate_memory_hotplug; #define VMSTATE_MEMORY_HOTPLUG(memhp, state) \ diff --git a/include/hw/acpi/pc-hotplug.h b/include/hw/acpi/pc-hotplug.h index b9db29576c..77b1569007 100644 --- a/include/hw/acpi/pc-hotplug.h +++ b/include/hw/acpi/pc-hotplug.h @@ -16,7 +16,6 @@ * ONLY DEFINEs are permited in this file since it's shared * between C and ASL code. */ -#define ACPI_CPU_HOTPLUG_STATUS 4 /* Limit for CPU arch IDs for CPU hotplug. All hotpluggable CPUs should * have CPUClass.get_arch_id() < ACPI_CPU_HOTPLUG_ID_LIMIT. @@ -28,6 +27,7 @@ #define ICH9_CPU_HOTPLUG_IO_BASE 0x0CD8 #define PIIX4_CPU_HOTPLUG_IO_BASE 0xaf00 +#define CPU_HOTPLUG_RESOURCE_DEVICE PRES #define ACPI_MEMORY_HOTPLUG_IO_LEN 24 #define ACPI_MEMORY_HOTPLUG_BASE 0x0a00 @@ -42,6 +42,8 @@ #define MEMORY_SLOT_PROXIMITY MPX #define MEMORY_SLOT_ENABLED MES #define MEMORY_SLOT_INSERT_EVENT MINS +#define MEMORY_SLOT_REMOVE_EVENT MRMV +#define MEMORY_SLOT_EJECT MEJ #define MEMORY_SLOT_SLECTOR MSEL #define MEMORY_SLOT_OST_EVENT MOEV #define MEMORY_SLOT_OST_STATUS MOSC @@ -50,6 +52,7 @@ #define MEMORY_SLOT_CRS_METHOD MCRS #define MEMORY_SLOT_OST_METHOD MOST #define MEMORY_SLOT_PROXIMITY_METHOD MPXM +#define MEMORY_SLOT_EJECT_METHOD MEJ0 #define MEMORY_SLOT_NOTIFY_METHOD MTFY #define MEMORY_SLOT_SCAN_METHOD MSCN diff --git a/include/hw/acpi/pcihp.h b/include/hw/acpi/pcihp.h index 9323838319..f3526d4aaf 100644 --- a/include/hw/acpi/pcihp.h +++ b/include/hw/acpi/pcihp.h @@ -32,6 +32,9 @@ #include "hw/acpi/acpi.h" #include "migration/vmstate.h" +#define ACPI_PCIHP_IO_BASE_PROP "acpi-pcihp-io-base" +#define ACPI_PCIHP_IO_LEN_PROP "acpi-pcihp-io-len" + typedef struct AcpiPciHpPciStatus { uint32_t up; uint32_t down; @@ -48,9 +51,11 @@ typedef struct AcpiPciHpState { PCIBus *root; MemoryRegion io; bool legacy_piix; + uint16_t io_base; + uint16_t io_len; } AcpiPciHpState; -void acpi_pcihp_init(AcpiPciHpState *, PCIBus *root, +void acpi_pcihp_init(Object *owner, AcpiPciHpState *, PCIBus *root, MemoryRegion *address_space_io, bool bridges_enabled); void acpi_pcihp_device_plug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s, diff --git a/include/hw/acpi/tco.h b/include/hw/acpi/tco.h new file mode 100644 index 0000000000..c63afc8ca3 --- /dev/null +++ b/include/hw/acpi/tco.h @@ -0,0 +1,82 @@ +/* + * QEMU ICH9 TCO emulation + * + * Copyright (c) 2015 Paulo Alcantara <pcacjr@zytor.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. + */ +#ifndef HW_ACPI_TCO_H +#define HW_ACPI_TCO_H + +#include "qemu/typedefs.h" +#include "qemu-common.h" + +/* As per ICH9 spec, the internal timer has an error of ~0.6s on every tick */ +#define TCO_TICK_NSEC 600000000LL + +/* TCO I/O register offsets */ +enum { + TCO_RLD = 0x00, + TCO_DAT_IN = 0x02, + TCO_DAT_OUT = 0x03, + TCO1_STS = 0x04, + TCO2_STS = 0x06, + TCO1_CNT = 0x08, + TCO2_CNT = 0x0a, + TCO_MESSAGE1 = 0x0c, + TCO_MESSAGE2 = 0x0d, + TCO_WDCNT = 0x0e, + SW_IRQ_GEN = 0x10, + TCO_TMR = 0x12, +}; + +/* TCO I/O register control/status bits */ +enum { + SW_TCO_SMI = 1 << 1, + TCO_INT_STS = 1 << 2, + TCO_LOCK = 1 << 12, + TCO_TMR_HLT = 1 << 11, + TCO_TIMEOUT = 1 << 3, + TCO_SECOND_TO_STS = 1 << 1, + TCO_BOOT_STS = 1 << 2, +}; + +/* TCO I/O registers mask bits */ +enum { + TCO_RLD_MASK = 0x3ff, + TCO1_STS_MASK = 0xe870, + TCO2_STS_MASK = 0xfff8, + TCO1_CNT_MASK = 0xfeff, + TCO_TMR_MASK = 0x3ff, +}; + +typedef struct TCOIORegs { + struct { + uint16_t rld; + uint8_t din; + uint8_t dout; + uint16_t sts1; + uint16_t sts2; + uint16_t cnt1; + uint16_t cnt2; + uint8_t msg1; + uint8_t msg2; + uint8_t wdcnt; + uint16_t tmr; + } tco; + uint8_t sw_irq_gen; + + QEMUTimer *tco_timer; + int64_t expire_time; + uint8_t timeouts_no; + + MemoryRegion io; +} TCOIORegs; + +/* tco.c */ +void acpi_pm_tco_init(TCOIORegs *tr, MemoryRegion *parent); + +extern const VMStateDescription vmstate_tco_io_sts; + +#endif /* HW_ACPI_TCO_H */ diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h index 792fcbf5b1..6d516c6a7f 100644 --- a/include/hw/acpi/tpm.h +++ b/include/hw/acpi/tpm.h @@ -26,4 +26,9 @@ #define TPM_TCPA_ACPI_CLASS_CLIENT 0 #define TPM_TCPA_ACPI_CLASS_SERVER 1 +#define TPM2_ACPI_CLASS_CLIENT 0 +#define TPM2_ACPI_CLASS_SERVER 1 + +#define TPM2_START_METHOD_MMIO 6 + #endif /* HW_ACPI_TPM_H */ diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h index cefc9e6988..4dcd4f9b63 100644 --- a/include/hw/arm/arm.h +++ b/include/hw/arm/arm.h @@ -13,12 +13,22 @@ #include "exec/memory.h" #include "hw/irq.h" +#include "qemu/notify.h" +#include "cpu.h" /* armv7m.c */ -qemu_irq *armv7m_init(MemoryRegion *system_memory, - int flash_size, int sram_size, +qemu_irq *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq, const char *kernel_filename, const char *cpu_model); +/* + * struct used as a parameter of the arm_load_kernel machine init + * done notifier + */ +typedef struct { + Notifier notifier; /* actual notifier */ + ARMCPU *cpu; /* handle to the first cpu object */ +} ArmLoadKernelNotifier; + /* arm_boot.c */ struct arm_boot_info { uint64_t ram_size; @@ -37,6 +47,10 @@ struct arm_boot_info { hwaddr gic_cpu_if_addr; int nb_cpus; int board_id; + /* ARM machines that support the ARM Security Extensions use this field to + * control whether Linux is booted as secure(true) or non-secure(false). + */ + bool secure_boot; int (*atag_board)(const struct arm_boot_info *info, void *p); /* multicore boards that use the default secondary core boot functions * can ignore these two function calls. If the default functions won't @@ -61,12 +75,35 @@ struct arm_boot_info { * the user it should implement this hook. */ void (*modify_dtb)(const struct arm_boot_info *info, void *fdt); + /* machine init done notifier executing arm_load_dtb */ + ArmLoadKernelNotifier load_kernel_notifier; /* Used internally by arm_boot.c */ int is_linux; hwaddr initrd_start; hwaddr initrd_size; hwaddr entry; + + /* Boot firmware has been loaded, typically at address 0, with -bios or + * -pflash. It also implies that fw_cfg_find() will succeed. + */ + bool firmware_loaded; }; + +/** + * arm_load_kernel - Loads memory with everything needed to boot + * + * @cpu: handle to the first CPU object + * @info: handle to the boot info struct + * Registers a machine init done notifier that copies to memory + * everything needed to boot, depending on machine and user options: + * kernel image, boot loaders, initrd, dtb. Also registers the CPU + * reset handler. + * + * In case the machine file supports the platform bus device and its + * dynamically instantiable sysbus devices, this function must be called + * before sysbus-fdt arm_register_platform_bus_fdt_creator. Indeed the + * machine init done notifiers are called in registration reverse order. + */ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info); /* Multiplication factor to convert from system clock ticks to qemu timer diff --git a/include/hw/arm/fdt.h b/include/hw/arm/fdt.h new file mode 100644 index 0000000000..c3d5015013 --- /dev/null +++ b/include/hw/arm/fdt.h @@ -0,0 +1,34 @@ +/* + * + * Copyright (c) 2015 Linaro Limited + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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/>. + * + * Define macros useful when building ARM device tree nodes + */ + +#ifndef QEMU_ARM_FDT_H +#define QEMU_ARM_FDT_H + +#define GIC_FDT_IRQ_TYPE_SPI 0 +#define GIC_FDT_IRQ_TYPE_PPI 1 + +#define GIC_FDT_IRQ_FLAGS_EDGE_LO_HI 1 +#define GIC_FDT_IRQ_FLAGS_EDGE_HI_LO 2 +#define GIC_FDT_IRQ_FLAGS_LEVEL_HI 4 +#define GIC_FDT_IRQ_FLAGS_LEVEL_LO 8 + +#define GIC_FDT_IRQ_PPI_CPU_START 8 +#define GIC_FDT_IRQ_PPI_CPU_WIDTH 8 + +#endif diff --git a/include/hw/arm/stm32f205_soc.h b/include/hw/arm/stm32f205_soc.h new file mode 100644 index 0000000000..0390eff807 --- /dev/null +++ b/include/hw/arm/stm32f205_soc.h @@ -0,0 +1,57 @@ +/* + * STM32F205 SoC + * + * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef HW_ARM_STM32F205SOC_H +#define HW_ARM_STM32F205SOC_H + +#include "hw/misc/stm32f2xx_syscfg.h" +#include "hw/timer/stm32f2xx_timer.h" +#include "hw/char/stm32f2xx_usart.h" + +#define TYPE_STM32F205_SOC "stm32f205-soc" +#define STM32F205_SOC(obj) \ + OBJECT_CHECK(STM32F205State, (obj), TYPE_STM32F205_SOC) + +#define STM_NUM_USARTS 6 +#define STM_NUM_TIMERS 4 + +#define FLASH_BASE_ADDRESS 0x08000000 +#define FLASH_SIZE (1024 * 1024) +#define SRAM_BASE_ADDRESS 0x20000000 +#define SRAM_SIZE (128 * 1024) + +typedef struct STM32F205State { + /*< private >*/ + SysBusDevice parent_obj; + /*< public >*/ + + char *kernel_filename; + char *cpu_model; + + STM32F2XXSyscfgState syscfg; + STM32F2XXUsartState usart[STM_NUM_USARTS]; + STM32F2XXTimerState timer[STM_NUM_TIMERS]; +} STM32F205State; + +#endif diff --git a/include/hw/arm/sysbus-fdt.h b/include/hw/arm/sysbus-fdt.h new file mode 100644 index 0000000000..e15bb81807 --- /dev/null +++ b/include/hw/arm/sysbus-fdt.h @@ -0,0 +1,60 @@ +/* + * Dynamic sysbus device tree node generation API + * + * Copyright Linaro Limited, 2014 + * + * Authors: + * Alex Graf <agraf@suse.de> + * Eric Auger <eric.auger@linaro.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 HW_ARM_SYSBUS_FDT_H +#define HW_ARM_SYSBUS_FDT_H + +#include "hw/arm/arm.h" +#include "qemu-common.h" +#include "hw/sysbus.h" + +/* + * struct that contains dimensioning parameters of the platform bus + */ +typedef struct { + hwaddr platform_bus_base; /* start address of the bus */ + hwaddr platform_bus_size; /* size of the bus */ + int platform_bus_first_irq; /* first hwirq assigned to the bus */ + int platform_bus_num_irqs; /* number of hwirq assigned to the bus */ +} ARMPlatformBusSystemParams; + +/* + * struct that contains all relevant info to build the fdt nodes of + * platform bus and attached dynamic sysbus devices + * in the future might be augmented with additional info + * such as PHY, CLK handles ... + */ +typedef struct { + const ARMPlatformBusSystemParams *system_params; + struct arm_boot_info *binfo; + const char *intc; /* parent interrupt controller name */ +} ARMPlatformBusFDTParams; + +/** + * arm_register_platform_bus_fdt_creator - register a machine init done + * notifier that creates the device tree nodes of the platform bus and + * associated dynamic sysbus devices + */ +void arm_register_platform_bus_fdt_creator(ARMPlatformBusFDTParams *fdt_params); + +#endif diff --git a/include/hw/arm/virt-acpi-build.h b/include/hw/arm/virt-acpi-build.h new file mode 100644 index 0000000000..04f174d528 --- /dev/null +++ b/include/hw/arm/virt-acpi-build.h @@ -0,0 +1,44 @@ +/* + * + * Copyright (c) 2015 HUAWEI TECHNOLOGIES CO.,LTD. + * + * Author: Shannon Zhao <zhaoshenglong@huawei.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 QEMU_VIRT_ACPI_BUILD_H +#define QEMU_VIRT_ACPI_BUILD_H + +#include "qemu-common.h" +#include "hw/arm/virt.h" + +#define VIRT_ACPI_CPU_ID_LIMIT 8 +#define ACPI_GICC_ENABLED 1 + +typedef struct VirtGuestInfo { + int smp_cpus; + FWCfgState *fw_cfg; + const MemMapEntry *memmap; + const int *irqmap; +} VirtGuestInfo; + + +typedef struct VirtGuestInfoState { + VirtGuestInfo info; + Notifier machine_done; +} VirtGuestInfoState; + +void virt_acpi_setup(VirtGuestInfo *guest_info); + +#endif diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h new file mode 100644 index 0000000000..d22fd8e508 --- /dev/null +++ b/include/hw/arm/virt.h @@ -0,0 +1,67 @@ +/* + * + * Copyright (c) 2015 Linaro Limited + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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/>. + * + * Emulate a virtual board which works by passing Linux all the information + * it needs about what devices are present via the device tree. + * There are some restrictions about what we can do here: + * + we can only present devices whose Linux drivers will work based + * purely on the device tree with no platform data at all + * + we want to present a very stripped-down minimalist platform, + * both because this reduces the security attack surface from the guest + * and also because it reduces our exposure to being broken when + * the kernel updates its device tree bindings and requires further + * information in a device binding that we aren't providing. + * This is essentially the same approach kvmtool uses. + */ + +#ifndef QEMU_ARM_VIRT_H +#define QEMU_ARM_VIRT_H + +#include "qemu-common.h" + +#define NUM_GICV2M_SPIS 64 +#define NUM_VIRTIO_TRANSPORTS 32 + +#define ARCH_TIMER_VIRT_IRQ 11 +#define ARCH_TIMER_S_EL1_IRQ 13 +#define ARCH_TIMER_NS_EL1_IRQ 14 +#define ARCH_TIMER_NS_EL2_IRQ 10 + +enum { + VIRT_FLASH, + VIRT_MEM, + VIRT_CPUPERIPHS, + VIRT_GIC_DIST, + VIRT_GIC_CPU, + VIRT_UART, + VIRT_MMIO, + VIRT_RTC, + VIRT_FW_CFG, + VIRT_PCIE, + VIRT_PCIE_MMIO, + VIRT_PCIE_PIO, + VIRT_PCIE_ECAM, + VIRT_GIC_V2M, + VIRT_PLATFORM_BUS, +}; + +typedef struct MemMapEntry { + hwaddr base; + hwaddr size; +} MemMapEntry; + + +#endif diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h new file mode 100644 index 0000000000..c379632f2a --- /dev/null +++ b/include/hw/arm/xlnx-zynqmp.h @@ -0,0 +1,63 @@ +/* + * Xilinx Zynq MPSoC emulation + * + * Copyright (C) 2015 Xilinx Inc + * Written by Peter Crosthwaite <peter.crosthwaite@xilinx.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. + */ + +#ifndef XLNX_ZYNQMP_H + +#include "qemu-common.h" +#include "hw/arm/arm.h" +#include "hw/intc/arm_gic.h" +#include "hw/net/cadence_gem.h" +#include "hw/char/cadence_uart.h" + +#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp" +#define XLNX_ZYNQMP(obj) OBJECT_CHECK(XlnxZynqMPState, (obj), \ + TYPE_XLNX_ZYNQMP) + +#define XLNX_ZYNQMP_NUM_APU_CPUS 4 +#define XLNX_ZYNQMP_NUM_RPU_CPUS 2 +#define XLNX_ZYNQMP_NUM_GEMS 4 +#define XLNX_ZYNQMP_NUM_UARTS 2 + +#define XLNX_ZYNQMP_GIC_REGIONS 2 + +/* ZynqMP maps the ARM GIC regions (GICC, GICD ...) at consecutive 64k offsets + * and under-decodes the 64k region. This mirrors the 4k regions to every 4k + * aligned address in the 64k region. To implement each GIC region needs a + * number of memory region aliases. + */ + +#define XLNX_ZYNQMP_GIC_REGION_SIZE 0x4000 +#define XLNX_ZYNQMP_GIC_ALIASES (0x10000 / XLNX_ZYNQMP_GIC_REGION_SIZE - 1) + +typedef struct XlnxZynqMPState { + /*< private >*/ + DeviceState parent_obj; + + /*< public >*/ + ARMCPU apu_cpu[XLNX_ZYNQMP_NUM_APU_CPUS]; + ARMCPU rpu_cpu[XLNX_ZYNQMP_NUM_RPU_CPUS]; + GICState gic; + MemoryRegion gic_mr[XLNX_ZYNQMP_GIC_REGIONS][XLNX_ZYNQMP_GIC_ALIASES]; + CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS]; + CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS]; + + char *boot_cpu; + ARMCPU *boot_cpu_ptr; +} XlnxZynqMPState; + +#define XLNX_ZYNQMP_H +#endif diff --git a/include/hw/block/block.h b/include/hw/block/block.h index 0d0ce9a467..8d7c4b413f 100644 --- a/include/hw/block/block.h +++ b/include/hw/block/block.h @@ -44,9 +44,9 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf) #define DEFINE_BLOCK_PROPERTIES(_state, _conf) \ DEFINE_PROP_DRIVE("drive", _state, _conf.blk), \ DEFINE_PROP_BLOCKSIZE("logical_block_size", _state, \ - _conf.logical_block_size, 512), \ + _conf.logical_block_size), \ DEFINE_PROP_BLOCKSIZE("physical_block_size", _state, \ - _conf.physical_block_size, 512), \ + _conf.physical_block_size), \ 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_UINT32("discard_granularity", _state, \ @@ -63,6 +63,7 @@ void blkconf_serial(BlockConf *conf, char **serial); void blkconf_geometry(BlockConf *conf, int *trans, unsigned cyls_max, unsigned heads_max, unsigned secs_max, Error **errp); +void blkconf_blocksizes(BlockConf *conf); /* Hard disk geometry */ diff --git a/include/hw/boards.h b/include/hw/boards.h index e0a67903ef..2aec9cbb12 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -19,31 +19,18 @@ 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; QEMUMachineInitFunc *init; - QEMUMachineResetFunc *reset; - 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, - use_virtcon:1, - use_sclp:1, - no_floppy:1, - no_cdrom:1, + unsigned int 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; }; void memory_region_allocate_system_memory(MemoryRegion *mr, Object *owner, @@ -65,6 +52,15 @@ int qemu_register_machine(QEMUMachine *m); MachineClass *find_default_machine(void); extern MachineState *current_machine; +bool machine_usb(MachineState *machine); +bool machine_iommu(MachineState *machine); +bool machine_kernel_irqchip_allowed(MachineState *machine); +bool machine_kernel_irqchip_required(MachineState *machine); +int machine_kvm_shadow_mem(MachineState *machine); +int machine_phandle_start(MachineState *machine); +bool machine_dump_guest_core(MachineState *machine); +bool machine_mem_merge(MachineState *machine); + /** * MachineClass: * @qemu_machine: #QEMUMachine @@ -73,6 +69,10 @@ extern MachineState *current_machine; * of HotplugHandler object, which handles hotplug operation * for a given @dev. It may return NULL if @dev doesn't require * any actions to be performed by hotplug handler. + * @cpu_index_to_socket_id: + * used to provide @cpu_index to socket number mapping, allowing + * a machine to group CPU threads belonging to the same socket/package + * Returns: socket number given cpu_index belongs to. */ struct MachineClass { /*< private >*/ @@ -99,16 +99,19 @@ struct MachineClass { no_floppy:1, no_cdrom:1, no_sdcard:1, - has_dynamic_sysbus:1; + has_dynamic_sysbus:1, + no_tco: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; + ram_addr_t default_ram_size; HotplugHandler *(*get_hotplug_handler)(MachineState *machine, DeviceState *dev); + unsigned (*cpu_index_to_socket_id)(unsigned cpu_index); }; /** @@ -122,7 +125,8 @@ struct MachineState { /*< public >*/ char *accel; - bool kernel_irqchip; + bool kernel_irqchip_allowed; + bool kernel_irqchip_required; int kvm_shadow_mem; char *dtb; char *dumpdtb; @@ -131,8 +135,10 @@ struct MachineState { bool dump_guest_core; bool mem_merge; bool usb; + bool usb_disabled; char *firmware; bool iommu; + bool suppress_vmdesc; ram_addr_t ram_size; ram_addr_t maxram_size; diff --git a/include/hw/char/cadence_uart.h b/include/hw/char/cadence_uart.h new file mode 100644 index 0000000000..6310f52512 --- /dev/null +++ b/include/hw/char/cadence_uart.h @@ -0,0 +1,53 @@ +/* + * Device model for Cadence UART + * + * Copyright (c) 2010 Xilinx Inc. + * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.crosthwaite@petalogix.com) + * Copyright (c) 2012 PetaLogix Pty Ltd. + * Written by Haibing Ma + * M.Habib + * + * 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. + * + * 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 CADENCE_UART_H + +#include "hw/sysbus.h" +#include "sysemu/char.h" +#include "qemu/timer.h" + +#define CADENCE_UART_RX_FIFO_SIZE 16 +#define CADENCE_UART_TX_FIFO_SIZE 16 + +#define CADENCE_UART_R_MAX (0x48/4) + +#define TYPE_CADENCE_UART "cadence_uart" +#define CADENCE_UART(obj) OBJECT_CHECK(CadenceUARTState, (obj), \ + TYPE_CADENCE_UART) + +typedef struct { + /*< private >*/ + SysBusDevice parent_obj; + + /*< public >*/ + MemoryRegion iomem; + uint32_t r[CADENCE_UART_R_MAX]; + uint8_t rx_fifo[CADENCE_UART_RX_FIFO_SIZE]; + uint8_t tx_fifo[CADENCE_UART_TX_FIFO_SIZE]; + uint32_t rx_wpos; + uint32_t rx_count; + uint32_t tx_count; + uint64_t char_tx_time; + CharDriverState *chr; + qemu_irq irq; + QEMUTimer *fifo_trigger_handle; +} CadenceUARTState; + +#define CADENCE_UART_H +#endif diff --git a/include/hw/char/serial.h b/include/hw/char/serial.h index f431764bf5..15beb6b45c 100644 --- a/include/hw/char/serial.h +++ b/include/hw/char/serial.h @@ -92,6 +92,6 @@ SerialState *serial_mm_init(MemoryRegion *address_space, /* serial-isa.c */ #define TYPE_ISA_SERIAL "isa-serial" -bool serial_isa_init(ISABus *bus, int index, CharDriverState *chr); +void serial_hds_isa_init(ISABus *bus, int n); #endif diff --git a/include/hw/char/stm32f2xx_usart.h b/include/hw/char/stm32f2xx_usart.h new file mode 100644 index 0000000000..b97f192a45 --- /dev/null +++ b/include/hw/char/stm32f2xx_usart.h @@ -0,0 +1,73 @@ +/* + * STM32F2XX USART + * + * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef HW_STM32F2XX_USART_H +#define HW_STM32F2XX_USART_H + +#include "hw/sysbus.h" +#include "sysemu/char.h" +#include "hw/hw.h" + +#define USART_SR 0x00 +#define USART_DR 0x04 +#define USART_BRR 0x08 +#define USART_CR1 0x0C +#define USART_CR2 0x10 +#define USART_CR3 0x14 +#define USART_GTPR 0x18 + +#define USART_SR_RESET 0x00C00000 + +#define USART_SR_TXE (1 << 7) +#define USART_SR_TC (1 << 6) +#define USART_SR_RXNE (1 << 5) + +#define USART_CR1_UE (1 << 13) +#define USART_CR1_RXNEIE (1 << 5) +#define USART_CR1_TE (1 << 3) +#define USART_CR1_RE (1 << 2) + +#define TYPE_STM32F2XX_USART "stm32f2xx-usart" +#define STM32F2XX_USART(obj) \ + OBJECT_CHECK(STM32F2XXUsartState, (obj), TYPE_STM32F2XX_USART) + +typedef struct { + /* <private> */ + SysBusDevice parent_obj; + + /* <public> */ + MemoryRegion mmio; + + uint32_t usart_sr; + uint32_t usart_dr; + uint32_t usart_brr; + uint32_t usart_cr1; + uint32_t usart_cr2; + uint32_t usart_cr3; + uint32_t usart_gtpr; + + CharDriverState *chr; + qemu_irq irq; +} STM32F2XXUsartState; +#endif /* HW_STM32F2XX_USART_H */ diff --git a/include/hw/compat.h b/include/hw/compat.h index 313682a708..94c8097d0c 100644 --- a/include/hw/compat.h +++ b/include/hw/compat.h @@ -1,6 +1,32 @@ #ifndef HW_COMPAT_H #define HW_COMPAT_H +#define HW_COMPAT_2_3 \ + {\ + .driver = "virtio-blk-pci",\ + .property = "any_layout",\ + .value = "off",\ + },{\ + .driver = "virtio-balloon-pci",\ + .property = "any_layout",\ + .value = "off",\ + },{\ + .driver = "virtio-serial-pci",\ + .property = "any_layout",\ + .value = "off",\ + },{\ + .driver = "virtio-9p-pci",\ + .property = "any_layout",\ + .value = "off",\ + },{\ + .driver = "virtio-rng-pci",\ + .property = "any_layout",\ + .value = "off",\ + }, + +#define HW_COMPAT_2_2 \ + /* empty */ + #define HW_COMPAT_2_1 \ {\ .driver = "intel-hda",\ @@ -30,6 +56,6 @@ .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 a517753a6f..bd71968143 100644 --- a/include/hw/elf_ops.h +++ b/include/hw/elf_ops.h @@ -49,6 +49,13 @@ static void glue(bswap_sym, SZ)(struct elf_sym *sym) bswap16s(&sym->st_shndx); } +static void glue(bswap_rela, SZ)(struct elf_rela *rela) +{ + bswapSZs(&rela->r_offset); + bswapSZs(&rela->r_info); + bswapSZs((elf_word *)&rela->r_addend); +} + static struct elf_shdr *glue(find_section, SZ)(struct elf_shdr *shdr_table, int n, int type) { @@ -182,6 +189,75 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab, return -1; } +static int glue(elf_reloc, SZ)(struct elfhdr *ehdr, int fd, int must_swab, + uint64_t (*translate_fn)(void *, uint64_t), + void *translate_opaque, uint8_t *data, + struct elf_phdr *ph, int elf_machine) +{ + struct elf_shdr *reltab, *shdr_table = NULL; + struct elf_rela *rels = NULL; + int nrels, i, ret = -1; + elf_word wordval; + void *addr; + + shdr_table = load_at(fd, ehdr->e_shoff, + sizeof(struct elf_shdr) * ehdr->e_shnum); + if (!shdr_table) { + return -1; + } + if (must_swab) { + for (i = 0; i < ehdr->e_shnum; i++) { + glue(bswap_shdr, SZ)(&shdr_table[i]); + } + } + + reltab = glue(find_section, SZ)(shdr_table, ehdr->e_shnum, SHT_RELA); + if (!reltab) { + goto fail; + } + rels = load_at(fd, reltab->sh_offset, reltab->sh_size); + if (!rels) { + goto fail; + } + nrels = reltab->sh_size / sizeof(struct elf_rela); + + for (i = 0; i < nrels; i++) { + if (must_swab) { + glue(bswap_rela, SZ)(&rels[i]); + } + if (rels[i].r_offset < ph->p_vaddr || + rels[i].r_offset >= ph->p_vaddr + ph->p_filesz) { + continue; + } + addr = &data[rels[i].r_offset - ph->p_vaddr]; + switch (elf_machine) { + case EM_S390: + switch (rels[i].r_info) { + case R_390_RELATIVE: + wordval = *(elf_word *)addr; + if (must_swab) { + bswapSZs(&wordval); + } + wordval = translate_fn(translate_opaque, wordval); + if (must_swab) { + bswapSZs(&wordval); + } + *(elf_word *)addr = wordval; + break; + default: + fprintf(stderr, "Unsupported relocation type %i!\n", + (int)rels[i].r_info); + } + } + } + + ret = 0; +fail: + g_free(rels); + g_free(shdr_table); + return ret; +} + static int glue(load_elf, SZ)(const char *name, int fd, uint64_t (*translate_fn)(void *, uint64_t), void *translate_opaque, @@ -239,7 +315,9 @@ static int glue(load_elf, SZ)(const char *name, int fd, glue(load_symbols, SZ)(&ehdr, fd, must_swab, clear_lsb); size = ehdr.e_phnum * sizeof(phdr[0]); - lseek(fd, ehdr.e_phoff, SEEK_SET); + if (lseek(fd, ehdr.e_phoff, SEEK_SET) != ehdr.e_phoff) { + goto fail; + } phdr = g_malloc0(size); if (!phdr) goto fail; @@ -271,6 +349,8 @@ static int glue(load_elf, SZ)(const char *name, int fd, linked at the wrong physical address. */ if (translate_fn) { addr = translate_fn(translate_opaque, ph->p_paddr); + glue(elf_reloc, SZ)(&ehdr, fd, must_swab, translate_fn, + translate_opaque, data, ph, elf_machine); } else { addr = ph->p_paddr; } diff --git a/include/hw/hotplug.h b/include/hw/hotplug.h index 050d2f0530..2db025d0bd 100644 --- a/include/hw/hotplug.h +++ b/include/hw/hotplug.h @@ -52,7 +52,7 @@ typedef void (*hotplug_fn)(HotplugHandler *plug_handler, * require asynchronous unplug handling. * @unplug: unplug callback. * Used for device removal with devices that implement - * asynchronous and synchronous (suprise) removal. + * asynchronous and synchronous (surprise) removal. */ typedef struct HotplugHandlerClass { /* <private> */ diff --git a/include/hw/hw.h b/include/hw/hw.h index 33bdb92712..c78adae06a 100644 --- a/include/hw/hw.h +++ b/include/hw/hw.h @@ -41,12 +41,6 @@ typedef void QEMUResetHandler(void *opaque); void qemu_register_reset(QEMUResetHandler *func, void *opaque); void qemu_unregister_reset(QEMUResetHandler *func, void *opaque); -/* handler to set the boot_device order for a specific type of QEMUMachine */ -/* return 0 if success */ -typedef int QEMUBootSetHandler(void *opaque, const char *boot_order); -void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque); -int qemu_boot_set(const char *boot_order); - #ifdef NEED_CPU_H #if TARGET_LONG_BITS == 64 #define VMSTATE_UINTTL_V(_f, _s, _v) \ diff --git a/include/hw/i386/apic.h b/include/hw/i386/apic.h index 1d48e027c3..51eb6d3884 100644 --- a/include/hw/i386/apic.h +++ b/include/hw/i386/apic.h @@ -21,7 +21,7 @@ void apic_sipi(DeviceState *s); void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip, TPRAccess access); void apic_poll_irq(DeviceState *d); -void apic_designate_bsp(DeviceState *d); +void apic_designate_bsp(DeviceState *d, bool bsp); /* pc.c */ DeviceState *cpu_get_current_apic(void); diff --git a/include/hw/i386/apic_internal.h b/include/hw/i386/apic_internal.h index 83e2a42cc1..dc7a89d988 100644 --- a/include/hw/i386/apic_internal.h +++ b/include/hw/i386/apic_internal.h @@ -89,6 +89,7 @@ typedef struct APICCommonClass void (*external_nmi)(APICCommonState *s); void (*pre_save)(APICCommonState *s); void (*post_load)(APICCommonState *s); + void (*reset)(APICCommonState *s); } APICCommonClass; struct APICCommonState { diff --git a/include/hw/i386/ich9.h b/include/hw/i386/ich9.h index 59ea25b49a..b9d2b04b6e 100644 --- a/include/hw/i386/ich9.h +++ b/include/hw/i386/ich9.h @@ -2,7 +2,6 @@ #define HW_ICH9_H #include "hw/hw.h" -#include "qemu/range.h" #include "hw/isa/isa.h" #include "hw/sysbus.h" #include "hw/i386/pc.h" @@ -18,10 +17,12 @@ void ich9_lpc_set_irq(void *opaque, int irq_num, int level); int ich9_lpc_map_irq(PCIDevice *pci_dev, int intx); PCIINTxRoute ich9_route_intx_pin_to_irq(void *opaque, int pirq_pin); -void ich9_lpc_pm_init(PCIDevice *pci_lpc); -PCIBus *ich9_d2pbr_init(PCIBus *bus, int devfn, int sec_bus); +void ich9_lpc_pm_init(PCIDevice *pci_lpc, bool smm_enabled, bool enable_tco); I2CBus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base); +void ich9_generate_smi(void); +void ich9_generate_nmi(void); + #define ICH9_CC_SIZE (16 * 1024) /* 16KB */ #define TYPE_ICH9_LPC_DEVICE "ICH9-LPC" @@ -45,6 +46,11 @@ typedef struct ICH9LPCState { ICH9LPCPMRegs pm; uint32_t sci_level; /* track sci level */ + /* 2.24 Pin Straps */ + struct { + bool spkr_hi; + } pin_strap; + /* 10.1 Chipset Configuration registers(Memory Space) which is pointed by RCBA */ uint8_t chip_config[ICH9_CC_SIZE]; @@ -92,6 +98,9 @@ Object *ich9_lpc_find(void); #define ICH9_CC_DIR_MASK 0x7 #define ICH9_CC_OIC 0x31FF #define ICH9_CC_OIC_AEN 0x1 +#define ICH9_CC_GCS 0x3410 +#define ICH9_CC_GCS_DEFAULT 0x00000020 +#define ICH9_CC_GCS_NO_REBOOT (1 << 5) /* D28:F[0-5] */ #define ICH9_PCIE_DEV 28 @@ -154,6 +163,12 @@ Object *ich9_lpc_find(void); #define ICH9_LPC_PIRQ_ROUT_MASK Q35_MASK(8, 3, 0) #define ICH9_LPC_PIRQ_ROUT_DEFAULT 0x80 +#define ICH9_LPC_GEN_PMCON_1 0xa0 +#define ICH9_LPC_GEN_PMCON_1_SMI_LOCK (1 << 4) +#define ICH9_LPC_GEN_PMCON_2 0xa2 +#define ICH9_LPC_GEN_PMCON_3 0xa4 +#define ICH9_LPC_GEN_PMCON_LOCK 0xa6 + #define ICH9_LPC_RCBA 0xf0 #define ICH9_LPC_RCBA_BA_MASK Q35_MASK(32, 31, 14) #define ICH9_LPC_RCBA_EN 0x1 @@ -182,7 +197,10 @@ Object *ich9_lpc_find(void); #define ICH9_PMIO_GPE0_LEN 16 #define ICH9_PMIO_SMI_EN 0x30 #define ICH9_PMIO_SMI_EN_APMC_EN (1 << 5) +#define ICH9_PMIO_SMI_EN_TCO_EN (1 << 13) #define ICH9_PMIO_SMI_STS 0x34 +#define ICH9_PMIO_TCO_RLD 0x60 +#define ICH9_PMIO_TCO_LEN 32 /* FADT ACPI_ENABLE/ACPI_DISABLE */ #define ICH9_APM_ACPI_ENABLE 0x2 diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 9e22094f8b..1c21f45589 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -15,14 +15,12 @@ #include "hw/pci/pci.h" #include "hw/boards.h" #include "hw/compat.h" +#include "hw/mem/pc-dimm.h" #define HPET_INTCAP "hpet-intcap" /** * PCMachineState: - * @hotplug_memory_base: address in guest RAM address space where hotplug memory - * 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 @@ -32,14 +30,14 @@ struct PCMachineState { MachineState parent_obj; /* <public> */ - ram_addr_t hotplug_memory_base; - MemoryRegion hotplug_memory; + MemoryHotplugState hotplug_memory; HotplugHandler *acpi_dev; ISADevice *rtc; uint64_t max_ram_below_4g; OnOffAuto vmport; + OnOffAuto smm; bool enforce_aligned_dimm; }; @@ -47,6 +45,7 @@ struct PCMachineState { #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_SMM "smm" #define PC_MACHINE_ENFORCE_ALIGNED_DIMM "enforce-aligned-dimm" /** @@ -73,8 +72,6 @@ typedef struct PCMachineClass PCMachineClass; #define PC_MACHINE_CLASS(klass) \ OBJECT_CLASS_CHECK(PCMachineClass, (klass), TYPE_PC_MACHINE) -void qemu_register_pc_machine(QEMUMachine *m); - /* PC-style peripherals (also used by other machines). */ typedef struct PcPciInfo { @@ -91,6 +88,7 @@ typedef struct PcPciInfo { #define ACPI_PM_PROP_PM_IO_BASE "pm_io_base" #define ACPI_PM_PROP_GPE0_BLK "gpe0_blk" #define ACPI_PM_PROP_GPE0_BLK_LEN "gpe0_blk_len" +#define ACPI_PM_PROP_TCO_ENABLED "enable_tco" struct PcGuestInfo { bool isapc_ram_fw; @@ -104,26 +102,12 @@ struct PcGuestInfo { int legacy_acpi_table_size; bool has_acpi_build; bool has_reserved_memory; + bool rsdp_in_ram; }; /* parallel.c */ -static inline bool parallel_init(ISABus *bus, int index, CharDriverState *chr) -{ - DeviceState *dev; - ISADevice *isadev; - isadev = isa_try_create(bus, "isa-parallel"); - if (!isadev) { - return false; - } - dev = DEVICE(isadev); - qdev_prop_set_uint32(dev, "index", index); - qdev_prop_set_chr(dev, "chardev", chr); - if (qdev_init(dev) < 0) { - return false; - } - return true; -} +void parallel_hds_isa_init(ISABus *bus, int n); bool parallel_mm_init(MemoryRegion *address_space, hwaddr base, int it_shift, qemu_irq irq, @@ -136,8 +120,8 @@ qemu_irq *i8259_init(ISABus *bus, qemu_irq parent_irq); qemu_irq *kvm_i8259_init(ISABus *bus); int pic_read_irq(DeviceState *d); int pic_get_output(DeviceState *d); -void pic_info(Monitor *mon, const QDict *qdict); -void irq_info(Monitor *mon, const QDict *qdict); +void hmp_info_pic(Monitor *mon, const QDict *qdict); +void hmp_info_irq(Monitor *mon, const QDict *qdict); /* Global System Interrupts */ @@ -174,6 +158,7 @@ void i8042_setup_a20_line(ISADevice *dev, qemu_irq *a20_out); /* pc.c */ extern int fd_bootchk; +bool pc_machine_is_smm_enabled(PCMachineState *pcms); void pc_register_ferr_irq(qemu_irq irq); void pc_acpi_smi_interrupt(void *opaque, int irq, int level); @@ -212,23 +197,22 @@ FWCfgState *pc_memory_init(MachineState *machine, MemoryRegion *rom_memory, MemoryRegion **ram_memory, PcGuestInfo *guest_info); -qemu_irq *pc_allocate_cpu_irq(void); +qemu_irq pc_allocate_cpu_irq(void); DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus); void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi, ISADevice **rtc_state, - ISADevice **floppy, + bool create_fdctrl, bool no_vmport, 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, MachineState *machine, - ISADevice *floppy, BusState *ide0, BusState *ide1, + BusState *ide0, BusState *ide1, ISADevice *s); void pc_nic_init(ISABus *isa_bus, PCIBus *pci_bus); void pc_pci_device_init(PCIBus *pci_bus); typedef void (*cpu_set_smm_t)(int smm, void *arg); -void cpu_smm_register(cpu_set_smm_t callback, void *arg); void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name); @@ -236,8 +220,7 @@ void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name); I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, qemu_irq sci_irq, qemu_irq smi_irq, - int kvm_enabled, FWCfgState *fw_cfg, - DeviceState **piix4_pm); + int smm_enabled, DeviceState **piix4_pm); void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr); /* hpet.c */ @@ -312,8 +295,96 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t); int e820_get_num_entries(void); bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); +#define PC_COMPAT_2_3 \ + HW_COMPAT_2_3 \ + {\ + .driver = TYPE_X86_CPU,\ + .property = "arat",\ + .value = "off",\ + },{\ + .driver = "qemu64" "-" TYPE_X86_CPU,\ + .property = "level",\ + .value = stringify(4),\ + },{\ + .driver = "kvm64" "-" TYPE_X86_CPU,\ + .property = "level",\ + .value = stringify(5),\ + },{\ + .driver = "pentium3" "-" TYPE_X86_CPU,\ + .property = "level",\ + .value = stringify(2),\ + },{\ + .driver = "n270" "-" TYPE_X86_CPU,\ + .property = "level",\ + .value = stringify(5),\ + },{\ + .driver = "Conroe" "-" TYPE_X86_CPU,\ + .property = "level",\ + .value = stringify(4),\ + },{\ + .driver = "Penryn" "-" TYPE_X86_CPU,\ + .property = "level",\ + .value = stringify(4),\ + },{\ + .driver = "Nehalem" "-" TYPE_X86_CPU,\ + .property = "level",\ + .value = stringify(4),\ + },{\ + .driver = "n270" "-" TYPE_X86_CPU,\ + .property = "xlevel",\ + .value = stringify(0x8000000a),\ + },{\ + .driver = "Penryn" "-" TYPE_X86_CPU,\ + .property = "xlevel",\ + .value = stringify(0x8000000a),\ + },{\ + .driver = "Conroe" "-" TYPE_X86_CPU,\ + .property = "xlevel",\ + .value = stringify(0x8000000a),\ + },{\ + .driver = "Nehalem" "-" TYPE_X86_CPU,\ + .property = "xlevel",\ + .value = stringify(0x8000000a),\ + },{\ + .driver = "Westmere" "-" TYPE_X86_CPU,\ + .property = "xlevel",\ + .value = stringify(0x8000000a),\ + },{\ + .driver = "SandyBridge" "-" TYPE_X86_CPU,\ + .property = "xlevel",\ + .value = stringify(0x8000000a),\ + },{\ + .driver = "IvyBridge" "-" TYPE_X86_CPU,\ + .property = "xlevel",\ + .value = stringify(0x8000000a),\ + },{\ + .driver = "Haswell" "-" TYPE_X86_CPU,\ + .property = "xlevel",\ + .value = stringify(0x8000000a),\ + },{\ + .driver = "Haswell-noTSX" "-" TYPE_X86_CPU,\ + .property = "xlevel",\ + .value = stringify(0x8000000a),\ + },{\ + .driver = "Broadwell" "-" TYPE_X86_CPU,\ + .property = "xlevel",\ + .value = stringify(0x8000000a),\ + },{\ + .driver = "Broadwell-noTSX" "-" TYPE_X86_CPU,\ + .property = "xlevel",\ + .value = stringify(0x8000000a),\ + }, + +#define PC_COMPAT_2_2 \ + PC_COMPAT_2_3 \ + HW_COMPAT_2_2 + +#define PC_COMPAT_2_1 \ + PC_COMPAT_2_2 \ + HW_COMPAT_2_1 + #define PC_COMPAT_2_0 \ - HW_COMPAT_2_1, \ + PC_COMPAT_2_1 \ {\ .driver = "virtio-scsi-pci",\ .property = "any_layout",\ @@ -370,10 +441,10 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); .driver = "ioh3420",\ .property = COMPAT_PROP_PCP,\ .value = "off",\ - } + }, #define PC_COMPAT_1_7 \ - PC_COMPAT_2_0, \ + PC_COMPAT_2_0 \ {\ .driver = TYPE_USB_DEVICE,\ .property = "msos-desc",\ @@ -388,10 +459,10 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); .driver = "hpet",\ .property = HPET_INTCAP,\ .value = stringify(4),\ - } + }, #define PC_COMPAT_1_6 \ - PC_COMPAT_1_7, \ + PC_COMPAT_1_7 \ {\ .driver = "e1000",\ .property = "mitigation",\ @@ -412,10 +483,10 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); .driver = "q35-pcihost",\ .property = "short_root_bus",\ .value = stringify(1),\ - } + }, #define PC_COMPAT_1_5 \ - PC_COMPAT_1_6, \ + PC_COMPAT_1_6 \ {\ .driver = "Conroe-" TYPE_X86_CPU,\ .property = "model",\ @@ -456,31 +527,31 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); .driver = "q35-pcihost",\ .property = "short_root_bus",\ .value = stringify(0),\ - } + }, #define PC_COMPAT_1_4 \ - PC_COMPAT_1_5, \ + PC_COMPAT_1_5 \ {\ .driver = "scsi-hd",\ .property = "discard_granularity",\ .value = stringify(0),\ - },{\ + },{\ .driver = "scsi-cd",\ .property = "discard_granularity",\ .value = stringify(0),\ - },{\ + },{\ .driver = "scsi-disk",\ .property = "discard_granularity",\ .value = stringify(0),\ - },{\ + },{\ .driver = "ide-hd",\ .property = "discard_granularity",\ .value = stringify(0),\ - },{\ + },{\ .driver = "ide-cd",\ .property = "discard_granularity",\ .value = stringify(0),\ - },{\ + },{\ .driver = "ide-drive",\ .property = "discard_granularity",\ .value = stringify(0),\ @@ -488,7 +559,7 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); .driver = "virtio-blk-pci",\ .property = "discard_granularity",\ .value = stringify(0),\ - },{\ + },{\ .driver = "virtio-serial-pci",\ .property = "vectors",\ /* DEV_NVECTORS_UNSPECIFIED as a uint32_t string */\ @@ -521,14 +592,45 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); .driver = "486-" TYPE_X86_CPU,\ .property = "model",\ .value = stringify(0),\ - } + }, -#define PC_COMMON_MACHINE_OPTIONS \ - .default_boot_order = "cad" +static inline void pc_common_machine_options(MachineClass *m) +{ + m->default_boot_order = "cad"; +} + +static inline void pc_default_machine_options(MachineClass *m) +{ + pc_common_machine_options(m); + m->hot_add_cpu = pc_hot_add_cpu; + m->max_cpus = 255; +} -#define PC_DEFAULT_MACHINE_OPTIONS \ - PC_COMMON_MACHINE_OPTIONS, \ - .hot_add_cpu = pc_hot_add_cpu, \ - .max_cpus = 255 +#define DEFINE_PC_MACHINE(suffix, namestr, initfn, optsfn) \ + static void pc_machine_##suffix##_class_init(ObjectClass *oc, void *data) \ + { \ + MachineClass *mc = MACHINE_CLASS(oc); \ + optsfn(mc); \ + mc->name = namestr; \ + mc->init = initfn; \ + } \ + static const TypeInfo pc_machine_type_##suffix = { \ + .name = namestr TYPE_MACHINE_SUFFIX, \ + .parent = TYPE_PC_MACHINE, \ + .class_init = pc_machine_##suffix##_class_init, \ + }; \ + static void pc_machine_init_##suffix(void) \ + { \ + type_register(&pc_machine_type_##suffix); \ + } \ + machine_init(pc_machine_init_##suffix) + +#define SET_MACHINE_COMPAT(m, COMPAT) do { \ + static GlobalProperty props[] = { \ + COMPAT \ + { /* end of list */ } \ + }; \ + (m)->compat_props = props; \ +} while (0) #endif diff --git a/include/hw/i386/topology.h b/include/hw/i386/topology.h new file mode 100644 index 0000000000..9c6f3a937a --- /dev/null +++ b/include/hw/i386/topology.h @@ -0,0 +1,134 @@ +/* + * x86 CPU topology data structures and functions + * + * Copyright (c) 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef HW_I386_TOPOLOGY_H +#define HW_I386_TOPOLOGY_H + +/* This file implements the APIC-ID-based CPU topology enumeration logic, + * documented at the following document: + * Intel® 64 Architecture Processor Topology Enumeration + * http://software.intel.com/en-us/articles/intel-64-architecture-processor-topology-enumeration/ + * + * This code should be compatible with AMD's "Extended Method" described at: + * AMD CPUID Specification (Publication #25481) + * Section 3: Multiple Core Calcuation + * as long as: + * nr_threads is set to 1; + * OFFSET_IDX is assumed to be 0; + * CPUID Fn8000_0008_ECX[ApicIdCoreIdSize[3:0]] is set to apicid_core_width(). + */ + +#include <stdint.h> +#include <string.h> + +#include "qemu/bitops.h" + +/* APIC IDs can be 32-bit, but beware: APIC IDs > 255 require x2APIC support + */ +typedef uint32_t apic_id_t; + +/* Return the bit width needed for 'count' IDs + */ +static unsigned apicid_bitwidth_for_count(unsigned count) +{ + g_assert(count >= 1); + count -= 1; + return count ? 32 - clz32(count) : 0; +} + +/* Bit width of the SMT_ID (thread ID) field on the APIC ID + */ +static inline unsigned apicid_smt_width(unsigned nr_cores, unsigned nr_threads) +{ + return apicid_bitwidth_for_count(nr_threads); +} + +/* Bit width of the Core_ID field + */ +static inline unsigned apicid_core_width(unsigned nr_cores, unsigned nr_threads) +{ + return apicid_bitwidth_for_count(nr_cores); +} + +/* Bit offset of the Core_ID field + */ +static inline unsigned apicid_core_offset(unsigned nr_cores, + unsigned nr_threads) +{ + return apicid_smt_width(nr_cores, nr_threads); +} + +/* Bit offset of the Pkg_ID (socket ID) field + */ +static inline unsigned apicid_pkg_offset(unsigned nr_cores, unsigned nr_threads) +{ + return apicid_core_offset(nr_cores, nr_threads) + + apicid_core_width(nr_cores, nr_threads); +} + +/* Make APIC ID for the CPU based on Pkg_ID, Core_ID, SMT_ID + * + * The caller must make sure core_id < nr_cores and smt_id < nr_threads. + */ +static inline apic_id_t apicid_from_topo_ids(unsigned nr_cores, + unsigned nr_threads, + unsigned pkg_id, + unsigned core_id, + unsigned smt_id) +{ + return (pkg_id << apicid_pkg_offset(nr_cores, nr_threads)) | + (core_id << apicid_core_offset(nr_cores, nr_threads)) | + smt_id; +} + +/* Calculate thread/core/package IDs for a specific topology, + * based on (contiguous) CPU index + */ +static inline void x86_topo_ids_from_idx(unsigned nr_cores, + unsigned nr_threads, + unsigned cpu_index, + unsigned *pkg_id, + unsigned *core_id, + unsigned *smt_id) +{ + unsigned core_index = cpu_index / nr_threads; + *smt_id = cpu_index % nr_threads; + *core_id = core_index % nr_cores; + *pkg_id = core_index / nr_cores; +} + +/* Make APIC ID for the CPU 'cpu_index' + * + * 'cpu_index' is a sequential, contiguous ID for the CPU. + */ +static inline apic_id_t x86_apicid_from_cpu_idx(unsigned nr_cores, + unsigned nr_threads, + unsigned cpu_index) +{ + unsigned pkg_id, core_id, smt_id; + x86_topo_ids_from_idx(nr_cores, nr_threads, cpu_index, + &pkg_id, &core_id, &smt_id); + return apicid_from_topo_ids(nr_cores, nr_threads, pkg_id, core_id, smt_id); +} + +#endif /* HW_I386_TOPOLOGY_H */ diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h index f6887ed92b..899db3d7a0 100644 --- a/include/hw/intc/arm_gic_common.h +++ b/include/hw/intc/arm_gic_common.h @@ -34,6 +34,9 @@ #define MAX_NR_GROUP_PRIO 128 #define GIC_NR_APRS (MAX_NR_GROUP_PRIO / 32) +#define GIC_MIN_BPR 0 +#define GIC_MIN_ABPR (GIC_MIN_BPR + 1) + typedef struct gic_irq_state { /* The enable bits are only banked for per-cpu interrupts. */ uint8_t enabled; @@ -42,6 +45,7 @@ typedef struct gic_irq_state { uint8_t level; bool model; /* 0 = N:N, 1 = 1:N */ bool edge_trigger; /* true: edge-triggered, false: level-triggered */ + uint8_t group; } gic_irq_state; typedef struct GICState { @@ -50,8 +54,15 @@ typedef struct GICState { /*< public >*/ qemu_irq parent_irq[GIC_NCPU]; - bool enabled; - bool cpu_enabled[GIC_NCPU]; + qemu_irq parent_fiq[GIC_NCPU]; + /* GICD_CTLR; for a GIC with the security extensions the NS banked version + * of this register is just an alias of bit 1 of the S banked version. + */ + uint32_t ctlr; + /* GICC_CTLR; again, the NS banked version is just aliases of bits of + * the S banked register, so our state only needs to store the S version. + */ + uint32_t cpu_ctlr[GIC_NCPU]; gic_irq_state irq_state[GIC_MAXIRQ]; uint8_t irq_target[GIC_MAXIRQ]; @@ -71,9 +82,11 @@ typedef struct GICState { uint16_t running_priority[GIC_NCPU]; uint16_t current_pending[GIC_NCPU]; - /* We present the GICv2 without security extensions to a guest and - * therefore the guest can configure the GICC_CTLR to configure group 1 - * binary point in the abpr. + /* If we present the GICv2 without security extensions to a guest, + * the guest can configure the GICC_CTLR to configure group 1 binary point + * in the abpr. + * For a GIC with Security Extensions we use use bpr for the + * secure copy and abpr as storage for the non-secure copy of the register. */ uint8_t bpr[GIC_NCPU]; uint8_t abpr[GIC_NCPU]; @@ -104,6 +117,7 @@ typedef struct GICState { MemoryRegion cpuiomem[GIC_NCPU + 1]; /* CPU interfaces */ uint32_t num_irq; uint32_t revision; + bool security_extn; int dev_fd; /* kvm device fd if backed by kvm vgic support */ } GICState; diff --git a/include/hw/isa/isa.h b/include/hw/isa/isa.h index e0c749f9e9..f21ceaafc6 100644 --- a/include/hw/isa/isa.h +++ b/include/hw/isa/isa.h @@ -21,10 +21,17 @@ #define ISA_BUS(obj) OBJECT_CHECK(ISABus, (obj), TYPE_ISA_BUS) #define TYPE_APPLE_SMC "isa-applesmc" +#define APPLESMC_MAX_DATA_LENGTH 32 +#define APPLESMC_PROP_IO_BASE "iobase" -static inline bool applesmc_find(void) +static inline uint16_t applesmc_port(void) { - return object_resolve_path_type("", TYPE_APPLE_SMC, NULL); + Object *obj = object_resolve_path_type("", TYPE_APPLE_SMC, NULL); + + if (obj) { + return object_property_get_int(obj, APPLESMC_PROP_IO_BASE, NULL); + } + return 0; } typedef struct ISADeviceClass { @@ -36,6 +43,7 @@ struct ISABus { BusState parent_obj; /*< public >*/ + MemoryRegion *address_space; MemoryRegion *address_space_io; qemu_irq *irqs; }; @@ -50,7 +58,8 @@ struct ISADevice { int ioport_id; }; -ISABus *isa_bus_new(DeviceState *dev, MemoryRegion *address_space_io); +ISABus *isa_bus_new(DeviceState *dev, MemoryRegion *address_space, + MemoryRegion *address_space_io); void isa_bus_irqs(ISABus *bus, qemu_irq *irqs); qemu_irq isa_get_irq(ISADevice *dev, int isairq); void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq); @@ -97,8 +106,6 @@ static inline ISABus *isa_bus_from_device(ISADevice *d) return ISA_BUS(qdev_get_parent_bus(DEVICE(d))); } -extern hwaddr isa_mem_base; - /* dma.c */ int DMA_get_channel_mode (int nchan); int DMA_read_memory (int nchan, void *buf, int pos, int size); diff --git a/include/hw/lm32/lm32_pic.h b/include/hw/lm32/lm32_pic.h index 555680304e..189fa386f7 100644 --- a/include/hw/lm32/lm32_pic.h +++ b/include/hw/lm32/lm32_pic.h @@ -8,7 +8,7 @@ uint32_t lm32_pic_get_im(DeviceState *d); void lm32_pic_set_ip(DeviceState *d, uint32_t ip); void lm32_pic_set_im(DeviceState *d, uint32_t im); -void lm32_do_pic_info(Monitor *mon, const QDict *qdict); -void lm32_irq_info(Monitor *mon, const QDict *qdict); +void lm32_hmp_info_pic(Monitor *mon, const QDict *qdict); +void lm32_hmp_info_irq(Monitor *mon, const QDict *qdict); #endif /* QEMU_HW_LM32_PIC_H */ diff --git a/include/hw/loader.h b/include/hw/loader.h index 64816395dc..f7b43ab62f 100644 --- a/include/hw/loader.h +++ b/include/hw/loader.h @@ -16,6 +16,15 @@ 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); + +/* This is the limit on the maximum uncompressed image size that + * load_image_gzipped_buffer() and load_image_gzipped() will read. It prevents + * g_malloc() in those functions from allocating a huge amount of memory. + */ +#define LOAD_IMAGE_MAX_GUNZIP_BYTES (256 << 20) + +int load_image_gzipped_buffer(const char *filename, uint64_t max_sz, + uint8_t **buffer); int load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz); #define ELF_LOAD_FAILED -1 @@ -59,22 +68,23 @@ 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); -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); +MemoryRegion *rom_add_blob(const char *name, const void *blob, size_t len, + size_t max_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, size_t romsize, hwaddr addr); -int rom_load_all(void); -void rom_load_done(void); +int rom_check_and_register_reset(void); void rom_set_fw(FWCfgState *f); int rom_copy(uint8_t *dest, hwaddr addr, size_t size); void *rom_ptr(hwaddr addr); -void do_info_roms(Monitor *mon, const QDict *qdict); +void hmp_info_roms(Monitor *mon, const QDict *qdict); #define rom_add_file_fixed(_f, _a, _i) \ rom_add_file(_f, NULL, _a, _i, false) #define rom_add_blob_fixed(_f, _b, _l, _a) \ - rom_add_blob(_f, _b, _l, _a, NULL, NULL, NULL) + rom_add_blob(_f, _b, _l, _l, _a, NULL, NULL, NULL) #define PC_ROM_MIN_VGA 0xc0000 #define PC_ROM_MIN_OPTION 0xc8000 diff --git a/include/hw/mem/pc-dimm.h b/include/hw/mem/pc-dimm.h index e1dcbbcd58..d83bf30ea9 100644 --- a/include/hw/mem/pc-dimm.h +++ b/include/hw/mem/pc-dimm.h @@ -70,6 +70,17 @@ typedef struct PCDIMMDeviceClass { MemoryRegion *(*get_memory_region)(PCDIMMDevice *dimm); } PCDIMMDeviceClass; +/** + * MemoryHotplugState: + * @base: address in guest RAM address space where hotplug memory + * address space begins. + * @mr: hotplug memory address space container + */ +typedef struct MemoryHotplugState { + ram_addr_t base; + MemoryRegion mr; +} MemoryHotplugState; + uint64_t pc_dimm_get_free_addr(uint64_t address_space_start, uint64_t address_space_size, uint64_t *hint, uint64_t align, uint64_t size, @@ -78,4 +89,9 @@ uint64_t pc_dimm_get_free_addr(uint64_t address_space_start, int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp); int qmp_pc_dimm_device_list(Object *obj, void *opaque); +uint64_t pc_existing_dimms_capacity(Error **errp); +void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms, + MemoryRegion *mr, uint64_t align, Error **errp); +void pc_dimm_memory_unplug(DeviceState *dev, MemoryHotplugState *hpms, + MemoryRegion *mr); #endif diff --git a/include/hw/mips/mips.h b/include/hw/mips/mips.h index 2a7a9c9f42..e0065ce808 100644 --- a/include/hw/mips/mips.h +++ b/include/hw/mips/mips.h @@ -15,18 +15,9 @@ PCIBus *bonito_init(qemu_irq *pic); /* rc4030.c */ typedef struct rc4030DMAState *rc4030_dma; -void rc4030_dma_memory_rw(void *opaque, hwaddr addr, uint8_t *buf, int len, int is_write); void rc4030_dma_read(void *dma, uint8_t *buf, int len); void rc4030_dma_write(void *dma, uint8_t *buf, int len); -void *rc4030_init(qemu_irq timer, qemu_irq jazz_bus, - qemu_irq **irqs, rc4030_dma **dmas, - MemoryRegion *sysmem); - -/* dp8393x.c */ -void dp83932_init(NICInfo *nd, hwaddr base, int it_shift, - MemoryRegion *address_space, - qemu_irq irq, void* mem_opaque, - void (*memory_rw)(void *opaque, hwaddr addr, uint8_t *buf, int len, int is_write)); +DeviceState *rc4030_init(rc4030_dma **dmas, MemoryRegion **dma_mr); #endif diff --git a/include/hw/misc/stm32f2xx_syscfg.h b/include/hw/misc/stm32f2xx_syscfg.h new file mode 100644 index 0000000000..69e6a30fc5 --- /dev/null +++ b/include/hw/misc/stm32f2xx_syscfg.h @@ -0,0 +1,61 @@ +/* + * STM32F2XX SYSCFG + * + * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef HW_STM32F2XX_SYSCFG_H +#define HW_STM32F2XX_SYSCFG_H + +#include "hw/sysbus.h" +#include "hw/hw.h" + +#define SYSCFG_MEMRMP 0x00 +#define SYSCFG_PMC 0x04 +#define SYSCFG_EXTICR1 0x08 +#define SYSCFG_EXTICR2 0x0C +#define SYSCFG_EXTICR3 0x10 +#define SYSCFG_EXTICR4 0x14 +#define SYSCFG_CMPCR 0x20 + +#define TYPE_STM32F2XX_SYSCFG "stm32f2xx-syscfg" +#define STM32F2XX_SYSCFG(obj) \ + OBJECT_CHECK(STM32F2XXSyscfgState, (obj), TYPE_STM32F2XX_SYSCFG) + +typedef struct { + /* <private> */ + SysBusDevice parent_obj; + + /* <public> */ + MemoryRegion mmio; + + uint32_t syscfg_memrmp; + uint32_t syscfg_pmc; + uint32_t syscfg_exticr1; + uint32_t syscfg_exticr2; + uint32_t syscfg_exticr3; + uint32_t syscfg_exticr4; + uint32_t syscfg_cmpcr; + + qemu_irq irq; +} STM32F2XXSyscfgState; + +#endif /* HW_STM32F2XX_SYSCFG_H */ diff --git a/include/hw/net/allwinner_emac.h b/include/hw/net/allwinner_emac.h index 5ae7717300..9f21aa7e45 100644 --- a/include/hw/net/allwinner_emac.h +++ b/include/hw/net/allwinner_emac.h @@ -24,6 +24,7 @@ #include "net/net.h" #include "qemu/fifo8.h" +#include "hw/net/mii.h" #define TYPE_AW_EMAC "allwinner-emac" #define AW_EMAC(obj) OBJECT_CHECK(AwEmacState, (obj), TYPE_AW_EMAC) @@ -118,45 +119,6 @@ #define EMAC_RX_IO_DATA_STATUS_OK (1 << 7) #define EMAC_UNDOCUMENTED_MAGIC 0x0143414d /* header for RX frames */ -/* PHY registers */ -#define MII_BMCR 0 -#define MII_BMSR 1 -#define MII_PHYID1 2 -#define MII_PHYID2 3 -#define MII_ANAR 4 -#define MII_ANLPAR 5 -#define MII_ANER 6 -#define MII_NSR 16 -#define MII_LBREMR 17 -#define MII_REC 18 -#define MII_SNRDR 19 -#define MII_TEST 25 - -/* PHY registers fields */ -#define MII_BMCR_RESET (1 << 15) -#define MII_BMCR_LOOPBACK (1 << 14) -#define MII_BMCR_SPEED (1 << 13) -#define MII_BMCR_AUTOEN (1 << 12) -#define MII_BMCR_FD (1 << 8) - -#define MII_BMSR_100TX_FD (1 << 14) -#define MII_BMSR_100TX_HD (1 << 13) -#define MII_BMSR_10T_FD (1 << 12) -#define MII_BMSR_10T_HD (1 << 11) -#define MII_BMSR_MFPS (1 << 6) -#define MII_BMSR_AN_COMP (1 << 5) -#define MII_BMSR_AUTONEG (1 << 3) -#define MII_BMSR_LINK_ST (1 << 2) - -#define MII_ANAR_TXFD (1 << 8) -#define MII_ANAR_TX (1 << 7) -#define MII_ANAR_10FD (1 << 6) -#define MII_ANAR_10 (1 << 5) -#define MII_ANAR_CSMACD (1 << 0) - -#define RTL8201CP_PHYID1 0x0000 -#define RTL8201CP_PHYID2 0x8201 - /* INT CTL and INT STA registers fields */ #define EMAC_INT_TX_CHAN(x) (1 << (x)) #define EMAC_INT_RX (1 << 8) diff --git a/include/hw/net/cadence_gem.h b/include/hw/net/cadence_gem.h new file mode 100644 index 0000000000..f2e08e3575 --- /dev/null +++ b/include/hw/net/cadence_gem.h @@ -0,0 +1,73 @@ +/* + * QEMU Cadence GEM emulation + * + * Copyright (c) 2011 Xilinx, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef CADENCE_GEM_H + +#define TYPE_CADENCE_GEM "cadence_gem" +#define CADENCE_GEM(obj) OBJECT_CHECK(CadenceGEMState, (obj), TYPE_CADENCE_GEM) + +#include "net/net.h" +#include "hw/sysbus.h" + +#define CADENCE_GEM_MAXREG (0x00000640/4) /* Last valid GEM address */ + +typedef struct CadenceGEMState { + /*< private >*/ + SysBusDevice parent_obj; + + /*< public >*/ + MemoryRegion iomem; + NICState *nic; + NICConf conf; + qemu_irq irq; + + /* GEM registers backing store */ + uint32_t regs[CADENCE_GEM_MAXREG]; + /* Mask of register bits which are write only */ + uint32_t regs_wo[CADENCE_GEM_MAXREG]; + /* Mask of register bits which are read only */ + uint32_t regs_ro[CADENCE_GEM_MAXREG]; + /* Mask of register bits which are clear on read */ + uint32_t regs_rtc[CADENCE_GEM_MAXREG]; + /* Mask of register bits which are write 1 to clear */ + uint32_t regs_w1c[CADENCE_GEM_MAXREG]; + + /* PHY registers backing store */ + uint16_t phy_regs[32]; + + uint8_t phy_loop; /* Are we in phy loopback? */ + + /* The current DMA descriptor pointers */ + uint32_t rx_desc_addr; + uint32_t tx_desc_addr; + + uint8_t can_rx_state; /* Debug only */ + + unsigned rx_desc[2]; + + bool sar_active[4]; +} CadenceGEMState; + +#define CADENCE_GEM_H +#endif diff --git a/include/hw/net/mii.h b/include/hw/net/mii.h new file mode 100644 index 0000000000..9fdd7bbe75 --- /dev/null +++ b/include/hw/net/mii.h @@ -0,0 +1,76 @@ +/* + * Common network MII address and register definitions. + * + * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com> + * + * Allwinner EMAC register definitions from Linux kernel are: + * Copyright 2012 Stefan Roese <sr@denx.de> + * Copyright 2013 Maxime Ripard <maxime.ripard@free-electrons.com> + * Copyright 1997 Sten Wang + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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. + * + */ +#ifndef MII_H +#define MII_H + +/* PHY registers */ +#define MII_BMCR 0 +#define MII_BMSR 1 +#define MII_PHYID1 2 +#define MII_PHYID2 3 +#define MII_ANAR 4 +#define MII_ANLPAR 5 +#define MII_ANER 6 +#define MII_NSR 16 +#define MII_LBREMR 17 +#define MII_REC 18 +#define MII_SNRDR 19 +#define MII_TEST 25 + +/* PHY registers fields */ +#define MII_BMCR_RESET (1 << 15) +#define MII_BMCR_LOOPBACK (1 << 14) +#define MII_BMCR_SPEED (1 << 13) +#define MII_BMCR_AUTOEN (1 << 12) +#define MII_BMCR_FD (1 << 8) + +#define MII_BMSR_100TX_FD (1 << 14) +#define MII_BMSR_100TX_HD (1 << 13) +#define MII_BMSR_10T_FD (1 << 12) +#define MII_BMSR_10T_HD (1 << 11) +#define MII_BMSR_MFPS (1 << 6) +#define MII_BMSR_AN_COMP (1 << 5) +#define MII_BMSR_AUTONEG (1 << 3) +#define MII_BMSR_LINK_ST (1 << 2) + +#define MII_ANAR_TXFD (1 << 8) +#define MII_ANAR_TX (1 << 7) +#define MII_ANAR_10FD (1 << 6) +#define MII_ANAR_10 (1 << 5) +#define MII_ANAR_CSMACD (1 << 0) + +#define MII_ANLPAR_ACK (1 << 14) +#define MII_ANLPAR_TXFD (1 << 8) +#define MII_ANLPAR_TX (1 << 7) +#define MII_ANLPAR_10FD (1 << 6) +#define MII_ANLPAR_10 (1 << 5) +#define MII_ANLPAR_CSMACD (1 << 0) + +/* List of vendor identifiers */ +/* RealTek 8201 */ +#define RTL8201CP_PHYID1 0x0000 +#define RTL8201CP_PHYID2 0x8201 + +/* National Semiconductor DP83848 */ +#define DP83848_PHYID1 0x2000 +#define DP83848_PHYID2 0x5c90 + +#endif /* MII_H */ diff --git a/include/hw/nmi.h b/include/hw/nmi.h index b541772e1d..f4cec6257d 100644 --- a/include/hw/nmi.h +++ b/include/hw/nmi.h @@ -45,5 +45,6 @@ typedef struct NMIClass { } NMIClass; void nmi_monitor_handle(int cpu_index, Error **errp); +void inject_nmi(void); #endif /* NMI_H */ diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h index 56e1ed7122..e60d3ca212 100644 --- a/include/hw/nvram/fw_cfg.h +++ b/include/hw/nvram/fw_cfg.h @@ -67,10 +67,9 @@ typedef void (*FWCfgReadCallback)(void *opaque, uint32_t offset); void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len); void fw_cfg_add_string(FWCfgState *s, uint16_t key, const char *value); void fw_cfg_add_i16(FWCfgState *s, uint16_t key, uint16_t value); +void fw_cfg_modify_i16(FWCfgState *s, uint16_t key, uint16_t value); void fw_cfg_add_i32(FWCfgState *s, uint16_t key, uint32_t value); void fw_cfg_add_i64(FWCfgState *s, uint16_t key, uint64_t value); -void fw_cfg_add_callback(FWCfgState *s, uint16_t key, FWCfgCallback callback, - void *callback_opaque, void *data, size_t len); void fw_cfg_add_file(FWCfgState *s, const char *filename, void *data, size_t len); void fw_cfg_add_file_callback(FWCfgState *s, const char *filename, @@ -78,8 +77,10 @@ void fw_cfg_add_file_callback(FWCfgState *s, const char *filename, 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); +FWCfgState *fw_cfg_init_io(uint32_t iobase); +FWCfgState *fw_cfg_init_mem(hwaddr ctl_addr, hwaddr data_addr); +FWCfgState *fw_cfg_init_mem_wide(hwaddr ctl_addr, hwaddr data_addr, + uint32_t data_width); FWCfgState *fw_cfg_find(void); diff --git a/include/hw/pci-host/gpex.h b/include/hw/pci-host/gpex.h new file mode 100644 index 0000000000..68c93488c9 --- /dev/null +++ b/include/hw/pci-host/gpex.h @@ -0,0 +1,56 @@ +/* + * QEMU Generic PCI Express Bridge Emulation + * + * Copyright (C) 2015 Alexander Graf <agraf@suse.de> + * + * 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 Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#ifndef HW_GPEX_H +#define HW_GPEX_H + +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/pci/pci.h" +#include "hw/pci/pcie_host.h" + +#define TYPE_GPEX_HOST "gpex-pcihost" +#define GPEX_HOST(obj) \ + OBJECT_CHECK(GPEXHost, (obj), TYPE_GPEX_HOST) + +#define TYPE_GPEX_ROOT_DEVICE "gpex-root" +#define MCH_PCI_DEVICE(obj) \ + OBJECT_CHECK(GPEXRootState, (obj), TYPE_GPEX_ROOT_DEVICE) + +#define GPEX_NUM_IRQS 4 + +typedef struct GPEXRootState { + /*< private >*/ + PCIDevice parent_obj; + /*< public >*/ +} GPEXRootState; + +typedef struct GPEXHost { + /*< private >*/ + PCIExpressHost parent_obj; + /*< public >*/ + + GPEXRootState gpex_root; + + MemoryRegion io_ioport; + MemoryRegion io_mmio; + qemu_irq irq[GPEX_NUM_IRQS]; +} GPEXHost; + +#endif /* HW_GPEX_H */ diff --git a/include/hw/pci-host/pam.h b/include/hw/pci-host/pam.h index 4d03e4bf18..6116c638f9 100644 --- a/include/hw/pci-host/pam.h +++ b/include/hw/pci-host/pam.h @@ -86,10 +86,6 @@ typedef struct PAMMemoryRegion { unsigned current; } PAMMemoryRegion; -void smram_update(MemoryRegion *smram_region, uint8_t smram, - uint8_t smm_enabled); -void smram_set_smm(uint8_t *host_smm_enabled, int smm, uint8_t smram, - MemoryRegion *smram_region); void init_pam(DeviceState *dev, MemoryRegion *ram, MemoryRegion *system, MemoryRegion *pci, PAMMemoryRegion *mem, uint32_t start, uint32_t size); void pam_update(PAMMemoryRegion *mem, int idx, uint8_t val); diff --git a/include/hw/pci-host/q35.h b/include/hw/pci-host/q35.h index 025d6e69af..dbe6dc05b5 100644 --- a/include/hw/pci-host/q35.h +++ b/include/hw/pci-host/q35.h @@ -23,7 +23,6 @@ #define HW_Q35_H #include "hw/hw.h" -#include "qemu/range.h" #include "hw/isa/isa.h" #include "hw/sysbus.h" #include "hw/i386/pc.h" @@ -53,9 +52,10 @@ typedef struct MCHPCIState { MemoryRegion *system_memory; MemoryRegion *address_space_io; PAMMemoryRegion pam_regions[13]; - MemoryRegion smram_region; + MemoryRegion smram_region, open_high_smram; + MemoryRegion smram, low_smram, high_smram; + MemoryRegion tseg_blackhole, tseg_window; PcPciInfo pci_info; - uint8_t smm_enabled; ram_addr_t below_4g_mem_size; ram_addr_t above_4g_mem_size; uint64_t pci_hole64_size; @@ -128,8 +128,7 @@ typedef struct Q35PCIHost { #define MCH_HOST_BRIDGE_PAM_MASK ((uint8_t)0x3) #define MCH_HOST_BRIDGE_SMRAM 0x9d -#define MCH_HOST_BRIDGE_SMRAM_SIZE 1 -#define MCH_HOST_BRIDGE_SMRAM_DEFAULT ((uint8_t)0x2) +#define MCH_HOST_BRIDGE_SMRAM_SIZE 2 #define MCH_HOST_BRIDGE_SMRAM_D_OPEN ((uint8_t)(1 << 6)) #define MCH_HOST_BRIDGE_SMRAM_D_CLS ((uint8_t)(1 << 5)) #define MCH_HOST_BRIDGE_SMRAM_D_LCK ((uint8_t)(1 << 4)) @@ -140,18 +139,36 @@ typedef struct Q35PCIHost { #define MCH_HOST_BRIDGE_SMRAM_C_END 0xc0000 #define MCH_HOST_BRIDGE_SMRAM_C_SIZE 0x20000 #define MCH_HOST_BRIDGE_UPPER_SYSTEM_BIOS_END 0x100000 +#define MCH_HOST_BRIDGE_SMRAM_DEFAULT \ + MCH_HOST_BRIDGE_SMRAM_C_BASE_SEG +#define MCH_HOST_BRIDGE_SMRAM_WMASK \ + (MCH_HOST_BRIDGE_SMRAM_D_OPEN | \ + MCH_HOST_BRIDGE_SMRAM_D_CLS | \ + MCH_HOST_BRIDGE_SMRAM_D_LCK | \ + MCH_HOST_BRIDGE_SMRAM_G_SMRAME) +#define MCH_HOST_BRIDGE_SMRAM_WMASK_LCK \ + MCH_HOST_BRIDGE_SMRAM_D_CLS #define MCH_HOST_BRIDGE_ESMRAMC 0x9e -#define MCH_HOST_BRIDGE_ESMRAMC_H_SMRAME ((uint8_t)(1 << 6)) -#define MCH_HOST_BRIDGE_ESMRAMC_E_SMERR ((uint8_t)(1 << 5)) -#define MCH_HOST_BRIDGE_ESMRAMC_SM_CACHE ((uint8_t)(1 << 4)) -#define MCH_HOST_BRIDGE_ESMRAMC_SM_L1 ((uint8_t)(1 << 3)) -#define MCH_HOST_BRIDGE_ESMRAMC_SM_L2 ((uint8_t)(1 << 2)) +#define MCH_HOST_BRIDGE_ESMRAMC_H_SMRAME ((uint8_t)(1 << 7)) +#define MCH_HOST_BRIDGE_ESMRAMC_E_SMERR ((uint8_t)(1 << 6)) +#define MCH_HOST_BRIDGE_ESMRAMC_SM_CACHE ((uint8_t)(1 << 5)) +#define MCH_HOST_BRIDGE_ESMRAMC_SM_L1 ((uint8_t)(1 << 4)) +#define MCH_HOST_BRIDGE_ESMRAMC_SM_L2 ((uint8_t)(1 << 3)) #define MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_MASK ((uint8_t)(0x3 << 1)) #define MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_1MB ((uint8_t)(0x0 << 1)) #define MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_2MB ((uint8_t)(0x1 << 1)) #define MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_8MB ((uint8_t)(0x2 << 1)) #define MCH_HOST_BRIDGE_ESMRAMC_T_EN ((uint8_t)1) +#define MCH_HOST_BRIDGE_ESMRAMC_DEFAULT \ + (MCH_HOST_BRIDGE_ESMRAMC_SM_CACHE | \ + MCH_HOST_BRIDGE_ESMRAMC_SM_L1 | \ + MCH_HOST_BRIDGE_ESMRAMC_SM_L2) +#define MCH_HOST_BRIDGE_ESMRAMC_WMASK \ + (MCH_HOST_BRIDGE_ESMRAMC_H_SMRAME | \ + MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_MASK | \ + MCH_HOST_BRIDGE_ESMRAMC_T_EN) +#define MCH_HOST_BRIDGE_ESMRAMC_WMASK_LCK 0 /* D1:F0 PCIE* port*/ #define MCH_PCIE_DEV 1 diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h index 4ea2a0d14a..5322b560eb 100644 --- a/include/hw/pci-host/spapr.h +++ b/include/hw/pci-host/spapr.h @@ -49,6 +49,10 @@ struct sPAPRPHBClass { PCIHostBridgeClass parent_class; void (*finish_realize)(sPAPRPHBState *sphb, Error **errp); + int (*eeh_set_option)(sPAPRPHBState *sphb, unsigned int addr, int option); + int (*eeh_get_state)(sPAPRPHBState *sphb, int *state); + int (*eeh_reset)(sPAPRPHBState *sphb, int option); + int (*eeh_configure)(sPAPRPHBState *sphb); }; typedef struct spapr_pci_msi { @@ -64,9 +68,10 @@ typedef struct spapr_pci_msi_mig { struct sPAPRPHBState { PCIHostState parent_obj; - int32_t index; + uint32_t index; uint64_t buid; char *dtbusname; + bool dr_enabled; MemoryRegion memspace, iospace; hwaddr mem_win_addr, mem_win_size, io_win_addr, io_win_size; @@ -94,32 +99,43 @@ struct sPAPRPHBVFIOState { int32_t iommugroupid; }; +#define SPAPR_PCI_MAX_INDEX 255 + #define SPAPR_PCI_BASE_BUID 0x800000020000000ULL +#define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL + #define SPAPR_PCI_WINDOW_BASE 0x10000000000ULL #define SPAPR_PCI_WINDOW_SPACING 0x1000000000ULL #define SPAPR_PCI_MMIO_WIN_OFF 0xA0000000 -#define SPAPR_PCI_MMIO_WIN_SIZE 0x20000000 +#define SPAPR_PCI_MMIO_WIN_SIZE (SPAPR_PCI_WINDOW_SPACING - \ + SPAPR_PCI_MEM_WIN_BUS_OFFSET) #define SPAPR_PCI_IO_WIN_OFF 0x80000000 #define SPAPR_PCI_IO_WIN_SIZE 0x10000 #define SPAPR_PCI_MSI_WINDOW 0x40000000000ULL -#define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL +#define SPAPR_PCI_DMA32_SIZE 0x40000000 static inline qemu_irq spapr_phb_lsi_qirq(struct sPAPRPHBState *phb, int pin) { + sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); + return xics_get_qirq(spapr->icp, phb->lsi_table[pin].irq); } -PCIHostState *spapr_create_phb(sPAPREnvironment *spapr, int index); +PCIHostState *spapr_create_phb(sPAPRMachineState *spapr, int index); int spapr_populate_pci_dt(sPAPRPHBState *phb, uint32_t xics_phandle, void *fdt); -void spapr_pci_msi_init(sPAPREnvironment *spapr, hwaddr addr); +void spapr_pci_msi_init(sPAPRMachineState *spapr, hwaddr addr); void spapr_pci_rtas_init(void); +sPAPRPHBState *spapr_pci_find_phb(sPAPRMachineState *spapr, uint64_t buid); +PCIDevice *spapr_pci_find_dev(sPAPRMachineState *spapr, uint64_t buid, + uint32_t config_addr); + #endif /* __HW_SPAPR_PCI_H__ */ diff --git a/include/hw/pci/msi.h b/include/hw/pci/msi.h index 81a3848a31..50e452bd05 100644 --- a/include/hw/pci/msi.h +++ b/include/hw/pci/msi.h @@ -39,6 +39,7 @@ int msi_init(struct PCIDevice *dev, uint8_t offset, void msi_uninit(struct PCIDevice *dev); void msi_reset(PCIDevice *dev); void msi_notify(PCIDevice *dev, unsigned int vector); +void msi_send_message(PCIDevice *dev, MSIMessage msg); void msi_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int len); unsigned int msi_nr_vectors_allocated(const PCIDevice *dev); diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index c352c7b3ad..551cb3d608 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -88,6 +88,11 @@ #define PCI_DEVICE_ID_REDHAT_SERIAL2 0x0003 #define PCI_DEVICE_ID_REDHAT_SERIAL4 0x0004 #define PCI_DEVICE_ID_REDHAT_TEST 0x0005 +#define PCI_DEVICE_ID_REDHAT_ROCKER 0x0006 +#define PCI_DEVICE_ID_REDHAT_SDHCI 0x0007 +#define PCI_DEVICE_ID_REDHAT_PCIE_HOST 0x0008 +#define PCI_DEVICE_ID_REDHAT_PXB 0x0009 +#define PCI_DEVICE_ID_REDHAT_BRIDGE_SEAT 0x000a #define PCI_DEVICE_ID_REDHAT_QXL 0x0100 #define FMT_PCIBUS PRIx64 @@ -135,7 +140,7 @@ enum { #define PCI_CONFIG_HEADER_SIZE 0x40 /* Size of the standard PCI config space */ #define PCI_CONFIG_SPACE_SIZE 0x100 -/* Size of the standart PCIe config space: 4KB */ +/* Size of the standard PCIe config space: 4KB */ #define PCIE_CONFIG_SPACE_SIZE 0x1000 #define PCI_NUM_PINS 4 /* A-D */ @@ -183,7 +188,8 @@ typedef struct PCIINTxRoute { typedef struct PCIDeviceClass { DeviceClass parent_class; - int (*init)(PCIDevice *dev); + void (*realize)(PCIDevice *dev, Error **errp); + int (*init)(PCIDevice *dev);/* TODO convert to realize() and remove */ PCIUnregisterFunc *exit; PCIConfigReadFunc *config_read; PCIConfigWriteFunc *config_write; @@ -330,12 +336,20 @@ int pci_device_load(PCIDevice *s, QEMUFile *f); MemoryRegion *pci_address_space(PCIDevice *dev); MemoryRegion *pci_address_space_io(PCIDevice *dev); +/* + * Should not normally be used by devices. For use by sPAPR target + * where QEMU emulates firmware. + */ +int pci_bar(PCIDevice *d, int reg); + typedef void (*pci_set_irq_fn)(void *opaque, int irq_num, int level); typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num); typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque, int pin); #define TYPE_PCI_BUS "PCI" #define PCI_BUS(obj) OBJECT_CHECK(PCIBus, (obj), TYPE_PCI_BUS) +#define PCI_BUS_CLASS(klass) OBJECT_CLASS_CHECK(PCIBusClass, (klass), TYPE_PCI_BUS) +#define PCI_BUS_GET_CLASS(obj) OBJECT_GET_CLASS(PCIBusClass, (obj), TYPE_PCI_BUS) #define TYPE_PCIE_BUS "PCIE" bool pci_bus_is_express(PCIBus *bus); @@ -368,9 +382,6 @@ void pci_device_set_intx_routing_notifier(PCIDevice *dev, PCIINTxRoutingNotifier notifier); void pci_device_reset(PCIDevice *dev); -PCIDevice *pci_nic_init(NICInfo *nd, PCIBus *rootbus, - const char *default_model, - const char *default_devaddr); PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus, const char *default_model, const char *default_devaddr); @@ -378,6 +389,7 @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus, PCIDevice *pci_vga_init(PCIBus *bus); int pci_bus_num(PCIBus *s); +int pci_bus_numa_node(PCIBus *bus); void pci_for_each_device(PCIBus *bus, int bus_num, void (*fn)(PCIBus *bus, PCIDevice *d, void *opaque), void *opaque); @@ -400,12 +412,8 @@ PCIBus *pci_device_root_bus(const PCIDevice *d); const char *pci_root_bus_path(PCIDevice *dev); PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn); int pci_qdev_find_device(const char *id, PCIDevice **pdev); -PCIBus *pci_get_bus_devfn(int *devfnp, PCIBus *root, const char *devaddr); void pci_bus_get_w64_range(PCIBus *bus, Range *range); -int pci_parse_devaddr(const char *addr, int *domp, int *busp, - unsigned int *slotp, unsigned int *funcp); - void pci_device_deassert_intx(PCIDevice *dev); typedef AddressSpace *(*PCIIOMMUFunc)(PCIBus *, void *, int); @@ -572,7 +580,7 @@ static inline void pci_set_byte_by_mask(uint8_t *config, uint8_t mask, uint8_t reg) { uint8_t val = pci_get_byte(config); - uint8_t rval = reg << (ffs(mask) - 1); + uint8_t rval = reg << ctz32(mask); pci_set_byte(config, (~mask & val) | (mask & rval)); } @@ -580,14 +588,14 @@ static inline uint8_t pci_get_byte_by_mask(uint8_t *config, uint8_t mask) { uint8_t val = pci_get_byte(config); - return (val & mask) >> (ffs(mask) - 1); + return (val & mask) >> ctz32(mask); } static inline void pci_set_word_by_mask(uint8_t *config, uint16_t mask, uint16_t reg) { uint16_t val = pci_get_word(config); - uint16_t rval = reg << (ffs(mask) - 1); + uint16_t rval = reg << ctz32(mask); pci_set_word(config, (~mask & val) | (mask & rval)); } @@ -595,14 +603,14 @@ static inline uint16_t pci_get_word_by_mask(uint8_t *config, uint16_t mask) { uint16_t val = pci_get_word(config); - return (val & mask) >> (ffs(mask) - 1); + return (val & mask) >> ctz32(mask); } static inline void pci_set_long_by_mask(uint8_t *config, uint32_t mask, uint32_t reg) { uint32_t val = pci_get_long(config); - uint32_t rval = reg << (ffs(mask) - 1); + uint32_t rval = reg << ctz32(mask); pci_set_long(config, (~mask & val) | (mask & rval)); } @@ -610,14 +618,14 @@ static inline uint32_t pci_get_long_by_mask(uint8_t *config, uint32_t mask) { uint32_t val = pci_get_long(config); - return (val & mask) >> (ffs(mask) - 1); + return (val & mask) >> ctz32(mask); } static inline void pci_set_quad_by_mask(uint8_t *config, uint64_t mask, uint64_t reg) { uint64_t val = pci_get_quad(config); - uint64_t rval = reg << (ffs(mask) - 1); + uint64_t rval = reg << ctz32(mask); pci_set_quad(config, (~mask & val) | (mask & rval)); } @@ -625,7 +633,7 @@ static inline uint64_t pci_get_quad_by_mask(uint8_t *config, uint64_t mask) { uint64_t val = pci_get_quad(config); - return (val & mask) >> (ffs(mask) - 1); + return (val & mask) >> ctz32(mask); } PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction, diff --git a/include/hw/pci/pci_bridge.h b/include/hw/pci/pci_bridge.h index 1d8f9973c7..93b621cef3 100644 --- a/include/hw/pci/pci_bridge.h +++ b/include/hw/pci/pci_bridge.h @@ -28,6 +28,10 @@ #include "hw/pci/pci.h" +#define PCI_BRIDGE_DEV_PROP_CHASSIS_NR "chassis_nr" +#define PCI_BRIDGE_DEV_PROP_MSI "msi" +#define PCI_BRIDGE_DEV_PROP_SHPC "shpc" + int pci_bridge_ssvid_init(PCIDevice *dev, uint8_t offset, uint16_t svid, uint16_t ssid); diff --git a/include/hw/pci/pci_bus.h b/include/hw/pci/pci_bus.h index fabaeee86b..403fec6e58 100644 --- a/include/hw/pci/pci_bus.h +++ b/include/hw/pci/pci_bus.h @@ -8,6 +8,16 @@ * use accessor functions in pci.h, pci_bridge.h */ +typedef struct PCIBusClass { + /*< private >*/ + BusClass parent_class; + /*< public >*/ + + bool (*is_root)(PCIBus *bus); + int (*bus_num)(PCIBus *bus); + uint16_t (*numa_node)(PCIBus *bus); +} PCIBusClass; + struct PCIBus { BusState qbus; PCIIOMMUFunc iommu_fn; diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h index 321d622b78..d98e6c915d 100644 --- a/include/hw/pci/pci_ids.h +++ b/include/hw/pci/pci_ids.h @@ -23,6 +23,7 @@ #define PCI_CLASS_STORAGE_OTHER 0x0180 #define PCI_CLASS_NETWORK_ETHERNET 0x0200 +#define PCI_CLASS_NETWORK_OTHER 0x0280 #define PCI_CLASS_DISPLAY_VGA 0x0300 #define PCI_CLASS_DISPLAY_OTHER 0x0380 @@ -31,6 +32,7 @@ #define PCI_CLASS_MEMORY_RAM 0x0500 +#define PCI_CLASS_SYSTEM_SDHCI 0x0805 #define PCI_CLASS_SYSTEM_OTHER 0x0880 #define PCI_CLASS_SERIAL_USB 0x0c03 @@ -45,6 +47,13 @@ #define PCI_CLASS_COMMUNICATION_SERIAL 0x0700 #define PCI_CLASS_COMMUNICATION_OTHER 0x0780 +#define PCI_CLASS_INPUT_KEYBOARD 0x0900 +#define PCI_CLASS_INPUT_PEN 0x0901 +#define PCI_CLASS_INPUT_MOUSE 0x0902 +#define PCI_CLASS_INPUT_SCANNER 0x0903 +#define PCI_CLASS_INPUT_GAMEPORT 0x0904 +#define PCI_CLASS_INPUT_OTHER 0x0980 + #define PCI_CLASS_PROCESSOR_CO 0x0b40 #define PCI_CLASS_PROCESSOR_POWERPC 0x0b20 @@ -105,6 +114,8 @@ #define PCI_VENDOR_ID_ENSONIQ 0x1274 #define PCI_DEVICE_ID_ENSONIQ_ES1370 0x5000 +#define PCI_VENDOR_ID_CHELSIO 0x1425 + #define PCI_VENDOR_ID_FREESCALE 0x1957 #define PCI_DEVICE_ID_MPC8533E 0x0030 diff --git a/include/hw/pci/pci_regs.h b/include/hw/pci/pci_regs.h index 56a404be6e..ba8cbe9278 100644 --- a/include/hw/pci/pci_regs.h +++ b/include/hw/pci/pci_regs.h @@ -1,717 +1 @@ -/* - * pci_regs.h - * - * PCI standard defines - * Copyright 1994, Drew Eckhardt - * Copyright 1997--1999 Martin Mares <mj@ucw.cz> - * - * For more information, please consult the following manuals (look at - * http://www.pcisig.com/ for how to get them): - * - * PCI BIOS Specification - * PCI Local Bus Specification - * PCI to PCI Bridge Specification - * PCI System Design Guide - * - * For hypertransport information, please consult the following manuals - * from http://www.hypertransport.org - * - * The Hypertransport I/O Link Specification - */ - -#ifndef LINUX_PCI_REGS_H -#define LINUX_PCI_REGS_H - -/* - * Under PCI, each device has 256 bytes of configuration address space, - * of which the first 64 bytes are standardized as follows: - */ -#define PCI_VENDOR_ID 0x00 /* 16 bits */ -#define PCI_DEVICE_ID 0x02 /* 16 bits */ -#define PCI_COMMAND 0x04 /* 16 bits */ -#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */ -#define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */ -#define PCI_COMMAND_MASTER 0x4 /* Enable bus mastering */ -#define PCI_COMMAND_SPECIAL 0x8 /* Enable response to special cycles */ -#define PCI_COMMAND_INVALIDATE 0x10 /* Use memory write and invalidate */ -#define PCI_COMMAND_VGA_PALETTE 0x20 /* Enable palette snooping */ -#define PCI_COMMAND_PARITY 0x40 /* Enable parity checking */ -#define PCI_COMMAND_WAIT 0x80 /* Enable address/data stepping */ -#define PCI_COMMAND_SERR 0x100 /* Enable SERR */ -#define PCI_COMMAND_FAST_BACK 0x200 /* Enable back-to-back writes */ -#define PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */ - -#define PCI_STATUS 0x06 /* 16 bits */ -#define PCI_STATUS_INTERRUPT 0x08 /* Interrupt status */ -#define PCI_STATUS_CAP_LIST 0x10 /* Support Capability List */ -#define PCI_STATUS_66MHZ 0x20 /* Support 66 Mhz PCI 2.1 bus */ -#define PCI_STATUS_UDF 0x40 /* Support User Definable Features [obsolete] */ -#define PCI_STATUS_FAST_BACK 0x80 /* Accept fast-back to back */ -#define PCI_STATUS_PARITY 0x100 /* Detected parity error */ -#define PCI_STATUS_DEVSEL_MASK 0x600 /* DEVSEL timing */ -#define PCI_STATUS_DEVSEL_FAST 0x000 -#define PCI_STATUS_DEVSEL_MEDIUM 0x200 -#define PCI_STATUS_DEVSEL_SLOW 0x400 -#define PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */ -#define PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */ -#define PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */ -#define PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */ -#define PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */ - -#define PCI_CLASS_REVISION 0x08 /* High 24 bits are class, low 8 revision */ -#define PCI_REVISION_ID 0x08 /* Revision ID */ -#define PCI_CLASS_PROG 0x09 /* Reg. Level Programming Interface */ -#define PCI_CLASS_DEVICE 0x0a /* Device class */ - -#define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */ -#define PCI_LATENCY_TIMER 0x0d /* 8 bits */ -#define PCI_HEADER_TYPE 0x0e /* 8 bits */ -#define PCI_HEADER_TYPE_NORMAL 0 -#define PCI_HEADER_TYPE_BRIDGE 1 -#define PCI_HEADER_TYPE_CARDBUS 2 - -#define PCI_BIST 0x0f /* 8 bits */ -#define PCI_BIST_CODE_MASK 0x0f /* Return result */ -#define PCI_BIST_START 0x40 /* 1 to start BIST, 2 secs or less */ -#define PCI_BIST_CAPABLE 0x80 /* 1 if BIST capable */ - -/* - * Base addresses specify locations in memory or I/O space. - * Decoded size can be determined by writing a value of - * 0xffffffff to the register, and reading it back. Only - * 1 bits are decoded. - */ -#define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */ -#define PCI_BASE_ADDRESS_1 0x14 /* 32 bits [htype 0,1 only] */ -#define PCI_BASE_ADDRESS_2 0x18 /* 32 bits [htype 0 only] */ -#define PCI_BASE_ADDRESS_3 0x1c /* 32 bits */ -#define PCI_BASE_ADDRESS_4 0x20 /* 32 bits */ -#define PCI_BASE_ADDRESS_5 0x24 /* 32 bits */ -#define PCI_BASE_ADDRESS_SPACE 0x01 /* 0 = memory, 1 = I/O */ -#define PCI_BASE_ADDRESS_SPACE_IO 0x01 -#define PCI_BASE_ADDRESS_SPACE_MEMORY 0x00 -#define PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06 -#define PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 /* 32 bit address */ -#define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M [obsolete] */ -#define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */ -#define PCI_BASE_ADDRESS_MEM_PREFETCH 0x08 /* prefetchable? */ -#define PCI_BASE_ADDRESS_MEM_MASK (~0x0fUL) -#define PCI_BASE_ADDRESS_IO_MASK (~0x03UL) -/* bit 1 is reserved if address_space = 1 */ - -/* Header type 0 (normal devices) */ -#define PCI_CARDBUS_CIS 0x28 -#define PCI_SUBSYSTEM_VENDOR_ID 0x2c -#define PCI_SUBSYSTEM_ID 0x2e -#define PCI_ROM_ADDRESS 0x30 /* Bits 31..11 are address, 10..1 reserved */ -#define PCI_ROM_ADDRESS_ENABLE 0x01 -#define PCI_ROM_ADDRESS_MASK (~0x7ffUL) - -#define PCI_CAPABILITY_LIST 0x34 /* Offset of first capability list entry */ - -/* 0x35-0x3b are reserved */ -#define PCI_INTERRUPT_LINE 0x3c /* 8 bits */ -#define PCI_INTERRUPT_PIN 0x3d /* 8 bits */ -#define PCI_MIN_GNT 0x3e /* 8 bits */ -#define PCI_MAX_LAT 0x3f /* 8 bits */ - -/* Header type 1 (PCI-to-PCI bridges) */ -#define PCI_PRIMARY_BUS 0x18 /* Primary bus number */ -#define PCI_SECONDARY_BUS 0x19 /* Secondary bus number */ -#define PCI_SUBORDINATE_BUS 0x1a /* Highest bus number behind the bridge */ -#define PCI_SEC_LATENCY_TIMER 0x1b /* Latency timer for secondary interface */ -#define PCI_IO_BASE 0x1c /* I/O range behind the bridge */ -#define PCI_IO_LIMIT 0x1d -#define PCI_IO_RANGE_TYPE_MASK 0x0fUL /* I/O bridging type */ -#define PCI_IO_RANGE_TYPE_16 0x00 -#define PCI_IO_RANGE_TYPE_32 0x01 -#define PCI_IO_RANGE_MASK (~0x0fUL) -#define PCI_SEC_STATUS 0x1e /* Secondary status register, only bit 14 used */ -#define PCI_MEMORY_BASE 0x20 /* Memory range behind */ -#define PCI_MEMORY_LIMIT 0x22 -#define PCI_MEMORY_RANGE_TYPE_MASK 0x0fUL -#define PCI_MEMORY_RANGE_MASK (~0x0fUL) -#define PCI_PREF_MEMORY_BASE 0x24 /* Prefetchable memory range behind */ -#define PCI_PREF_MEMORY_LIMIT 0x26 -#define PCI_PREF_RANGE_TYPE_MASK 0x0fUL -#define PCI_PREF_RANGE_TYPE_32 0x00 -#define PCI_PREF_RANGE_TYPE_64 0x01 -#define PCI_PREF_RANGE_MASK (~0x0fUL) -#define PCI_PREF_BASE_UPPER32 0x28 /* Upper half of prefetchable memory range */ -#define PCI_PREF_LIMIT_UPPER32 0x2c -#define PCI_IO_BASE_UPPER16 0x30 /* Upper half of I/O addresses */ -#define PCI_IO_LIMIT_UPPER16 0x32 -/* 0x34 same as for htype 0 */ -/* 0x35-0x3b is reserved */ -#define PCI_ROM_ADDRESS1 0x38 /* Same as PCI_ROM_ADDRESS, but for htype 1 */ -/* 0x3c-0x3d are same as for htype 0 */ -#define PCI_BRIDGE_CONTROL 0x3e -#define PCI_BRIDGE_CTL_PARITY 0x01 /* Enable parity detection on secondary interface */ -#define PCI_BRIDGE_CTL_SERR 0x02 /* The same for SERR forwarding */ -#define PCI_BRIDGE_CTL_ISA 0x04 /* Enable ISA mode */ -#define PCI_BRIDGE_CTL_VGA 0x08 /* Forward VGA addresses */ -#define PCI_BRIDGE_CTL_MASTER_ABORT 0x20 /* Report master aborts */ -#define PCI_BRIDGE_CTL_BUS_RESET 0x40 /* Secondary bus reset */ -#define PCI_BRIDGE_CTL_FAST_BACK 0x80 /* Fast Back2Back enabled on secondary interface */ - -/* Header type 2 (CardBus bridges) */ -#define PCI_CB_CAPABILITY_LIST 0x14 -/* 0x15 reserved */ -#define PCI_CB_SEC_STATUS 0x16 /* Secondary status */ -#define PCI_CB_PRIMARY_BUS 0x18 /* PCI bus number */ -#define PCI_CB_CARD_BUS 0x19 /* CardBus bus number */ -#define PCI_CB_SUBORDINATE_BUS 0x1a /* Subordinate bus number */ -#define PCI_CB_LATENCY_TIMER 0x1b /* CardBus latency timer */ -#define PCI_CB_MEMORY_BASE_0 0x1c -#define PCI_CB_MEMORY_LIMIT_0 0x20 -#define PCI_CB_MEMORY_BASE_1 0x24 -#define PCI_CB_MEMORY_LIMIT_1 0x28 -#define PCI_CB_IO_BASE_0 0x2c -#define PCI_CB_IO_BASE_0_HI 0x2e -#define PCI_CB_IO_LIMIT_0 0x30 -#define PCI_CB_IO_LIMIT_0_HI 0x32 -#define PCI_CB_IO_BASE_1 0x34 -#define PCI_CB_IO_BASE_1_HI 0x36 -#define PCI_CB_IO_LIMIT_1 0x38 -#define PCI_CB_IO_LIMIT_1_HI 0x3a -#define PCI_CB_IO_RANGE_MASK (~0x03UL) -/* 0x3c-0x3d are same as for htype 0 */ -#define PCI_CB_BRIDGE_CONTROL 0x3e -#define PCI_CB_BRIDGE_CTL_PARITY 0x01 /* Similar to standard bridge control register */ -#define PCI_CB_BRIDGE_CTL_SERR 0x02 -#define PCI_CB_BRIDGE_CTL_ISA 0x04 -#define PCI_CB_BRIDGE_CTL_VGA 0x08 -#define PCI_CB_BRIDGE_CTL_MASTER_ABORT 0x20 -#define PCI_CB_BRIDGE_CTL_CB_RESET 0x40 /* CardBus reset */ -#define PCI_CB_BRIDGE_CTL_16BIT_INT 0x80 /* Enable interrupt for 16-bit cards */ -#define PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 0x100 /* Prefetch enable for both memory regions */ -#define PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 0x200 -#define PCI_CB_BRIDGE_CTL_POST_WRITES 0x400 -#define PCI_CB_SUBSYSTEM_VENDOR_ID 0x40 -#define PCI_CB_SUBSYSTEM_ID 0x42 -#define PCI_CB_LEGACY_MODE_BASE 0x44 /* 16-bit PC Card legacy mode base address (ExCa) */ -/* 0x48-0x7f reserved */ - -/* Capability lists */ - -#define PCI_CAP_LIST_ID 0 /* Capability ID */ -#define PCI_CAP_ID_PM 0x01 /* Power Management */ -#define PCI_CAP_ID_AGP 0x02 /* Accelerated Graphics Port */ -#define PCI_CAP_ID_VPD 0x03 /* Vital Product Data */ -#define PCI_CAP_ID_SLOTID 0x04 /* Slot Identification */ -#define PCI_CAP_ID_MSI 0x05 /* Message Signalled Interrupts */ -#define PCI_CAP_ID_CHSWP 0x06 /* CompactPCI HotSwap */ -#define PCI_CAP_ID_PCIX 0x07 /* PCI-X */ -#define PCI_CAP_ID_HT 0x08 /* HyperTransport */ -#define PCI_CAP_ID_VNDR 0x09 /* Vendor specific */ -#define PCI_CAP_ID_DBG 0x0A /* Debug port */ -#define PCI_CAP_ID_CCRC 0x0B /* CompactPCI Central Resource Control */ -#define PCI_CAP_ID_SHPC 0x0C /* PCI Standard Hot-Plug Controller */ -#define PCI_CAP_ID_SSVID 0x0D /* Bridge subsystem vendor/device ID */ -#define PCI_CAP_ID_AGP3 0x0E /* AGP Target PCI-PCI bridge */ -#define PCI_CAP_ID_EXP 0x10 /* PCI Express */ -#define PCI_CAP_ID_MSIX 0x11 /* MSI-X */ -#define PCI_CAP_ID_SATA 0x12 /* Serial ATA */ -#define PCI_CAP_ID_AF 0x13 /* PCI Advanced Features */ -#define PCI_CAP_LIST_NEXT 1 /* Next capability in the list */ -#define PCI_CAP_FLAGS 2 /* Capability defined flags (16 bits) */ -#define PCI_CAP_SIZEOF 4 - -/* Power Management Registers */ - -#define PCI_PM_PMC 2 /* PM Capabilities Register */ -#define PCI_PM_CAP_VER_MASK 0x0007 /* Version */ -#define PCI_PM_CAP_PME_CLOCK 0x0008 /* PME clock required */ -#define PCI_PM_CAP_RESERVED 0x0010 /* Reserved field */ -#define PCI_PM_CAP_DSI 0x0020 /* Device specific initialization */ -#define PCI_PM_CAP_AUX_POWER 0x01C0 /* Auxiliary power support mask */ -#define PCI_PM_CAP_D1 0x0200 /* D1 power state support */ -#define PCI_PM_CAP_D2 0x0400 /* D2 power state support */ -#define PCI_PM_CAP_PME 0x0800 /* PME pin supported */ -#define PCI_PM_CAP_PME_MASK 0xF800 /* PME Mask of all supported states */ -#define PCI_PM_CAP_PME_D0 0x0800 /* PME# from D0 */ -#define PCI_PM_CAP_PME_D1 0x1000 /* PME# from D1 */ -#define PCI_PM_CAP_PME_D2 0x2000 /* PME# from D2 */ -#define PCI_PM_CAP_PME_D3 0x4000 /* PME# from D3 (hot) */ -#define PCI_PM_CAP_PME_D3cold 0x8000 /* PME# from D3 (cold) */ -#define PCI_PM_CAP_PME_SHIFT 11 /* Start of the PME Mask in PMC */ -#define PCI_PM_CTRL 4 /* PM control and status register */ -#define PCI_PM_CTRL_STATE_MASK 0x0003 /* Current power state (D0 to D3) */ -#define PCI_PM_CTRL_NO_SOFT_RESET 0x0008 /* No reset for D3hot->D0 */ -#define PCI_PM_CTRL_PME_ENABLE 0x0100 /* PME pin enable */ -#define PCI_PM_CTRL_DATA_SEL_MASK 0x1e00 /* Data select (??) */ -#define PCI_PM_CTRL_DATA_SCALE_MASK 0x6000 /* Data scale (??) */ -#define PCI_PM_CTRL_PME_STATUS 0x8000 /* PME pin status */ -#define PCI_PM_PPB_EXTENSIONS 6 /* PPB support extensions (??) */ -#define PCI_PM_PPB_B2_B3 0x40 /* Stop clock when in D3hot (??) */ -#define PCI_PM_BPCC_ENABLE 0x80 /* Bus power/clock control enable (??) */ -#define PCI_PM_DATA_REGISTER 7 /* (??) */ -#define PCI_PM_SIZEOF 8 - -/* AGP registers */ - -#define PCI_AGP_VERSION 2 /* BCD version number */ -#define PCI_AGP_RFU 3 /* Rest of capability flags */ -#define PCI_AGP_STATUS 4 /* Status register */ -#define PCI_AGP_STATUS_RQ_MASK 0xff000000 /* Maximum number of requests - 1 */ -#define PCI_AGP_STATUS_SBA 0x0200 /* Sideband addressing supported */ -#define PCI_AGP_STATUS_64BIT 0x0020 /* 64-bit addressing supported */ -#define PCI_AGP_STATUS_FW 0x0010 /* FW transfers supported */ -#define PCI_AGP_STATUS_RATE4 0x0004 /* 4x transfer rate supported */ -#define PCI_AGP_STATUS_RATE2 0x0002 /* 2x transfer rate supported */ -#define PCI_AGP_STATUS_RATE1 0x0001 /* 1x transfer rate supported */ -#define PCI_AGP_COMMAND 8 /* Control register */ -#define PCI_AGP_COMMAND_RQ_MASK 0xff000000 /* Master: Maximum number of requests */ -#define PCI_AGP_COMMAND_SBA 0x0200 /* Sideband addressing enabled */ -#define PCI_AGP_COMMAND_AGP 0x0100 /* Allow processing of AGP transactions */ -#define PCI_AGP_COMMAND_64BIT 0x0020 /* Allow processing of 64-bit addresses */ -#define PCI_AGP_COMMAND_FW 0x0010 /* Force FW transfers */ -#define PCI_AGP_COMMAND_RATE4 0x0004 /* Use 4x rate */ -#define PCI_AGP_COMMAND_RATE2 0x0002 /* Use 2x rate */ -#define PCI_AGP_COMMAND_RATE1 0x0001 /* Use 1x rate */ -#define PCI_AGP_SIZEOF 12 - -/* Vital Product Data */ - -#define PCI_VPD_ADDR 2 /* Address to access (15 bits!) */ -#define PCI_VPD_ADDR_MASK 0x7fff /* Address mask */ -#define PCI_VPD_ADDR_F 0x8000 /* Write 0, 1 indicates completion */ -#define PCI_VPD_DATA 4 /* 32-bits of data returned here */ - -/* Slot Identification */ - -#define PCI_SID_ESR 2 /* Expansion Slot Register */ -#define PCI_SID_ESR_NSLOTS 0x1f /* Number of expansion slots available */ -#define PCI_SID_ESR_FIC 0x20 /* First In Chassis Flag */ -#define PCI_SID_CHASSIS_NR 3 /* Chassis Number */ - -/* Message Signalled Interrupts registers */ - -#define PCI_MSI_FLAGS 2 /* Various flags */ -#define PCI_MSI_FLAGS_64BIT 0x80 /* 64-bit addresses allowed */ -#define PCI_MSI_FLAGS_QSIZE 0x70 /* Message queue size configured */ -#define PCI_MSI_FLAGS_QMASK 0x0e /* Maximum queue size available */ -#define PCI_MSI_FLAGS_ENABLE 0x01 /* MSI feature enabled */ -#define PCI_MSI_FLAGS_MASKBIT 0x100 /* 64-bit mask bits allowed */ -#define PCI_MSI_RFU 3 /* Rest of capability flags */ -#define PCI_MSI_ADDRESS_LO 4 /* Lower 32 bits */ -#define PCI_MSI_ADDRESS_HI 8 /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */ -#define PCI_MSI_DATA_32 8 /* 16 bits of data for 32-bit devices */ -#define PCI_MSI_MASK_32 12 /* Mask bits register for 32-bit devices */ -#define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */ -#define PCI_MSI_MASK_64 16 /* Mask bits register for 64-bit devices */ - -/* MSI-X registers */ -#define PCI_MSIX_FLAGS 2 -#define PCI_MSIX_FLAGS_QSIZE 0x7FF -#define PCI_MSIX_FLAGS_ENABLE (1 << 15) -#define PCI_MSIX_FLAGS_MASKALL (1 << 14) -#define PCI_MSIX_TABLE 4 -#define PCI_MSIX_PBA 8 -#define PCI_MSIX_FLAGS_BIRMASK (7 << 0) - -/* MSI-X entry's format */ -#define PCI_MSIX_ENTRY_SIZE 16 -#define PCI_MSIX_ENTRY_LOWER_ADDR 0 -#define PCI_MSIX_ENTRY_UPPER_ADDR 4 -#define PCI_MSIX_ENTRY_DATA 8 -#define PCI_MSIX_ENTRY_VECTOR_CTRL 12 -#define PCI_MSIX_ENTRY_CTRL_MASKBIT 1 - -/* CompactPCI Hotswap Register */ - -#define PCI_CHSWP_CSR 2 /* Control and Status Register */ -#define PCI_CHSWP_DHA 0x01 /* Device Hiding Arm */ -#define PCI_CHSWP_EIM 0x02 /* ENUM# Signal Mask */ -#define PCI_CHSWP_PIE 0x04 /* Pending Insert or Extract */ -#define PCI_CHSWP_LOO 0x08 /* LED On / Off */ -#define PCI_CHSWP_PI 0x30 /* Programming Interface */ -#define PCI_CHSWP_EXT 0x40 /* ENUM# status - extraction */ -#define PCI_CHSWP_INS 0x80 /* ENUM# status - insertion */ - -/* PCI Advanced Feature registers */ - -#define PCI_AF_LENGTH 2 -#define PCI_AF_CAP 3 -#define PCI_AF_CAP_TP 0x01 -#define PCI_AF_CAP_FLR 0x02 -#define PCI_AF_CTRL 4 -#define PCI_AF_CTRL_FLR 0x01 -#define PCI_AF_STATUS 5 -#define PCI_AF_STATUS_TP 0x01 - -/* PCI-X registers */ - -#define PCI_X_CMD 2 /* Modes & Features */ -#define PCI_X_CMD_DPERR_E 0x0001 /* Data Parity Error Recovery Enable */ -#define PCI_X_CMD_ERO 0x0002 /* Enable Relaxed Ordering */ -#define PCI_X_CMD_READ_512 0x0000 /* 512 byte maximum read byte count */ -#define PCI_X_CMD_READ_1K 0x0004 /* 1Kbyte maximum read byte count */ -#define PCI_X_CMD_READ_2K 0x0008 /* 2Kbyte maximum read byte count */ -#define PCI_X_CMD_READ_4K 0x000c /* 4Kbyte maximum read byte count */ -#define PCI_X_CMD_MAX_READ 0x000c /* Max Memory Read Byte Count */ - /* Max # of outstanding split transactions */ -#define PCI_X_CMD_SPLIT_1 0x0000 /* Max 1 */ -#define PCI_X_CMD_SPLIT_2 0x0010 /* Max 2 */ -#define PCI_X_CMD_SPLIT_3 0x0020 /* Max 3 */ -#define PCI_X_CMD_SPLIT_4 0x0030 /* Max 4 */ -#define PCI_X_CMD_SPLIT_8 0x0040 /* Max 8 */ -#define PCI_X_CMD_SPLIT_12 0x0050 /* Max 12 */ -#define PCI_X_CMD_SPLIT_16 0x0060 /* Max 16 */ -#define PCI_X_CMD_SPLIT_32 0x0070 /* Max 32 */ -#define PCI_X_CMD_MAX_SPLIT 0x0070 /* Max Outstanding Split Transactions */ -#define PCI_X_CMD_VERSION(x) (((x) >> 12) & 3) /* Version */ -#define PCI_X_STATUS 4 /* PCI-X capabilities */ -#define PCI_X_STATUS_DEVFN 0x000000ff /* A copy of devfn */ -#define PCI_X_STATUS_BUS 0x0000ff00 /* A copy of bus nr */ -#define PCI_X_STATUS_64BIT 0x00010000 /* 64-bit device */ -#define PCI_X_STATUS_133MHZ 0x00020000 /* 133 MHz capable */ -#define PCI_X_STATUS_SPL_DISC 0x00040000 /* Split Completion Discarded */ -#define PCI_X_STATUS_UNX_SPL 0x00080000 /* Unexpected Split Completion */ -#define PCI_X_STATUS_COMPLEX 0x00100000 /* Device Complexity */ -#define PCI_X_STATUS_MAX_READ 0x00600000 /* Designed Max Memory Read Count */ -#define PCI_X_STATUS_MAX_SPLIT 0x03800000 /* Designed Max Outstanding Split Transactions */ -#define PCI_X_STATUS_MAX_CUM 0x1c000000 /* Designed Max Cumulative Read Size */ -#define PCI_X_STATUS_SPL_ERR 0x20000000 /* Rcvd Split Completion Error Msg */ -#define PCI_X_STATUS_266MHZ 0x40000000 /* 266 MHz capable */ -#define PCI_X_STATUS_533MHZ 0x80000000 /* 533 MHz capable */ - -/* PCI Bridge Subsystem ID registers */ - -#define PCI_SSVID_VENDOR_ID 4 /* PCI-Bridge subsystem vendor id register */ -#define PCI_SSVID_DEVICE_ID 6 /* PCI-Bridge subsystem device id register */ - -/* PCI Express capability registers */ - -#define PCI_EXP_FLAGS 2 /* Capabilities register */ -#define PCI_EXP_FLAGS_VERS 0x000f /* Capability version */ -#define PCI_EXP_FLAGS_TYPE 0x00f0 /* Device/Port type */ -#define PCI_EXP_TYPE_ENDPOINT 0x0 /* Express Endpoint */ -#define PCI_EXP_TYPE_LEG_END 0x1 /* Legacy Endpoint */ -#define PCI_EXP_TYPE_ROOT_PORT 0x4 /* Root Port */ -#define PCI_EXP_TYPE_UPSTREAM 0x5 /* Upstream Port */ -#define PCI_EXP_TYPE_DOWNSTREAM 0x6 /* Downstream Port */ -#define PCI_EXP_TYPE_PCI_BRIDGE 0x7 /* PCI/PCI-X Bridge */ -#define PCI_EXP_TYPE_PCIE_BRIDGE 0x8 /* PCI/PCI-X to PCIE Bridge */ -#define PCI_EXP_TYPE_RC_END 0x9 /* Root Complex Integrated Endpoint */ -#define PCI_EXP_TYPE_RC_EC 0xa /* Root Complex Event Collector */ -#define PCI_EXP_FLAGS_SLOT 0x0100 /* Slot implemented */ -#define PCI_EXP_FLAGS_IRQ 0x3e00 /* Interrupt message number */ -#define PCI_EXP_DEVCAP 4 /* Device capabilities */ -#define PCI_EXP_DEVCAP_PAYLOAD 0x07 /* Max_Payload_Size */ -#define PCI_EXP_DEVCAP_PHANTOM 0x18 /* Phantom functions */ -#define PCI_EXP_DEVCAP_EXT_TAG 0x20 /* Extended tags */ -#define PCI_EXP_DEVCAP_L0S 0x1c0 /* L0s Acceptable Latency */ -#define PCI_EXP_DEVCAP_L1 0xe00 /* L1 Acceptable Latency */ -#define PCI_EXP_DEVCAP_ATN_BUT 0x1000 /* Attention Button Present */ -#define PCI_EXP_DEVCAP_ATN_IND 0x2000 /* Attention Indicator Present */ -#define PCI_EXP_DEVCAP_PWR_IND 0x4000 /* Power Indicator Present */ -#define PCI_EXP_DEVCAP_RBER 0x8000 /* Role-Based Error Reporting */ -#define PCI_EXP_DEVCAP_PWR_VAL 0x3fc0000 /* Slot Power Limit Value */ -#define PCI_EXP_DEVCAP_PWR_SCL 0xc000000 /* Slot Power Limit Scale */ -#define PCI_EXP_DEVCAP_FLR 0x10000000 /* Function Level Reset */ -#define PCI_EXP_DEVCTL 8 /* Device Control */ -#define PCI_EXP_DEVCTL_CERE 0x0001 /* Correctable Error Reporting En. */ -#define PCI_EXP_DEVCTL_NFERE 0x0002 /* Non-Fatal Error Reporting Enable */ -#define PCI_EXP_DEVCTL_FERE 0x0004 /* Fatal Error Reporting Enable */ -#define PCI_EXP_DEVCTL_URRE 0x0008 /* Unsupported Request Reporting En. */ -#define PCI_EXP_DEVCTL_RELAX_EN 0x0010 /* Enable relaxed ordering */ -#define PCI_EXP_DEVCTL_PAYLOAD 0x00e0 /* Max_Payload_Size */ -#define PCI_EXP_DEVCTL_EXT_TAG 0x0100 /* Extended Tag Field Enable */ -#define PCI_EXP_DEVCTL_PHANTOM 0x0200 /* Phantom Functions Enable */ -#define PCI_EXP_DEVCTL_AUX_PME 0x0400 /* Auxiliary Power PM Enable */ -#define PCI_EXP_DEVCTL_NOSNOOP_EN 0x0800 /* Enable No Snoop */ -#define PCI_EXP_DEVCTL_READRQ 0x7000 /* Max_Read_Request_Size */ -#define PCI_EXP_DEVCTL_BCR_FLR 0x8000 /* Bridge Configuration Retry / FLR */ -#define PCI_EXP_DEVSTA 10 /* Device Status */ -#define PCI_EXP_DEVSTA_CED 0x01 /* Correctable Error Detected */ -#define PCI_EXP_DEVSTA_NFED 0x02 /* Non-Fatal Error Detected */ -#define PCI_EXP_DEVSTA_FED 0x04 /* Fatal Error Detected */ -#define PCI_EXP_DEVSTA_URD 0x08 /* Unsupported Request Detected */ -#define PCI_EXP_DEVSTA_AUXPD 0x10 /* AUX Power Detected */ -#define PCI_EXP_DEVSTA_TRPND 0x20 /* Transactions Pending */ -#define PCI_EXP_LNKCAP 12 /* Link Capabilities */ -#define PCI_EXP_LNKCAP_SLS 0x0000000f /* Supported Link Speeds */ -#define PCI_EXP_LNKCAP_MLW 0x000003f0 /* Maximum Link Width */ -#define PCI_EXP_LNKCAP_ASPMS 0x00000c00 /* ASPM Support */ -#define PCI_EXP_LNKCAP_L0SEL 0x00007000 /* L0s Exit Latency */ -#define PCI_EXP_LNKCAP_L1EL 0x00038000 /* L1 Exit Latency */ -#define PCI_EXP_LNKCAP_CLKPM 0x00040000 /* L1 Clock Power Management */ -#define PCI_EXP_LNKCAP_SDERC 0x00080000 /* Surprise Down Error Reporting Capable */ -#define PCI_EXP_LNKCAP_DLLLARC 0x00100000 /* Data Link Layer Link Active Reporting Capable */ -#define PCI_EXP_LNKCAP_LBNC 0x00200000 /* Link Bandwidth Notification Capability */ -#define PCI_EXP_LNKCAP_PN 0xff000000 /* Port Number */ -#define PCI_EXP_LNKCTL 16 /* Link Control */ -#define PCI_EXP_LNKCTL_ASPMC 0x0003 /* ASPM Control */ -#define PCI_EXP_LNKCTL_RCB 0x0008 /* Read Completion Boundary */ -#define PCI_EXP_LNKCTL_LD 0x0010 /* Link Disable */ -#define PCI_EXP_LNKCTL_RL 0x0020 /* Retrain Link */ -#define PCI_EXP_LNKCTL_CCC 0x0040 /* Common Clock Configuration */ -#define PCI_EXP_LNKCTL_ES 0x0080 /* Extended Synch */ -#define PCI_EXP_LNKCTL_CLKREQ_EN 0x100 /* Enable clkreq */ -#define PCI_EXP_LNKCTL_HAWD 0x0200 /* Hardware Autonomous Width Disable */ -#define PCI_EXP_LNKCTL_LBMIE 0x0400 /* Link Bandwidth Management Interrupt Enable */ -#define PCI_EXP_LNKCTL_LABIE 0x0800 /* Lnk Autonomous Bandwidth Interrupt Enable */ -#define PCI_EXP_LNKSTA 18 /* Link Status */ -#define PCI_EXP_LNKSTA_CLS 0x000f /* Current Link Speed */ -#define PCI_EXP_LNKSTA_CLS_2_5GB 0x01 /* Current Link Speed 2.5GT/s */ -#define PCI_EXP_LNKSTA_CLS_5_0GB 0x02 /* Current Link Speed 5.0GT/s */ -#define PCI_EXP_LNKSTA_NLW 0x03f0 /* Nogotiated Link Width */ -#define PCI_EXP_LNKSTA_NLW_SHIFT 4 /* start of NLW mask in link status */ -#define PCI_EXP_LNKSTA_LT 0x0800 /* Link Training */ -#define PCI_EXP_LNKSTA_SLC 0x1000 /* Slot Clock Configuration */ -#define PCI_EXP_LNKSTA_DLLLA 0x2000 /* Data Link Layer Link Active */ -#define PCI_EXP_LNKSTA_LBMS 0x4000 /* Link Bandwidth Management Status */ -#define PCI_EXP_LNKSTA_LABS 0x8000 /* Link Autonomous Bandwidth Status */ -#define PCI_EXP_SLTCAP 20 /* Slot Capabilities */ -#define PCI_EXP_SLTCAP_ABP 0x00000001 /* Attention Button Present */ -#define PCI_EXP_SLTCAP_PCP 0x00000002 /* Power Controller Present */ -#define PCI_EXP_SLTCAP_MRLSP 0x00000004 /* MRL Sensor Present */ -#define PCI_EXP_SLTCAP_AIP 0x00000008 /* Attention Indicator Present */ -#define PCI_EXP_SLTCAP_PIP 0x00000010 /* Power Indicator Present */ -#define PCI_EXP_SLTCAP_HPS 0x00000020 /* Hot-Plug Surprise */ -#define PCI_EXP_SLTCAP_HPC 0x00000040 /* Hot-Plug Capable */ -#define PCI_EXP_SLTCAP_SPLV 0x00007f80 /* Slot Power Limit Value */ -#define PCI_EXP_SLTCAP_SPLS 0x00018000 /* Slot Power Limit Scale */ -#define PCI_EXP_SLTCAP_EIP 0x00020000 /* Electromechanical Interlock Present */ -#define PCI_EXP_SLTCAP_NCCS 0x00040000 /* No Command Completed Support */ -#define PCI_EXP_SLTCAP_PSN 0xfff80000 /* Physical Slot Number */ -#define PCI_EXP_SLTCTL 24 /* Slot Control */ -#define PCI_EXP_SLTCTL_ABPE 0x0001 /* Attention Button Pressed Enable */ -#define PCI_EXP_SLTCTL_PFDE 0x0002 /* Power Fault Detected Enable */ -#define PCI_EXP_SLTCTL_MRLSCE 0x0004 /* MRL Sensor Changed Enable */ -#define PCI_EXP_SLTCTL_PDCE 0x0008 /* Presence Detect Changed Enable */ -#define PCI_EXP_SLTCTL_CCIE 0x0010 /* Command Completed Interrupt Enable */ -#define PCI_EXP_SLTCTL_HPIE 0x0020 /* Hot-Plug Interrupt Enable */ -#define PCI_EXP_SLTCTL_AIC 0x00c0 /* Attention Indicator Control */ -#define PCI_EXP_SLTCTL_PIC 0x0300 /* Power Indicator Control */ -#define PCI_EXP_SLTCTL_PCC 0x0400 /* Power Controller Control */ -#define PCI_EXP_SLTCTL_EIC 0x0800 /* Electromechanical Interlock Control */ -#define PCI_EXP_SLTCTL_DLLSCE 0x1000 /* Data Link Layer State Changed Enable */ -#define PCI_EXP_SLTSTA 26 /* Slot Status */ -#define PCI_EXP_SLTSTA_ABP 0x0001 /* Attention Button Pressed */ -#define PCI_EXP_SLTSTA_PFD 0x0002 /* Power Fault Detected */ -#define PCI_EXP_SLTSTA_MRLSC 0x0004 /* MRL Sensor Changed */ -#define PCI_EXP_SLTSTA_PDC 0x0008 /* Presence Detect Changed */ -#define PCI_EXP_SLTSTA_CC 0x0010 /* Command Completed */ -#define PCI_EXP_SLTSTA_MRLSS 0x0020 /* MRL Sensor State */ -#define PCI_EXP_SLTSTA_PDS 0x0040 /* Presence Detect State */ -#define PCI_EXP_SLTSTA_EIS 0x0080 /* Electromechanical Interlock Status */ -#define PCI_EXP_SLTSTA_DLLSC 0x0100 /* Data Link Layer State Changed */ -#define PCI_EXP_RTCTL 28 /* Root Control */ -#define PCI_EXP_RTCTL_SECEE 0x01 /* System Error on Correctable Error */ -#define PCI_EXP_RTCTL_SENFEE 0x02 /* System Error on Non-Fatal Error */ -#define PCI_EXP_RTCTL_SEFEE 0x04 /* System Error on Fatal Error */ -#define PCI_EXP_RTCTL_PMEIE 0x08 /* PME Interrupt Enable */ -#define PCI_EXP_RTCTL_CRSSVE 0x10 /* CRS Software Visibility Enable */ -#define PCI_EXP_RTCAP 30 /* Root Capabilities */ -#define PCI_EXP_RTSTA 32 /* Root Status */ -#define PCI_EXP_RTSTA_PME 0x10000 /* PME status */ -#define PCI_EXP_RTSTA_PENDING 0x20000 /* PME pending */ -#define PCI_EXP_DEVCAP2 36 /* Device Capabilities 2 */ -#define PCI_EXP_DEVCAP2_ARI 0x20 /* Alternative Routing-ID */ -#define PCI_EXP_DEVCAP2_LTR 0x800 /* Latency tolerance reporting */ -#define PCI_EXP_OBFF_MASK 0xc0000 /* OBFF support mechanism */ -#define PCI_EXP_OBFF_MSG 0x40000 /* New message signaling */ -#define PCI_EXP_OBFF_WAKE 0x80000 /* Re-use WAKE# for OBFF */ -#define PCI_EXP_DEVCTL2 40 /* Device Control 2 */ -#define PCI_EXP_DEVCTL2_ARI 0x20 /* Alternative Routing-ID */ -#define PCI_EXP_IDO_REQ_EN 0x100 /* ID-based ordering request enable */ -#define PCI_EXP_IDO_CMP_EN 0x200 /* ID-based ordering completion enable */ -#define PCI_EXP_LTR_EN 0x400 /* Latency tolerance reporting */ -#define PCI_EXP_OBFF_MSGA_EN 0x2000 /* OBFF enable with Message type A */ -#define PCI_EXP_OBFF_MSGB_EN 0x4000 /* OBFF enable with Message type B */ -#define PCI_EXP_OBFF_WAKE_EN 0x6000 /* OBFF using WAKE# signaling */ -#define PCI_EXP_LNKCTL2 48 /* Link Control 2 */ -#define PCI_EXP_SLTCTL2 56 /* Slot Control 2 */ - -/* Extended Capabilities (PCI-X 2.0 and Express) */ -#define PCI_EXT_CAP_ID(header) (header & 0x0000ffff) -#define PCI_EXT_CAP_VER(header) ((header >> 16) & 0xf) -#define PCI_EXT_CAP_NEXT(header) ((header >> 20) & 0xffc) - -#define PCI_EXT_CAP_ID_ERR 1 -#define PCI_EXT_CAP_ID_VC 2 -#define PCI_EXT_CAP_ID_DSN 3 -#define PCI_EXT_CAP_ID_PWR 4 -#define PCI_EXT_CAP_ID_VNDR 11 -#define PCI_EXT_CAP_ID_ACS 13 -#define PCI_EXT_CAP_ID_ARI 14 -#define PCI_EXT_CAP_ID_ATS 15 -#define PCI_EXT_CAP_ID_SRIOV 16 -#define PCI_EXT_CAP_ID_LTR 24 - -/* Advanced Error Reporting */ -#define PCI_ERR_UNCOR_STATUS 4 /* Uncorrectable Error Status */ -#define PCI_ERR_UNC_TRAIN 0x00000001 /* Training */ -#define PCI_ERR_UNC_DLP 0x00000010 /* Data Link Protocol */ -#define PCI_ERR_UNC_POISON_TLP 0x00001000 /* Poisoned TLP */ -#define PCI_ERR_UNC_FCP 0x00002000 /* Flow Control Protocol */ -#define PCI_ERR_UNC_COMP_TIME 0x00004000 /* Completion Timeout */ -#define PCI_ERR_UNC_COMP_ABORT 0x00008000 /* Completer Abort */ -#define PCI_ERR_UNC_UNX_COMP 0x00010000 /* Unexpected Completion */ -#define PCI_ERR_UNC_RX_OVER 0x00020000 /* Receiver Overflow */ -#define PCI_ERR_UNC_MALF_TLP 0x00040000 /* Malformed TLP */ -#define PCI_ERR_UNC_ECRC 0x00080000 /* ECRC Error Status */ -#define PCI_ERR_UNC_UNSUP 0x00100000 /* Unsupported Request */ -#define PCI_ERR_UNCOR_MASK 8 /* Uncorrectable Error Mask */ - /* Same bits as above */ -#define PCI_ERR_UNCOR_SEVER 12 /* Uncorrectable Error Severity */ - /* Same bits as above */ -#define PCI_ERR_COR_STATUS 16 /* Correctable Error Status */ -#define PCI_ERR_COR_RCVR 0x00000001 /* Receiver Error Status */ -#define PCI_ERR_COR_BAD_TLP 0x00000040 /* Bad TLP Status */ -#define PCI_ERR_COR_BAD_DLLP 0x00000080 /* Bad DLLP Status */ -#define PCI_ERR_COR_REP_ROLL 0x00000100 /* REPLAY_NUM Rollover */ -#define PCI_ERR_COR_REP_TIMER 0x00001000 /* Replay Timer Timeout */ -#define PCI_ERR_COR_MASK 20 /* Correctable Error Mask */ - /* Same bits as above */ -#define PCI_ERR_CAP 24 /* Advanced Error Capabilities */ -#define PCI_ERR_CAP_FEP(x) ((x) & 31) /* First Error Pointer */ -#define PCI_ERR_CAP_ECRC_GENC 0x00000020 /* ECRC Generation Capable */ -#define PCI_ERR_CAP_ECRC_GENE 0x00000040 /* ECRC Generation Enable */ -#define PCI_ERR_CAP_ECRC_CHKC 0x00000080 /* ECRC Check Capable */ -#define PCI_ERR_CAP_ECRC_CHKE 0x00000100 /* ECRC Check Enable */ -#define PCI_ERR_HEADER_LOG 28 /* Header Log Register (16 bytes) */ -#define PCI_ERR_ROOT_COMMAND 44 /* Root Error Command */ -/* Correctable Err Reporting Enable */ -#define PCI_ERR_ROOT_CMD_COR_EN 0x00000001 -/* Non-fatal Err Reporting Enable */ -#define PCI_ERR_ROOT_CMD_NONFATAL_EN 0x00000002 -/* Fatal Err Reporting Enable */ -#define PCI_ERR_ROOT_CMD_FATAL_EN 0x00000004 -#define PCI_ERR_ROOT_STATUS 48 -#define PCI_ERR_ROOT_COR_RCV 0x00000001 /* ERR_COR Received */ -/* Multi ERR_COR Received */ -#define PCI_ERR_ROOT_MULTI_COR_RCV 0x00000002 -/* ERR_FATAL/NONFATAL Recevied */ -#define PCI_ERR_ROOT_UNCOR_RCV 0x00000004 -/* Multi ERR_FATAL/NONFATAL Recevied */ -#define PCI_ERR_ROOT_MULTI_UNCOR_RCV 0x00000008 -#define PCI_ERR_ROOT_FIRST_FATAL 0x00000010 /* First Fatal */ -#define PCI_ERR_ROOT_NONFATAL_RCV 0x00000020 /* Non-Fatal Received */ -#define PCI_ERR_ROOT_FATAL_RCV 0x00000040 /* Fatal Received */ -#define PCI_ERR_ROOT_ERR_SRC 52 /* Error Source Identification */ - -/* Virtual Channel */ -#define PCI_VC_PORT_REG1 4 -#define PCI_VC_PORT_REG2 8 -#define PCI_VC_PORT_CTRL 12 -#define PCI_VC_PORT_STATUS 14 -#define PCI_VC_RES_CAP 16 -#define PCI_VC_RES_CTRL 20 -#define PCI_VC_RES_STATUS 26 - -/* Power Budgeting */ -#define PCI_PWR_DSR 4 /* Data Select Register */ -#define PCI_PWR_DATA 8 /* Data Register */ -#define PCI_PWR_DATA_BASE(x) ((x) & 0xff) /* Base Power */ -#define PCI_PWR_DATA_SCALE(x) (((x) >> 8) & 3) /* Data Scale */ -#define PCI_PWR_DATA_PM_SUB(x) (((x) >> 10) & 7) /* PM Sub State */ -#define PCI_PWR_DATA_PM_STATE(x) (((x) >> 13) & 3) /* PM State */ -#define PCI_PWR_DATA_TYPE(x) (((x) >> 15) & 7) /* Type */ -#define PCI_PWR_DATA_RAIL(x) (((x) >> 18) & 7) /* Power Rail */ -#define PCI_PWR_CAP 12 /* Capability */ -#define PCI_PWR_CAP_BUDGET(x) ((x) & 1) /* Included in system budget */ - -/* - * Hypertransport sub capability types - * - * Unfortunately there are both 3 bit and 5 bit capability types defined - * in the HT spec, catering for that is a little messy. You probably don't - * want to use these directly, just use pci_find_ht_capability() and it - * will do the right thing for you. - */ -#define HT_3BIT_CAP_MASK 0xE0 -#define HT_CAPTYPE_SLAVE 0x00 /* Slave/Primary link configuration */ -#define HT_CAPTYPE_HOST 0x20 /* Host/Secondary link configuration */ - -#define HT_5BIT_CAP_MASK 0xF8 -#define HT_CAPTYPE_IRQ 0x80 /* IRQ Configuration */ -#define HT_CAPTYPE_REMAPPING_40 0xA0 /* 40 bit address remapping */ -#define HT_CAPTYPE_REMAPPING_64 0xA2 /* 64 bit address remapping */ -#define HT_CAPTYPE_UNITID_CLUMP 0x90 /* Unit ID clumping */ -#define HT_CAPTYPE_EXTCONF 0x98 /* Extended Configuration Space Access */ -#define HT_CAPTYPE_MSI_MAPPING 0xA8 /* MSI Mapping Capability */ -#define HT_MSI_FLAGS 0x02 /* Offset to flags */ -#define HT_MSI_FLAGS_ENABLE 0x1 /* Mapping enable */ -#define HT_MSI_FLAGS_FIXED 0x2 /* Fixed mapping only */ -#define HT_MSI_FIXED_ADDR 0x00000000FEE00000ULL /* Fixed addr */ -#define HT_MSI_ADDR_LO 0x04 /* Offset to low addr bits */ -#define HT_MSI_ADDR_LO_MASK 0xFFF00000 /* Low address bit mask */ -#define HT_MSI_ADDR_HI 0x08 /* Offset to high addr bits */ -#define HT_CAPTYPE_DIRECT_ROUTE 0xB0 /* Direct routing configuration */ -#define HT_CAPTYPE_VCSET 0xB8 /* Virtual Channel configuration */ -#define HT_CAPTYPE_ERROR_RETRY 0xC0 /* Retry on error configuration */ -#define HT_CAPTYPE_GEN3 0xD0 /* Generation 3 hypertransport configuration */ -#define HT_CAPTYPE_PM 0xE0 /* Hypertransport powermanagement configuration */ - -/* Alternative Routing-ID Interpretation */ -#define PCI_ARI_CAP 0x04 /* ARI Capability Register */ -#define PCI_ARI_CAP_MFVC 0x0001 /* MFVC Function Groups Capability */ -#define PCI_ARI_CAP_ACS 0x0002 /* ACS Function Groups Capability */ -#define PCI_ARI_CAP_NFN(x) (((x) >> 8) & 0xff) /* Next Function Number */ -#define PCI_ARI_CTRL 0x06 /* ARI Control Register */ -#define PCI_ARI_CTRL_MFVC 0x0001 /* MFVC Function Groups Enable */ -#define PCI_ARI_CTRL_ACS 0x0002 /* ACS Function Groups Enable */ -#define PCI_ARI_CTRL_FG(x) (((x) >> 4) & 7) /* Function Group */ - -/* Address Translation Service */ -#define PCI_ATS_CAP 0x04 /* ATS Capability Register */ -#define PCI_ATS_CAP_QDEP(x) ((x) & 0x1f) /* Invalidate Queue Depth */ -#define PCI_ATS_MAX_QDEP 32 /* Max Invalidate Queue Depth */ -#define PCI_ATS_CTRL 0x06 /* ATS Control Register */ -#define PCI_ATS_CTRL_ENABLE 0x8000 /* ATS Enable */ -#define PCI_ATS_CTRL_STU(x) ((x) & 0x1f) /* Smallest Translation Unit */ -#define PCI_ATS_MIN_STU 12 /* shift of minimum STU block */ - -/* Single Root I/O Virtualization */ -#define PCI_SRIOV_CAP 0x04 /* SR-IOV Capabilities */ -#define PCI_SRIOV_CAP_VFM 0x01 /* VF Migration Capable */ -#define PCI_SRIOV_CAP_INTR(x) ((x) >> 21) /* Interrupt Message Number */ -#define PCI_SRIOV_CTRL 0x08 /* SR-IOV Control */ -#define PCI_SRIOV_CTRL_VFE 0x01 /* VF Enable */ -#define PCI_SRIOV_CTRL_VFM 0x02 /* VF Migration Enable */ -#define PCI_SRIOV_CTRL_INTR 0x04 /* VF Migration Interrupt Enable */ -#define PCI_SRIOV_CTRL_MSE 0x08 /* VF Memory Space Enable */ -#define PCI_SRIOV_CTRL_ARI 0x10 /* ARI Capable Hierarchy */ -#define PCI_SRIOV_STATUS 0x0a /* SR-IOV Status */ -#define PCI_SRIOV_STATUS_VFM 0x01 /* VF Migration Status */ -#define PCI_SRIOV_INITIAL_VF 0x0c /* Initial VFs */ -#define PCI_SRIOV_TOTAL_VF 0x0e /* Total VFs */ -#define PCI_SRIOV_NUM_VF 0x10 /* Number of VFs */ -#define PCI_SRIOV_FUNC_LINK 0x12 /* Function Dependency Link */ -#define PCI_SRIOV_VF_OFFSET 0x14 /* First VF Offset */ -#define PCI_SRIOV_VF_STRIDE 0x16 /* Following VF Stride */ -#define PCI_SRIOV_VF_DID 0x1a /* VF Device ID */ -#define PCI_SRIOV_SUP_PGSIZE 0x1c /* Supported Page Sizes */ -#define PCI_SRIOV_SYS_PGSIZE 0x20 /* System Page Size */ -#define PCI_SRIOV_BAR 0x24 /* VF BAR0 */ -#define PCI_SRIOV_NUM_BARS 6 /* Number of VF BARs */ -#define PCI_SRIOV_VFM 0x3c /* VF Migration State Array Offset*/ -#define PCI_SRIOV_VFM_BIR(x) ((x) & 7) /* State BIR */ -#define PCI_SRIOV_VFM_OFFSET(x) ((x) & ~7) /* State Offset */ -#define PCI_SRIOV_VFM_UA 0x0 /* Inactive.Unavailable */ -#define PCI_SRIOV_VFM_MI 0x1 /* Dormant.MigrateIn */ -#define PCI_SRIOV_VFM_MO 0x2 /* Active.MigrateOut */ -#define PCI_SRIOV_VFM_AV 0x3 /* Active.Available */ - -#define PCI_LTR_MAX_SNOOP_LAT 0x4 -#define PCI_LTR_MAX_NOSNOOP_LAT 0x6 -#define PCI_LTR_VALUE_MASK 0x000003ff -#define PCI_LTR_SCALE_MASK 0x00001c00 -#define PCI_LTR_SCALE_SHIFT 10 - -/* Access Control Service */ -#define PCI_ACS_CAP 0x04 /* ACS Capability Register */ -#define PCI_ACS_SV 0x01 /* Source Validation */ -#define PCI_ACS_TB 0x02 /* Translation Blocking */ -#define PCI_ACS_RR 0x04 /* P2P Request Redirect */ -#define PCI_ACS_CR 0x08 /* P2P Completion Redirect */ -#define PCI_ACS_UF 0x10 /* Upstream Forwarding */ -#define PCI_ACS_EC 0x20 /* P2P Egress Control */ -#define PCI_ACS_DT 0x40 /* Direct Translated P2P */ -#define PCI_ACS_CTRL 0x06 /* ACS Control Register */ -#define PCI_ACS_EGRESS_CTL_V 0x08 /* ACS Egress Control Vector */ - -#endif /* LINUX_PCI_REGS_H */ +#include "standard-headers/linux/pci_regs.h" diff --git a/include/hw/pci/pcie_aer.h b/include/hw/pci/pcie_aer.h index bcac80a7b0..2fb83882be 100644 --- a/include/hw/pci/pcie_aer.h +++ b/include/hw/pci/pcie_aer.h @@ -51,7 +51,7 @@ struct PCIEAERLog { PCIEAERErr *log; }; -/* aer error message: error signaling message has only error sevirity and +/* aer error message: error signaling message has only error severity and source id. See 2.2.8.3 error signaling messages */ struct PCIEAERMsg { /* diff --git a/include/hw/pci/pcie_host.h b/include/hw/pci/pcie_host.h index ff44ef6fca..4d23c80759 100644 --- a/include/hw/pci/pcie_host.h +++ b/include/hw/pci/pcie_host.h @@ -50,6 +50,7 @@ struct PCIExpressHost { }; void pcie_host_mmcfg_unmap(PCIExpressHost *e); +void pcie_host_mmcfg_init(PCIExpressHost *e, uint32_t size); void pcie_host_mmcfg_map(PCIExpressHost *e, hwaddr addr, uint32_t size); void pcie_host_mmcfg_update(PCIExpressHost *e, int enable, diff --git a/include/hw/pci/pcie_regs.h b/include/hw/pci/pcie_regs.h index 652d9fc58c..6a28b33e69 100644 --- a/include/hw/pci/pcie_regs.h +++ b/include/hw/pci/pcie_regs.h @@ -27,34 +27,34 @@ /* PCI_EXP_FLAGS */ #define PCI_EXP_FLAGS_VER2 2 /* for now, supports only ver. 2 */ -#define PCI_EXP_FLAGS_IRQ_SHIFT (ffs(PCI_EXP_FLAGS_IRQ) - 1) -#define PCI_EXP_FLAGS_TYPE_SHIFT (ffs(PCI_EXP_FLAGS_TYPE) - 1) +#define PCI_EXP_FLAGS_IRQ_SHIFT ctz32(PCI_EXP_FLAGS_IRQ) +#define PCI_EXP_FLAGS_TYPE_SHIFT ctz32(PCI_EXP_FLAGS_TYPE) /* PCI_EXP_LINK{CAP, STA} */ /* link speed */ #define PCI_EXP_LNK_LS_25 1 -#define PCI_EXP_LNK_MLW_SHIFT (ffs(PCI_EXP_LNKCAP_MLW) - 1) +#define PCI_EXP_LNK_MLW_SHIFT ctz32(PCI_EXP_LNKCAP_MLW) #define PCI_EXP_LNK_MLW_1 (1 << PCI_EXP_LNK_MLW_SHIFT) /* PCI_EXP_LINKCAP */ -#define PCI_EXP_LNKCAP_ASPMS_SHIFT (ffs(PCI_EXP_LNKCAP_ASPMS) - 1) +#define PCI_EXP_LNKCAP_ASPMS_SHIFT ctz32(PCI_EXP_LNKCAP_ASPMS) #define PCI_EXP_LNKCAP_ASPMS_0S (1 << PCI_EXP_LNKCAP_ASPMS_SHIFT) -#define PCI_EXP_LNKCAP_PN_SHIFT (ffs(PCI_EXP_LNKCAP_PN) - 1) +#define PCI_EXP_LNKCAP_PN_SHIFT ctz32(PCI_EXP_LNKCAP_PN) -#define PCI_EXP_SLTCAP_PSN_SHIFT (ffs(PCI_EXP_SLTCAP_PSN) - 1) +#define PCI_EXP_SLTCAP_PSN_SHIFT ctz32(PCI_EXP_SLTCAP_PSN) #define PCI_EXP_SLTCTL_IND_RESERVED 0x0 #define PCI_EXP_SLTCTL_IND_ON 0x1 #define PCI_EXP_SLTCTL_IND_BLINK 0x2 #define PCI_EXP_SLTCTL_IND_OFF 0x3 -#define PCI_EXP_SLTCTL_AIC_SHIFT (ffs(PCI_EXP_SLTCTL_AIC) - 1) +#define PCI_EXP_SLTCTL_AIC_SHIFT ctz32(PCI_EXP_SLTCTL_AIC) #define PCI_EXP_SLTCTL_AIC_OFF \ (PCI_EXP_SLTCTL_IND_OFF << PCI_EXP_SLTCTL_AIC_SHIFT) -#define PCI_EXP_SLTCTL_PIC_SHIFT (ffs(PCI_EXP_SLTCTL_PIC) - 1) +#define PCI_EXP_SLTCTL_PIC_SHIFT ctz32(PCI_EXP_SLTCTL_PIC) #define PCI_EXP_SLTCTL_PIC_OFF \ (PCI_EXP_SLTCTL_IND_OFF << PCI_EXP_SLTCTL_PIC_SHIFT) #define PCI_EXP_SLTCTL_PIC_ON \ @@ -72,7 +72,7 @@ #define PCI_EXP_DEVCAP2_EFF 0x100000 #define PCI_EXP_DEVCAP2_EETLPP 0x200000 -#define PCI_EXP_DEVCTL2_EETLPPB 0x80 +#define PCI_EXP_DEVCTL2_EETLPPB 0x8000 /* ARI */ #define PCI_ARI_VER 1 @@ -109,7 +109,7 @@ #define PCI_ERR_ROOT_IRQ_MAX 32 #define PCI_ERR_ROOT_IRQ 0xf8000000 -#define PCI_ERR_ROOT_IRQ_SHIFT (ffs(PCI_ERR_ROOT_IRQ) - 1) +#define PCI_ERR_ROOT_IRQ_SHIFT ctz32(PCI_ERR_ROOT_IRQ) #define PCI_ERR_ROOT_STATUS_REPORT_MASK (PCI_ERR_ROOT_COR_RCV | \ PCI_ERR_ROOT_MULTI_COR_RCV | \ PCI_ERR_ROOT_UNCOR_RCV | \ diff --git a/include/hw/pci/shpc.h b/include/hw/pci/shpc.h index 025bc5b268..2c871b947b 100644 --- a/include/hw/pci/shpc.h +++ b/include/hw/pci/shpc.h @@ -6,6 +6,7 @@ #include "migration/vmstate.h" #include "qapi/error.h" #include "hw/hotplug.h" +#include "hw/pci/pci.h" struct SHPCDevice { /* Capability offset in device's config space */ @@ -41,6 +42,7 @@ void shpc_reset(PCIDevice *d); int shpc_bar_size(PCIDevice *dev); int shpc_init(PCIDevice *dev, PCIBus *sec_bus, MemoryRegion *bar, unsigned off); void shpc_cleanup(PCIDevice *dev, MemoryRegion *bar); +void shpc_free(PCIDevice *dev); void shpc_cap_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int len); @@ -50,7 +52,13 @@ void shpc_device_hot_unplug_request_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp); extern VMStateInfo shpc_vmstate_info; -#define SHPC_VMSTATE(_field, _type) \ - VMSTATE_BUFFER_UNSAFE_INFO(_field, _type, 0, shpc_vmstate_info, 0) +#define SHPC_VMSTATE(_field, _type, _test) \ + VMSTATE_BUFFER_UNSAFE_INFO_TEST(_field, _type, _test, 0, \ + shpc_vmstate_info, 0) + +static inline bool shpc_present(const PCIDevice *dev) +{ + return dev->cap_present & QEMU_PCI_CAP_SHPC; +} #endif diff --git a/include/hw/ppc/mac_dbdma.h b/include/hw/ppc/mac_dbdma.h index d7db06c031..c6870212e9 100644 --- a/include/hw/ppc/mac_dbdma.h +++ b/include/hw/ppc/mac_dbdma.h @@ -40,13 +40,9 @@ struct DBDMA_io { /* DMA is in progress, don't start another one */ bool processing; /* unaligned last sector of a request */ - uint8_t remainder[0x200]; - int remainder_len; + uint8_t head_remainder[0x200]; + uint8_t tail_remainder[0x200]; QEMUIOVector iov; - bool finish_remain_read; - hwaddr finish_addr; - hwaddr finish_len; - int requests; }; /* diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 749daf4dd7..91a61abbc4 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -2,21 +2,53 @@ #define __HW_SPAPR_H__ #include "sysemu/dma.h" +#include "hw/boards.h" #include "hw/ppc/xics.h" +#include "hw/ppc/spapr_drc.h" struct VIOsPAPRBus; struct sPAPRPHBState; struct sPAPRNVRAM; +typedef struct sPAPRConfigureConnectorState sPAPRConfigureConnectorState; +typedef struct sPAPREventLogEntry sPAPREventLogEntry; #define HPTE64_V_HPTE_DIRTY 0x0000000000000040ULL +#define SPAPR_ENTRY_POINT 0x100 + +typedef struct sPAPRMachineClass sPAPRMachineClass; +typedef struct sPAPRMachineState sPAPRMachineState; + +#define TYPE_SPAPR_MACHINE "spapr-machine" +#define SPAPR_MACHINE(obj) \ + OBJECT_CHECK(sPAPRMachineState, (obj), TYPE_SPAPR_MACHINE) +#define SPAPR_MACHINE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(sPAPRMachineClass, obj, TYPE_SPAPR_MACHINE) +#define SPAPR_MACHINE_CLASS(klass) \ + OBJECT_CLASS_CHECK(sPAPRMachineClass, klass, TYPE_SPAPR_MACHINE) + +/** + * sPAPRMachineClass: + */ +struct sPAPRMachineClass { + /*< private >*/ + MachineClass parent_class; + + /*< public >*/ +}; + +/** + * sPAPRMachineState: + */ +struct sPAPRMachineState { + /*< private >*/ + MachineState parent_obj; -typedef struct sPAPREnvironment { struct VIOsPAPRBus *vio_bus; QLIST_HEAD(, sPAPRPHBState) phbs; struct sPAPRNVRAM *nvram; XICSState *icp; + DeviceState *rtc; - hwaddr ram_limit; void *htab; uint32_t htab_shift; hwaddr rma_size; @@ -25,19 +57,26 @@ typedef struct sPAPREnvironment { ssize_t rtas_size; void *rtas_blob; void *fdt_skel; - target_ulong entry_point; - uint64_t rtc_offset; + uint64_t rtc_offset; /* Now used only during incoming migration */ struct PPCTimebase tb; bool has_graphics; - uint32_t epow_irq; + uint32_t check_exception_irq; Notifier epow_notifier; + QTAILQ_HEAD(, sPAPREventLogEntry) pending_events; /* Migration state */ int htab_save_index; bool htab_first_pass; int htab_fd; -} sPAPREnvironment; + bool htab_fd_stale; + + /* RTAS state */ + QTAILQ_HEAD(, sPAPRConfigureConnectorState) ccs_list; + + /*< public >*/ + char *kvm_type; +}; #define H_SUCCESS 0 #define H_BUSY 1 /* Hardware busy -- retry later */ @@ -310,8 +349,6 @@ typedef struct sPAPREnvironment { #define KVMPPC_H_CAS (KVMPPC_HCALL_BASE + 0x2) #define KVMPPC_HCALL_MAX KVMPPC_H_CAS -extern sPAPREnvironment *spapr; - typedef struct sPAPRDeviceTreeUpdateHeader { uint32_t version_id; } sPAPRDeviceTreeUpdateHeader; @@ -326,7 +363,7 @@ typedef struct sPAPRDeviceTreeUpdateHeader { do { } while (0) #endif -typedef target_ulong (*spapr_hcall_fn)(PowerPCCPU *cpu, sPAPREnvironment *spapr, +typedef target_ulong (*spapr_hcall_fn)(PowerPCCPU *cpu, sPAPRMachineState *sm, target_ulong opcode, target_ulong *args); @@ -337,6 +374,39 @@ target_ulong spapr_hypercall(PowerPCCPU *cpu, target_ulong opcode, int spapr_allocate_irq(int hint, bool lsi); int spapr_allocate_irq_block(int num, bool lsi, bool msi); +/* ibm,set-eeh-option */ +#define RTAS_EEH_DISABLE 0 +#define RTAS_EEH_ENABLE 1 +#define RTAS_EEH_THAW_IO 2 +#define RTAS_EEH_THAW_DMA 3 + +/* ibm,get-config-addr-info2 */ +#define RTAS_GET_PE_ADDR 0 +#define RTAS_GET_PE_MODE 1 +#define RTAS_PE_MODE_NONE 0 +#define RTAS_PE_MODE_NOT_SHARED 1 +#define RTAS_PE_MODE_SHARED 2 + +/* ibm,read-slot-reset-state2 */ +#define RTAS_EEH_PE_STATE_NORMAL 0 +#define RTAS_EEH_PE_STATE_RESET 1 +#define RTAS_EEH_PE_STATE_STOPPED_IO_DMA 2 +#define RTAS_EEH_PE_STATE_STOPPED_DMA 4 +#define RTAS_EEH_PE_STATE_UNAVAIL 5 +#define RTAS_EEH_NOT_SUPPORT 0 +#define RTAS_EEH_SUPPORT 1 +#define RTAS_EEH_PE_UNAVAIL_INFO 1000 +#define RTAS_EEH_PE_RECOVER_INFO 0 + +/* ibm,set-slot-reset */ +#define RTAS_SLOT_RESET_DEACTIVATE 0 +#define RTAS_SLOT_RESET_HOT 1 +#define RTAS_SLOT_RESET_FUNDAMENTAL 3 + +/* ibm,slot-error-detail */ +#define RTAS_SLOT_TEMP_ERR_LOG 1 +#define RTAS_SLOT_PERM_ERR_LOG 2 + /* RTAS return codes */ #define RTAS_OUT_SUCCESS 0 #define RTAS_OUT_NO_ERRORS_FOUND 1 @@ -381,14 +451,31 @@ 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_SET_EEH_OPTION (RTAS_TOKEN_BASE + 0x20) +#define RTAS_IBM_GET_CONFIG_ADDR_INFO2 (RTAS_TOKEN_BASE + 0x21) +#define RTAS_IBM_READ_SLOT_RESET_STATE2 (RTAS_TOKEN_BASE + 0x22) +#define RTAS_IBM_SET_SLOT_RESET (RTAS_TOKEN_BASE + 0x23) +#define RTAS_IBM_CONFIGURE_PE (RTAS_TOKEN_BASE + 0x24) +#define RTAS_IBM_SLOT_ERROR_DETAIL (RTAS_TOKEN_BASE + 0x25) -#define RTAS_TOKEN_MAX (RTAS_TOKEN_BASE + 0x20) +#define RTAS_TOKEN_MAX (RTAS_TOKEN_BASE + 0x26) /* RTAS ibm,get-system-parameter token values */ #define RTAS_SYSPARM_SPLPAR_CHARACTERISTICS 20 #define RTAS_SYSPARM_DIAGNOSTICS_RUN_MODE 42 #define RTAS_SYSPARM_UUID 48 +/* RTAS indicator/sensor types + * + * as defined by PAPR+ 2.7 7.3.5.4, Table 41 + * + * NOTE: currently only DR-related sensors are implemented here + */ +#define RTAS_SENSOR_TYPE_ISOLATION_STATE 9001 +#define RTAS_SENSOR_TYPE_DR 9002 +#define RTAS_SENSOR_TYPE_ALLOCATION_STATE 9003 +#define RTAS_SENSOR_TYPE_ENTITY_SENSE RTAS_SENSOR_TYPE_ALLOCATION_STATE + /* Possible values for the platform-processor-diagnostics-run-mode parameter * of the RTAS ibm,get-system-parameter call. */ @@ -412,6 +499,13 @@ static inline void rtas_st(target_ulong phys, int n, uint32_t val) stl_be_phys(&address_space_memory, ppc64_phys_to_real(phys + 4*n), val); } +static inline void rtas_st_buffer_direct(target_ulong phys, + target_ulong phys_len, + uint8_t *buffer, uint16_t buffer_len) +{ + cpu_physical_memory_write(ppc64_phys_to_real(phys), buffer, + MIN(buffer_len, phys_len)); +} static inline void rtas_st_buffer(target_ulong phys, target_ulong phys_len, uint8_t *buffer, uint16_t buffer_len) @@ -421,16 +515,15 @@ static inline void rtas_st_buffer(target_ulong phys, target_ulong phys_len, } stw_be_phys(&address_space_memory, ppc64_phys_to_real(phys), buffer_len); - cpu_physical_memory_write(ppc64_phys_to_real(phys + 2), - buffer, MIN(buffer_len, phys_len - 2)); + rtas_st_buffer_direct(phys + 2, phys_len - 2, buffer, buffer_len); } -typedef void (*spapr_rtas_fn)(PowerPCCPU *cpu, sPAPREnvironment *spapr, +typedef void (*spapr_rtas_fn)(PowerPCCPU *cpu, sPAPRMachineState *sm, uint32_t token, uint32_t nargs, target_ulong args, uint32_t nret, target_ulong rets); void spapr_rtas_register(int token, const char *name, spapr_rtas_fn fn); -target_ulong spapr_rtas_call(PowerPCCPU *cpu, sPAPREnvironment *spapr, +target_ulong spapr_rtas_call(PowerPCCPU *cpu, sPAPRMachineState *sm, uint32_t token, uint32_t nargs, target_ulong args, uint32_t nret, target_ulong rets); int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr, @@ -441,10 +534,16 @@ int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr, #define SPAPR_TCE_PAGE_MASK (SPAPR_TCE_PAGE_SIZE - 1) #define SPAPR_VIO_BASE_LIOBN 0x00000000 -#define SPAPR_PCI_BASE_LIOBN 0x80000000 +#define SPAPR_VIO_LIOBN(reg) (0x00000000 | (reg)) +#define SPAPR_PCI_LIOBN(phb_index, window_num) \ + (0x80000000 | ((phb_index) << 8) | (window_num)) +#define SPAPR_IS_PCI_LIOBN(liobn) (!!((liobn) & 0x80000000)) +#define SPAPR_PCI_DMA_WINDOW_NUM(liobn) ((liobn) & 0xff) #define RTAS_ERROR_LOG_MAX 2048 +#define RTAS_EVENT_SCAN_RATE 1 + typedef struct sPAPRTCETable sPAPRTCETable; #define TYPE_SPAPR_TCE_TABLE "spapr-tce-table" @@ -462,22 +561,52 @@ struct sPAPRTCETable { bool vfio_accel; int fd; MemoryRegion iommu; + struct VIOsPAPRDevice *vdev; /* for @bypass migration compatibility only */ QLIST_ENTRY(sPAPRTCETable) list; }; -void spapr_events_init(sPAPREnvironment *spapr); +sPAPRTCETable *spapr_tce_find_by_liobn(target_ulong liobn); + +struct sPAPREventLogEntry { + int log_type; + bool exception; + void *data; + QTAILQ_ENTRY(sPAPREventLogEntry) next; +}; + +void spapr_events_init(sPAPRMachineState *sm); void spapr_events_fdt_skel(void *fdt, uint32_t epow_irq); -int spapr_h_cas_compose_response(target_ulong addr, target_ulong size); +int spapr_h_cas_compose_response(sPAPRMachineState *sm, + target_ulong addr, target_ulong size); sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn, uint64_t bus_offset, uint32_t page_shift, uint32_t nb_table, bool vfio_accel); MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet); -void spapr_tce_set_bypass(sPAPRTCETable *tcet, bool bypass); int spapr_dma_dt(void *fdt, int node_off, const char *propname, uint32_t liobn, uint64_t window, uint32_t size); int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname, sPAPRTCETable *tcet); +void spapr_pci_switch_vga(bool big_endian); +void spapr_hotplug_req_add_event(sPAPRDRConnector *drc); +void spapr_hotplug_req_remove_event(sPAPRDRConnector *drc); + +/* rtas-configure-connector state */ +struct sPAPRConfigureConnectorState { + uint32_t drc_index; + int fdt_offset; + int fdt_depth; + QTAILQ_ENTRY(sPAPRConfigureConnectorState) next; +}; + +void spapr_ccs_reset_hook(void *opaque); + +#define TYPE_SPAPR_RTC "spapr-rtc" + +void spapr_rtc_read(DeviceState *dev, struct tm *tm, uint32_t *ns); +int spapr_rtc_import_offset(DeviceState *dev, int64_t legacy_offset); + +#define SPAPR_MEMORY_BLOCK_SIZE (1 << 28) /* 256MB */ #endif /* !defined (__HW_SPAPR_H__) */ diff --git a/include/hw/ppc/spapr_drc.h b/include/hw/ppc/spapr_drc.h new file mode 100644 index 0000000000..60cda35ed2 --- /dev/null +++ b/include/hw/ppc/spapr_drc.h @@ -0,0 +1,201 @@ +/* + * QEMU SPAPR Dynamic Reconfiguration Connector Implementation + * + * Copyright IBM Corp. 2014 + * + * Authors: + * Michael Roth <mdroth@linux.vnet.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. + */ +#if !defined(__HW_SPAPR_DRC_H__) +#define __HW_SPAPR_DRC_H__ + +#include "qom/object.h" +#include "hw/qdev.h" +#include "libfdt.h" + +#define TYPE_SPAPR_DR_CONNECTOR "spapr-dr-connector" +#define SPAPR_DR_CONNECTOR_GET_CLASS(obj) \ + OBJECT_GET_CLASS(sPAPRDRConnectorClass, obj, TYPE_SPAPR_DR_CONNECTOR) +#define SPAPR_DR_CONNECTOR_CLASS(klass) \ + OBJECT_CLASS_CHECK(sPAPRDRConnectorClass, klass, \ + TYPE_SPAPR_DR_CONNECTOR) +#define SPAPR_DR_CONNECTOR(obj) OBJECT_CHECK(sPAPRDRConnector, (obj), \ + TYPE_SPAPR_DR_CONNECTOR) + +/* + * Various hotplug types managed by sPAPRDRConnector + * + * these are somewhat arbitrary, but to make things easier + * when generating DRC indexes later we've aligned the bit + * positions with the values used to assign DRC indexes on + * pSeries. we use those values as bit shifts to allow for + * the OR'ing of these values in various QEMU routines, but + * for values exposed to the guest (via DRC indexes for + * instance) we will use the shift amounts. + */ +typedef enum { + SPAPR_DR_CONNECTOR_TYPE_SHIFT_CPU = 1, + SPAPR_DR_CONNECTOR_TYPE_SHIFT_PHB = 2, + SPAPR_DR_CONNECTOR_TYPE_SHIFT_VIO = 3, + SPAPR_DR_CONNECTOR_TYPE_SHIFT_PCI = 4, + SPAPR_DR_CONNECTOR_TYPE_SHIFT_LMB = 8, +} sPAPRDRConnectorTypeShift; + +typedef enum { + SPAPR_DR_CONNECTOR_TYPE_ANY = ~0, + SPAPR_DR_CONNECTOR_TYPE_CPU = 1 << SPAPR_DR_CONNECTOR_TYPE_SHIFT_CPU, + SPAPR_DR_CONNECTOR_TYPE_PHB = 1 << SPAPR_DR_CONNECTOR_TYPE_SHIFT_PHB, + SPAPR_DR_CONNECTOR_TYPE_VIO = 1 << SPAPR_DR_CONNECTOR_TYPE_SHIFT_VIO, + SPAPR_DR_CONNECTOR_TYPE_PCI = 1 << SPAPR_DR_CONNECTOR_TYPE_SHIFT_PCI, + SPAPR_DR_CONNECTOR_TYPE_LMB = 1 << SPAPR_DR_CONNECTOR_TYPE_SHIFT_LMB, +} sPAPRDRConnectorType; + +/* + * set via set-indicator RTAS calls + * as documented by PAPR+ 2.7 13.5.3.4, Table 177 + * + * isolated: put device under firmware control + * unisolated: claim OS control of device (may or may not be in use) + */ +typedef enum { + SPAPR_DR_ISOLATION_STATE_ISOLATED = 0, + SPAPR_DR_ISOLATION_STATE_UNISOLATED = 1 +} sPAPRDRIsolationState; + +/* + * set via set-indicator RTAS calls + * as documented by PAPR+ 2.7 13.5.3.4, Table 177 + * + * unusable: mark device as unavailable to OS + * usable: mark device as available to OS + * exchange: (currently unused) + * recover: (currently unused) + */ +typedef enum { + SPAPR_DR_ALLOCATION_STATE_UNUSABLE = 0, + SPAPR_DR_ALLOCATION_STATE_USABLE = 1, + SPAPR_DR_ALLOCATION_STATE_EXCHANGE = 2, + SPAPR_DR_ALLOCATION_STATE_RECOVER = 3 +} sPAPRDRAllocationState; + +/* + * LED/visual indicator state + * + * set via set-indicator RTAS calls + * as documented by PAPR+ 2.7 13.5.3.4, Table 177, + * and PAPR+ 2.7 13.5.4.1, Table 180 + * + * inactive: hotpluggable entity inactive and safely removable + * active: hotpluggable entity in use and not safely removable + * identify: (currently unused) + * action: (currently unused) + */ +typedef enum { + SPAPR_DR_INDICATOR_STATE_INACTIVE = 0, + SPAPR_DR_INDICATOR_STATE_ACTIVE = 1, + SPAPR_DR_INDICATOR_STATE_IDENTIFY = 2, + SPAPR_DR_INDICATOR_STATE_ACTION = 3, +} sPAPRDRIndicatorState; + +/* + * returned via get-sensor-state RTAS calls + * as documented by PAPR+ 2.7 13.5.3.3, Table 175: + * + * empty: connector slot empty (e.g. empty hotpluggable PCI slot) + * present: connector slot populated and device available to OS + * unusable: device not currently available to OS + * exchange: (currently unused) + * recover: (currently unused) + */ +typedef enum { + SPAPR_DR_ENTITY_SENSE_EMPTY = 0, + SPAPR_DR_ENTITY_SENSE_PRESENT = 1, + SPAPR_DR_ENTITY_SENSE_UNUSABLE = 2, + SPAPR_DR_ENTITY_SENSE_EXCHANGE = 3, + SPAPR_DR_ENTITY_SENSE_RECOVER = 4, +} sPAPRDREntitySense; + +typedef enum { + SPAPR_DR_CC_RESPONSE_NEXT_SIB = 1, /* currently unused */ + SPAPR_DR_CC_RESPONSE_NEXT_CHILD = 2, + SPAPR_DR_CC_RESPONSE_NEXT_PROPERTY = 3, + SPAPR_DR_CC_RESPONSE_PREV_PARENT = 4, + SPAPR_DR_CC_RESPONSE_SUCCESS = 0, + SPAPR_DR_CC_RESPONSE_ERROR = -1, + SPAPR_DR_CC_RESPONSE_CONTINUE = -2, +} sPAPRDRCCResponse; + +typedef void (spapr_drc_detach_cb)(DeviceState *d, void *opaque); + +typedef struct sPAPRDRConnector { + /*< private >*/ + DeviceState parent; + + sPAPRDRConnectorType type; + uint32_t id; + Object *owner; + const char *name; + + /* sensor/indicator states */ + uint32_t isolation_state; + uint32_t allocation_state; + uint32_t indicator_state; + + /* configure-connector state */ + void *fdt; + int fdt_start_offset; + bool configured; + + bool awaiting_release; + + /* device pointer, via link property */ + DeviceState *dev; + spapr_drc_detach_cb *detach_cb; + void *detach_cb_opaque; +} sPAPRDRConnector; + +typedef struct sPAPRDRConnectorClass { + /*< private >*/ + DeviceClass parent; + + /*< public >*/ + + /* accessors for guest-visible (generally via RTAS) DR state */ + int (*set_isolation_state)(sPAPRDRConnector *drc, + sPAPRDRIsolationState state); + int (*set_indicator_state)(sPAPRDRConnector *drc, + sPAPRDRIndicatorState state); + int (*set_allocation_state)(sPAPRDRConnector *drc, + sPAPRDRAllocationState state); + uint32_t (*get_index)(sPAPRDRConnector *drc); + uint32_t (*get_type)(sPAPRDRConnector *drc); + const char *(*get_name)(sPAPRDRConnector *drc); + + sPAPRDREntitySense (*entity_sense)(sPAPRDRConnector *drc); + + /* QEMU interfaces for managing FDT/configure-connector */ + const void *(*get_fdt)(sPAPRDRConnector *drc, int *fdt_start_offset); + void (*set_configured)(sPAPRDRConnector *drc); + + /* QEMU interfaces for managing hotplug operations */ + void (*attach)(sPAPRDRConnector *drc, DeviceState *d, void *fdt, + int fdt_start_offset, bool coldplug, Error **errp); + void (*detach)(sPAPRDRConnector *drc, DeviceState *d, + spapr_drc_detach_cb *detach_cb, + void *detach_cb_opaque, Error **errp); + bool (*release_pending)(sPAPRDRConnector *drc); +} sPAPRDRConnectorClass; + +sPAPRDRConnector *spapr_dr_connector_new(Object *owner, + sPAPRDRConnectorType type, + uint32_t id); +sPAPRDRConnector *spapr_dr_connector_by_index(uint32_t index); +sPAPRDRConnector *spapr_dr_connector_by_id(sPAPRDRConnectorType type, + uint32_t id); +int spapr_drc_populate_dt(void *fdt, int fdt_offset, Object *owner, + uint32_t drc_type_mask); + +#endif /* __HW_SPAPR_DRC_H__ */ diff --git a/include/hw/ppc/spapr_vio.h b/include/hw/ppc/spapr_vio.h index 46edc2a20c..2299a5405a 100644 --- a/include/hw/ppc/spapr_vio.h +++ b/include/hw/ppc/spapr_vio.h @@ -52,7 +52,7 @@ typedef struct VIOsPAPRDeviceClass { const char *dt_name, *dt_type, *dt_compatible; target_ulong signal_mask; uint32_t rtce_window_size; - int (*init)(VIOsPAPRDevice *dev); + void (*realize)(VIOsPAPRDevice *dev, Error **errp); void (*reset)(VIOsPAPRDevice *dev); int (*devnode)(VIOsPAPRDevice *dev, void *fdt, int node_off); } VIOsPAPRDeviceClass; @@ -64,6 +64,8 @@ struct VIOsPAPRDevice { target_ulong signal_state; VIOsPAPR_CRQ crq; AddressSpace as; + MemoryRegion mrroot; + MemoryRegion mrbypass; sPAPRTCETable *tcet; }; @@ -86,6 +88,8 @@ extern int spapr_vio_signal(VIOsPAPRDevice *dev, target_ulong mode); static inline qemu_irq spapr_vio_qirq(VIOsPAPRDevice *dev) { + sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); + return xics_get_qirq(spapr->icp, dev->irq); } @@ -124,7 +128,7 @@ static inline int spapr_vio_dma_set(VIOsPAPRDevice *dev, uint64_t taddr, int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq); -VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg); +VIOsPAPRDevice *vty_lookup(sPAPRMachineState *spapr, target_ulong reg); void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len); void spapr_vty_create(VIOsPAPRBus *bus, CharDriverState *chardev); void spapr_vlan_create(VIOsPAPRBus *bus, NICInfo *nd); @@ -139,4 +143,6 @@ extern const VMStateDescription vmstate_spapr_vio; #define VMSTATE_SPAPR_VIO(_f, _s) \ VMSTATE_STRUCT(_f, _s, 0, vmstate_spapr_vio, VIOsPAPRDevice) +void spapr_vio_set_bypass(VIOsPAPRDevice *dev, bool bypass); + #endif /* _HW_SPAPR_VIO_H */ diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h index a214dd7f28..355a96623c 100644 --- a/include/hw/ppc/xics.h +++ b/include/hw/ppc/xics.h @@ -109,6 +109,7 @@ struct ICPState { uint8_t pending_priority; uint8_t mfrr; qemu_irq output; + bool cap_irq_xics_enabled; }; #define TYPE_ICS "ics" diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 589bbe7360..038b54d94b 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -65,8 +65,8 @@ struct VMStateDescription; * Operations depending on @props static properties should go into @realize. * After successful realization, setting static properties will fail. * - * As an interim step, the #DeviceState:realized property is set by deprecated - * functions qdev_init() and qdev_init_nofail(). + * As an interim step, the #DeviceState:realized property can also be + * set with qdev_init_nofail(). * In the future, devices will propagate this state change to their children * and along busses they expose. * The point in time will be deferred to machine creation, so that values @@ -165,6 +165,12 @@ struct DeviceState { int alias_required_for_version; }; +struct DeviceListener { + void (*realize)(DeviceListener *listener, DeviceState *dev); + void (*unrealize)(DeviceListener *listener, DeviceState *dev); + QTAILQ_ENTRY(DeviceListener) link; +}; + #define TYPE_BUS "bus" #define BUS(obj) OBJECT_CHECK(BusState, (obj), TYPE_BUS) #define BUS_CLASS(klass) OBJECT_CLASS_CHECK(BusClass, (klass), TYPE_BUS) @@ -220,7 +226,7 @@ struct Property { PropertyInfo *info; int offset; uint8_t bitnr; - uint8_t qtype; + qtype_code qtype; int64_t defval; int arrayoffset; PropertyInfo *arrayinfo; @@ -230,7 +236,7 @@ struct Property { struct PropertyInfo { const char *name; const char *description; - const char **enum_table; + const char * const *enum_table; int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len); ObjectPropertyAccessor *get; ObjectPropertyAccessor *set; @@ -256,10 +262,10 @@ typedef struct GlobalProperty { DeviceState *qdev_create(BusState *bus, const char *name); DeviceState *qdev_try_create(BusState *bus, const char *name); -int qdev_init(DeviceState *dev) QEMU_WARN_UNUSED_RESULT; void qdev_init_nofail(DeviceState *dev); void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id, int required_for_version); +HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev); void qdev_unplug(DeviceState *dev, Error **errp); void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp); @@ -336,6 +342,7 @@ void qbus_reset_all_fn(void *opaque); BusState *sysbus_get_default(void); char *qdev_get_fw_dev_path(DeviceState *dev); +char *qdev_get_own_fw_dev_path_from_handler(BusState *bus, DeviceState *dev); /** * @qdev_machine_init @@ -376,4 +383,8 @@ static inline bool qbus_is_hotpluggable(BusState *bus) { return bus->hotplug_handler; } + +void device_listener_register(DeviceListener *listener); +void device_listener_unregister(DeviceListener *listener); + #endif diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h index 070006c715..77538a8ca2 100644 --- a/include/hw/qdev-properties.h +++ b/include/hw/qdev-properties.h @@ -6,6 +6,7 @@ /*** qdev-properties.c ***/ extern PropertyInfo qdev_prop_bit; +extern PropertyInfo qdev_prop_bit64; extern PropertyInfo qdev_prop_bool; extern PropertyInfo qdev_prop_uint8; extern PropertyInfo qdev_prop_uint16; @@ -50,6 +51,15 @@ extern PropertyInfo qdev_prop_arraylen; .qtype = QTYPE_QBOOL, \ .defval = (bool)_defval, \ } +#define DEFINE_PROP_BIT64(_name, _state, _field, _bit, _defval) { \ + .name = (_name), \ + .info = &(qdev_prop_bit64), \ + .bitnr = (_bit), \ + .offset = offsetof(_state, _field) \ + + type_check(uint64_t, typeof_field(_state, _field)), \ + .qtype = QTYPE_QBOOL, \ + .defval = (bool)_defval, \ + } #define DEFINE_PROP_BOOL(_name, _state, _field, _defval) { \ .name = (_name), \ @@ -149,8 +159,8 @@ extern PropertyInfo qdev_prop_arraylen; LostTickPolicy) #define DEFINE_PROP_BIOS_CHS_TRANS(_n, _s, _f, _d) \ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_bios_chs_trans, int) -#define DEFINE_PROP_BLOCKSIZE(_n, _s, _f, _d) \ - DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_blocksize, uint16_t) +#define DEFINE_PROP_BLOCKSIZE(_n, _s, _f) \ + DEFINE_PROP_DEFAULT(_n, _s, _f, 0, qdev_prop_blocksize, uint16_t) #define DEFINE_PROP_PCI_HOST_DEVADDR(_n, _s, _f) \ DEFINE_PROP(_n, _s, _f, qdev_prop_pci_host_devaddr, PCIHostDeviceAddress) @@ -168,8 +178,8 @@ 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, - BlockBackend *value) QEMU_WARN_UNUSED_RESULT; +void qdev_prop_set_drive(DeviceState *dev, const char *name, + BlockBackend *value, Error **errp); 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); @@ -180,9 +190,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_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); +void qdev_prop_set_globals(DeviceState *dev); void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev, Property *prop, const char *value); diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h index 489d73b9b3..200e7e93fa 100644 --- a/include/hw/s390x/s390_flic.h +++ b/include/hw/s390x/s390_flic.h @@ -17,10 +17,13 @@ #include "hw/s390x/adapter.h" #include "hw/virtio/virtio.h" +#define ADAPTER_ROUTES_MAX_GSI 64 +#define VIRTIO_CCW_QUEUE_MAX ADAPTER_ROUTES_MAX_GSI + typedef struct AdapterRoutes { AdapterInfo adapter; int num_routes; - int gsi[VIRTIO_PCI_QUEUE_MAX]; + int gsi[ADAPTER_ROUTES_MAX_GSI]; } AdapterRoutes; #define TYPE_S390_FLIC_COMMON "s390-flic" diff --git a/include/hw/s390x/sclp.h b/include/hw/s390x/sclp.h index ec07a118f2..e8a64e25b7 100644 --- a/include/hw/s390x/sclp.h +++ b/include/hw/s390x/sclp.h @@ -43,14 +43,22 @@ #define SCLP_CMDW_CONFIGURE_CPU 0x00110001 #define SCLP_CMDW_DECONFIGURE_CPU 0x00100001 +/* SCLP PCI codes */ +#define SCLP_HAS_PCI_RECONFIG 0x0000000040000000ULL +#define SCLP_CMDW_CONFIGURE_PCI 0x001a0001 +#define SCLP_CMDW_DECONFIGURE_PCI 0x001b0001 +#define SCLP_RECONFIG_PCI_ATPYE 2 + /* SCLP response codes */ #define SCLP_RC_NORMAL_READ_COMPLETION 0x0010 #define SCLP_RC_NORMAL_COMPLETION 0x0020 #define SCLP_RC_SCCB_BOUNDARY_VIOLATION 0x0100 +#define SCLP_RC_NO_ACTION_REQUIRED 0x0120 #define SCLP_RC_INVALID_SCLP_COMMAND 0x01f0 #define SCLP_RC_CONTAINED_EQUIPMENT_CHECK 0x0340 #define SCLP_RC_INSUFFICIENT_SCCB_LENGTH 0x0300 #define SCLP_RC_STANDBY_READ_COMPLETION 0x0410 +#define SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED 0x09f0 #define SCLP_RC_INVALID_FUNCTION 0x40f0 #define SCLP_RC_NO_EVENT_BUFFERS_STORED 0x60f0 #define SCLP_RC_INVALID_SELECTION_MASK 0x70f0 diff --git a/include/hw/sparc/grlib.h b/include/hw/sparc/grlib.h index 470ce72250..9a0db7b47b 100644 --- a/include/hw/sparc/grlib.h +++ b/include/hw/sparc/grlib.h @@ -55,9 +55,7 @@ DeviceState *grlib_irqmp_create(hwaddr base, qdev_prop_set_ptr(dev, "set_pil_in", set_pil_in); qdev_prop_set_ptr(dev, "set_pil_in_opaque", env); - if (qdev_init(dev)) { - return NULL; - } + qdev_init_nofail(dev); env->irq_manager = dev; @@ -87,9 +85,7 @@ DeviceState *grlib_gptimer_create(hwaddr base, qdev_prop_set_uint32(dev, "frequency", freq); qdev_prop_set_uint32(dev, "irq-line", base_irq); - if (qdev_init(dev)) { - return NULL; - } + qdev_init_nofail(dev); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); @@ -112,9 +108,7 @@ DeviceState *grlib_apbuart_create(hwaddr base, dev = qdev_create(NULL, "grlib,apbuart"); qdev_prop_set_chr(dev, "chrdev", serial); - if (qdev_init(dev)) { - return NULL; - } + qdev_init_nofail(dev); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); diff --git a/include/hw/sparc/sun4m.h b/include/hw/sparc/sun4m.h index a587700a8b..9c17425a43 100644 --- a/include/hw/sparc/sun4m.h +++ b/include/hw/sparc/sun4m.h @@ -29,8 +29,8 @@ void slavio_pic_info(Monitor *mon, DeviceState *dev); void slavio_irq_info(Monitor *mon, DeviceState *dev); /* sun4m.c */ -void sun4m_pic_info(Monitor *mon, const QDict *qdict); -void sun4m_irq_info(Monitor *mon, const QDict *qdict); +void sun4m_hmp_info_pic(Monitor *mon, const QDict *qdict); +void sun4m_hmp_info_irq(Monitor *mon, const QDict *qdict); /* sparc32_dma.c */ #include "hw/sparc/sparc32_dma.h" diff --git a/include/hw/sysbus.h b/include/hw/sysbus.h index d1f3f000f9..cc1dba49bf 100644 --- a/include/hw/sysbus.h +++ b/include/hw/sysbus.h @@ -41,6 +41,24 @@ typedef struct SysBusDeviceClass { /*< public >*/ int (*init)(SysBusDevice *dev); + + /* + * Let the sysbus device format its own non-PIO, non-MMIO unit address. + * + * Sometimes a class of SysBusDevices has neither MMIO nor PIO resources, + * yet instances of it would like to distinguish themselves, in + * OpenFirmware device paths, from other instances of the same class on the + * sysbus. For that end we expose this callback. + * + * The implementation is not supposed to change *@dev, or incur other + * observable change. + * + * The function returns a dynamically allocated string. On error, NULL + * should be returned; the unit address portion of the OFW node will be + * omitted then. (This is not considered a fatal error.) + */ + char *(*explicit_ofw_unit_address)(const SysBusDevice *dev); + void (*connect_irq_notifier)(SysBusDevice *dev, qemu_irq irq); } SysBusDeviceClass; struct SysBusDevice { diff --git a/include/hw/timer/a9gtimer.h b/include/hw/timer/a9gtimer.h index b88c02a6ef..98d8e0ae53 100644 --- a/include/hw/timer/a9gtimer.h +++ b/include/hw/timer/a9gtimer.h @@ -37,7 +37,7 @@ #define R_CONTROL_TIMER_ENABLE (1 << 0) #define R_CONTROL_COMP_ENABLE (1 << 1) #define R_CONTROL_IRQ_ENABLE (1 << 2) -#define R_CONTROL_AUTO_INCREMENT (1 << 2) +#define R_CONTROL_AUTO_INCREMENT (1 << 3) #define R_CONTROL_PRESCALER_SHIFT 8 #define R_CONTROL_PRESCALER_LEN 8 #define R_CONTROL_PRESCALER_MASK (((1 << R_CONTROL_PRESCALER_LEN) - 1) << \ diff --git a/include/hw/timer/m48t59.h b/include/hw/timer/m48t59.h index 8217522291..3367923639 100644 --- a/include/hw/timer/m48t59.h +++ b/include/hw/timer/m48t59.h @@ -1,37 +1,34 @@ #ifndef NVRAM_H #define NVRAM_H -/* NVRAM helpers */ -typedef uint32_t (*nvram_read_t)(void *private, uint32_t addr); -typedef void (*nvram_write_t)(void *private, uint32_t addr, uint32_t val); -typedef struct nvram_t { - void *opaque; - nvram_read_t read_fn; - nvram_write_t write_fn; -} nvram_t; - -uint32_t NVRAM_get_lword (nvram_t *nvram, uint32_t addr); -int NVRAM_get_string (nvram_t *nvram, uint8_t *dst, uint16_t addr, int max); - -int PPC_NVRAM_set_params (nvram_t *nvram, uint16_t NVRAM_size, - const char *arch, - uint32_t RAM_size, int boot_device, - uint32_t kernel_image, uint32_t kernel_size, - const char *cmdline, - uint32_t initrd_image, uint32_t initrd_size, - uint32_t NVRAM_image, - int width, int height, int depth); - -#define TYPE_SYSBUS_M48T59 "m48t59" - -typedef struct M48t59State M48t59State; - -void m48t59_write (void *private, uint32_t addr, uint32_t val); -uint32_t m48t59_read (void *private, uint32_t addr); -void m48t59_toggle_lock (void *private, int lock); -M48t59State *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size, - int type); -M48t59State *m48t59_init(qemu_irq IRQ, hwaddr mem_base, - uint32_t io_base, uint16_t size, int type); +#include "qemu-common.h" +#include "qom/object.h" + +#define TYPE_NVRAM "nvram" + +#define NVRAM_CLASS(klass) \ + OBJECT_CLASS_CHECK(NvramClass, (klass), TYPE_NVRAM) +#define NVRAM_GET_CLASS(obj) \ + OBJECT_GET_CLASS(NvramClass, (obj), TYPE_NVRAM) +#define NVRAM(obj) \ + INTERFACE_CHECK(Nvram, (obj), TYPE_NVRAM) + +typedef struct Nvram { + Object parent; +} Nvram; + +typedef struct NvramClass { + InterfaceClass parent; + + uint32_t (*read)(Nvram *obj, uint32_t addr); + void (*write)(Nvram *obj, uint32_t addr, uint32_t val); + void (*toggle_lock)(Nvram *obj, int lock); +} NvramClass; + +Nvram *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size, + int base_year, int type); +Nvram *m48t59_init(qemu_irq IRQ, hwaddr mem_base, + uint32_t io_base, uint16_t size, int base_year, + int type); #endif /* !NVRAM_H */ diff --git a/include/hw/timer/stm32f2xx_timer.h b/include/hw/timer/stm32f2xx_timer.h new file mode 100644 index 0000000000..e6a83237a5 --- /dev/null +++ b/include/hw/timer/stm32f2xx_timer.h @@ -0,0 +1,101 @@ +/* + * STM32F2XX Timer + * + * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef HW_STM32F2XX_TIMER_H +#define HW_STM32F2XX_TIMER_H + +#include "hw/sysbus.h" +#include "qemu/timer.h" +#include "sysemu/sysemu.h" + +#define TIM_CR1 0x00 +#define TIM_CR2 0x04 +#define TIM_SMCR 0x08 +#define TIM_DIER 0x0C +#define TIM_SR 0x10 +#define TIM_EGR 0x14 +#define TIM_CCMR1 0x18 +#define TIM_CCMR2 0x1C +#define TIM_CCER 0x20 +#define TIM_CNT 0x24 +#define TIM_PSC 0x28 +#define TIM_ARR 0x2C +#define TIM_CCR1 0x34 +#define TIM_CCR2 0x38 +#define TIM_CCR3 0x3C +#define TIM_CCR4 0x40 +#define TIM_DCR 0x48 +#define TIM_DMAR 0x4C +#define TIM_OR 0x50 + +#define TIM_CR1_CEN 1 + +#define TIM_EGR_UG 1 + +#define TIM_CCER_CC2E (1 << 4) +#define TIM_CCMR1_OC2M2 (1 << 14) +#define TIM_CCMR1_OC2M1 (1 << 13) +#define TIM_CCMR1_OC2M0 (1 << 12) +#define TIM_CCMR1_OC2PE (1 << 11) + +#define TIM_DIER_UIE 1 + +#define TYPE_STM32F2XX_TIMER "stm32f2xx-timer" +#define STM32F2XXTIMER(obj) OBJECT_CHECK(STM32F2XXTimerState, \ + (obj), TYPE_STM32F2XX_TIMER) + +typedef struct STM32F2XXTimerState { + /* <private> */ + SysBusDevice parent_obj; + + /* <public> */ + MemoryRegion iomem; + QEMUTimer *timer; + qemu_irq irq; + + int64_t tick_offset; + uint64_t hit_time; + uint64_t freq_hz; + + uint32_t tim_cr1; + uint32_t tim_cr2; + uint32_t tim_smcr; + uint32_t tim_dier; + uint32_t tim_sr; + uint32_t tim_egr; + uint32_t tim_ccmr1; + uint32_t tim_ccmr2; + uint32_t tim_ccer; + uint32_t tim_psc; + uint32_t tim_arr; + uint32_t tim_ccr1; + uint32_t tim_ccr2; + uint32_t tim_ccr3; + uint32_t tim_ccr4; + uint32_t tim_dcr; + uint32_t tim_dmar; + uint32_t tim_or; +} STM32F2XXTimerState; + +#endif /* HW_STM32F2XX_TIMER_H */ diff --git a/include/hw/usb.h b/include/hw/usb.h index b20b959123..c8b6e7b571 100644 --- a/include/hw/usb.h +++ b/include/hw/usb.h @@ -445,15 +445,11 @@ void usb_ep_reset(USBDevice *dev); void usb_ep_dump(USBDevice *dev); struct USBEndpoint *usb_ep_get(USBDevice *dev, int pid, int ep); uint8_t usb_ep_get_type(USBDevice *dev, int pid, int ep); -uint8_t usb_ep_get_ifnum(USBDevice *dev, int pid, int ep); void usb_ep_set_type(USBDevice *dev, int pid, int ep, uint8_t type); void usb_ep_set_ifnum(USBDevice *dev, int pid, int ep, uint8_t ifnum); void usb_ep_set_max_packet_size(USBDevice *dev, int pid, int ep, uint16_t raw); -int usb_ep_get_max_packet_size(USBDevice *dev, int pid, int ep); void usb_ep_set_max_streams(USBDevice *dev, int pid, int ep, uint8_t raw); -int usb_ep_get_max_streams(USBDevice *dev, int pid, int ep); -void usb_ep_set_pipeline(USBDevice *dev, int pid, int ep, bool enabled); void usb_ep_set_halted(USBDevice *dev, int pid, int ep, bool halted); USBPacket *usb_ep_find_packet_by_id(USBDevice *dev, int pid, int ep, uint64_t id); @@ -469,11 +465,10 @@ void usb_port_reset(USBPort *port); void usb_device_reset(USBDevice *dev); void usb_wakeup(USBEndpoint *ep, unsigned int stream); void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p); -int set_usb_string(uint8_t *buf, const char *str); /* usb-linux.c */ USBDevice *usb_host_device_open(USBBus *bus, const char *devname); -void usb_host_info(Monitor *mon, const QDict *qdict); +void hmp_info_usbhost(Monitor *mon, const QDict *qdict); /* usb ports of the VM */ @@ -526,8 +521,9 @@ struct USBBus { }; struct USBBusOps { - int (*register_companion)(USBBus *bus, USBPort *ports[], - uint32_t portcount, uint32_t firstport); + void (*register_companion)(USBBus *bus, USBPort *ports[], + uint32_t portcount, uint32_t firstport, + Error **errp); void (*wakeup_endpoint)(USBBus *bus, USBEndpoint *ep, unsigned int stream); }; @@ -543,9 +539,10 @@ USBDevice *usb_create_simple(USBBus *bus, const char *name); USBDevice *usbdevice_create(const char *cmdline); void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index, USBPortOps *ops, int speedmask); -int usb_register_companion(const char *masterbus, USBPort *ports[], - uint32_t portcount, uint32_t firstport, - void *opaque, USBPortOps *ops, int speedmask); +void usb_register_companion(const char *masterbus, USBPort *ports[], + uint32_t portcount, uint32_t firstport, + void *opaque, USBPortOps *ops, int speedmask, + Error **errp); void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr); void usb_unregister_port(USBBus *bus, USBPort *port); void usb_claim_port(USBDevice *dev, Error **errp); diff --git a/include/hw/vfio/vfio-calxeda-xgmac.h b/include/hw/vfio/vfio-calxeda-xgmac.h new file mode 100644 index 0000000000..f994775c09 --- /dev/null +++ b/include/hw/vfio/vfio-calxeda-xgmac.h @@ -0,0 +1,46 @@ +/* + * VFIO calxeda xgmac device + * + * Copyright Linaro Limited, 2014 + * + * Authors: + * Eric Auger <eric.auger@linaro.org> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ + +#ifndef HW_VFIO_VFIO_CALXEDA_XGMAC_H +#define HW_VFIO_VFIO_CALXEDA_XGMAC_H + +#include "hw/vfio/vfio-platform.h" + +#define TYPE_VFIO_CALXEDA_XGMAC "vfio-calxeda-xgmac" + +/** + * This device exposes: + * - a single MMIO region corresponding to its register space + * - 3 IRQS (main and 2 power related IRQs) + */ +typedef struct VFIOCalxedaXgmacDevice { + VFIOPlatformDevice vdev; +} VFIOCalxedaXgmacDevice; + +typedef struct VFIOCalxedaXgmacDeviceClass { + /*< private >*/ + VFIOPlatformDeviceClass parent_class; + /*< public >*/ + DeviceRealize parent_realize; +} VFIOCalxedaXgmacDeviceClass; + +#define VFIO_CALXEDA_XGMAC_DEVICE(obj) \ + OBJECT_CHECK(VFIOCalxedaXgmacDevice, (obj), TYPE_VFIO_CALXEDA_XGMAC) +#define VFIO_CALXEDA_XGMAC_DEVICE_CLASS(klass) \ + OBJECT_CLASS_CHECK(VFIOCalxedaXgmacDeviceClass, (klass), \ + TYPE_VFIO_CALXEDA_XGMAC) +#define VFIO_CALXEDA_XGMAC_DEVICE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(VFIOCalxedaXgmacDeviceClass, (obj), \ + TYPE_VFIO_CALXEDA_XGMAC) + +#endif diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h new file mode 100644 index 0000000000..59a321d479 --- /dev/null +++ b/include/hw/vfio/vfio-common.h @@ -0,0 +1,149 @@ +/* + * common header for vfio based device assignment support + * + * Copyright Red Hat, Inc. 2012 + * + * Authors: + * Alex Williamson <alex.williamson@redhat.com> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + * Based on qemu-kvm device-assignment: + * Adapted for KVM by Qumranet. + * Copyright (c) 2007, Neocleus, Alex Novik (alex@neocleus.com) + * Copyright (c) 2007, Neocleus, Guy Zana (guy@neocleus.com) + * Copyright (C) 2008, Qumranet, Amit Shah (amit.shah@qumranet.com) + * Copyright (C) 2008, Red Hat, Amit Shah (amit.shah@redhat.com) + * Copyright (C) 2008, IBM, Muli Ben-Yehuda (muli@il.ibm.com) + */ +#ifndef HW_VFIO_VFIO_COMMON_H +#define HW_VFIO_VFIO_COMMON_H + +#include "qemu-common.h" +#include "exec/address-spaces.h" +#include "exec/memory.h" +#include "qemu/queue.h" +#include "qemu/notify.h" + +/*#define DEBUG_VFIO*/ +#ifdef DEBUG_VFIO +#define DPRINTF(fmt, ...) \ + do { fprintf(stderr, "vfio: " fmt, ## __VA_ARGS__); } while (0) +#else +#define DPRINTF(fmt, ...) \ + do { } while (0) +#endif + +/* Extra debugging, trap acceleration paths for more logging */ +#define VFIO_ALLOW_KVM_INTX 1 +#define VFIO_ALLOW_KVM_MSI 1 +#define VFIO_ALLOW_KVM_MSIX 1 + +enum { + VFIO_DEVICE_TYPE_PCI = 0, + VFIO_DEVICE_TYPE_PLATFORM = 1, +}; + +typedef struct VFIORegion { + struct VFIODevice *vbasedev; + off_t fd_offset; /* offset of region within device fd */ + MemoryRegion mem; /* slow, read/write access */ + MemoryRegion mmap_mem; /* direct mapped access */ + void *mmap; + size_t size; + uint32_t flags; /* VFIO region flags (rd/wr/mmap) */ + uint8_t nr; /* cache the region number for debug */ +} VFIORegion; + +typedef struct VFIOAddressSpace { + AddressSpace *as; + QLIST_HEAD(, VFIOContainer) containers; + QLIST_ENTRY(VFIOAddressSpace) list; +} VFIOAddressSpace; + +struct VFIOGroup; + +typedef struct VFIOType1 { + MemoryListener listener; + int error; + bool initialized; +} VFIOType1; + +typedef struct VFIOContainer { + VFIOAddressSpace *space; + int fd; /* /dev/vfio/vfio, empowered by the attached groups */ + struct { + /* enable abstraction to support various iommu backends */ + union { + VFIOType1 type1; + }; + void (*release)(struct VFIOContainer *); + } iommu_data; + QLIST_HEAD(, VFIOGuestIOMMU) giommu_list; + QLIST_HEAD(, VFIOGroup) group_list; + QLIST_ENTRY(VFIOContainer) next; +} VFIOContainer; + +typedef struct VFIOGuestIOMMU { + VFIOContainer *container; + MemoryRegion *iommu; + Notifier n; + QLIST_ENTRY(VFIOGuestIOMMU) giommu_next; +} VFIOGuestIOMMU; + +typedef struct VFIODeviceOps VFIODeviceOps; + +typedef struct VFIODevice { + QLIST_ENTRY(VFIODevice) next; + struct VFIOGroup *group; + char *name; + int fd; + int type; + bool reset_works; + bool needs_reset; + bool allow_mmap; + VFIODeviceOps *ops; + unsigned int num_irqs; + unsigned int num_regions; + unsigned int flags; +} VFIODevice; + +struct VFIODeviceOps { + void (*vfio_compute_needs_reset)(VFIODevice *vdev); + int (*vfio_hot_reset_multi)(VFIODevice *vdev); + void (*vfio_eoi)(VFIODevice *vdev); +}; + +typedef struct VFIOGroup { + int fd; + int groupid; + VFIOContainer *container; + QLIST_HEAD(, VFIODevice) device_list; + QLIST_ENTRY(VFIOGroup) next; + QLIST_ENTRY(VFIOGroup) container_next; +} VFIOGroup; + +void vfio_put_base_device(VFIODevice *vbasedev); +void vfio_disable_irqindex(VFIODevice *vbasedev, int index); +void vfio_unmask_single_irqindex(VFIODevice *vbasedev, int index); +void vfio_mask_single_irqindex(VFIODevice *vbasedev, int index); +void vfio_region_write(void *opaque, hwaddr addr, + uint64_t data, unsigned size); +uint64_t vfio_region_read(void *opaque, + hwaddr addr, unsigned size); +int vfio_mmap_region(Object *vdev, VFIORegion *region, + MemoryRegion *mem, MemoryRegion *submem, + void **map, size_t size, off_t offset, + const char *name); +void vfio_reset_handler(void *opaque); +VFIOGroup *vfio_get_group(int groupid, AddressSpace *as); +void vfio_put_group(VFIOGroup *group); +int vfio_get_device(VFIOGroup *group, const char *name, + VFIODevice *vbasedev); + +extern const MemoryRegionOps vfio_region_ops; +extern QLIST_HEAD(vfio_group_head, VFIOGroup) vfio_group_list; +extern QLIST_HEAD(vfio_as_head, VFIOAddressSpace) vfio_address_spaces; + +#endif /* !HW_VFIO_VFIO_COMMON_H */ diff --git a/include/hw/vfio/vfio-platform.h b/include/hw/vfio/vfio-platform.h new file mode 100644 index 0000000000..c5cf1d79f3 --- /dev/null +++ b/include/hw/vfio/vfio-platform.h @@ -0,0 +1,77 @@ +/* + * vfio based device assignment support - platform devices + * + * Copyright Linaro Limited, 2014 + * + * Authors: + * Kim Phillips <kim.phillips@linaro.org> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + * Based on vfio based PCI device assignment support: + * Copyright Red Hat, Inc. 2012 + */ + +#ifndef HW_VFIO_VFIO_PLATFORM_H +#define HW_VFIO_VFIO_PLATFORM_H + +#include "hw/sysbus.h" +#include "hw/vfio/vfio-common.h" +#include "qemu/event_notifier.h" +#include "qemu/queue.h" +#include "hw/irq.h" + +#define TYPE_VFIO_PLATFORM "vfio-platform" + +enum { + VFIO_IRQ_INACTIVE = 0, + VFIO_IRQ_PENDING = 1, + VFIO_IRQ_ACTIVE = 2, + /* VFIO_IRQ_ACTIVE_AND_PENDING cannot happen with VFIO */ +}; + +typedef struct VFIOINTp { + QLIST_ENTRY(VFIOINTp) next; /* entry for IRQ list */ + QSIMPLEQ_ENTRY(VFIOINTp) pqnext; /* entry for pending IRQ queue */ + EventNotifier interrupt; /* eventfd triggered on interrupt */ + EventNotifier unmask; /* eventfd for unmask on QEMU bypass */ + qemu_irq qemuirq; + struct VFIOPlatformDevice *vdev; /* back pointer to device */ + int state; /* inactive, pending, active */ + uint8_t pin; /* index */ + uint32_t flags; /* IRQ info flags */ + bool kvm_accel; /* set when QEMU bypass through KVM enabled */ +} VFIOINTp; + +/* function type for user side eventfd handler */ +typedef void (*eventfd_user_side_handler_t)(VFIOINTp *intp); + +typedef struct VFIOPlatformDevice { + SysBusDevice sbdev; + VFIODevice vbasedev; /* not a QOM object */ + VFIORegion **regions; + QLIST_HEAD(, VFIOINTp) intp_list; /* list of IRQs */ + /* queue of pending IRQs */ + QSIMPLEQ_HEAD(pending_intp_queue, VFIOINTp) pending_intp_queue; + char *compat; /* compatibility string */ + uint32_t mmap_timeout; /* delay to re-enable mmaps after interrupt */ + QEMUTimer *mmap_timer; /* allows fast-path resume after IRQ hit */ + QemuMutex intp_mutex; /* protect the intp_list IRQ state */ + bool irqfd_allowed; /* debug option to force irqfd on/off */ +} VFIOPlatformDevice; + +typedef struct VFIOPlatformDeviceClass { + /*< private >*/ + SysBusDeviceClass parent_class; + /*< public >*/ +} VFIOPlatformDeviceClass; + +#define VFIO_PLATFORM_DEVICE(obj) \ + OBJECT_CHECK(VFIOPlatformDevice, (obj), TYPE_VFIO_PLATFORM) +#define VFIO_PLATFORM_DEVICE_CLASS(klass) \ + OBJECT_CLASS_CHECK(VFIOPlatformDeviceClass, (klass), TYPE_VFIO_PLATFORM) +#define VFIO_PLATFORM_DEVICE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(VFIOPlatformDeviceClass, (obj), TYPE_VFIO_PLATFORM) + +#endif /*HW_VFIO_VFIO_PLATFORM_H*/ diff --git a/include/hw/misc/vfio.h b/include/hw/vfio/vfio.h index 0b26cd8e11..0b26cd8e11 100644 --- a/include/hw/misc/vfio.h +++ b/include/hw/vfio/vfio.h diff --git a/include/hw/virtio/dataplane/vring-accessors.h b/include/hw/virtio/dataplane/vring-accessors.h new file mode 100644 index 0000000000..815c19b6ef --- /dev/null +++ b/include/hw/virtio/dataplane/vring-accessors.h @@ -0,0 +1,75 @@ +#ifndef VRING_ACCESSORS_H +#define VRING_ACCESSORS_H + +#include "standard-headers/linux/virtio_ring.h" +#include "hw/virtio/virtio.h" +#include "hw/virtio/virtio-access.h" + +static inline uint16_t vring_get_used_idx(VirtIODevice *vdev, Vring *vring) +{ + return virtio_tswap16(vdev, vring->vr.used->idx); +} + +static inline void vring_set_used_idx(VirtIODevice *vdev, Vring *vring, + uint16_t idx) +{ + vring->vr.used->idx = virtio_tswap16(vdev, idx); +} + +static inline uint16_t vring_get_avail_idx(VirtIODevice *vdev, Vring *vring) +{ + return virtio_tswap16(vdev, vring->vr.avail->idx); +} + +static inline uint16_t vring_get_avail_ring(VirtIODevice *vdev, Vring *vring, + int i) +{ + return virtio_tswap16(vdev, vring->vr.avail->ring[i]); +} + +static inline void vring_set_used_ring_id(VirtIODevice *vdev, Vring *vring, + int i, uint32_t id) +{ + vring->vr.used->ring[i].id = virtio_tswap32(vdev, id); +} + +static inline void vring_set_used_ring_len(VirtIODevice *vdev, Vring *vring, + int i, uint32_t len) +{ + vring->vr.used->ring[i].len = virtio_tswap32(vdev, len); +} + +static inline uint16_t vring_get_used_flags(VirtIODevice *vdev, Vring *vring) +{ + return virtio_tswap16(vdev, vring->vr.used->flags); +} + +static inline uint16_t vring_get_avail_flags(VirtIODevice *vdev, Vring *vring) +{ + return virtio_tswap16(vdev, vring->vr.avail->flags); +} + +static inline void vring_set_used_flags(VirtIODevice *vdev, Vring *vring, + uint16_t flags) +{ + vring->vr.used->flags |= virtio_tswap16(vdev, flags); +} + +static inline void vring_clear_used_flags(VirtIODevice *vdev, Vring *vring, + uint16_t flags) +{ + vring->vr.used->flags &= virtio_tswap16(vdev, ~flags); +} + +static inline unsigned int vring_get_num(Vring *vring) +{ + return vring->vr.num; +} + +/* Are there more descriptors available? */ +static inline bool vring_more_avail(VirtIODevice *vdev, Vring *vring) +{ + return vring_get_avail_idx(vdev, vring) != vring->last_avail_idx; +} + +#endif diff --git a/include/hw/virtio/dataplane/vring.h b/include/hw/virtio/dataplane/vring.h index d3e086aefc..8d97db9e2d 100644 --- a/include/hw/virtio/dataplane/vring.h +++ b/include/hw/virtio/dataplane/vring.h @@ -18,7 +18,7 @@ #define VRING_H #include "qemu-common.h" -#include "hw/virtio/virtio_ring.h" +#include "standard-headers/linux/virtio_ring.h" #include "hw/virtio/virtio.h" typedef struct { @@ -31,17 +31,6 @@ typedef struct { bool broken; /* was there a fatal error? */ } Vring; -static inline unsigned int vring_get_num(Vring *vring) -{ - return vring->vr.num; -} - -/* Are there more descriptors available? */ -static inline bool vring_more_avail(Vring *vring) -{ - return vring->vr.avail->idx != vring->last_avail_idx; -} - /* Fail future vring_pop() and vring_push() calls until reset */ static inline void vring_set_broken(Vring *vring) { @@ -54,6 +43,7 @@ void vring_disable_notification(VirtIODevice *vdev, Vring *vring); bool vring_enable_notification(VirtIODevice *vdev, Vring *vring); bool vring_should_notify(VirtIODevice *vdev, Vring *vring); int vring_pop(VirtIODevice *vdev, Vring *vring, VirtQueueElement *elem); -void vring_push(Vring *vring, VirtQueueElement *elem, int len); +void vring_push(VirtIODevice *vdev, Vring *vring, VirtQueueElement *elem, + int len); #endif /* VRING_H */ diff --git a/include/hw/virtio/vhost-scsi.h b/include/hw/virtio/vhost-scsi.h index 85cc031281..701bfee619 100644 --- a/include/hw/virtio/vhost-scsi.h +++ b/include/hw/virtio/vhost-scsi.h @@ -60,14 +60,10 @@ typedef struct VHostSCSI { Error *migration_blocker; struct vhost_dev dev; + int32_t bootindex; + int channel; + int target; + int lun; } VHostSCSI; -#define DEFINE_VHOST_SCSI_PROPERTIES(_state, _conf_field) \ - DEFINE_PROP_STRING("vhostfd", _state, _conf_field.vhostfd), \ - DEFINE_PROP_STRING("wwpn", _state, _conf_field.wwpn), \ - DEFINE_PROP_UINT32("num_queues", _state, _conf_field.num_queues, 1), \ - DEFINE_PROP_UINT32("max_sectors", _state, _conf_field.max_sectors, 0xFFFF), \ - DEFINE_PROP_UINT32("cmd_per_lun", _state, _conf_field.cmd_per_lun, 128) - - #endif diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h index d5593d1620..dd510509eb 100644 --- a/include/hw/virtio/vhost.h +++ b/include/hw/virtio/vhost.h @@ -28,6 +28,12 @@ typedef unsigned long vhost_log_chunk_t; #define VHOST_LOG_CHUNK (VHOST_LOG_PAGE * VHOST_LOG_BITS) #define VHOST_INVALID_FEATURE_BIT (0xff) +struct vhost_log { + unsigned long long size; + int refcnt; + vhost_log_chunk_t log[0]; +}; + struct vhost_memory; struct vhost_dev { MemoryListener memory_listener; @@ -36,26 +42,25 @@ struct vhost_dev { MemoryRegionSection *mem_sections; struct vhost_virtqueue *vqs; int nvqs; - /* the first virtuque which would be used by this vhost dev */ + /* the first virtqueue which would be used by this vhost dev */ int vq_index; unsigned long long features; unsigned long long acked_features; unsigned long long backend_features; bool started; bool log_enabled; - vhost_log_chunk_t *log; unsigned long long log_size; Error *migration_blocker; - bool force; bool memory_changed; hwaddr mem_changed_start_addr; hwaddr mem_changed_end_addr; const VhostOps *vhost_ops; void *opaque; + struct vhost_log *log; }; int vhost_dev_init(struct vhost_dev *hdev, void *opaque, - VhostBackendType backend_type, bool force); + VhostBackendType backend_type); void vhost_dev_cleanup(struct vhost_dev *hdev); bool vhost_dev_query(struct vhost_dev *hdev, VirtIODevice *vdev); int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev); @@ -72,8 +77,8 @@ bool vhost_virtqueue_pending(struct vhost_dev *hdev, int n); */ void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n, bool mask); -unsigned vhost_get_features(struct vhost_dev *hdev, const int *feature_bits, - unsigned features); +uint64_t vhost_get_features(struct vhost_dev *hdev, const int *feature_bits, + uint64_t features); void vhost_ack_features(struct vhost_dev *hdev, const int *feature_bits, - unsigned features); + uint64_t features); #endif diff --git a/include/hw/virtio/virtio-access.h b/include/hw/virtio/virtio-access.h index 46456fd9da..1ec1dfdb6c 100644 --- a/include/hw/virtio/virtio-access.h +++ b/include/hw/virtio/virtio-access.h @@ -19,6 +19,10 @@ static inline bool virtio_access_is_big_endian(VirtIODevice *vdev) { + if (virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) { + /* Devices conforming to VIRTIO 1.0 or later are always LE. */ + return false; + } #if defined(TARGET_IS_BIENDIAN) return virtio_is_big_endian(vdev); #elif defined(TARGET_WORDS_BIGENDIAN) @@ -28,6 +32,19 @@ static inline bool virtio_access_is_big_endian(VirtIODevice *vdev) #endif } +static inline bool virtio_legacy_is_cross_endian(VirtIODevice *vdev) +{ +#ifdef TARGET_IS_BIENDIAN +#ifdef HOST_WORDS_BIGENDIAN + return !virtio_is_big_endian(vdev); +#else + return virtio_is_big_endian(vdev); +#endif +#else + return false; +#endif +} + static inline uint16_t virtio_lduw_phys(VirtIODevice *vdev, hwaddr pa) { if (virtio_access_is_big_endian(vdev)) { @@ -126,6 +143,15 @@ static inline uint64_t virtio_ldq_p(VirtIODevice *vdev, const void *ptr) } } +static inline bool virtio_needs_swap(VirtIODevice *vdev) +{ +#ifdef HOST_WORDS_BIGENDIAN + return virtio_access_is_big_endian(vdev) ? false : true; +#else + return virtio_access_is_big_endian(vdev) ? true : false; +#endif +} + static inline uint16_t virtio_tswap16(VirtIODevice *vdev, uint16_t s) { #ifdef HOST_WORDS_BIGENDIAN diff --git a/include/hw/virtio/virtio-balloon.h b/include/hw/virtio/virtio-balloon.h index f863bfe27a..09c2ce4dcd 100644 --- a/include/hw/virtio/virtio-balloon.h +++ b/include/hw/virtio/virtio-balloon.h @@ -15,6 +15,7 @@ #ifndef _QEMU_VIRTIO_BALLOON_H #define _QEMU_VIRTIO_BALLOON_H +#include "standard-headers/linux/virtio_balloon.h" #include "hw/virtio/virtio.h" #include "hw/pci/pci.h" @@ -22,39 +23,13 @@ #define VIRTIO_BALLOON(obj) \ OBJECT_CHECK(VirtIOBalloon, (obj), TYPE_VIRTIO_BALLOON) -/* from Linux's linux/virtio_balloon.h */ +typedef struct virtio_balloon_stat VirtIOBalloonStat; -/* The ID for virtio_balloon */ -#define VIRTIO_ID_BALLOON 5 - -/* The feature bitmap for virtio balloon */ -#define VIRTIO_BALLOON_F_MUST_TELL_HOST 0 /* Tell before reclaiming pages */ -#define VIRTIO_BALLOON_F_STATS_VQ 1 /* Memory stats virtqueue */ - -/* Size of a PFN in the balloon interface. */ -#define VIRTIO_BALLOON_PFN_SHIFT 12 - -struct virtio_balloon_config -{ - /* Number of pages host wants Guest to give up. */ - uint32_t num_pages; - /* Number of pages we've actually got in balloon. */ - uint32_t actual; -}; - -/* Memory Statistics */ -#define VIRTIO_BALLOON_S_SWAP_IN 0 /* Amount of memory swapped in */ -#define VIRTIO_BALLOON_S_SWAP_OUT 1 /* Amount of memory swapped out */ -#define VIRTIO_BALLOON_S_MAJFLT 2 /* Number of major faults */ -#define VIRTIO_BALLOON_S_MINFLT 3 /* Number of minor faults */ -#define VIRTIO_BALLOON_S_MEMFREE 4 /* Total amount of free memory */ -#define VIRTIO_BALLOON_S_MEMTOT 5 /* Total amount of memory */ -#define VIRTIO_BALLOON_S_NR 6 - -typedef struct VirtIOBalloonStat { - uint16_t tag; - uint64_t val; -} QEMU_PACKED VirtIOBalloonStat; +typedef struct virtio_balloon_stat_modern { + uint16_t tag; + uint8_t reserved[6]; + uint64_t val; +} VirtIOBalloonStatModern; typedef struct VirtIOBalloon { VirtIODevice parent_obj; @@ -67,6 +42,7 @@ typedef struct VirtIOBalloon { QEMUTimer *stats_timer; int64_t stats_last_update; int64_t stats_poll_interval; + uint32_t host_features; } VirtIOBalloon; #endif diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h index 3979dc41af..6bf5905c52 100644 --- a/include/hw/virtio/virtio-blk.h +++ b/include/hw/virtio/virtio-blk.h @@ -14,6 +14,7 @@ #ifndef _QEMU_VIRTIO_BLK_H #define _QEMU_VIRTIO_BLK_H +#include "standard-headers/linux/virtio_blk.h" #include "hw/virtio/virtio.h" #include "hw/block/block.h" #include "sysemu/iothread.h" @@ -23,88 +24,12 @@ #define VIRTIO_BLK(obj) \ OBJECT_CHECK(VirtIOBlock, (obj), TYPE_VIRTIO_BLK) -/* from Linux's linux/virtio_blk.h */ - -/* The ID for virtio_block */ -#define VIRTIO_ID_BLOCK 2 - -/* Feature bits */ -#define VIRTIO_BLK_F_BARRIER 0 /* Does host support barriers? */ -#define VIRTIO_BLK_F_SIZE_MAX 1 /* Indicates maximum segment size */ -#define VIRTIO_BLK_F_SEG_MAX 2 /* Indicates maximum # of segments */ -#define VIRTIO_BLK_F_GEOMETRY 4 /* Indicates support of legacy geometry */ -#define VIRTIO_BLK_F_RO 5 /* Disk is read-only */ -#define VIRTIO_BLK_F_BLK_SIZE 6 /* Block size of disk is available*/ -#define VIRTIO_BLK_F_SCSI 7 /* Supports scsi command passthru */ -/* #define VIRTIO_BLK_F_IDENTIFY 8 ATA IDENTIFY supported, DEPRECATED */ -#define VIRTIO_BLK_F_WCE 9 /* write cache enabled */ -#define VIRTIO_BLK_F_TOPOLOGY 10 /* Topology information is available */ -#define VIRTIO_BLK_F_CONFIG_WCE 11 /* write cache configurable */ - -#define VIRTIO_BLK_ID_BYTES 20 /* ID string length */ - -struct virtio_blk_config -{ - uint64_t capacity; - uint32_t size_max; - uint32_t seg_max; - uint16_t cylinders; - uint8_t heads; - uint8_t sectors; - uint32_t blk_size; - uint8_t physical_block_exp; - uint8_t alignment_offset; - uint16_t min_io_size; - uint32_t opt_io_size; - uint8_t wce; -} QEMU_PACKED; - -/* These two define direction. */ -#define VIRTIO_BLK_T_IN 0 -#define VIRTIO_BLK_T_OUT 1 - -/* This bit says it's a scsi command, not an actual read or write. */ -#define VIRTIO_BLK_T_SCSI_CMD 2 - -/* Flush the volatile write cache */ -#define VIRTIO_BLK_T_FLUSH 4 - -/* return the device ID string */ -#define VIRTIO_BLK_T_GET_ID 8 - -/* Barrier before this op. */ -#define VIRTIO_BLK_T_BARRIER 0x80000000 - -/* This is the first element of the read scatter-gather list. */ -struct virtio_blk_outhdr -{ - /* VIRTIO_BLK_T* */ - uint32_t type; - /* io priority. */ - uint32_t ioprio; - /* Sector (ie. 512 byte offset) */ - uint64_t sector; -}; - -#define VIRTIO_BLK_S_OK 0 -#define VIRTIO_BLK_S_IOERR 1 -#define VIRTIO_BLK_S_UNSUPP 2 - /* This is the last element of the write scatter-gather list */ struct virtio_blk_inhdr { unsigned char status; }; -/* SCSI pass-through header */ -struct virtio_scsi_inhdr -{ - uint32_t errors; - uint32_t data_len; - uint32_t sense_len; - uint32_t residual; -}; - struct VirtIOBlkConf { BlockConf conf; @@ -113,6 +38,7 @@ struct VirtIOBlkConf uint32_t scsi; uint32_t config_wce; uint32_t data_plane; + uint32_t request_merging; }; struct VirtIOBlockDataPlane; @@ -134,30 +60,33 @@ typedef struct VirtIOBlock { struct VirtIOBlockDataPlane *dataplane; } VirtIOBlock; -typedef struct MultiReqBuffer { - BlockRequest blkreq[32]; - unsigned int num_writes; -} MultiReqBuffer; - typedef struct VirtIOBlockReq { + int64_t sector_num; VirtIOBlock *dev; VirtQueueElement elem; struct virtio_blk_inhdr *in; struct virtio_blk_outhdr out; QEMUIOVector qiov; + size_t in_len; struct VirtIOBlockReq *next; + struct VirtIOBlockReq *mr_next; BlockAcctCookie acct; } VirtIOBlockReq; +#define VIRTIO_BLK_MAX_MERGE_REQS 32 + +typedef struct MultiReqBuffer { + VirtIOBlockReq *reqs[VIRTIO_BLK_MAX_MERGE_REQS]; + unsigned int num_reqs; + bool is_write; +} MultiReqBuffer; + VirtIOBlockReq *virtio_blk_alloc_request(VirtIOBlock *s); void virtio_blk_free_request(VirtIOBlockReq *req); -int virtio_blk_handle_scsi_req(VirtIOBlock *blk, - VirtQueueElement *elem); - void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb); -void virtio_submit_multiwrite(BlockBackend *blk, MultiReqBuffer *mrb); +void virtio_blk_submit_multireq(BlockBackend *blk, MultiReqBuffer *mrb); #endif diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h index 0756545d4d..8811415fa6 100644 --- a/include/hw/virtio/virtio-bus.h +++ b/include/hw/virtio/virtio-bus.h @@ -47,7 +47,6 @@ typedef struct VirtioBusClass { int (*load_config)(DeviceState *d, QEMUFile *f); int (*load_queue)(DeviceState *d, int n, QEMUFile *f); int (*load_done)(DeviceState *d, QEMUFile *f); - unsigned (*get_features)(DeviceState *d); bool (*query_guest_notifiers)(DeviceState *d); int (*set_guest_notifiers)(DeviceState *d, int nvqs, bool assign); int (*set_host_notifier)(DeviceState *d, int n, bool assigned); @@ -56,12 +55,13 @@ typedef struct VirtioBusClass { * transport independent init function. * This is called by virtio-bus just after the device is plugged. */ - void (*device_plugged)(DeviceState *d); + void (*device_plugged)(DeviceState *d, Error **errp); /* * transport independent exit function. * This is called by virtio-bus just before the device is unplugged. */ void (*device_unplugged)(DeviceState *d); + int (*query_nvectors)(DeviceState *d); /* * Does the transport have variable vring alignment? * (ie can it ever call virtio_queue_set_align()?) @@ -74,7 +74,7 @@ struct VirtioBusState { BusState parent_obj; }; -int virtio_bus_device_plugged(VirtIODevice *vdev); +void virtio_bus_device_plugged(VirtIODevice *vdev, Error **errp); void virtio_bus_reset(VirtioBusState *bus); void virtio_bus_device_unplugged(VirtIODevice *bus); /* Get the device id of the plugged device. */ @@ -84,9 +84,6 @@ size_t virtio_bus_get_vdev_config_len(VirtioBusState *bus); /* Get the features of the plugged device. */ uint32_t virtio_bus_get_vdev_features(VirtioBusState *bus, uint32_t requested_features); -/* Set the features of the plugged device. */ -void virtio_bus_set_vdev_features(VirtioBusState *bus, - uint32_t requested_features); /* Get bad features of the plugged device. */ uint32_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus); /* Get config of the plugged device. */ diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h new file mode 100644 index 0000000000..889676147a --- /dev/null +++ b/include/hw/virtio/virtio-gpu.h @@ -0,0 +1,142 @@ +/* + * Virtio GPU Device + * + * Copyright Red Hat, Inc. 2013-2014 + * + * Authors: + * Dave Airlie <airlied@redhat.com> + * Gerd Hoffmann <kraxel@redhat.com> + * + * This work is licensed under the terms of the GNU GPL, version 2. + * See the COPYING file in the top-level directory. + */ + +#ifndef _QEMU_VIRTIO_VGA_H +#define _QEMU_VIRTIO_VGA_H + +#include "qemu/queue.h" +#include "ui/qemu-pixman.h" +#include "ui/console.h" +#include "hw/virtio/virtio.h" +#include "hw/pci/pci.h" + +#include "standard-headers/linux/virtio_gpu.h" +#define TYPE_VIRTIO_GPU "virtio-gpu-device" +#define VIRTIO_GPU(obj) \ + OBJECT_CHECK(VirtIOGPU, (obj), TYPE_VIRTIO_GPU) + +#define VIRTIO_ID_GPU 16 + +#define VIRTIO_GPU_MAX_SCANOUT 4 + +struct virtio_gpu_simple_resource { + uint32_t resource_id; + uint32_t width; + uint32_t height; + uint32_t format; + struct iovec *iov; + unsigned int iov_cnt; + uint32_t scanout_bitmask; + pixman_image_t *image; + QTAILQ_ENTRY(virtio_gpu_simple_resource) next; +}; + +struct virtio_gpu_scanout { + QemuConsole *con; + DisplaySurface *ds; + uint32_t width, height; + int x, y; + int invalidate; + uint32_t resource_id; + QEMUCursor *current_cursor; +}; + +struct virtio_gpu_requested_state { + uint32_t width, height; + int x, y; +}; + +struct virtio_gpu_conf { + uint32_t max_outputs; +}; + +struct virtio_gpu_ctrl_command { + VirtQueueElement elem; + VirtQueue *vq; + struct virtio_gpu_ctrl_hdr cmd_hdr; + uint32_t error; + bool finished; + QTAILQ_ENTRY(virtio_gpu_ctrl_command) next; +}; + +typedef struct VirtIOGPU { + VirtIODevice parent_obj; + + QEMUBH *ctrl_bh; + QEMUBH *cursor_bh; + VirtQueue *ctrl_vq; + VirtQueue *cursor_vq; + + int enable; + + int config_size; + DeviceState *qdev; + + QTAILQ_HEAD(, virtio_gpu_simple_resource) reslist; + QTAILQ_HEAD(, virtio_gpu_ctrl_command) fenceq; + + struct virtio_gpu_scanout scanout[VIRTIO_GPU_MAX_SCANOUT]; + struct virtio_gpu_requested_state req_state[VIRTIO_GPU_MAX_SCANOUT]; + + struct virtio_gpu_conf conf; + int enabled_output_bitmask; + struct virtio_gpu_config virtio_config; + + QEMUTimer *fence_poll; + QEMUTimer *print_stats; + + struct { + uint32_t inflight; + uint32_t max_inflight; + uint32_t requests; + uint32_t req_3d; + uint32_t bytes_3d; + } stats; +} VirtIOGPU; + +extern const GraphicHwOps virtio_gpu_ops; + +/* to share between PCI and VGA */ +#define DEFINE_VIRTIO_GPU_PCI_PROPERTIES(_state) \ + DEFINE_PROP_BIT("ioeventfd", _state, flags, \ + VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false), \ + DEFINE_PROP_UINT32("vectors", _state, nvectors, 3) + +#define VIRTIO_GPU_FILL_CMD(out) do { \ + size_t s; \ + s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num, 0, \ + &out, sizeof(out)); \ + if (s != sizeof(out)) { \ + qemu_log_mask(LOG_GUEST_ERROR, \ + "%s: command size incorrect %zu vs %zu\n", \ + __func__, s, sizeof(out)); \ + return; \ + } \ + } while (0) + +/* virtio-gpu.c */ +void virtio_gpu_ctrl_response(VirtIOGPU *g, + struct virtio_gpu_ctrl_command *cmd, + struct virtio_gpu_ctrl_hdr *resp, + size_t resp_len); +void virtio_gpu_ctrl_response_nodata(VirtIOGPU *g, + struct virtio_gpu_ctrl_command *cmd, + enum virtio_gpu_ctrl_type type); +void virtio_gpu_get_display_info(VirtIOGPU *g, + struct virtio_gpu_ctrl_command *cmd); +int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab, + struct virtio_gpu_ctrl_command *cmd, + struct iovec **iov); +void virtio_gpu_cleanup_mapping_iov(struct iovec *iov, uint32_t count); + +#endif diff --git a/include/hw/virtio/virtio-input.h b/include/hw/virtio/virtio-input.h new file mode 100644 index 0000000000..af1c207ab1 --- /dev/null +++ b/include/hw/virtio/virtio-input.h @@ -0,0 +1,119 @@ +#ifndef _QEMU_VIRTIO_INPUT_H +#define _QEMU_VIRTIO_INPUT_H + +#include "ui/input.h" + +/* ----------------------------------------------------------------- */ +/* virtio input protocol */ + +#include "standard-headers/linux/virtio_ids.h" +#include "standard-headers/linux/virtio_input.h" + +typedef struct virtio_input_absinfo virtio_input_absinfo; +typedef struct virtio_input_config virtio_input_config; +typedef struct virtio_input_event virtio_input_event; + +#if defined(HOST_WORDS_BIGENDIAN) +# define const_le32(_x) \ + (((_x & 0x000000ffU) << 24) | \ + ((_x & 0x0000ff00U) << 8) | \ + ((_x & 0x00ff0000U) >> 8) | \ + ((_x & 0xff000000U) >> 24)) +# define const_le16(_x) \ + (((_x & 0x00ff) << 8) | \ + ((_x & 0xff00) >> 8)) +#else +# define const_le32(_x) (_x) +# define const_le16(_x) (_x) +#endif + +/* ----------------------------------------------------------------- */ +/* qemu internals */ + +#define TYPE_VIRTIO_INPUT "virtio-input-device" +#define VIRTIO_INPUT(obj) \ + OBJECT_CHECK(VirtIOInput, (obj), TYPE_VIRTIO_INPUT) +#define VIRTIO_INPUT_GET_PARENT_CLASS(obj) \ + OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_INPUT) +#define VIRTIO_INPUT_GET_CLASS(obj) \ + OBJECT_GET_CLASS(VirtIOInputClass, obj, TYPE_VIRTIO_INPUT) +#define VIRTIO_INPUT_CLASS(klass) \ + OBJECT_CLASS_CHECK(VirtIOInputClass, klass, TYPE_VIRTIO_INPUT) + +#define TYPE_VIRTIO_INPUT_HID "virtio-input-hid-device" +#define TYPE_VIRTIO_KEYBOARD "virtio-keyboard-device" +#define TYPE_VIRTIO_MOUSE "virtio-mouse-device" +#define TYPE_VIRTIO_TABLET "virtio-tablet-device" + +#define VIRTIO_INPUT_HID(obj) \ + OBJECT_CHECK(VirtIOInputHID, (obj), TYPE_VIRTIO_INPUT_HID) +#define VIRTIO_INPUT_HID_GET_PARENT_CLASS(obj) \ + OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_INPUT_HID) + +#define TYPE_VIRTIO_INPUT_HOST "virtio-input-host-device" +#define VIRTIO_INPUT_HOST(obj) \ + OBJECT_CHECK(VirtIOInputHost, (obj), TYPE_VIRTIO_INPUT_HOST) +#define VIRTIO_INPUT_HOST_GET_PARENT_CLASS(obj) \ + OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_INPUT_HOST) + +typedef struct VirtIOInput VirtIOInput; +typedef struct VirtIOInputClass VirtIOInputClass; +typedef struct VirtIOInputConfig VirtIOInputConfig; +typedef struct VirtIOInputHID VirtIOInputHID; +typedef struct VirtIOInputHost VirtIOInputHost; + +struct VirtIOInputConfig { + virtio_input_config config; + QTAILQ_ENTRY(VirtIOInputConfig) node; +}; + +struct VirtIOInput { + VirtIODevice parent_obj; + uint8_t cfg_select; + uint8_t cfg_subsel; + uint32_t cfg_size; + QTAILQ_HEAD(, VirtIOInputConfig) cfg_list; + VirtQueue *evt, *sts; + char *serial; + + virtio_input_event *queue; + uint32_t qindex, qsize; + + bool active; +}; + +struct VirtIOInputClass { + /*< private >*/ + VirtioDeviceClass parent; + /*< public >*/ + + DeviceRealize realize; + DeviceUnrealize unrealize; + void (*change_active)(VirtIOInput *vinput); + void (*handle_status)(VirtIOInput *vinput, virtio_input_event *event); +}; + +struct VirtIOInputHID { + VirtIOInput parent_obj; + char *display; + uint32_t head; + QemuInputHandler *handler; + QemuInputHandlerState *hs; + int ledstate; +}; + +struct VirtIOInputHost { + VirtIOInput parent_obj; + char *evdev; + int fd; +}; + +void virtio_input_send(VirtIOInput *vinput, virtio_input_event *event); +void virtio_input_init_config(VirtIOInput *vinput, + virtio_input_config *config); +void virtio_input_add_config(VirtIOInput *vinput, + virtio_input_config *config); +void virtio_input_idstr_config(VirtIOInput *vinput, + uint8_t select, const char *string); + +#endif /* _QEMU_VIRTIO_INPUT_H */ diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h index 6ceb5aa92e..60b11d5c2c 100644 --- a/include/hw/virtio/virtio-net.h +++ b/include/hw/virtio/virtio-net.h @@ -14,50 +14,13 @@ #ifndef _QEMU_VIRTIO_NET_H #define _QEMU_VIRTIO_NET_H +#include "standard-headers/linux/virtio_net.h" #include "hw/virtio/virtio.h" -#include "hw/pci/pci.h" #define TYPE_VIRTIO_NET "virtio-net-device" #define VIRTIO_NET(obj) \ OBJECT_CHECK(VirtIONet, (obj), TYPE_VIRTIO_NET) -#define ETH_ALEN 6 - -/* from Linux's virtio_net.h */ - -/* The ID for virtio_net */ -#define VIRTIO_ID_NET 1 - -/* The feature bitmap for virtio net */ -#define VIRTIO_NET_F_CSUM 0 /* Host handles pkts w/ partial csum */ -#define VIRTIO_NET_F_GUEST_CSUM 1 /* Guest handles pkts w/ partial csum */ -#define VIRTIO_NET_F_CTRL_GUEST_OFFLOADS 2 /* Control channel offload - * configuration support */ -#define VIRTIO_NET_F_MAC 5 /* Host has given MAC address. */ -#define VIRTIO_NET_F_GSO 6 /* Host handles pkts w/ any GSO type */ -#define VIRTIO_NET_F_GUEST_TSO4 7 /* Guest can handle TSOv4 in. */ -#define VIRTIO_NET_F_GUEST_TSO6 8 /* Guest can handle TSOv6 in. */ -#define VIRTIO_NET_F_GUEST_ECN 9 /* Guest can handle TSO[6] w/ ECN in. */ -#define VIRTIO_NET_F_GUEST_UFO 10 /* Guest can handle UFO in. */ -#define VIRTIO_NET_F_HOST_TSO4 11 /* Host can handle TSOv4 in. */ -#define VIRTIO_NET_F_HOST_TSO6 12 /* Host can handle TSOv6 in. */ -#define VIRTIO_NET_F_HOST_ECN 13 /* Host can handle TSO[6] w/ ECN in. */ -#define VIRTIO_NET_F_HOST_UFO 14 /* Host can handle UFO in. */ -#define VIRTIO_NET_F_MRG_RXBUF 15 /* Host can merge receive buffers. */ -#define VIRTIO_NET_F_STATUS 16 /* virtio_net_config.status available */ -#define VIRTIO_NET_F_CTRL_VQ 17 /* Control channel available */ -#define VIRTIO_NET_F_CTRL_RX 18 /* Control channel RX mode support */ -#define VIRTIO_NET_F_CTRL_VLAN 19 /* Control channel VLAN filtering */ -#define VIRTIO_NET_F_CTRL_RX_EXTRA 20 /* Extra RX mode control support */ -#define VIRTIO_NET_F_GUEST_ANNOUNCE 21 /* Guest can announce itself */ -#define VIRTIO_NET_F_MQ 22 /* Device supports Receive Flow - * Steering */ - -#define VIRTIO_NET_F_CTRL_MAC_ADDR 23 /* Set MAC address */ - -#define VIRTIO_NET_S_LINK_UP 1 /* Link is up */ -#define VIRTIO_NET_S_ANNOUNCE 2 /* Announcement is needed */ - #define TX_TIMER_INTERVAL 150000 /* 150 us */ /* Limit the number of packets that can be sent via a single flush @@ -77,72 +40,6 @@ typedef struct virtio_net_conf /* Maximum packet size we can receive from tap device: header + 64k */ #define VIRTIO_NET_MAX_BUFSIZE (sizeof(struct virtio_net_hdr) + (64 << 10)) -struct virtio_net_config -{ - /* The config defining mac address ($ETH_ALEN bytes) */ - uint8_t mac[ETH_ALEN]; - /* See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above */ - uint16_t status; - /* Max virtqueue pairs supported by the device */ - uint16_t max_virtqueue_pairs; -} QEMU_PACKED; - -/* - * Control virtqueue data structures - * - * The control virtqueue expects a header in the first sg entry - * and an ack/status response in the last entry. Data for the - * command goes in between. - */ -struct virtio_net_ctrl_hdr { - uint8_t class; - uint8_t cmd; -}; - -typedef uint8_t virtio_net_ctrl_ack; - -#define VIRTIO_NET_OK 0 -#define VIRTIO_NET_ERR 1 - -/* - * Control the RX mode, ie. promisucous, allmulti, etc... - * All commands require an "out" sg entry containing a 1 byte - * state value, zero = disable, non-zero = enable. Commands - * 0 and 1 are supported with the VIRTIO_NET_F_CTRL_RX feature. - * Commands 2-5 are added with VIRTIO_NET_F_CTRL_RX_EXTRA. - */ -#define VIRTIO_NET_CTRL_RX 0 - #define VIRTIO_NET_CTRL_RX_PROMISC 0 - #define VIRTIO_NET_CTRL_RX_ALLMULTI 1 - #define VIRTIO_NET_CTRL_RX_ALLUNI 2 - #define VIRTIO_NET_CTRL_RX_NOMULTI 3 - #define VIRTIO_NET_CTRL_RX_NOUNI 4 - #define VIRTIO_NET_CTRL_RX_NOBCAST 5 - -/* - * Control the MAC - * - * The MAC filter table is managed by the hypervisor, the guest should - * assume the size is infinite. Filtering should be considered - * non-perfect, ie. based on hypervisor resources, the guest may - * received packets from sources not specified in the filter list. - * - * In addition to the class/cmd header, the TABLE_SET command requires - * two out scatterlists. Each contains a 4 byte count of entries followed - * by a concatenated byte stream of the ETH_ALEN MAC addresses. The - * first sg list contains unicast addresses, the second is for multicast. - * This functionality is present if the VIRTIO_NET_F_CTRL_RX feature - * is available. - * - * The ADDR_SET command requests one out scatterlist, it contains a - * 6 bytes MAC address. This functionality is present if the - * VIRTIO_NET_F_CTRL_MAC_ADDR feature is available. - */ -struct virtio_net_ctrl_mac { - uint32_t entries; - uint8_t macs[][ETH_ALEN]; -}; - typedef struct VirtIONetQueue { VirtQueue *rx_vq; VirtQueue *tx_vq; @@ -168,6 +65,7 @@ typedef struct VirtIONet { uint32_t has_vnet_hdr; size_t host_hdr_len; size_t guest_hdr_len; + uint32_t host_features; uint8_t has_ufo; int mergeable_rx_bufs; uint8_t promisc; @@ -199,94 +97,6 @@ typedef struct VirtIONet { int announce_counter; } VirtIONet; -#define VIRTIO_NET_CTRL_MAC 1 - #define VIRTIO_NET_CTRL_MAC_TABLE_SET 0 - #define VIRTIO_NET_CTRL_MAC_ADDR_SET 1 - -/* - * Control VLAN filtering - * - * The VLAN filter table is controlled via a simple ADD/DEL interface. - * VLAN IDs not added may be filterd by the hypervisor. Del is the - * opposite of add. Both commands expect an out entry containing a 2 - * byte VLAN ID. VLAN filterting is available with the - * VIRTIO_NET_F_CTRL_VLAN feature bit. - */ -#define VIRTIO_NET_CTRL_VLAN 2 - #define VIRTIO_NET_CTRL_VLAN_ADD 0 - #define VIRTIO_NET_CTRL_VLAN_DEL 1 - -/* - * Control link announce acknowledgement - * - * VIRTIO_NET_S_ANNOUNCE bit in the status field requests link announcement from - * guest driver. The driver is notified by config space change interrupt. The - * command VIRTIO_NET_CTRL_ANNOUNCE_ACK is used to indicate that the driver has - * received the notification. It makes the device clear the bit - * VIRTIO_NET_S_ANNOUNCE in the status field. - */ -#define VIRTIO_NET_CTRL_ANNOUNCE 3 - #define VIRTIO_NET_CTRL_ANNOUNCE_ACK 0 - -/* - * Control Multiqueue - * - * The command VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET - * enables multiqueue, specifying the number of the transmit and - * receive queues that will be used. After the command is consumed and acked by - * the device, the device will not steer new packets on receive virtqueues - * other than specified nor read from transmit virtqueues other than specified. - * Accordingly, driver should not transmit new packets on virtqueues other than - * specified. - */ -struct virtio_net_ctrl_mq { - uint16_t virtqueue_pairs; -}; - -#define VIRTIO_NET_CTRL_MQ 4 - #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET 0 - #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN 1 - #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX 0x8000 - -/* - * Control network offloads - * - * Dynamic offloads are available with the - * VIRTIO_NET_F_CTRL_GUEST_OFFLOADS feature bit. - */ -#define VIRTIO_NET_CTRL_GUEST_OFFLOADS 5 - #define VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET 0 - -#define DEFINE_VIRTIO_NET_FEATURES(_state, _field) \ - DEFINE_PROP_BIT("any_layout", _state, _field, VIRTIO_F_ANY_LAYOUT, true), \ - DEFINE_PROP_BIT("csum", _state, _field, VIRTIO_NET_F_CSUM, true), \ - DEFINE_PROP_BIT("guest_csum", _state, _field, VIRTIO_NET_F_GUEST_CSUM, true), \ - DEFINE_PROP_BIT("gso", _state, _field, VIRTIO_NET_F_GSO, true), \ - DEFINE_PROP_BIT("guest_tso4", _state, _field, VIRTIO_NET_F_GUEST_TSO4, true), \ - DEFINE_PROP_BIT("guest_tso6", _state, _field, VIRTIO_NET_F_GUEST_TSO6, true), \ - DEFINE_PROP_BIT("guest_ecn", _state, _field, VIRTIO_NET_F_GUEST_ECN, true), \ - DEFINE_PROP_BIT("guest_ufo", _state, _field, VIRTIO_NET_F_GUEST_UFO, true), \ - DEFINE_PROP_BIT("guest_announce", _state, _field, VIRTIO_NET_F_GUEST_ANNOUNCE, true), \ - DEFINE_PROP_BIT("host_tso4", _state, _field, VIRTIO_NET_F_HOST_TSO4, true), \ - DEFINE_PROP_BIT("host_tso6", _state, _field, VIRTIO_NET_F_HOST_TSO6, true), \ - DEFINE_PROP_BIT("host_ecn", _state, _field, VIRTIO_NET_F_HOST_ECN, true), \ - DEFINE_PROP_BIT("host_ufo", _state, _field, VIRTIO_NET_F_HOST_UFO, true), \ - DEFINE_PROP_BIT("mrg_rxbuf", _state, _field, VIRTIO_NET_F_MRG_RXBUF, true), \ - DEFINE_PROP_BIT("status", _state, _field, VIRTIO_NET_F_STATUS, true), \ - DEFINE_PROP_BIT("ctrl_vq", _state, _field, VIRTIO_NET_F_CTRL_VQ, true), \ - DEFINE_PROP_BIT("ctrl_rx", _state, _field, VIRTIO_NET_F_CTRL_RX, true), \ - DEFINE_PROP_BIT("ctrl_vlan", _state, _field, VIRTIO_NET_F_CTRL_VLAN, true), \ - DEFINE_PROP_BIT("ctrl_rx_extra", _state, _field, VIRTIO_NET_F_CTRL_RX_EXTRA, true), \ - DEFINE_PROP_BIT("ctrl_mac_addr", _state, _field, VIRTIO_NET_F_CTRL_MAC_ADDR, true), \ - DEFINE_PROP_BIT("ctrl_guest_offloads", _state, _field, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, true), \ - DEFINE_PROP_BIT("mq", _state, _field, VIRTIO_NET_F_MQ, false) - -#define DEFINE_VIRTIO_NET_PROPERTIES(_state, _field) \ - DEFINE_PROP_UINT32("x-txtimer", _state, _field.txtimer, TX_TIMER_INTERVAL),\ - DEFINE_PROP_INT32("x-txburst", _state, _field.txburst, TX_BURST), \ - DEFINE_PROP_STRING("tx", _state, _field.tx) - -void virtio_net_set_config_size(VirtIONet *n, uint32_t host_features); void virtio_net_set_netclient_name(VirtIONet *n, const char *name, const char *type); diff --git a/include/hw/virtio/virtio-rng.h b/include/hw/virtio/virtio-rng.h index 14e85a5a3a..3f07de70c7 100644 --- a/include/hw/virtio/virtio-rng.h +++ b/include/hw/virtio/virtio-rng.h @@ -14,6 +14,7 @@ #include "sysemu/rng.h" #include "sysemu/rng-random.h" +#include "standard-headers/linux/virtio_rng.h" #define TYPE_VIRTIO_RNG "virtio-rng-device" #define VIRTIO_RNG(obj) \ @@ -21,9 +22,6 @@ #define VIRTIO_RNG_GET_PARENT_CLASS(obj) \ OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_RNG) -/* The Virtio ID for the virtio rng device */ -#define VIRTIO_ID_RNG 4 - struct VirtIORNGConf { RngBackend *rng; uint64_t max_bytes; @@ -46,16 +44,7 @@ typedef struct VirtIORNG { */ QEMUTimer *rate_limit_timer; int64_t quota_remaining; + bool activate_timer; } VirtIORNG; -/* Set a default rate limit of 2^47 bytes per minute or roughly 2TB/s. If - you have an entropy source capable of generating more entropy than this - and you can pass it through via virtio-rng, then hats off to you. Until - then, this is unlimited for all practical purposes. -*/ -#define DEFINE_VIRTIO_RNG_PROPERTIES(_state, _conf_field) \ - DEFINE_PROP_UINT64("max-bytes", _state, _conf_field.max_bytes, \ - INT64_MAX), \ - DEFINE_PROP_UINT32("period", _state, _conf_field.period_ms, 1 << 16) - #endif diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h index bf17cc9ea5..088fe9f4b9 100644 --- a/include/hw/virtio/virtio-scsi.h +++ b/include/hw/virtio/virtio-scsi.h @@ -14,6 +14,10 @@ #ifndef _QEMU_VIRTIO_SCSI_H #define _QEMU_VIRTIO_SCSI_H +/* Override CDB/sense data size: they are dynamic (guest controlled) in QEMU */ +#define VIRTIO_SCSI_CDB_SIZE 0 +#define VIRTIO_SCSI_SENSE_SIZE 0 +#include "standard-headers/linux/virtio_scsi.h" #include "hw/virtio/virtio.h" #include "hw/pci/pci.h" #include "hw/scsi/scsi.h" @@ -28,124 +32,19 @@ #define VIRTIO_SCSI(obj) \ OBJECT_CHECK(VirtIOSCSI, (obj), TYPE_VIRTIO_SCSI) - -/* The ID for virtio_scsi */ -#define VIRTIO_ID_SCSI 8 - -/* Feature Bits */ -#define VIRTIO_SCSI_F_INOUT 0 -#define VIRTIO_SCSI_F_HOTPLUG 1 -#define VIRTIO_SCSI_F_CHANGE 2 - #define VIRTIO_SCSI_VQ_SIZE 128 -#define VIRTIO_SCSI_CDB_SIZE 32 -#define VIRTIO_SCSI_SENSE_SIZE 96 #define VIRTIO_SCSI_MAX_CHANNEL 0 #define VIRTIO_SCSI_MAX_TARGET 255 #define VIRTIO_SCSI_MAX_LUN 16383 -/* Response codes */ -#define VIRTIO_SCSI_S_OK 0 -#define VIRTIO_SCSI_S_OVERRUN 1 -#define VIRTIO_SCSI_S_ABORTED 2 -#define VIRTIO_SCSI_S_BAD_TARGET 3 -#define VIRTIO_SCSI_S_RESET 4 -#define VIRTIO_SCSI_S_BUSY 5 -#define VIRTIO_SCSI_S_TRANSPORT_FAILURE 6 -#define VIRTIO_SCSI_S_TARGET_FAILURE 7 -#define VIRTIO_SCSI_S_NEXUS_FAILURE 8 -#define VIRTIO_SCSI_S_FAILURE 9 -#define VIRTIO_SCSI_S_FUNCTION_SUCCEEDED 10 -#define VIRTIO_SCSI_S_FUNCTION_REJECTED 11 -#define VIRTIO_SCSI_S_INCORRECT_LUN 12 - -/* Controlq type codes. */ -#define VIRTIO_SCSI_T_TMF 0 -#define VIRTIO_SCSI_T_AN_QUERY 1 -#define VIRTIO_SCSI_T_AN_SUBSCRIBE 2 - -/* Valid TMF subtypes. */ -#define VIRTIO_SCSI_T_TMF_ABORT_TASK 0 -#define VIRTIO_SCSI_T_TMF_ABORT_TASK_SET 1 -#define VIRTIO_SCSI_T_TMF_CLEAR_ACA 2 -#define VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET 3 -#define VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET 4 -#define VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET 5 -#define VIRTIO_SCSI_T_TMF_QUERY_TASK 6 -#define VIRTIO_SCSI_T_TMF_QUERY_TASK_SET 7 - -/* Events. */ -#define VIRTIO_SCSI_T_EVENTS_MISSED 0x80000000 -#define VIRTIO_SCSI_T_NO_EVENT 0 -#define VIRTIO_SCSI_T_TRANSPORT_RESET 1 -#define VIRTIO_SCSI_T_ASYNC_NOTIFY 2 -#define VIRTIO_SCSI_T_PARAM_CHANGE 3 - -/* Reasons for transport reset event */ -#define VIRTIO_SCSI_EVT_RESET_HARD 0 -#define VIRTIO_SCSI_EVT_RESET_RESCAN 1 -#define VIRTIO_SCSI_EVT_RESET_REMOVED 2 - -/* SCSI command request, followed by CDB and data-out */ -typedef struct { - uint8_t lun[8]; /* Logical Unit Number */ - uint64_t tag; /* Command identifier */ - uint8_t task_attr; /* Task attribute */ - uint8_t prio; - uint8_t crn; -} QEMU_PACKED VirtIOSCSICmdReq; - -/* Response, followed by sense data and data-in */ -typedef struct { - uint32_t sense_len; /* Sense data length */ - uint32_t resid; /* Residual bytes in data buffer */ - uint16_t status_qualifier; /* Status qualifier */ - uint8_t status; /* Command completion status */ - uint8_t response; /* Response values */ -} QEMU_PACKED VirtIOSCSICmdResp; - -/* Task Management Request */ -typedef struct { - uint32_t type; - uint32_t subtype; - uint8_t lun[8]; - uint64_t tag; -} QEMU_PACKED VirtIOSCSICtrlTMFReq; - -typedef struct { - uint8_t response; -} QEMU_PACKED VirtIOSCSICtrlTMFResp; - -/* Asynchronous notification query/subscription */ -typedef struct { - uint32_t type; - uint8_t lun[8]; - uint32_t event_requested; -} QEMU_PACKED VirtIOSCSICtrlANReq; - -typedef struct { - uint32_t event_actual; - uint8_t response; -} QEMU_PACKED VirtIOSCSICtrlANResp; - -typedef struct { - uint32_t event; - uint8_t lun[8]; - uint32_t reason; -} QEMU_PACKED VirtIOSCSIEvent; - -typedef struct { - uint32_t num_queues; - uint32_t seg_max; - uint32_t max_sectors; - uint32_t cmd_per_lun; - uint32_t event_info_size; - uint32_t sense_size; - uint32_t cdb_size; - uint16_t max_channel; - uint16_t max_target; - uint32_t max_lun; -} QEMU_PACKED VirtIOSCSIConfig; +typedef struct virtio_scsi_cmd_req VirtIOSCSICmdReq; +typedef struct virtio_scsi_cmd_resp VirtIOSCSICmdResp; +typedef struct virtio_scsi_ctrl_tmf_req VirtIOSCSICtrlTMFReq; +typedef struct virtio_scsi_ctrl_tmf_resp VirtIOSCSICtrlTMFResp; +typedef struct virtio_scsi_ctrl_an_req VirtIOSCSICtrlANReq; +typedef struct virtio_scsi_ctrl_an_resp VirtIOSCSICtrlANResp; +typedef struct virtio_scsi_event VirtIOSCSIEvent; +typedef struct virtio_scsi_config VirtIOSCSIConfig; struct VirtIOSCSIConf { uint32_t num_queues; @@ -153,6 +52,7 @@ struct VirtIOSCSIConf { uint32_t cmd_per_lun; char *vhostfd; char *wwpn; + uint32_t boot_tpgt; IOThread *iothread; }; @@ -198,6 +98,7 @@ typedef struct VirtIOSCSI { bool dataplane_fenced; Error *blocker; Notifier migration_state_notifier; + uint32_t host_features; } VirtIOSCSI; typedef struct VirtIOSCSIReq { @@ -209,8 +110,7 @@ typedef struct VirtIOSCSIReq { /* 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. + * - fields after elem are zeroed by virtio_scsi_init_req. * */ VirtQueueElement elem; @@ -235,31 +135,12 @@ typedef struct VirtIOSCSIReq { VirtIOSCSIEvent event; } resp; union { - struct { - VirtIOSCSICmdReq cmd; - uint8_t cdb[]; - } QEMU_PACKED; + VirtIOSCSICmdReq cmd; 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),\ - DEFINE_PROP_UINT32("cmd_per_lun", _state, _conf_field.cmd_per_lun, 128) - -#define DEFINE_VIRTIO_SCSI_FEATURES(_state, _feature_field) \ - DEFINE_PROP_BIT("any_layout", _state, _feature_field, \ - VIRTIO_F_ANY_LAYOUT, true), \ - DEFINE_PROP_BIT("hotplug", _state, _feature_field, VIRTIO_SCSI_F_HOTPLUG, \ - true), \ - DEFINE_PROP_BIT("param_change", _state, _feature_field, \ - VIRTIO_SCSI_F_CHANGE, true) - typedef void (*HandleOutput)(VirtIODevice *, VirtQueue *); void virtio_scsi_common_realize(DeviceState *dev, Error **errp, diff --git a/include/hw/virtio/virtio-serial.h b/include/hw/virtio/virtio-serial.h index a679e54aab..527d0bf624 100644 --- a/include/hw/virtio/virtio-serial.h +++ b/include/hw/virtio/virtio-serial.h @@ -15,53 +15,15 @@ #ifndef _QEMU_VIRTIO_SERIAL_H #define _QEMU_VIRTIO_SERIAL_H +#include "standard-headers/linux/virtio_console.h" #include "hw/qdev.h" #include "hw/virtio/virtio.h" -/* == Interface shared between the guest kernel and qemu == */ - -/* The Virtio ID for virtio console / serial ports */ -#define VIRTIO_ID_CONSOLE 3 - -/* Features supported */ -#define VIRTIO_CONSOLE_F_MULTIPORT 1 - -#define VIRTIO_CONSOLE_BAD_ID (~(uint32_t)0) - -struct virtio_console_config { - /* - * These two fields are used by VIRTIO_CONSOLE_F_SIZE which - * isn't implemented here yet - */ - uint16_t cols; - uint16_t rows; - - uint32_t max_nr_ports; -} QEMU_PACKED; - -struct virtio_console_control { - uint32_t id; /* Port number */ - uint16_t event; /* The kind of control event (see below) */ - uint16_t value; /* Extra information for the key */ -}; - struct virtio_serial_conf { /* Max. number of ports we can have for a virtio-serial device */ uint32_t max_virtserial_ports; }; -/* Some events for the internal messages (control packets) */ -#define VIRTIO_CONSOLE_DEVICE_READY 0 -#define VIRTIO_CONSOLE_PORT_ADD 1 -#define VIRTIO_CONSOLE_PORT_REMOVE 2 -#define VIRTIO_CONSOLE_PORT_READY 3 -#define VIRTIO_CONSOLE_CONSOLE_PORT 4 -#define VIRTIO_CONSOLE_RESIZE 5 -#define VIRTIO_CONSOLE_PORT_OPEN 6 -#define VIRTIO_CONSOLE_PORT_NAME 7 - -/* == In-qemu interface == */ - #define TYPE_VIRTIO_SERIAL_PORT "virtio-serial-port" #define VIRTIO_SERIAL_PORT(obj) \ OBJECT_CHECK(VirtIOSerialPort, (obj), TYPE_VIRTIO_SERIAL_PORT) @@ -98,6 +60,17 @@ typedef struct VirtIOSerialPortClass { /* Guest is now ready to accept data (virtqueues set up). */ void (*guest_ready)(VirtIOSerialPort *port); + /* + * Guest has enqueued a buffer for the host to write into. + * Called each time a buffer is enqueued by the guest; + * irrespective of whether there already were free buffers the + * host could have consumed. + * + * This is dependent on both the guest and host end being + * connected. + */ + void (*guest_writable)(VirtIOSerialPort *port); + /* * Guest wrote some data to the port. This data is handed over to * the app via this callback. The app can return a size less than @@ -207,8 +180,6 @@ struct VirtIOSerial { /* bitmap for identifying active ports */ uint32_t *ports_map; - struct virtio_console_config config; - struct VirtIOSerialPostLoad *post_load; virtio_serial_conf serial; @@ -250,7 +221,4 @@ void virtio_serial_throttle_port(VirtIOSerialPort *port, bool throttle); #define VIRTIO_SERIAL(obj) \ OBJECT_CHECK(VirtIOSerial, (obj), TYPE_VIRTIO_SERIAL) -#define DEFINE_VIRTIO_SERIAL_PROPERTIES(_state, _field) \ - DEFINE_PROP_UINT32("max_ports", _state, _field.max_virtserial_ports, 31) - #endif diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 0726d76f49..cccae89d83 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -19,55 +19,15 @@ #include "hw/qdev.h" #include "sysemu/sysemu.h" #include "qemu/event_notifier.h" -#ifdef CONFIG_VIRTFS -#include "hw/virtio/virtio-9p.h" -#endif +#include "standard-headers/linux/virtio_config.h" +#include "standard-headers/linux/virtio_ring.h" -/* from Linux's linux/virtio_config.h */ - -/* Status byte for guest to report progress, and synchronize features. */ -/* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */ -#define VIRTIO_CONFIG_S_ACKNOWLEDGE 1 -/* We have found a driver for the device. */ -#define VIRTIO_CONFIG_S_DRIVER 2 -/* Driver has used its parts of the config, and is happy */ -#define VIRTIO_CONFIG_S_DRIVER_OK 4 -/* We've given up on this device. */ -#define VIRTIO_CONFIG_S_FAILED 0x80 - -/* Some virtio feature bits (currently bits 28 through 31) are reserved for the - * transport being used (eg. virtio_ring), the rest are per-device feature bits. */ -#define VIRTIO_TRANSPORT_F_START 28 -#define VIRTIO_TRANSPORT_F_END 32 - -/* We notify when the ring is completely used, even if the guest is suppressing - * callbacks */ -#define VIRTIO_F_NOTIFY_ON_EMPTY 24 -/* Can the device handle any descriptor layout? */ -#define VIRTIO_F_ANY_LAYOUT 27 -/* 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 /* A guest should never accept this. It implies negotiation is broken. */ #define VIRTIO_F_BAD_FEATURE 30 -/* from Linux's linux/virtio_ring.h */ - -/* 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 - -/* This means don't notify other side when buffer added. */ -#define VRING_USED_F_NO_NOTIFY 1 -/* This means don't interrupt guest when buffer consumed. */ -#define VRING_AVAIL_F_NO_INTERRUPT 1 +#define VIRTIO_LEGACY_FEATURES ((0x1ULL << VIRTIO_F_BAD_FEATURE) | \ + (0x1ULL << VIRTIO_F_NOTIFY_ON_EMPTY) | \ + (0x1ULL << VIRTIO_F_ANY_LAYOUT)) struct VirtQueue; @@ -92,7 +52,7 @@ typedef struct VirtQueueElement struct iovec out_sg[VIRTQUEUE_MAX_SIZE]; } VirtQueueElement; -#define VIRTIO_PCI_QUEUE_MAX 64 +#define VIRTIO_QUEUE_MAX 1024 #define VIRTIO_NO_VECTOR 0xffff @@ -117,10 +77,12 @@ struct VirtIODevice uint8_t status; uint8_t isr; uint16_t queue_sel; - uint32_t guest_features; + uint64_t guest_features; + uint64_t host_features; size_t config_len; void *config; uint16_t config_vector; + uint32_t generation; int nvectors; VirtQueue *vq; uint16_t device_id; @@ -128,6 +90,7 @@ struct VirtIODevice VMChangeStateEntry *vmstate; char *bus_name; uint8_t device_endian; + QLIST_HEAD(, VirtQueue) *vector_queues; }; typedef struct VirtioDeviceClass { @@ -138,9 +101,12 @@ typedef struct VirtioDeviceClass { /* This is what a VirtioDevice must implement */ DeviceRealize realize; DeviceUnrealize unrealize; - uint32_t (*get_features)(VirtIODevice *vdev, uint32_t requested_features); - uint32_t (*bad_features)(VirtIODevice *vdev); - void (*set_features)(VirtIODevice *vdev, uint32_t val); + uint64_t (*get_features)(VirtIODevice *vdev, + uint64_t requested_features, + Error **errp); + uint64_t (*bad_features)(VirtIODevice *vdev); + void (*set_features)(VirtIODevice *vdev, uint64_t val); + int (*validate_features)(VirtIODevice *vdev); void (*get_config)(VirtIODevice *vdev, uint8_t *config); void (*set_config)(VirtIODevice *vdev, const uint8_t *config); void (*reset)(VirtIODevice *vdev); @@ -214,34 +180,49 @@ uint32_t virtio_config_readl(VirtIODevice *vdev, uint32_t addr); void virtio_config_writeb(VirtIODevice *vdev, uint32_t addr, uint32_t data); void virtio_config_writew(VirtIODevice *vdev, uint32_t addr, uint32_t data); void virtio_config_writel(VirtIODevice *vdev, uint32_t addr, uint32_t data); +uint32_t virtio_config_modern_readb(VirtIODevice *vdev, uint32_t addr); +uint32_t virtio_config_modern_readw(VirtIODevice *vdev, uint32_t addr); +uint32_t virtio_config_modern_readl(VirtIODevice *vdev, uint32_t addr); +void virtio_config_modern_writeb(VirtIODevice *vdev, + uint32_t addr, uint32_t data); +void virtio_config_modern_writew(VirtIODevice *vdev, + uint32_t addr, uint32_t data); +void virtio_config_modern_writel(VirtIODevice *vdev, + uint32_t addr, uint32_t data); void virtio_queue_set_addr(VirtIODevice *vdev, int n, hwaddr addr); hwaddr virtio_queue_get_addr(VirtIODevice *vdev, int n); void virtio_queue_set_num(VirtIODevice *vdev, int n, int num); int virtio_queue_get_num(VirtIODevice *vdev, int n); +int virtio_get_num_queues(VirtIODevice *vdev); +void virtio_queue_set_rings(VirtIODevice *vdev, int n, hwaddr desc, + hwaddr avail, hwaddr used); +void virtio_queue_update_rings(VirtIODevice *vdev, int n); void virtio_queue_set_align(VirtIODevice *vdev, int n, int align); void virtio_queue_notify(VirtIODevice *vdev, int n); uint16_t virtio_queue_vector(VirtIODevice *vdev, int n); void virtio_queue_set_vector(VirtIODevice *vdev, int n, uint16_t vector); -void virtio_set_status(VirtIODevice *vdev, uint8_t val); +int virtio_set_status(VirtIODevice *vdev, uint8_t val); void virtio_reset(void *opaque); void virtio_update_irq(VirtIODevice *vdev); -int virtio_set_features(VirtIODevice *vdev, uint32_t val); +int virtio_set_features(VirtIODevice *vdev, uint64_t val); /* Base devices. */ typedef struct VirtIOBlkConf VirtIOBlkConf; struct virtio_net_conf; -VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf, - struct virtio_net_conf *net, - uint32_t host_features); typedef struct virtio_serial_conf virtio_serial_conf; +typedef struct virtio_input_conf virtio_input_conf; typedef struct VirtIOSCSIConf VirtIOSCSIConf; typedef struct VirtIORNGConf VirtIORNGConf; #define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \ - DEFINE_PROP_BIT("indirect_desc", _state, _field, \ - VIRTIO_RING_F_INDIRECT_DESC, true), \ - DEFINE_PROP_BIT("event_idx", _state, _field, \ - VIRTIO_RING_F_EVENT_IDX, true) + DEFINE_PROP_BIT64("indirect_desc", _state, _field, \ + VIRTIO_RING_F_INDIRECT_DESC, true), \ + DEFINE_PROP_BIT64("event_idx", _state, _field, \ + VIRTIO_RING_F_EVENT_IDX, true), \ + DEFINE_PROP_BIT64("notify_on_empty", _state, _field, \ + VIRTIO_F_NOTIFY_ON_EMPTY, true), \ + DEFINE_PROP_BIT64("any_layout", _state, _field, \ + VIRTIO_F_ANY_LAYOUT, true) hwaddr virtio_queue_get_desc_addr(VirtIODevice *vdev, int n); hwaddr virtio_queue_get_avail_addr(VirtIODevice *vdev, int n); @@ -265,10 +246,45 @@ void virtio_queue_set_host_notifier_fd_handler(VirtQueue *vq, bool assign, bool set_handler); void virtio_queue_notify_vq(VirtQueue *vq); void virtio_irq(VirtQueue *vq); +VirtQueue *virtio_vector_first_queue(VirtIODevice *vdev, uint16_t vector); +VirtQueue *virtio_vector_next_queue(VirtQueue *vq); + +static inline void virtio_add_feature(uint64_t *features, unsigned int fbit) +{ + assert(fbit < 64); + *features |= (1ULL << fbit); +} + +static inline void virtio_clear_feature(uint64_t *features, unsigned int fbit) +{ + assert(fbit < 64); + *features &= ~(1ULL << fbit); +} + +static inline bool __virtio_has_feature(uint64_t features, unsigned int fbit) +{ + assert(fbit < 64); + return !!(features & (1ULL << fbit)); +} + +static inline bool virtio_has_feature(VirtIODevice *vdev, unsigned int fbit) +{ + return __virtio_has_feature(vdev->guest_features, fbit); +} + +static inline bool virtio_host_has_feature(VirtIODevice *vdev, + unsigned int fbit) +{ + return __virtio_has_feature(vdev->host_features, fbit); +} static inline bool virtio_is_big_endian(VirtIODevice *vdev) { - assert(vdev->device_endian != VIRTIO_DEVICE_ENDIAN_UNKNOWN); - return vdev->device_endian == VIRTIO_DEVICE_ENDIAN_BIG; + if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) { + assert(vdev->device_endian != VIRTIO_DEVICE_ENDIAN_UNKNOWN); + return vdev->device_endian == VIRTIO_DEVICE_ENDIAN_BIG; + } + /* Devices conforming to VIRTIO 1.0 or later are always LE. */ + return false; } #endif diff --git a/include/hw/virtio/virtio_ring.h b/include/hw/virtio/virtio_ring.h deleted file mode 100644 index 0b42e6eae5..0000000000 --- a/include/hw/virtio/virtio_ring.h +++ /dev/null @@ -1,167 +0,0 @@ -#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/watchdog/wdt_diag288.h b/include/hw/watchdog/wdt_diag288.h new file mode 100644 index 0000000000..7f3fd450dc --- /dev/null +++ b/include/hw/watchdog/wdt_diag288.h @@ -0,0 +1,36 @@ +#ifndef WDT_DIAG288_H +#define WDT_DIAG288_H + +#include "hw/qdev.h" + +#define TYPE_WDT_DIAG288 "diag288" +#define DIAG288(obj) \ + OBJECT_CHECK(DIAG288State, (obj), TYPE_WDT_DIAG288) +#define DIAG288_CLASS(klass) \ + OBJECT_CLASS_CHECK(DIAG288Class, (klass), TYPE_WDT_DIAG288) +#define DIAG288_GET_CLASS(obj) \ + OBJECT_GET_CLASS(DIAG288Class, (obj), TYPE_WDT_DIAG288) + +#define WDT_DIAG288_INIT 0 +#define WDT_DIAG288_CHANGE 1 +#define WDT_DIAG288_CANCEL 2 + +typedef struct DIAG288State { + /*< private >*/ + DeviceState parent_obj; + QEMUTimer *timer; + bool enabled; + + /*< public >*/ +} DIAG288State; + +typedef struct DIAG288Class { + /*< private >*/ + DeviceClass parent_class; + + /*< public >*/ + int (*handle_timer)(DIAG288State *dev, + uint64_t func, uint64_t timeout); +} DIAG288Class; + +#endif /* WDT_DIAG288_H */ diff --git a/include/hw/xen/xen.h b/include/hw/xen/xen.h index b0ed04caa9..4356af4560 100644 --- a/include/hw/xen/xen.h +++ b/include/hw/xen/xen.h @@ -32,7 +32,6 @@ int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num); void xen_piix3_set_irq(void *opaque, int irq_num, int level); void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len); void xen_hvm_inject_msi(uint64_t addr, uint32_t data); -void xen_cmos_set_s3_resume(void *opaque, int irq, int level); qemu_irq *xen_interrupt_controller_init(void); diff --git a/include/hw/xen/xen_common.h b/include/hw/xen/xen_common.h index 95612a40c1..ed5fd3e1a2 100644 --- a/include/hw/xen/xen_common.h +++ b/include/hw/xen/xen_common.h @@ -16,7 +16,9 @@ #include "hw/hw.h" #include "hw/xen/xen.h" +#include "hw/pci/pci.h" #include "qemu/queue.h" +#include "trace.h" /* * We don't support Xen prior to 3.3.0. @@ -166,17 +168,243 @@ 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) + xen_pfn_t *vmport_regs_pfn) { - return xc_get_hvm_param(xc, dom, HVM_PARAM_VMPORT_REGS_PFN, - vmport_regs_pfn); + int rc; + uint64_t value; + rc = xc_hvm_param_get(xc, dom, HVM_PARAM_VMPORT_REGS_PFN, &value); + if (rc >= 0) { + *vmport_regs_pfn = (xen_pfn_t) value; + } + return rc; } #else static inline int xen_get_vmport_regs_pfn(XenXC xc, domid_t dom, - unsigned long *vmport_regs_pfn) + xen_pfn_t *vmport_regs_pfn) { return -ENOSYS; } #endif +/* Xen before 4.5 */ +#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 450 + +#ifndef HVM_PARAM_BUFIOREQ_EVTCHN +#define HVM_PARAM_BUFIOREQ_EVTCHN 26 +#endif + +#define IOREQ_TYPE_PCI_CONFIG 2 + +typedef uint16_t ioservid_t; + +static inline void xen_map_memory_section(XenXC xc, domid_t dom, + ioservid_t ioservid, + MemoryRegionSection *section) +{ +} + +static inline void xen_unmap_memory_section(XenXC xc, domid_t dom, + ioservid_t ioservid, + MemoryRegionSection *section) +{ +} + +static inline void xen_map_io_section(XenXC xc, domid_t dom, + ioservid_t ioservid, + MemoryRegionSection *section) +{ +} + +static inline void xen_unmap_io_section(XenXC xc, domid_t dom, + ioservid_t ioservid, + MemoryRegionSection *section) +{ +} + +static inline void xen_map_pcidev(XenXC xc, domid_t dom, + ioservid_t ioservid, + PCIDevice *pci_dev) +{ +} + +static inline void xen_unmap_pcidev(XenXC xc, domid_t dom, + ioservid_t ioservid, + PCIDevice *pci_dev) +{ +} + +static inline int xen_create_ioreq_server(XenXC xc, domid_t dom, + ioservid_t *ioservid) +{ + return 0; +} + +static inline void xen_destroy_ioreq_server(XenXC xc, domid_t dom, + ioservid_t ioservid) +{ +} + +static inline int xen_get_ioreq_server_info(XenXC xc, domid_t dom, + ioservid_t ioservid, + xen_pfn_t *ioreq_pfn, + xen_pfn_t *bufioreq_pfn, + evtchn_port_t *bufioreq_evtchn) +{ + unsigned long param; + int rc; + + rc = xc_get_hvm_param(xc, dom, HVM_PARAM_IOREQ_PFN, ¶m); + if (rc < 0) { + fprintf(stderr, "failed to get HVM_PARAM_IOREQ_PFN\n"); + return -1; + } + + *ioreq_pfn = param; + + rc = xc_get_hvm_param(xc, dom, HVM_PARAM_BUFIOREQ_PFN, ¶m); + if (rc < 0) { + fprintf(stderr, "failed to get HVM_PARAM_BUFIOREQ_PFN\n"); + return -1; + } + + *bufioreq_pfn = param; + + rc = xc_get_hvm_param(xc, dom, HVM_PARAM_BUFIOREQ_EVTCHN, + ¶m); + if (rc < 0) { + fprintf(stderr, "failed to get HVM_PARAM_BUFIOREQ_EVTCHN\n"); + return -1; + } + + *bufioreq_evtchn = param; + + return 0; +} + +static inline int xen_set_ioreq_server_state(XenXC xc, domid_t dom, + ioservid_t ioservid, + bool enable) +{ + return 0; +} + +/* Xen 4.5 */ +#else + +static inline void xen_map_memory_section(XenXC xc, domid_t dom, + ioservid_t ioservid, + MemoryRegionSection *section) +{ + hwaddr start_addr = section->offset_within_address_space; + ram_addr_t size = int128_get64(section->size); + hwaddr end_addr = start_addr + size - 1; + + trace_xen_map_mmio_range(ioservid, start_addr, end_addr); + xc_hvm_map_io_range_to_ioreq_server(xc, dom, ioservid, 1, + start_addr, end_addr); +} + +static inline void xen_unmap_memory_section(XenXC xc, domid_t dom, + ioservid_t ioservid, + MemoryRegionSection *section) +{ + hwaddr start_addr = section->offset_within_address_space; + ram_addr_t size = int128_get64(section->size); + hwaddr end_addr = start_addr + size - 1; + + trace_xen_unmap_mmio_range(ioservid, start_addr, end_addr); + xc_hvm_unmap_io_range_from_ioreq_server(xc, dom, ioservid, 1, + start_addr, end_addr); +} + +static inline void xen_map_io_section(XenXC xc, domid_t dom, + ioservid_t ioservid, + MemoryRegionSection *section) +{ + hwaddr start_addr = section->offset_within_address_space; + ram_addr_t size = int128_get64(section->size); + hwaddr end_addr = start_addr + size - 1; + + trace_xen_map_portio_range(ioservid, start_addr, end_addr); + xc_hvm_map_io_range_to_ioreq_server(xc, dom, ioservid, 0, + start_addr, end_addr); +} + +static inline void xen_unmap_io_section(XenXC xc, domid_t dom, + ioservid_t ioservid, + MemoryRegionSection *section) +{ + hwaddr start_addr = section->offset_within_address_space; + ram_addr_t size = int128_get64(section->size); + hwaddr end_addr = start_addr + size - 1; + + trace_xen_unmap_portio_range(ioservid, start_addr, end_addr); + xc_hvm_unmap_io_range_from_ioreq_server(xc, dom, ioservid, 0, + start_addr, end_addr); +} + +static inline void xen_map_pcidev(XenXC xc, domid_t dom, + ioservid_t ioservid, + PCIDevice *pci_dev) +{ + trace_xen_map_pcidev(ioservid, pci_bus_num(pci_dev->bus), + PCI_SLOT(pci_dev->devfn), PCI_FUNC(pci_dev->devfn)); + xc_hvm_map_pcidev_to_ioreq_server(xc, dom, ioservid, + 0, pci_bus_num(pci_dev->bus), + PCI_SLOT(pci_dev->devfn), + PCI_FUNC(pci_dev->devfn)); +} + +static inline void xen_unmap_pcidev(XenXC xc, domid_t dom, + ioservid_t ioservid, + PCIDevice *pci_dev) +{ + trace_xen_unmap_pcidev(ioservid, pci_bus_num(pci_dev->bus), + PCI_SLOT(pci_dev->devfn), PCI_FUNC(pci_dev->devfn)); + xc_hvm_unmap_pcidev_from_ioreq_server(xc, dom, ioservid, + 0, pci_bus_num(pci_dev->bus), + PCI_SLOT(pci_dev->devfn), + PCI_FUNC(pci_dev->devfn)); +} + +static inline int xen_create_ioreq_server(XenXC xc, domid_t dom, + ioservid_t *ioservid) +{ + int rc = xc_hvm_create_ioreq_server(xc, dom, 1, ioservid); + + if (rc == 0) { + trace_xen_ioreq_server_create(*ioservid); + } + + return rc; +} + +static inline void xen_destroy_ioreq_server(XenXC xc, domid_t dom, + ioservid_t ioservid) +{ + trace_xen_ioreq_server_destroy(ioservid); + xc_hvm_destroy_ioreq_server(xc, dom, ioservid); +} + +static inline int xen_get_ioreq_server_info(XenXC xc, domid_t dom, + ioservid_t ioservid, + xen_pfn_t *ioreq_pfn, + xen_pfn_t *bufioreq_pfn, + evtchn_port_t *bufioreq_evtchn) +{ + return xc_hvm_get_ioreq_server_info(xc, dom, ioservid, + ioreq_pfn, bufioreq_pfn, + bufioreq_evtchn); +} + +static inline int xen_set_ioreq_server_state(XenXC xc, domid_t dom, + ioservid_t ioservid, + bool enable) +{ + trace_xen_ioreq_server_state(ioservid, enable); + return xc_hvm_set_ioreq_server_state(xc, dom, ioservid, enable); +} + +#endif + #endif /* QEMU_HW_XEN_COMMON_H */ |