diff options
Diffstat (limited to 'src/include/hw/i386')
-rw-r--r-- | src/include/hw/i386/apic-msidef.h | 30 | ||||
-rw-r--r-- | src/include/hw/i386/apic.h | 32 | ||||
-rw-r--r-- | src/include/hw/i386/apic_internal.h | 225 | ||||
-rw-r--r-- | src/include/hw/i386/ich9.h | 239 | ||||
-rw-r--r-- | src/include/hw/i386/intel_iommu.h | 132 | ||||
-rw-r--r-- | src/include/hw/i386/ioapic.h | 28 | ||||
-rw-r--r-- | src/include/hw/i386/ioapic_internal.h | 110 | ||||
-rw-r--r-- | src/include/hw/i386/pc.h | 807 | ||||
-rw-r--r-- | src/include/hw/i386/topology.h | 135 |
9 files changed, 1738 insertions, 0 deletions
diff --git a/src/include/hw/i386/apic-msidef.h b/src/include/hw/i386/apic-msidef.h new file mode 100644 index 0000000..6e2eb71 --- /dev/null +++ b/src/include/hw/i386/apic-msidef.h @@ -0,0 +1,30 @@ +#ifndef HW_APIC_MSIDEF_H +#define HW_APIC_MSIDEF_H + +/* + * Intel APIC constants: from include/asm/msidef.h + */ + +/* + * Shifts for MSI data + */ + +#define MSI_DATA_VECTOR_SHIFT 0 +#define MSI_DATA_VECTOR_MASK 0x000000ff + +#define MSI_DATA_DELIVERY_MODE_SHIFT 8 +#define MSI_DATA_LEVEL_SHIFT 14 +#define MSI_DATA_TRIGGER_SHIFT 15 + +/* + * Shift/mask fields for msi address + */ + +#define MSI_ADDR_DEST_MODE_SHIFT 2 + +#define MSI_ADDR_REDIRECTION_SHIFT 3 + +#define MSI_ADDR_DEST_ID_SHIFT 12 +#define MSI_ADDR_DEST_ID_MASK 0x00ffff0 + +#endif /* HW_APIC_MSIDEF_H */ diff --git a/src/include/hw/i386/apic.h b/src/include/hw/i386/apic.h new file mode 100644 index 0000000..51eb6d3 --- /dev/null +++ b/src/include/hw/i386/apic.h @@ -0,0 +1,32 @@ +#ifndef APIC_H +#define APIC_H + +#include "qemu-common.h" + +/* apic.c */ +void apic_deliver_irq(uint8_t dest, uint8_t dest_mode, uint8_t delivery_mode, + uint8_t vector_num, uint8_t trigger_mode); +int apic_accept_pic_intr(DeviceState *s); +void apic_deliver_pic_intr(DeviceState *s, int level); +void apic_deliver_nmi(DeviceState *d); +int apic_get_interrupt(DeviceState *s); +void apic_reset_irq_delivered(void); +int apic_get_irq_delivered(void); +void cpu_set_apic_base(DeviceState *s, uint64_t val); +uint64_t cpu_get_apic_base(DeviceState *s); +void cpu_set_apic_tpr(DeviceState *s, uint8_t val); +uint8_t cpu_get_apic_tpr(DeviceState *s); +void apic_init_reset(DeviceState *s); +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, bool bsp); + +/* pc.c */ +DeviceState *cpu_get_current_apic(void); + +/* cpu.c */ +bool cpu_is_bsp(X86CPU *cpu); + +#endif diff --git a/src/include/hw/i386/apic_internal.h b/src/include/hw/i386/apic_internal.h new file mode 100644 index 0000000..74fe935 --- /dev/null +++ b/src/include/hw/i386/apic_internal.h @@ -0,0 +1,225 @@ +/* + * APIC support - internal interfaces + * + * Copyright (c) 2004-2005 Fabrice Bellard + * Copyright (c) 2011 Jan Kiszka, Siemens AG + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ +#ifndef QEMU_APIC_INTERNAL_H +#define QEMU_APIC_INTERNAL_H + +#include "cpu.h" +#include "exec/memory.h" +#include "qemu/timer.h" + +/* APIC Local Vector Table */ +#define APIC_LVT_TIMER 0 +#define APIC_LVT_THERMAL 1 +#define APIC_LVT_PERFORM 2 +#define APIC_LVT_LINT0 3 +#define APIC_LVT_LINT1 4 +#define APIC_LVT_ERROR 5 +#define APIC_LVT_NB 6 + +/* APIC delivery modes */ +#define APIC_DM_FIXED 0 +#define APIC_DM_LOWPRI 1 +#define APIC_DM_SMI 2 +#define APIC_DM_NMI 4 +#define APIC_DM_INIT 5 +#define APIC_DM_SIPI 6 +#define APIC_DM_EXTINT 7 + +/* APIC destination mode */ +#define APIC_DESTMODE_FLAT 0xf +#define APIC_DESTMODE_CLUSTER 1 + +#define APIC_TRIGGER_EDGE 0 +#define APIC_TRIGGER_LEVEL 1 + +#define APIC_VECTOR_MASK 0xff +#define APIC_DCR_MASK 0xf + +#define APIC_LVT_TIMER_SHIFT 17 +#define APIC_LVT_MASKED_SHIFT 16 +#define APIC_LVT_LEVEL_TRIGGER_SHIFT 15 +#define APIC_LVT_REMOTE_IRR_SHIFT 14 +#define APIC_LVT_INT_POLARITY_SHIFT 13 +#define APIC_LVT_DELIV_STS_SHIFT 12 +#define APIC_LVT_DELIV_MOD_SHIFT 8 + +#define APIC_LVT_TIMER_TSCDEADLINE (2 << APIC_LVT_TIMER_SHIFT) +#define APIC_LVT_TIMER_PERIODIC (1 << APIC_LVT_TIMER_SHIFT) +#define APIC_LVT_MASKED (1 << APIC_LVT_MASKED_SHIFT) +#define APIC_LVT_LEVEL_TRIGGER (1 << APIC_LVT_LEVEL_TRIGGER_SHIFT) +#define APIC_LVT_REMOTE_IRR (1 << APIC_LVT_REMOTE_IRR_SHIFT) +#define APIC_LVT_INT_POLARITY (1 << APIC_LVT_INT_POLARITY_SHIFT) +#define APIC_LVT_DELIV_STS (1 << APIC_LVT_DELIV_STS_SHIFT) +#define APIC_LVT_DELIV_MOD (7 << APIC_LVT_DELIV_MOD_SHIFT) + +#define APIC_ESR_ILL_ADDRESS_SHIFT 7 +#define APIC_ESR_RECV_ILL_VECT_SHIFT 6 +#define APIC_ESR_SEND_ILL_VECT_SHIFT 5 +#define APIC_ESR_RECV_ACCEPT_SHIFT 3 +#define APIC_ESR_SEND_ACCEPT_SHIFT 2 +#define APIC_ESR_RECV_CHECK_SUM_SHIFT 1 + +#define APIC_ESR_ILLEGAL_ADDRESS (1 << APIC_ESR_ILL_ADDRESS_SHIFT) +#define APIC_ESR_RECV_ILLEGAL_VECT (1 << APIC_ESR_RECV_ILL_VECT_SHIFT) +#define APIC_ESR_SEND_ILLEGAL_VECT (1 << APIC_ESR_SEND_ILL_VECT_SHIFT) +#define APIC_ESR_RECV_ACCEPT (1 << APIC_ESR_RECV_ACCEPT_SHIFT) +#define APIC_ESR_SEND_ACCEPT (1 << APIC_ESR_SEND_ACCEPT_SHIFT) +#define APIC_ESR_RECV_CHECK_SUM (1 << APIC_ESR_RECV_CHECK_SUM_SHIFT) +#define APIC_ESR_SEND_CHECK_SUM 1 + +#define APIC_ICR_DEST_SHIFT 24 +#define APIC_ICR_DEST_SHORT_SHIFT 18 +#define APIC_ICR_TRIGGER_MOD_SHIFT 15 +#define APIC_ICR_LEVEL_SHIFT 14 +#define APIC_ICR_DELIV_STS_SHIFT 12 +#define APIC_ICR_DEST_MOD_SHIFT 11 +#define APIC_ICR_DELIV_MOD_SHIFT 8 + +#define APIC_ICR_DEST_SHORT (3 << APIC_ICR_DEST_SHORT_SHIFT) +#define APIC_ICR_TRIGGER_MOD (1 << APIC_ICR_TRIGGER_MOD_SHIFT) +#define APIC_ICR_LEVEL (1 << APIC_ICR_LEVEL_SHIFT) +#define APIC_ICR_DELIV_STS (1 << APIC_ICR_DELIV_STS_SHIFT) +#define APIC_ICR_DEST_MOD (1 << APIC_ICR_DEST_MOD_SHIFT) +#define APIC_ICR_DELIV_MOD (7 << APIC_ICR_DELIV_MOD_SHIFT) + +#define APIC_PR_CLASS_SHIFT 4 +#define APIC_PR_SUB_CLASS 0xf + +#define APIC_LOGDEST_XAPIC_SHIFT 4 +#define APIC_LOGDEST_XAPIC_ID 0xf + +#define APIC_LOGDEST_X2APIC_SHIFT 16 +#define APIC_LOGDEST_X2APIC_ID 0xffff + +#define APIC_SPURIO_FOCUS_SHIFT 9 +#define APIC_SPURIO_ENABLED_SHIFT 8 + +#define APIC_SPURIO_FOCUS (1 << APIC_SPURIO_FOCUS_SHIFT) +#define APIC_SPURIO_ENABLED (1 << APIC_SPURIO_ENABLED_SHIFT) + +#define APIC_SV_DIRECTED_IO (1 << 12) +#define APIC_SV_ENABLE (1 << 8) + +#define VAPIC_ENABLE_BIT 0 +#define VAPIC_ENABLE_MASK (1 << VAPIC_ENABLE_BIT) + +#define MAX_APICS 255 + +typedef struct APICCommonState APICCommonState; + +#define TYPE_APIC_COMMON "apic-common" +#define APIC_COMMON(obj) \ + OBJECT_CHECK(APICCommonState, (obj), TYPE_APIC_COMMON) +#define APIC_COMMON_CLASS(klass) \ + OBJECT_CLASS_CHECK(APICCommonClass, (klass), TYPE_APIC_COMMON) +#define APIC_COMMON_GET_CLASS(obj) \ + OBJECT_GET_CLASS(APICCommonClass, (obj), TYPE_APIC_COMMON) + +typedef struct APICCommonClass +{ + DeviceClass parent_class; + + DeviceRealize realize; + void (*set_base)(APICCommonState *s, uint64_t val); + void (*set_tpr)(APICCommonState *s, uint8_t val); + uint8_t (*get_tpr)(APICCommonState *s); + void (*enable_tpr_reporting)(APICCommonState *s, bool enable); + void (*vapic_base_update)(APICCommonState *s); + void (*external_nmi)(APICCommonState *s); + void (*pre_save)(APICCommonState *s); + void (*post_load)(APICCommonState *s); + void (*reset)(APICCommonState *s); +} APICCommonClass; + +struct APICCommonState { + /*< private >*/ + DeviceState parent_obj; + /*< public >*/ + + MemoryRegion io_memory; + X86CPU *cpu; + uint32_t apicbase; + uint8_t id; + uint8_t version; + uint8_t arb_id; + uint8_t tpr; + uint32_t spurious_vec; + uint8_t log_dest; + uint8_t dest_mode; + uint32_t isr[8]; /* in service register */ + uint32_t tmr[8]; /* trigger mode register */ + uint32_t irr[8]; /* interrupt request register */ + uint32_t lvt[APIC_LVT_NB]; + uint32_t esr; /* error register */ + uint32_t icr[2]; + + uint32_t divide_conf; + int count_shift; + uint32_t initial_count; + int64_t initial_count_load_time; + int64_t next_time; + int idx; + QEMUTimer *timer; + int64_t timer_expiry; + int sipi_vector; + int wait_for_sipi; + + uint32_t vapic_control; + DeviceState *vapic; + hwaddr vapic_paddr; /* note: persistence via kvmvapic */ +}; + +typedef struct VAPICState { + uint8_t tpr; + uint8_t isr; + uint8_t zero; + uint8_t irr; + uint8_t enabled; +} QEMU_PACKED VAPICState; + +extern bool apic_report_tpr_access; + +void apic_report_irq_delivered(int delivered); +bool apic_next_timer(APICCommonState *s, int64_t current_time); +void apic_enable_tpr_access_reporting(DeviceState *d, bool enable); +void apic_enable_vapic(DeviceState *d, hwaddr paddr); + +void vapic_report_tpr_access(DeviceState *dev, CPUState *cpu, target_ulong ip, + TPRAccess access); + +int apic_get_ppr(APICCommonState *s); + +static inline void apic_set_bit(uint32_t *tab, int index) +{ + int i, mask; + i = index >> 5; + mask = 1 << (index & 0x1f); + tab[i] |= mask; +} + +static inline int apic_get_bit(uint32_t *tab, int index) +{ + int i, mask; + i = index >> 5; + mask = 1 << (index & 0x1f); + return !!(tab[i] & mask); +} + +#endif /* !QEMU_APIC_INTERNAL_H */ diff --git a/src/include/hw/i386/ich9.h b/src/include/hw/i386/ich9.h new file mode 100644 index 0000000..b9d2b04 --- /dev/null +++ b/src/include/hw/i386/ich9.h @@ -0,0 +1,239 @@ +#ifndef HW_ICH9_H +#define HW_ICH9_H + +#include "hw/hw.h" +#include "hw/isa/isa.h" +#include "hw/sysbus.h" +#include "hw/i386/pc.h" +#include "hw/isa/apm.h" +#include "hw/i386/ioapic.h" +#include "hw/pci/pci.h" +#include "hw/pci/pcie_host.h" +#include "hw/pci/pci_bridge.h" +#include "hw/acpi/acpi.h" +#include "hw/acpi/ich9.h" +#include "hw/pci/pci_bus.h" + +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, 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" +#define ICH9_LPC_DEVICE(obj) \ + OBJECT_CHECK(ICH9LPCState, (obj), TYPE_ICH9_LPC_DEVICE) + +typedef struct ICH9LPCState { + /* ICH9 LPC PCI to ISA bridge */ + PCIDevice d; + + /* (pci device, intx) -> pirq + * In real chipset case, the unused slots are never used + * as ICH9 supports only D25-D32 irq routing. + * On the other hand in qemu case, any slot/function can be populated + * via command line option. + * So fallback interrupt routing for any devices in any slots is necessary. + */ + uint8_t irr[PCI_SLOT_MAX][PCI_NUM_PINS]; + + APMState apm; + 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]; + + /* + * 13.7.5 RST_CNT---Reset Control Register (LPC I/F---D31:F0) + * + * register contents and IO memory region + */ + uint8_t rst_cnt; + MemoryRegion rst_cnt_mem; + + /* isa bus */ + ISABus *isa_bus; + MemoryRegion rbca_mem; + Notifier machine_ready; + + qemu_irq *pic; + qemu_irq *ioapic; +} ICH9LPCState; + +Object *ich9_lpc_find(void); + +#define Q35_MASK(bit, ms_bit, ls_bit) \ +((uint##bit##_t)(((1ULL << ((ms_bit) + 1)) - 1) & ~((1ULL << ls_bit) - 1))) + +/* ICH9: Chipset Configuration Registers */ +#define ICH9_CC_ADDR_MASK (ICH9_CC_SIZE - 1) + +#define ICH9_CC +#define ICH9_CC_D28IP 0x310C +#define ICH9_CC_D28IP_SHIFT 4 +#define ICH9_CC_D28IP_MASK 0xf +#define ICH9_CC_D28IP_DEFAULT 0x00214321 +#define ICH9_CC_D31IR 0x3140 +#define ICH9_CC_D30IR 0x3142 +#define ICH9_CC_D29IR 0x3144 +#define ICH9_CC_D28IR 0x3146 +#define ICH9_CC_D27IR 0x3148 +#define ICH9_CC_D26IR 0x314C +#define ICH9_CC_D25IR 0x3150 +#define ICH9_CC_DIR_DEFAULT 0x3210 +#define ICH9_CC_D30IR_DEFAULT 0x0 +#define ICH9_CC_DIR_SHIFT 4 +#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 +#define ICH9_PCIE_FUNC_MAX 6 + + +/* D29:F0 USB UHCI Controller #1 */ +#define ICH9_USB_UHCI1_DEV 29 +#define ICH9_USB_UHCI1_FUNC 0 + +/* D30:F0 DMI-to-PCI bridge */ +#define ICH9_D2P_BRIDGE "ICH9 D2P BRIDGE" +#define ICH9_D2P_BRIDGE_SAVEVM_VERSION 0 + +#define ICH9_D2P_BRIDGE_DEV 30 +#define ICH9_D2P_BRIDGE_FUNC 0 + +#define ICH9_D2P_SECONDARY_DEFAULT (256 - 8) + +#define ICH9_D2P_A2_REVISION 0x92 + +/* D31:F0 LPC Processor Interface */ +#define ICH9_RST_CNT_IOPORT 0xCF9 + +/* D31:F1 LPC controller */ +#define ICH9_A2_LPC "ICH9 A2 LPC" +#define ICH9_A2_LPC_SAVEVM_VERSION 0 + +#define ICH9_LPC_DEV 31 +#define ICH9_LPC_FUNC 0 + +#define ICH9_A2_LPC_REVISION 0x2 +#define ICH9_LPC_NB_PIRQS 8 /* PCI A-H */ + +#define ICH9_LPC_PMBASE 0x40 +#define ICH9_LPC_PMBASE_BASE_ADDRESS_MASK Q35_MASK(32, 15, 7) +#define ICH9_LPC_PMBASE_RTE 0x1 +#define ICH9_LPC_PMBASE_DEFAULT 0x1 +#define ICH9_LPC_ACPI_CTRL 0x44 +#define ICH9_LPC_ACPI_CTRL_ACPI_EN 0x80 +#define ICH9_LPC_ACPI_CTRL_SCI_IRQ_SEL_MASK Q35_MASK(8, 2, 0) +#define ICH9_LPC_ACPI_CTRL_9 0x0 +#define ICH9_LPC_ACPI_CTRL_10 0x1 +#define ICH9_LPC_ACPI_CTRL_11 0x2 +#define ICH9_LPC_ACPI_CTRL_20 0x4 +#define ICH9_LPC_ACPI_CTRL_21 0x5 +#define ICH9_LPC_ACPI_CTRL_DEFAULT 0x0 + +#define ICH9_LPC_PIRQA_ROUT 0x60 +#define ICH9_LPC_PIRQB_ROUT 0x61 +#define ICH9_LPC_PIRQC_ROUT 0x62 +#define ICH9_LPC_PIRQD_ROUT 0x63 + +#define ICH9_LPC_PIRQE_ROUT 0x68 +#define ICH9_LPC_PIRQF_ROUT 0x69 +#define ICH9_LPC_PIRQG_ROUT 0x6a +#define ICH9_LPC_PIRQH_ROUT 0x6b + +#define ICH9_LPC_PIRQ_ROUT_IRQEN 0x80 +#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 +#define ICH9_LPC_RCBA_DEFAULT 0x0 + +#define ICH9_LPC_PIC_NUM_PINS 16 +#define ICH9_LPC_IOAPIC_NUM_PINS 24 + +/* D31:F2 SATA Controller #1 */ +#define ICH9_SATA1_DEV 31 +#define ICH9_SATA1_FUNC 2 + +/* D30:F1 power management I/O registers + offset from the address ICH9_LPC_PMBASE */ + +/* ICH9 LPC PM I/O registers are 128 ports and 128-aligned */ +#define ICH9_PMIO_SIZE 128 +#define ICH9_PMIO_MASK (ICH9_PMIO_SIZE - 1) + +#define ICH9_PMIO_PM1_STS 0x00 +#define ICH9_PMIO_PM1_EN 0x02 +#define ICH9_PMIO_PM1_CNT 0x04 +#define ICH9_PMIO_PM1_TMR 0x08 +#define ICH9_PMIO_GPE0_STS 0x20 +#define ICH9_PMIO_GPE0_EN 0x28 +#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 +#define ICH9_APM_ACPI_DISABLE 0x3 + + +/* D31:F3 SMBus controller */ +#define ICH9_A2_SMB_REVISION 0x02 +#define ICH9_SMB_PI 0x00 + +#define ICH9_SMB_SMBMBAR0 0x10 +#define ICH9_SMB_SMBMBAR1 0x14 +#define ICH9_SMB_SMBM_BAR 0 +#define ICH9_SMB_SMBM_SIZE (1 << 8) +#define ICH9_SMB_SMB_BASE 0x20 +#define ICH9_SMB_SMB_BASE_BAR 4 +#define ICH9_SMB_SMB_BASE_SIZE (1 << 5) +#define ICH9_SMB_HOSTC 0x40 +#define ICH9_SMB_HOSTC_SSRESET ((uint8_t)(1 << 3)) +#define ICH9_SMB_HOSTC_I2C_EN ((uint8_t)(1 << 2)) +#define ICH9_SMB_HOSTC_SMB_SMI_EN ((uint8_t)(1 << 1)) +#define ICH9_SMB_HOSTC_HST_EN ((uint8_t)(1 << 0)) + +/* D31:F3 SMBus I/O and memory mapped I/O registers */ +#define ICH9_SMB_DEV 31 +#define ICH9_SMB_FUNC 3 + +#define ICH9_SMB_HST_STS 0x00 +#define ICH9_SMB_HST_CNT 0x02 +#define ICH9_SMB_HST_CMD 0x03 +#define ICH9_SMB_XMIT_SLVA 0x04 +#define ICH9_SMB_HST_D0 0x05 +#define ICH9_SMB_HST_D1 0x06 +#define ICH9_SMB_HOST_BLOCK_DB 0x07 + +#endif /* HW_ICH9_H */ diff --git a/src/include/hw/i386/intel_iommu.h b/src/include/hw/i386/intel_iommu.h new file mode 100644 index 0000000..5dbadb7 --- /dev/null +++ b/src/include/hw/i386/intel_iommu.h @@ -0,0 +1,132 @@ +/* + * QEMU emulation of an Intel IOMMU (VT-d) + * (DMA Remapping device) + * + * Copyright (C) 2013 Knut Omang, Oracle <knut.omang@oracle.com> + * Copyright (C) 2014 Le Tan, <tamlokveer@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef INTEL_IOMMU_H +#define INTEL_IOMMU_H +#include "hw/qdev.h" +#include "sysemu/dma.h" + +#define TYPE_INTEL_IOMMU_DEVICE "intel-iommu" +#define INTEL_IOMMU_DEVICE(obj) \ + OBJECT_CHECK(IntelIOMMUState, (obj), TYPE_INTEL_IOMMU_DEVICE) + +/* DMAR Hardware Unit Definition address (IOMMU unit) */ +#define Q35_HOST_BRIDGE_IOMMU_ADDR 0xfed90000ULL + +#define VTD_PCI_BUS_MAX 256 +#define VTD_PCI_SLOT_MAX 32 +#define VTD_PCI_FUNC_MAX 8 +#define VTD_PCI_DEVFN_MAX 256 +#define VTD_PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f) +#define VTD_PCI_FUNC(devfn) ((devfn) & 0x07) +#define VTD_SID_TO_BUS(sid) (((sid) >> 8) & 0xff) +#define VTD_SID_TO_DEVFN(sid) ((sid) & 0xff) + +#define DMAR_REG_SIZE 0x230 +#define VTD_HOST_ADDRESS_WIDTH 39 +#define VTD_HAW_MASK ((1ULL << VTD_HOST_ADDRESS_WIDTH) - 1) + +typedef struct VTDContextEntry VTDContextEntry; +typedef struct VTDContextCacheEntry VTDContextCacheEntry; +typedef struct IntelIOMMUState IntelIOMMUState; +typedef struct VTDAddressSpace VTDAddressSpace; +typedef struct VTDIOTLBEntry VTDIOTLBEntry; +typedef struct VTDBus VTDBus; + +/* Context-Entry */ +struct VTDContextEntry { + uint64_t lo; + uint64_t hi; +}; + +struct VTDContextCacheEntry { + /* The cache entry is obsolete if + * context_cache_gen!=IntelIOMMUState.context_cache_gen + */ + uint32_t context_cache_gen; + struct VTDContextEntry context_entry; +}; + +struct VTDAddressSpace { + PCIBus *bus; + uint8_t devfn; + AddressSpace as; + MemoryRegion iommu; + IntelIOMMUState *iommu_state; + VTDContextCacheEntry context_cache_entry; +}; + +struct VTDBus { + PCIBus* bus; /* A reference to the bus to provide translation for */ + VTDAddressSpace *dev_as[0]; /* A table of VTDAddressSpace objects indexed by devfn */ +}; + +struct VTDIOTLBEntry { + uint64_t gfn; + uint16_t domain_id; + uint64_t slpte; + bool read_flags; + bool write_flags; +}; + +/* The iommu (DMAR) device state struct */ +struct IntelIOMMUState { + SysBusDevice busdev; + MemoryRegion csrmem; + uint8_t csr[DMAR_REG_SIZE]; /* register values */ + uint8_t wmask[DMAR_REG_SIZE]; /* R/W bytes */ + uint8_t w1cmask[DMAR_REG_SIZE]; /* RW1C(Write 1 to Clear) bytes */ + uint8_t womask[DMAR_REG_SIZE]; /* WO (write only - read returns 0) */ + uint32_t version; + + dma_addr_t root; /* Current root table pointer */ + bool root_extended; /* Type of root table (extended or not) */ + bool dmar_enabled; /* Set if DMA remapping is enabled */ + + uint16_t iq_head; /* Current invalidation queue head */ + uint16_t iq_tail; /* Current invalidation queue tail */ + dma_addr_t iq; /* Current invalidation queue pointer */ + uint16_t iq_size; /* IQ Size in number of entries */ + bool qi_enabled; /* Set if the QI is enabled */ + uint8_t iq_last_desc_type; /* The type of last completed descriptor */ + + /* The index of the Fault Recording Register to be used next. + * Wraps around from N-1 to 0, where N is the number of FRCD_REG. + */ + uint16_t next_frcd_reg; + + uint64_t cap; /* The value of capability reg */ + uint64_t ecap; /* The value of extended capability reg */ + + uint32_t context_cache_gen; /* Should be in [1,MAX] */ + GHashTable *iotlb; /* IOTLB */ + + MemoryRegionIOMMUOps iommu_ops; + GHashTable *vtd_as_by_busptr; /* VTDBus objects indexed by PCIBus* reference */ + VTDBus *vtd_as_by_bus_num[VTD_PCI_BUS_MAX]; /* VTDBus objects indexed by bus number */ +}; + +/* Find the VTD Address space associated with the given bus pointer, + * create a new one if none exists + */ +VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn); + +#endif diff --git a/src/include/hw/i386/ioapic.h b/src/include/hw/i386/ioapic.h new file mode 100644 index 0000000..6245388 --- /dev/null +++ b/src/include/hw/i386/ioapic.h @@ -0,0 +1,28 @@ +/* + * ioapic.c IOAPIC emulation logic + * + * Copyright (c) 2011 Jan Kiszka, Siemens AG + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef HW_IOAPIC_H +#define HW_IOAPIC_H + +#define IOAPIC_NUM_PINS 24 +#define IO_APIC_DEFAULT_ADDRESS 0xfec00000 + +void ioapic_eoi_broadcast(int vector); + +#endif /* !HW_IOAPIC_H */ diff --git a/src/include/hw/i386/ioapic_internal.h b/src/include/hw/i386/ioapic_internal.h new file mode 100644 index 0000000..797ed47 --- /dev/null +++ b/src/include/hw/i386/ioapic_internal.h @@ -0,0 +1,110 @@ +/* + * IOAPIC emulation logic - internal interfaces + * + * Copyright (c) 2004-2005 Fabrice Bellard + * Copyright (c) 2009 Xiantao Zhang, Intel + * Copyright (c) 2011 Jan Kiszka, Siemens AG + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef QEMU_IOAPIC_INTERNAL_H +#define QEMU_IOAPIC_INTERNAL_H + +#include "hw/hw.h" +#include "exec/memory.h" +#include "hw/sysbus.h" + +#define MAX_IOAPICS 1 + +#define IOAPIC_VERSION 0x11 + +#define IOAPIC_LVT_DEST_SHIFT 56 +#define IOAPIC_LVT_MASKED_SHIFT 16 +#define IOAPIC_LVT_TRIGGER_MODE_SHIFT 15 +#define IOAPIC_LVT_REMOTE_IRR_SHIFT 14 +#define IOAPIC_LVT_POLARITY_SHIFT 13 +#define IOAPIC_LVT_DELIV_STATUS_SHIFT 12 +#define IOAPIC_LVT_DEST_MODE_SHIFT 11 +#define IOAPIC_LVT_DELIV_MODE_SHIFT 8 + +#define IOAPIC_LVT_MASKED (1 << IOAPIC_LVT_MASKED_SHIFT) +#define IOAPIC_LVT_TRIGGER_MODE (1 << IOAPIC_LVT_TRIGGER_MODE_SHIFT) +#define IOAPIC_LVT_REMOTE_IRR (1 << IOAPIC_LVT_REMOTE_IRR_SHIFT) +#define IOAPIC_LVT_POLARITY (1 << IOAPIC_LVT_POLARITY_SHIFT) +#define IOAPIC_LVT_DELIV_STATUS (1 << IOAPIC_LVT_DELIV_STATUS_SHIFT) +#define IOAPIC_LVT_DEST_MODE (1 << IOAPIC_LVT_DEST_MODE_SHIFT) +#define IOAPIC_LVT_DELIV_MODE (7 << IOAPIC_LVT_DELIV_MODE_SHIFT) + +#define IOAPIC_TRIGGER_EDGE 0 +#define IOAPIC_TRIGGER_LEVEL 1 + +/*io{apic,sapic} delivery mode*/ +#define IOAPIC_DM_FIXED 0x0 +#define IOAPIC_DM_LOWEST_PRIORITY 0x1 +#define IOAPIC_DM_PMI 0x2 +#define IOAPIC_DM_NMI 0x4 +#define IOAPIC_DM_INIT 0x5 +#define IOAPIC_DM_SIPI 0x6 +#define IOAPIC_DM_EXTINT 0x7 +#define IOAPIC_DM_MASK 0x7 + +#define IOAPIC_VECTOR_MASK 0xff + +#define IOAPIC_IOREGSEL 0x00 +#define IOAPIC_IOWIN 0x10 + +#define IOAPIC_REG_ID 0x00 +#define IOAPIC_REG_VER 0x01 +#define IOAPIC_REG_ARB 0x02 +#define IOAPIC_REG_REDTBL_BASE 0x10 +#define IOAPIC_ID 0x00 + +#define IOAPIC_ID_SHIFT 24 +#define IOAPIC_ID_MASK 0xf + +#define IOAPIC_VER_ENTRIES_SHIFT 16 + +typedef struct IOAPICCommonState IOAPICCommonState; + +#define TYPE_IOAPIC_COMMON "ioapic-common" +#define IOAPIC_COMMON(obj) \ + OBJECT_CHECK(IOAPICCommonState, (obj), TYPE_IOAPIC_COMMON) +#define IOAPIC_COMMON_CLASS(klass) \ + OBJECT_CLASS_CHECK(IOAPICCommonClass, (klass), TYPE_IOAPIC_COMMON) +#define IOAPIC_COMMON_GET_CLASS(obj) \ + OBJECT_GET_CLASS(IOAPICCommonClass, (obj), TYPE_IOAPIC_COMMON) + +typedef struct IOAPICCommonClass { + SysBusDeviceClass parent_class; + + DeviceRealize realize; + void (*pre_save)(IOAPICCommonState *s); + void (*post_load)(IOAPICCommonState *s); +} IOAPICCommonClass; + +struct IOAPICCommonState { + SysBusDevice busdev; + MemoryRegion io_memory; + uint8_t id; + uint8_t ioregsel; + uint32_t irr; + uint64_t ioredtbl[IOAPIC_NUM_PINS]; +}; + +void ioapic_reset_common(DeviceState *dev); + +void ioapic_print_redtbl(Monitor *mon, IOAPICCommonState *s); + +#endif /* !QEMU_IOAPIC_INTERNAL_H */ diff --git a/src/include/hw/i386/pc.h b/src/include/hw/i386/pc.h new file mode 100644 index 0000000..854c330 --- /dev/null +++ b/src/include/hw/i386/pc.h @@ -0,0 +1,807 @@ +#ifndef HW_PC_H +#define HW_PC_H + +#include "qemu-common.h" +#include "qemu/typedefs.h" +#include "exec/memory.h" +#include "hw/boards.h" +#include "hw/isa/isa.h" +#include "hw/block/fdc.h" +#include "net/net.h" +#include "hw/i386/ioapic.h" + +#include "qemu/range.h" +#include "qemu/bitmap.h" +#include "sysemu/sysemu.h" +#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: + * @acpi_dev: link to ACPI PM device that performs ACPI hotplug handling + * @enforce_aligned_dimm: check that DIMM's address/size is aligned by + * backend's alignment value if provided + */ +struct PCMachineState { + /*< private >*/ + MachineState parent_obj; + + /* <public> */ + MemoryHotplugState hotplug_memory; + + HotplugHandler *acpi_dev; + ISADevice *rtc; + + uint64_t max_ram_below_4g; + OnOffAuto vmport; + OnOffAuto smm; + bool enforce_aligned_dimm; + ram_addr_t below_4g_mem_size, above_4g_mem_size; +}; + +#define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device" +#define PC_MACHINE_MEMHP_REGION_SIZE "hotplug-memory-region-size" +#define PC_MACHINE_MAX_RAM_BELOW_4G "max-ram-below-4g" +#define PC_MACHINE_VMPORT "vmport" +#define PC_MACHINE_SMM "smm" +#define PC_MACHINE_ENFORCE_ALIGNED_DIMM "enforce-aligned-dimm" + +/** + * PCMachineClass: + * @get_hotplug_handler: pointer to parent class callback @get_hotplug_handler + */ +struct PCMachineClass { + /*< private >*/ + MachineClass parent_class; + + /*< public >*/ + bool broken_reserved_end; + HotplugHandler *(*get_hotplug_handler)(MachineState *machine, + DeviceState *dev); +}; + +#define TYPE_PC_MACHINE "generic-pc-machine" +#define PC_MACHINE(obj) \ + OBJECT_CHECK(PCMachineState, (obj), TYPE_PC_MACHINE) +#define PC_MACHINE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(PCMachineClass, (obj), TYPE_PC_MACHINE) +#define PC_MACHINE_CLASS(klass) \ + OBJECT_CLASS_CHECK(PCMachineClass, (klass), TYPE_PC_MACHINE) + +/* PC-style peripherals (also used by other machines). */ + +typedef struct PcPciInfo { + Range w32; + Range w64; +} PcPciInfo; + +#define ACPI_PM_PROP_S3_DISABLED "disable_s3" +#define ACPI_PM_PROP_S4_DISABLED "disable_s4" +#define ACPI_PM_PROP_S4_VAL "s4_val" +#define ACPI_PM_PROP_SCI_INT "sci_int" +#define ACPI_PM_PROP_ACPI_ENABLE_CMD "acpi_enable_cmd" +#define ACPI_PM_PROP_ACPI_DISABLE_CMD "acpi_disable_cmd" +#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; + hwaddr ram_size, ram_size_below_4g; + unsigned apic_id_limit; + bool apic_xrupt_override; + uint64_t numa_nodes; + uint64_t *node_mem; + uint64_t *node_cpu; + FWCfgState *fw_cfg; + int legacy_acpi_table_size; + bool has_acpi_build; + bool has_reserved_memory; + bool rsdp_in_ram; +}; + +/* parallel.c */ + +void parallel_hds_isa_init(ISABus *bus, int n); + +bool parallel_mm_init(MemoryRegion *address_space, + hwaddr base, int it_shift, qemu_irq irq, + CharDriverState *chr); + +/* i8259.c */ + +extern DeviceState *isa_pic; +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 hmp_info_pic(Monitor *mon, const QDict *qdict); +void hmp_info_irq(Monitor *mon, const QDict *qdict); + +/* ioapic.c */ + +void kvm_ioapic_dump_state(Monitor *mon, const QDict *qdict); +void ioapic_dump_state(Monitor *mon, const QDict *qdict); + +/* Global System Interrupts */ + +#define GSI_NUM_PINS IOAPIC_NUM_PINS + +typedef struct GSIState { + qemu_irq i8259_irq[ISA_NUM_IRQS]; + qemu_irq ioapic_irq[IOAPIC_NUM_PINS]; +} GSIState; + +void gsi_handler(void *opaque, int n, int level); + +/* vmport.c */ +typedef uint32_t (VMPortReadFunc)(void *opaque, uint32_t address); + +static inline void vmport_init(ISABus *bus) +{ + isa_create_simple(bus, "vmport"); +} + +void vmport_register(unsigned char command, VMPortReadFunc *func, void *opaque); +void vmmouse_get_data(uint32_t *data); +void vmmouse_set_data(const uint32_t *data); + +/* pckbd.c */ + +void i8042_init(qemu_irq kbd_irq, qemu_irq mouse_irq, uint32_t io_base); +void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq, + MemoryRegion *region, ram_addr_t size, + hwaddr mask); +void i8042_isa_mouse_fake_event(void *opaque); +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); + +void pc_cpus_init(PCMachineState *pcms); +void pc_hot_add_cpu(const int64_t id, Error **errp); +void pc_acpi_init(const char *default_dsdt); + +PcGuestInfo *pc_guest_info_init(PCMachineState *pcms); + +void pc_set_legacy_acpi_data_size(void); + +#define PCI_HOST_PROP_PCI_HOLE_START "pci-hole-start" +#define PCI_HOST_PROP_PCI_HOLE_END "pci-hole-end" +#define PCI_HOST_PROP_PCI_HOLE64_START "pci-hole64-start" +#define PCI_HOST_PROP_PCI_HOLE64_END "pci-hole64-end" +#define PCI_HOST_PROP_PCI_HOLE64_SIZE "pci-hole64-size" +#define DEFAULT_PCI_HOLE64_SIZE (~0x0ULL) + + +void pc_pci_as_mapping_init(Object *owner, MemoryRegion *system_memory, + MemoryRegion *pci_address_space); + +FWCfgState *xen_load_linux(PCMachineState *pcms, + PcGuestInfo *guest_info); +FWCfgState *pc_memory_init(PCMachineState *pcms, + MemoryRegion *system_memory, + MemoryRegion *rom_memory, + MemoryRegion **ram_memory, + PcGuestInfo *guest_info); +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, + bool create_fdctrl, + bool no_vmport, + uint32 hpet_irqs); +void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd); +void pc_cmos_init(PCMachineState *pcms, + 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 ioapic_init_gsi(GSIState *gsi_state, const char *parent_name); + +/* acpi_piix.c */ + +I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, + qemu_irq sci_irq, qemu_irq smi_irq, + int smm_enabled, DeviceState **piix4_pm); +void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr); + +/* hpet.c */ +extern int no_hpet; + +/* piix_pci.c */ +struct PCII440FXState; +typedef struct PCII440FXState PCII440FXState; + +#define TYPE_I440FX_PCI_HOST_BRIDGE "i440FX-pcihost" +#define TYPE_I440FX_PCI_DEVICE "i440FX" + +#define TYPE_IGD_PASSTHROUGH_I440FX_PCI_DEVICE "igd-passthrough-i440FX" + +PCIBus *i440fx_init(const char *host_type, const char *pci_type, + PCII440FXState **pi440fx_state, int *piix_devfn, + ISABus **isa_bus, qemu_irq *pic, + MemoryRegion *address_space_mem, + MemoryRegion *address_space_io, + ram_addr_t ram_size, + ram_addr_t below_4g_mem_size, + ram_addr_t above_4g_mem_size, + MemoryRegion *pci_memory, + MemoryRegion *ram_memory); + +PCIBus *find_i440fx(void); +/* piix4.c */ +extern PCIDevice *piix4_dev; +int piix4_init(PCIBus *bus, ISABus **isa_bus, int devfn); + +/* vga.c */ +enum vga_retrace_method { + VGA_RETRACE_DUMB, + VGA_RETRACE_PRECISE +}; + +extern enum vga_retrace_method vga_retrace_method; + +int isa_vga_mm_init(hwaddr vram_base, + hwaddr ctrl_base, int it_shift, + MemoryRegion *address_space); + +/* ne2000.c */ +static inline bool isa_ne2000_init(ISABus *bus, int base, int irq, NICInfo *nd) +{ + DeviceState *dev; + ISADevice *isadev; + + qemu_check_nic_model(nd, "ne2k_isa"); + + isadev = isa_try_create(bus, "ne2k_isa"); + if (!isadev) { + return false; + } + dev = DEVICE(isadev); + qdev_prop_set_uint32(dev, "iobase", base); + qdev_prop_set_uint32(dev, "irq", irq); + qdev_set_nic_properties(dev, nd); + qdev_init_nofail(dev); + return true; +} + +/* pc_sysfw.c */ +void pc_system_firmware_init(MemoryRegion *rom_memory, + bool isapc_ram_fw); + +/* pvpanic.c */ +uint16_t pvpanic_port(void); + +/* e820 types */ +#define E820_RAM 1 +#define E820_RESERVED 2 +#define E820_ACPI 3 +#define E820_NVS 4 +#define E820_UNUSABLE 5 + +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_4 \ + HW_COMPAT_2_4 \ + {\ + .driver = "Haswell-" TYPE_X86_CPU,\ + .property = "abm",\ + .value = "off",\ + },\ + {\ + .driver = "Haswell-noTSX-" TYPE_X86_CPU,\ + .property = "abm",\ + .value = "off",\ + },\ + {\ + .driver = "Broadwell-" TYPE_X86_CPU,\ + .property = "abm",\ + .value = "off",\ + },\ + {\ + .driver = "Broadwell-noTSX-" TYPE_X86_CPU,\ + .property = "abm",\ + .value = "off",\ + },\ + {\ + .driver = "host" "-" TYPE_X86_CPU,\ + .property = "host-cache-info",\ + .value = "on",\ + },\ + {\ + .driver = TYPE_X86_CPU,\ + .property = "check",\ + .value = "off",\ + },\ + {\ + .driver = "qemu64" "-" TYPE_X86_CPU,\ + .property = "sse4a",\ + .value = "on",\ + },\ + {\ + .driver = "qemu64" "-" TYPE_X86_CPU,\ + .property = "abm",\ + .value = "on",\ + },\ + {\ + .driver = "qemu64" "-" TYPE_X86_CPU,\ + .property = "popcnt",\ + .value = "on",\ + },\ + {\ + .driver = "qemu32" "-" TYPE_X86_CPU,\ + .property = "popcnt",\ + .value = "on",\ + },{\ + .driver = "Opteron_G2" "-" TYPE_X86_CPU,\ + .property = "rdtscp",\ + .value = "on",\ + },{\ + .driver = "Opteron_G3" "-" TYPE_X86_CPU,\ + .property = "rdtscp",\ + .value = "on",\ + },{\ + .driver = "Opteron_G4" "-" TYPE_X86_CPU,\ + .property = "rdtscp",\ + .value = "on",\ + },{\ + .driver = "Opteron_G5" "-" TYPE_X86_CPU,\ + .property = "rdtscp",\ + .value = "on",\ + }, + + +#define PC_COMPAT_2_3 \ + PC_COMPAT_2_4 \ + 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 \ + {\ + .driver = "kvm64" "-" TYPE_X86_CPU,\ + .property = "vme",\ + .value = "off",\ + },\ + {\ + .driver = "kvm32" "-" TYPE_X86_CPU,\ + .property = "vme",\ + .value = "off",\ + },\ + {\ + .driver = "Conroe" "-" TYPE_X86_CPU,\ + .property = "vme",\ + .value = "off",\ + },\ + {\ + .driver = "Penryn" "-" TYPE_X86_CPU,\ + .property = "vme",\ + .value = "off",\ + },\ + {\ + .driver = "Nehalem" "-" TYPE_X86_CPU,\ + .property = "vme",\ + .value = "off",\ + },\ + {\ + .driver = "Westmere" "-" TYPE_X86_CPU,\ + .property = "vme",\ + .value = "off",\ + },\ + {\ + .driver = "SandyBridge" "-" TYPE_X86_CPU,\ + .property = "vme",\ + .value = "off",\ + },\ + {\ + .driver = "Haswell" "-" TYPE_X86_CPU,\ + .property = "vme",\ + .value = "off",\ + },\ + {\ + .driver = "Broadwell" "-" TYPE_X86_CPU,\ + .property = "vme",\ + .value = "off",\ + },\ + {\ + .driver = "Opteron_G1" "-" TYPE_X86_CPU,\ + .property = "vme",\ + .value = "off",\ + },\ + {\ + .driver = "Opteron_G2" "-" TYPE_X86_CPU,\ + .property = "vme",\ + .value = "off",\ + },\ + {\ + .driver = "Opteron_G3" "-" TYPE_X86_CPU,\ + .property = "vme",\ + .value = "off",\ + },\ + {\ + .driver = "Opteron_G4" "-" TYPE_X86_CPU,\ + .property = "vme",\ + .value = "off",\ + },\ + {\ + .driver = "Opteron_G5" "-" TYPE_X86_CPU,\ + .property = "vme",\ + .value = "off",\ + },\ + {\ + .driver = "Haswell" "-" TYPE_X86_CPU,\ + .property = "f16c",\ + .value = "off",\ + },\ + {\ + .driver = "Haswell" "-" TYPE_X86_CPU,\ + .property = "rdrand",\ + .value = "off",\ + },\ + {\ + .driver = "Broadwell" "-" TYPE_X86_CPU,\ + .property = "f16c",\ + .value = "off",\ + },\ + {\ + .driver = "Broadwell" "-" TYPE_X86_CPU,\ + .property = "rdrand",\ + .value = "off",\ + }, + +#define PC_COMPAT_2_1 \ + PC_COMPAT_2_2 \ + HW_COMPAT_2_1 \ + {\ + .driver = "coreduo" "-" TYPE_X86_CPU,\ + .property = "vmx",\ + .value = "on",\ + },\ + {\ + .driver = "core2duo" "-" TYPE_X86_CPU,\ + .property = "vmx",\ + .value = "on",\ + }, + +#define PC_COMPAT_2_0 \ + PC_COMPAT_2_1 \ + {\ + .driver = "virtio-scsi-pci",\ + .property = "any_layout",\ + .value = "off",\ + },{\ + .driver = "PIIX4_PM",\ + .property = "memory-hotplug-support",\ + .value = "off",\ + },\ + {\ + .driver = "apic",\ + .property = "version",\ + .value = stringify(0x11),\ + },\ + {\ + .driver = "nec-usb-xhci",\ + .property = "superspeed-ports-first",\ + .value = "off",\ + },\ + {\ + .driver = "nec-usb-xhci",\ + .property = "force-pcie-endcap",\ + .value = "on",\ + },\ + {\ + .driver = "pci-serial",\ + .property = "prog_if",\ + .value = stringify(0),\ + },\ + {\ + .driver = "pci-serial-2x",\ + .property = "prog_if",\ + .value = stringify(0),\ + },\ + {\ + .driver = "pci-serial-4x",\ + .property = "prog_if",\ + .value = stringify(0),\ + },\ + {\ + .driver = "virtio-net-pci",\ + .property = "guest_announce",\ + .value = "off",\ + },\ + {\ + .driver = "ICH9-LPC",\ + .property = "memory-hotplug-support",\ + .value = "off",\ + },{\ + .driver = "xio3130-downstream",\ + .property = COMPAT_PROP_PCP,\ + .value = "off",\ + },{\ + .driver = "ioh3420",\ + .property = COMPAT_PROP_PCP,\ + .value = "off",\ + }, + +#define PC_COMPAT_1_7 \ + PC_COMPAT_2_0 \ + {\ + .driver = TYPE_USB_DEVICE,\ + .property = "msos-desc",\ + .value = "no",\ + },\ + {\ + .driver = "PIIX4_PM",\ + .property = "acpi-pci-hotplug-with-bridge-support",\ + .value = "off",\ + },\ + {\ + .driver = "hpet",\ + .property = HPET_INTCAP,\ + .value = stringify(4),\ + }, + +#define PC_COMPAT_1_6 \ + PC_COMPAT_1_7 \ + {\ + .driver = "e1000",\ + .property = "mitigation",\ + .value = "off",\ + },{\ + .driver = "qemu64-" TYPE_X86_CPU,\ + .property = "model",\ + .value = stringify(2),\ + },{\ + .driver = "qemu32-" TYPE_X86_CPU,\ + .property = "model",\ + .value = stringify(3),\ + },{\ + .driver = "i440FX-pcihost",\ + .property = "short_root_bus",\ + .value = stringify(1),\ + },{\ + .driver = "q35-pcihost",\ + .property = "short_root_bus",\ + .value = stringify(1),\ + }, + +#define PC_COMPAT_1_5 \ + PC_COMPAT_1_6 \ + {\ + .driver = "Conroe-" TYPE_X86_CPU,\ + .property = "model",\ + .value = stringify(2),\ + },{\ + .driver = "Conroe-" TYPE_X86_CPU,\ + .property = "level",\ + .value = stringify(2),\ + },{\ + .driver = "Penryn-" TYPE_X86_CPU,\ + .property = "model",\ + .value = stringify(2),\ + },{\ + .driver = "Penryn-" TYPE_X86_CPU,\ + .property = "level",\ + .value = stringify(2),\ + },{\ + .driver = "Nehalem-" TYPE_X86_CPU,\ + .property = "model",\ + .value = stringify(2),\ + },{\ + .driver = "Nehalem-" TYPE_X86_CPU,\ + .property = "level",\ + .value = stringify(2),\ + },{\ + .driver = "virtio-net-pci",\ + .property = "any_layout",\ + .value = "off",\ + },{\ + .driver = TYPE_X86_CPU,\ + .property = "pmu",\ + .value = "on",\ + },{\ + .driver = "i440FX-pcihost",\ + .property = "short_root_bus",\ + .value = stringify(0),\ + },{\ + .driver = "q35-pcihost",\ + .property = "short_root_bus",\ + .value = stringify(0),\ + }, + +#define PC_COMPAT_1_4 \ + 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),\ + },{\ + .driver = "virtio-blk-pci",\ + .property = "discard_granularity",\ + .value = stringify(0),\ + },{\ + .driver = "virtio-serial-pci",\ + .property = "vectors",\ + /* DEV_NVECTORS_UNSPECIFIED as a uint32_t string */\ + .value = stringify(0xFFFFFFFF),\ + },{ \ + .driver = "virtio-net-pci", \ + .property = "ctrl_guest_offloads", \ + .value = "off", \ + },{\ + .driver = "e1000",\ + .property = "romfile",\ + .value = "pxe-e1000.rom",\ + },{\ + .driver = "ne2k_pci",\ + .property = "romfile",\ + .value = "pxe-ne2k_pci.rom",\ + },{\ + .driver = "pcnet",\ + .property = "romfile",\ + .value = "pxe-pcnet.rom",\ + },{\ + .driver = "rtl8139",\ + .property = "romfile",\ + .value = "pxe-rtl8139.rom",\ + },{\ + .driver = "virtio-net-pci",\ + .property = "romfile",\ + .value = "pxe-virtio.rom",\ + },{\ + .driver = "486-" TYPE_X86_CPU,\ + .property = "model",\ + .value = stringify(0),\ + },\ + {\ + .driver = "n270" "-" TYPE_X86_CPU,\ + .property = "movbe",\ + .value = "off",\ + },\ + {\ + .driver = "Westmere" "-" TYPE_X86_CPU,\ + .property = "pclmulqdq",\ + .value = "off",\ + }, + +#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) + +extern void igd_passthrough_isa_bridge_create(PCIBus *bus, uint16_t gpu_dev_id); +#endif diff --git a/src/include/hw/i386/topology.h b/src/include/hw/i386/topology.h new file mode 100644 index 0000000..148cc1b --- /dev/null +++ b/src/include/hw/i386/topology.h @@ -0,0 +1,135 @@ +/* + * 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; + +typedef struct X86CPUTopoInfo { + unsigned pkg_id; + unsigned core_id; + unsigned smt_id; +} X86CPUTopoInfo; + +/* 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, + const X86CPUTopoInfo *topo) +{ + return (topo->pkg_id << apicid_pkg_offset(nr_cores, nr_threads)) | + (topo->core_id << apicid_core_offset(nr_cores, nr_threads)) | + topo->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, + X86CPUTopoInfo *topo) +{ + unsigned core_index = cpu_index / nr_threads; + topo->smt_id = cpu_index % nr_threads; + topo->core_id = core_index % nr_cores; + topo->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) +{ + X86CPUTopoInfo topo; + x86_topo_ids_from_idx(nr_cores, nr_threads, cpu_index, &topo); + return apicid_from_topo_ids(nr_cores, nr_threads, &topo); +} + +#endif /* HW_I386_TOPOLOGY_H */ |