diff options
author | 2023-10-10 11:40:56 +0000 | |
---|---|---|
committer | 2023-10-10 11:40:56 +0000 | |
commit | e02cda008591317b1625707ff8e115a4841aa889 (patch) | |
tree | aee302e3cf8b59ec2d32ec481be3d1afddfc8968 /include/hw/acpi | |
parent | cc668e6b7e0ffd8c9d130513d12053cf5eda1d3b (diff) |
Introduce Virtio-loopback epsilon release:
Epsilon release introduces a new compatibility layer which make virtio-loopback
design to work with QEMU and rust-vmm vhost-user backend without require any
changes.
Signed-off-by: Timos Ampelikiotis <t.ampelikiotis@virtualopensystems.com>
Change-Id: I52e57563e08a7d0bdc002f8e928ee61ba0c53dd9
Diffstat (limited to 'include/hw/acpi')
-rw-r--r-- | include/hw/acpi/acpi-defs.h | 95 | ||||
-rw-r--r-- | include/hw/acpi/acpi.h | 203 | ||||
-rw-r--r-- | include/hw/acpi/acpi_dev_interface.h | 59 | ||||
-rw-r--r-- | include/hw/acpi/aml-build.h | 500 | ||||
-rw-r--r-- | include/hw/acpi/bios-linker-loader.h | 39 | ||||
-rw-r--r-- | include/hw/acpi/cpu.h | 70 | ||||
-rw-r--r-- | include/hw/acpi/cpu_hotplug.h | 40 | ||||
-rw-r--r-- | include/hw/acpi/generic_event_device.h | 121 | ||||
-rw-r--r-- | include/hw/acpi/ghes.h | 84 | ||||
-rw-r--r-- | include/hw/acpi/ich9.h | 94 | ||||
-rw-r--r-- | include/hw/acpi/ipmi.h | 21 | ||||
-rw-r--r-- | include/hw/acpi/memory_hotplug.h | 57 | ||||
-rw-r--r-- | include/hw/acpi/pc-hotplug.h | 34 | ||||
-rw-r--r-- | include/hw/acpi/pci.h | 39 | ||||
-rw-r--r-- | include/hw/acpi/pcihp.h | 89 | ||||
-rw-r--r-- | include/hw/acpi/tco.h | 82 | ||||
-rw-r--r-- | include/hw/acpi/tpm.h | 216 | ||||
-rw-r--r-- | include/hw/acpi/utils.h | 8 | ||||
-rw-r--r-- | include/hw/acpi/vmgenid.h | 37 |
19 files changed, 1888 insertions, 0 deletions
diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h new file mode 100644 index 000000000..c97e8633a --- /dev/null +++ b/include/hw/acpi/acpi-defs.h @@ -0,0 +1,95 @@ +/* + * 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, +}; + +typedef struct AcpiRsdpData { + char *oem_id; /* OEM identification */ + uint8_t revision; /* Must be 0 for 1.0, 2 for 2.0 */ + + unsigned *rsdt_tbl_offset; + unsigned *xsdt_tbl_offset; +} AcpiRsdpData; + +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; /* ACPI 3.0: Minimum Access size (ACPI 3.0), + ACPI 2.0: Reserved, Table 5-1 */ + uint64_t address; /* 64-bit address of struct or register */ +}; + +typedef struct AcpiFadtData { + struct AcpiGenericAddress pm1a_cnt; /* PM1a_CNT_BLK */ + struct AcpiGenericAddress pm1a_evt; /* PM1a_EVT_BLK */ + struct AcpiGenericAddress pm_tmr; /* PM_TMR_BLK */ + struct AcpiGenericAddress gpe0_blk; /* GPE0_BLK */ + struct AcpiGenericAddress reset_reg; /* RESET_REG */ + struct AcpiGenericAddress sleep_ctl; /* SLEEP_CONTROL_REG */ + struct AcpiGenericAddress sleep_sts; /* SLEEP_STATUS_REG */ + uint8_t reset_val; /* RESET_VALUE */ + uint8_t rev; /* Revision */ + uint32_t flags; /* Flags */ + uint32_t smi_cmd; /* SMI_CMD */ + uint16_t sci_int; /* SCI_INT */ + uint8_t int_model; /* INT_MODEL */ + uint8_t acpi_enable_cmd; /* ACPI_ENABLE */ + uint8_t acpi_disable_cmd; /* ACPI_DISABLE */ + uint8_t rtc_century; /* CENTURY */ + uint16_t plvl2_lat; /* P_LVL2_LAT */ + uint16_t plvl3_lat; /* P_LVL3_LAT */ + uint16_t arm_boot_arch; /* ARM_BOOT_ARCH */ + uint8_t minor_ver; /* FADT Minor Version */ + + /* + * respective tables offsets within ACPI_BUILD_TABLE_FILE, + * NULL if table doesn't exist (in that case field's value + * won't be patched by linker and will be kept set to 0) + */ + unsigned *facs_tbl_offset; /* FACS offset in */ + unsigned *dsdt_tbl_offset; + unsigned *xdsdt_tbl_offset; +} AcpiFadtData; + +#define ACPI_FADT_ARM_PSCI_COMPLIANT (1 << 0) +#define ACPI_FADT_ARM_PSCI_USE_HVC (1 << 1) + +#endif diff --git a/include/hw/acpi/acpi.h b/include/hw/acpi/acpi.h new file mode 100644 index 000000000..cc0d37074 --- /dev/null +++ b/include/hw/acpi/acpi.h @@ -0,0 +1,203 @@ +#ifndef QEMU_HW_ACPI_H +#define QEMU_HW_ACPI_H + +/* + * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + * + * 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.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + * <http://www.gnu.org/licenses/>. + */ + +#include "qemu/notify.h" +#include "exec/memory.h" +#include "hw/acpi/acpi_dev_interface.h" + +/* + * current device naming scheme supports up to 256 memory devices + */ +#define ACPI_MAX_RAM_SLOTS 256 + +/* from linux include/acpi/actype.h */ +/* Default ACPI register widths */ + +#define ACPI_GPE_REGISTER_WIDTH 8 +#define ACPI_PM1_REGISTER_WIDTH 16 +#define ACPI_PM2_REGISTER_WIDTH 8 +#define ACPI_PM_TIMER_WIDTH 32 + +/* PC-style peripherals (also used by other machines). */ +#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_ACPI_PCIHP_BRIDGE "acpi-pci-hotplug-with-bridge-support" +#define ACPI_PM_PROP_ACPI_PCI_ROOTHP "acpi-root-pci-hotplug" + +/* PM Timer ticks per second (HZ) */ +#define PM_TIMER_FREQUENCY 3579545 + + +/* ACPI fixed hardware registers */ + +/* from linux/drivers/acpi/acpica/aclocal.h */ +/* Masks used to access the bit_registers */ + +/* PM1x_STS */ +#define ACPI_BITMASK_TIMER_STATUS 0x0001 +#define ACPI_BITMASK_BUS_MASTER_STATUS 0x0010 +#define ACPI_BITMASK_GLOBAL_LOCK_STATUS 0x0020 +#define ACPI_BITMASK_POWER_BUTTON_STATUS 0x0100 +#define ACPI_BITMASK_SLEEP_BUTTON_STATUS 0x0200 +#define ACPI_BITMASK_RT_CLOCK_STATUS 0x0400 +#define ACPI_BITMASK_PCIEXP_WAKE_STATUS 0x4000 /* ACPI 3.0 */ +#define ACPI_BITMASK_WAKE_STATUS 0x8000 + +#define ACPI_BITMASK_ALL_FIXED_STATUS (\ + ACPI_BITMASK_TIMER_STATUS | \ + ACPI_BITMASK_BUS_MASTER_STATUS | \ + ACPI_BITMASK_GLOBAL_LOCK_STATUS | \ + ACPI_BITMASK_POWER_BUTTON_STATUS | \ + ACPI_BITMASK_SLEEP_BUTTON_STATUS | \ + ACPI_BITMASK_RT_CLOCK_STATUS | \ + ACPI_BITMASK_WAKE_STATUS) + +/* PM1x_EN */ +#define ACPI_BITMASK_TIMER_ENABLE 0x0001 +#define ACPI_BITMASK_GLOBAL_LOCK_ENABLE 0x0020 +#define ACPI_BITMASK_POWER_BUTTON_ENABLE 0x0100 +#define ACPI_BITMASK_SLEEP_BUTTON_ENABLE 0x0200 +#define ACPI_BITMASK_RT_CLOCK_ENABLE 0x0400 +#define ACPI_BITMASK_PCIEXP_WAKE_DISABLE 0x4000 /* ACPI 3.0 */ + +#define ACPI_BITMASK_PM1_COMMON_ENABLED ( \ + ACPI_BITMASK_RT_CLOCK_ENABLE | \ + ACPI_BITMASK_POWER_BUTTON_ENABLE | \ + ACPI_BITMASK_GLOBAL_LOCK_ENABLE | \ + ACPI_BITMASK_TIMER_ENABLE) + +/* PM1x_CNT */ +#define ACPI_BITMASK_SCI_ENABLE 0x0001 +#define ACPI_BITMASK_BUS_MASTER_RLD 0x0002 +#define ACPI_BITMASK_GLOBAL_LOCK_RELEASE 0x0004 +#define ACPI_BITMASK_SLEEP_TYPE 0x1C00 +#define ACPI_BITMASK_SLEEP_ENABLE 0x2000 + +/* PM2_CNT */ +#define ACPI_BITMASK_ARB_DISABLE 0x0001 + +/* structs */ +typedef struct ACPIPMTimer ACPIPMTimer; +typedef struct ACPIPM1EVT ACPIPM1EVT; +typedef struct ACPIPM1CNT ACPIPM1CNT; +typedef struct ACPIGPE ACPIGPE; +typedef struct ACPIREGS ACPIREGS; + +typedef void (*acpi_update_sci_fn)(ACPIREGS *ar); + +struct ACPIPMTimer { + QEMUTimer *timer; + MemoryRegion io; + int64_t overflow_time; + + acpi_update_sci_fn update_sci; +}; + +struct ACPIPM1EVT { + MemoryRegion io; + uint16_t sts; + uint16_t en; + acpi_update_sci_fn update_sci; +}; + +struct ACPIPM1CNT { + MemoryRegion io; + uint16_t cnt; + uint8_t s4_val; + bool acpi_only; +}; + +struct ACPIGPE { + uint8_t len; + + uint8_t *sts; + uint8_t *en; +}; + +struct ACPIREGS { + ACPIPMTimer tmr; + ACPIGPE gpe; + struct { + ACPIPM1EVT evt; + ACPIPM1CNT cnt; + } pm1; + Notifier wakeup; +}; + +/* PM_TMR */ +void acpi_pm_tmr_update(ACPIREGS *ar, bool enable); +void acpi_pm_tmr_calc_overflow_time(ACPIREGS *ar); +void acpi_pm_tmr_init(ACPIREGS *ar, acpi_update_sci_fn update_sci, + MemoryRegion *parent); +void acpi_pm_tmr_reset(ACPIREGS *ar); + +/* PM1a_EVT: piix and ich9 don't implement PM1b. */ +uint16_t acpi_pm1_evt_get_sts(ACPIREGS *ar); +void acpi_pm1_evt_power_down(ACPIREGS *ar); +void acpi_pm1_evt_reset(ACPIREGS *ar); +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, + bool disable_s3, bool disable_s4, uint8_t s4_val, + bool acpi_only); +void acpi_pm1_cnt_update(ACPIREGS *ar, + bool sci_enable, bool sci_disable); +void acpi_pm1_cnt_reset(ACPIREGS *ar); + +/* GPE0 */ +void acpi_gpe_init(ACPIREGS *ar, uint8_t len); +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, + AcpiEventStatusBits status); + +void acpi_update_sci(ACPIREGS *acpi_regs, qemu_irq irq); + +/* acpi.c */ +extern char unsigned *acpi_tables; +extern size_t acpi_tables_len; + +uint8_t *acpi_table_first(void); +uint8_t *acpi_table_next(uint8_t *current); +unsigned acpi_table_len(void *current); +void acpi_table_add(const QemuOpts *opts, Error **errp); + +typedef struct AcpiSlicOem AcpiSlicOem; +struct AcpiSlicOem { + char *id; + char *table_id; +}; +int acpi_get_slic_oem(AcpiSlicOem *oem); + +#endif /* QEMU_HW_ACPI_H */ diff --git a/include/hw/acpi/acpi_dev_interface.h b/include/hw/acpi/acpi_dev_interface.h new file mode 100644 index 000000000..ea6056ab9 --- /dev/null +++ b/include/hw/acpi/acpi_dev_interface.h @@ -0,0 +1,59 @@ +#ifndef ACPI_DEV_INTERFACE_H +#define ACPI_DEV_INTERFACE_H + +#include "qapi/qapi-types-acpi.h" +#include "qom/object.h" +#include "hw/boards.h" +#include "hw/qdev-core.h" + +/* 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, + ACPI_NVDIMM_HOTPLUG_STATUS = 16, + ACPI_VMGENID_CHANGE_STATUS = 32, + ACPI_POWER_DOWN_STATUS = 64, +} AcpiEventStatusBits; + +#define TYPE_ACPI_DEVICE_IF "acpi-device-interface" + +typedef struct AcpiDeviceIfClass AcpiDeviceIfClass; +DECLARE_CLASS_CHECKERS(AcpiDeviceIfClass, ACPI_DEVICE_IF, + TYPE_ACPI_DEVICE_IF) +#define ACPI_DEVICE_IF(obj) \ + INTERFACE_CHECK(AcpiDeviceIf, (obj), \ + TYPE_ACPI_DEVICE_IF) + +typedef struct AcpiDeviceIf AcpiDeviceIf; + +void acpi_send_event(DeviceState *dev, AcpiEventStatusBits event); + +/** + * AcpiDeviceIfClass: + * + * ospm_status: returns status of ACPI device objects, reported + * via _OST method if device supports it. + * send_event: inject a specified event into guest + * madt_cpu: fills @entry with Interrupt Controller Structure + * for CPU indexed by @uid in @apic_ids array, + * returned structure types are: + * 0 - Local APIC, 9 - Local x2APIC, 0xB - GICC + * + * Interface is designed for providing unified interface + * to generic ACPI functionality that could be used without + * knowledge about internals of actual device that implements + * ACPI interface. + */ +struct AcpiDeviceIfClass { + /* <private> */ + InterfaceClass parent_class; + + /* <public> */ + void (*ospm_status)(AcpiDeviceIf *adev, ACPIOSTInfoList ***list); + void (*send_event)(AcpiDeviceIf *adev, AcpiEventStatusBits ev); + void (*madt_cpu)(AcpiDeviceIf *adev, int uid, + const CPUArchIdList *apic_ids, GArray *entry, + bool force_enabled); +}; +#endif diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h new file mode 100644 index 000000000..8346003a2 --- /dev/null +++ b/include/hw/acpi/aml-build.h @@ -0,0 +1,500 @@ +#ifndef HW_ACPI_AML_BUILD_H +#define HW_ACPI_AML_BUILD_H + +#include "hw/acpi/acpi-defs.h" +#include "hw/acpi/bios-linker-loader.h" + +#define ACPI_BUILD_APPNAME6 "BOCHS " +#define ACPI_BUILD_APPNAME8 "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" +#define ACPI_BUILD_LOADER_FILE "etc/table-loader" + +#define AML_NOTIFY_METHOD "NTFY" + +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 enum { + AML_COMPATIBILITY = 0, + AML_TYPEA = 1, + AML_TYPEB = 2, + AML_TYPEF = 3, +} AmlDmaType; + +typedef enum { + AML_NOTBUSMASTER = 0, + AML_BUSMASTER = 1, +} AmlDmaBusMaster; + +typedef enum { + AML_TRANSFER8 = 0, + AML_TRANSFER8_16 = 1, + AML_TRANSFER16 = 2, +} AmlTransferSize; + +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_NOLOCK = 0, + AML_LOCK = 1, +} AmlLockRule; + +typedef enum { + AML_PRESERVE = 0, + AML_WRITE_AS_ONES = 1, + AML_WRITE_AS_ZEROS = 2, +} AmlUpdateRule; + +typedef enum { + AML_AS_SYSTEM_MEMORY = 0X00, + AML_AS_SYSTEM_IO = 0X01, + AML_AS_PCI_CONFIG = 0X02, + AML_AS_EMBEDDED_CTRL = 0X03, + AML_AS_SMBUS = 0X04, + AML_AS_FFH = 0X7F, +} AmlAddressSpace; + +typedef enum { + AML_SYSTEM_MEMORY = 0X00, + AML_SYSTEM_IO = 0X01, + AML_PCI_CONFIG = 0X02, +} 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; + +/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: MethodFlags */ +typedef enum { + AML_NOTSERIALIZED = 0, + AML_SERIALIZED = 1, +} AmlSerializeFlag; + +/* + * ACPI 5.0: Table 6-189 GPIO Connection Descriptor Definition + * GPIO Connection Type + */ +typedef enum { + AML_INTERRUPT_CONNECTION = 0, + AML_IO_CONNECTION = 1, +} AmlGpioConnectionType; + +/* + * ACPI 5.0: Table 6-189 GPIO Connection Descriptor Definition + * _PPI field definition + */ +typedef enum { + AML_PULL_DEFAULT = 0, + AML_PULL_UP = 1, + AML_PULL_DOWN = 2, + AML_PULL_NONE = 3, +} AmlPinConfig; + +typedef enum { + MEM_AFFINITY_NOFLAGS = 0, + MEM_AFFINITY_ENABLED = (1 << 0), + MEM_AFFINITY_HOTPLUGGABLE = (1 << 1), + MEM_AFFINITY_NON_VOLATILE = (1 << 2), +} MemoryAffinityFlags; + +typedef +struct AcpiBuildTables { + GArray *table_data; + GArray *rsdp; + GArray *tcpalog; + GArray *vmgenid; + GArray *hardware_errors; + BIOSLinker *linker; +} AcpiBuildTables; + +typedef +struct CrsRangeEntry { + uint64_t base; + uint64_t limit; +} CrsRangeEntry; + +typedef +struct CrsRangeSet { + GPtrArray *io_ranges; + GPtrArray *mem_ranges; + GPtrArray *mem_64bit_ranges; +} CrsRangeSet; + + +/* + * ACPI 5.0: 6.4.3.8.2 Serial Bus Connection Descriptors + * Serial Bus Type + */ +#define AML_SERIAL_BUS_TYPE_I2C 1 +#define AML_SERIAL_BUS_TYPE_SPI 2 +#define AML_SERIAL_BUS_TYPE_UART 3 + +/* + * ACPI 5.0: 6.4.3.8.2 Serial Bus Connection Descriptors + * General Flags + */ +/* Slave Mode */ +#define AML_SERIAL_BUS_FLAG_MASTER_DEVICE (1 << 0) +/* Consumer/Producer */ +#define AML_SERIAL_BUS_FLAG_CONSUME_ONLY (1 << 1) + +/** + * 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_debug(void); +Aml *aml_return(Aml *val); +Aml *aml_int(const uint64_t val); +Aml *aml_arg(int pos); +Aml *aml_to_integer(Aml *arg); +Aml *aml_to_hexstring(Aml *src, Aml *dst); +Aml *aml_to_buffer(Aml *src, Aml *dst); +Aml *aml_to_decimalstring(Aml *src, Aml *dst); +Aml *aml_store(Aml *val, Aml *target); +Aml *aml_and(Aml *arg1, Aml *arg2, Aml *dst); +Aml *aml_or(Aml *arg1, Aml *arg2, Aml *dst); +Aml *aml_land(Aml *arg1, Aml *arg2); +Aml *aml_lor(Aml *arg1, Aml *arg2); +Aml *aml_shiftleft(Aml *arg1, Aml *count); +Aml *aml_shiftright(Aml *arg1, Aml *count, Aml *dst); +Aml *aml_lless(Aml *arg1, Aml *arg2); +Aml *aml_add(Aml *arg1, Aml *arg2, Aml *dst); +Aml *aml_subtract(Aml *arg1, Aml *arg2, Aml *dst); +Aml *aml_increment(Aml *arg); +Aml *aml_decrement(Aml *arg); +Aml *aml_index(Aml *arg1, Aml *idx); +Aml *aml_notify(Aml *arg1, Aml *arg2); +Aml *aml_break(void); +Aml *aml_call0(const char *method); +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_call5(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4, + Aml *arg5); +Aml *aml_call6(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4, + Aml *arg5, Aml *arg6); +Aml *aml_gpio_int(AmlConsumerAndProducer con_and_pro, + AmlLevelAndEdge edge_level, + AmlActiveHighAndLow active_level, AmlShared shared, + AmlPinConfig pin_config, uint16_t debounce_timeout, + const uint32_t pin_list[], uint32_t pin_count, + const char *resource_source_name, + const uint8_t *vendor_data, uint16_t vendor_data_len); +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_list, uint8_t irq_count); +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, + Aml *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_lgreater(Aml *arg1, Aml *arg2); +Aml *aml_lgreater_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); +Aml *aml_dma(AmlDmaType typ, AmlDmaBusMaster bm, AmlTransferSize sz, + uint8_t channel); +Aml *aml_sleep(uint64_t msec); +Aml *aml_i2c_serial_bus_device(uint16_t address, const char *resource_source); + +/* 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, AmlSerializeFlag sflag); +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, AmlLockRule lock, + AmlUpdateRule rule); +Aml *aml_mutex(const char *name, uint8_t sync_level); +Aml *aml_acquire(Aml *mutex, uint16_t timeout); +Aml *aml_release(Aml *mutex); +Aml *aml_alias(const char *source_object, const char *alias_object); +Aml *aml_create_field(Aml *srcbuf, Aml *bit_index, Aml *num_bits, + const char *name); +Aml *aml_create_dword_field(Aml *srcbuf, Aml *index, const char *name); +Aml *aml_create_qword_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); +Aml *aml_refof(Aml *arg); +Aml *aml_derefof(Aml *arg); +Aml *aml_sizeof(Aml *arg); +Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target); +Aml *aml_object_type(Aml *object); + +void build_append_int_noprefix(GArray *table, uint64_t value, int size); + +typedef struct AcpiTable { + const char *sig; + const uint8_t rev; + const char *oem_id; + const char *oem_table_id; + /* private vars tracking table state */ + GArray *array; + unsigned table_offset; +} AcpiTable; + +/** + * acpi_table_begin: + * initializes table header and keeps track of + * table data/offsets + * @desc: ACPI table descriptor + * @array: blob where the ACPI table will be composed/stored. + */ +void acpi_table_begin(AcpiTable *desc, GArray *array); + +/** + * acpi_table_end: + * sets actual table length and tells bios loader + * where table is for the later initialization on + * guest side. + * @linker: reference to BIOSLinker object to use for the table + * @table: ACPI table descriptor that was used with @acpi_table_begin + * counterpart + */ +void acpi_table_end(BIOSLinker *linker, AcpiTable *table); + +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_rsdp(GArray *tbl, BIOSLinker *linker, AcpiRsdpData *rsdp_data); +void +build_rsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets, + const char *oem_id, const char *oem_table_id); +void +build_xsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets, + const char *oem_id, const char *oem_table_id); + +int +build_append_named_dword(GArray *array, const char *name_format, ...) +GCC_FMT_ATTR(2, 3); + +void build_append_gas(GArray *table, AmlAddressSpace as, + uint8_t bit_width, uint8_t bit_offset, + uint8_t access_width, uint64_t address); + +static inline void +build_append_gas_from_struct(GArray *table, const struct AcpiGenericAddress *s) +{ + build_append_gas(table, s->space_id, s->bit_width, s->bit_offset, + s->access_width, s->address); +} + +void crs_range_insert(GPtrArray *ranges, uint64_t base, uint64_t limit); +void crs_replace_with_free_ranges(GPtrArray *ranges, + uint64_t start, uint64_t end); +void crs_range_set_init(CrsRangeSet *range_set); +void crs_range_set_free(CrsRangeSet *range_set); + +Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set, uint32_t io_offset, + uint32_t mmio32_offset, uint64_t mmio64_offset, + uint16_t bus_nr_offset); + +void build_srat_memory(GArray *table_data, uint64_t base, + uint64_t len, int node, MemoryAffinityFlags flags); + +void build_slit(GArray *table_data, BIOSLinker *linker, MachineState *ms, + const char *oem_id, const char *oem_table_id); + +void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms, + const char *oem_id, const char *oem_table_id); + +void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f, + const char *oem_id, const char *oem_table_id); + +void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog, + const char *oem_id, const char *oem_table_id); +#endif diff --git a/include/hw/acpi/bios-linker-loader.h b/include/hw/acpi/bios-linker-loader.h new file mode 100644 index 000000000..a711dbced --- /dev/null +++ b/include/hw/acpi/bios-linker-loader.h @@ -0,0 +1,39 @@ +#ifndef BIOS_LINKER_LOADER_H +#define BIOS_LINKER_LOADER_H + + +typedef struct BIOSLinker { + GArray *cmd_blob; + GArray *file_list; +} BIOSLinker; + +bool bios_linker_loader_can_write_pointer(void); + +BIOSLinker *bios_linker_loader_init(void); + +void bios_linker_loader_alloc(BIOSLinker *linker, + const char *file_name, + GArray *file_blob, + uint32_t alloc_align, + bool alloc_fseg); + +void bios_linker_loader_add_checksum(BIOSLinker *linker, const char *file, + unsigned start_offset, unsigned size, + unsigned checksum_offset); + +void bios_linker_loader_add_pointer(BIOSLinker *linker, + const char *dest_file, + uint32_t dst_patched_offset, + uint8_t dst_patched_size, + const char *src_file, + uint32_t src_offset); + +void bios_linker_loader_write_pointer(BIOSLinker *linker, + const char *dest_file, + uint32_t dst_patched_offset, + uint8_t dst_patched_size, + const char *src_file, + uint32_t src_offset); + +void bios_linker_loader_cleanup(BIOSLinker *linker); +#endif diff --git a/include/hw/acpi/cpu.h b/include/hw/acpi/cpu.h new file mode 100644 index 000000000..999caaf51 --- /dev/null +++ b/include/hw/acpi/cpu.h @@ -0,0 +1,70 @@ +/* + * QEMU ACPI hotplug utilities + * + * Copyright (C) 2016 Red Hat Inc + * + * Authors: + * Igor Mammedov <imammedo@redhat.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 ACPI_CPU_H +#define ACPI_CPU_H + +#include "hw/qdev-core.h" +#include "hw/acpi/acpi.h" +#include "hw/acpi/aml-build.h" +#include "hw/hotplug.h" + +typedef struct AcpiCpuStatus { + struct CPUState *cpu; + uint64_t arch_id; + bool is_inserting; + bool is_removing; + bool fw_remove; + uint32_t ost_event; + uint32_t ost_status; +} AcpiCpuStatus; + +typedef struct CPUHotplugState { + MemoryRegion ctrl_reg; + uint32_t selector; + uint8_t command; + uint32_t dev_count; + AcpiCpuStatus *devs; +} CPUHotplugState; + +void acpi_cpu_plug_cb(HotplugHandler *hotplug_dev, + CPUHotplugState *cpu_st, DeviceState *dev, Error **errp); + +void acpi_cpu_unplug_request_cb(HotplugHandler *hotplug_dev, + CPUHotplugState *cpu_st, + DeviceState *dev, Error **errp); + +void acpi_cpu_unplug_cb(CPUHotplugState *cpu_st, + DeviceState *dev, Error **errp); + +void cpu_hotplug_hw_init(MemoryRegion *as, Object *owner, + CPUHotplugState *state, hwaddr base_addr); + +typedef struct CPUHotplugFeatures { + bool acpi_1_compatible; + bool has_legacy_cphp; + bool fw_unplugs_cpu; + const char *smi_path; +} CPUHotplugFeatures; + +void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts, + hwaddr io_base, + const char *res_root, + const char *event_handler_method); + +void acpi_cpu_ospm_status(CPUHotplugState *cpu_st, ACPIOSTInfoList ***list); + +extern const VMStateDescription vmstate_cpu_hotplug; +#define VMSTATE_CPU_HOTPLUG(cpuhp, state) \ + VMSTATE_STRUCT(cpuhp, state, 1, \ + vmstate_cpu_hotplug, CPUHotplugState) + +#endif diff --git a/include/hw/acpi/cpu_hotplug.h b/include/hw/acpi/cpu_hotplug.h new file mode 100644 index 000000000..3b932abbb --- /dev/null +++ b/include/hw/acpi/cpu_hotplug.h @@ -0,0 +1,40 @@ +/* + * QEMU ACPI hotplug utilities + * + * Copyright (C) 2013 Red Hat Inc + * + * Authors: + * Igor Mammedov <imammedo@redhat.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_CPU_HOTPLUG_H +#define HW_ACPI_CPU_HOTPLUG_H + +#include "hw/acpi/acpi.h" +#include "hw/acpi/pc-hotplug.h" +#include "hw/acpi/aml-build.h" +#include "hw/hotplug.h" +#include "hw/acpi/cpu.h" + +typedef struct AcpiCpuHotplug { + Object *device; + MemoryRegion io; + uint8_t sts[ACPI_GPE_PROC_LEN]; +} AcpiCpuHotplug; + +void legacy_acpi_cpu_plug_cb(HotplugHandler *hotplug_dev, + AcpiCpuHotplug *g, DeviceState *dev, Error **errp); + +void legacy_acpi_cpu_hotplug_init(MemoryRegion *parent, Object *owner, + AcpiCpuHotplug *gpe_cpu, uint16_t base); + +void acpi_switch_to_modern_cphp(AcpiCpuHotplug *gpe_cpu, + CPUHotplugState *cpuhp_state, + uint16_t io_port); + +void build_legacy_cpu_hotplug_aml(Aml *ctx, MachineState *machine, + uint16_t io_base); +#endif diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h new file mode 100644 index 000000000..d49217c44 --- /dev/null +++ b/include/hw/acpi/generic_event_device.h @@ -0,0 +1,121 @@ +/* + * + * Copyright (c) 2018 Intel Corporation + * Copyright (c) 2019 Huawei Technologies R & D (UK) Ltd + * Written by Samuel Ortiz, Shameer Kolothum + * + * 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. + * + * The ACPI Generic Event Device (GED) is a hardware-reduced specific + * device[ACPI v6.1 Section 5.6.9] that handles all platform events, + * including the hotplug ones. Generic Event Device allows platforms + * to handle interrupts in ACPI ASL statements. It follows a very + * similar approach like the _EVT method from GPIO events. All + * interrupts are listed in _CRS and the handler is written in _EVT + * method. Here, we use a single interrupt for the GED device, relying + * on IO memory region to communicate the type of device affected by + * the interrupt. This way, we can support up to 32 events with a + * unique interrupt. + * + * Here is an example. + * + * Device (\_SB.GED) + * { + * Name (_HID, "ACPI0013") + * Name (_UID, Zero) + * Name (_CRS, ResourceTemplate () + * { + * Interrupt (ResourceConsumer, Edge, ActiveHigh, Exclusive, ,, ) + * { + * 0x00000029, + * } + * }) + * OperationRegion (EREG, SystemMemory, 0x09080000, 0x04) + * Field (EREG, DWordAcc, NoLock, WriteAsZeros) + * { + * ESEL, 32 + * } + * + * Method (_EVT, 1, Serialized) // _EVT: Event + * { + * Local0 = ESEL // ESEL = IO memory region which specifies the + * // device type. + * If (((Local0 & One) == One)) + * { + * MethodEvent1() + * } + * If ((Local0 & 0x2) == 0x2) + * { + * MethodEvent2() + * } + * ... + * } + * } + * + */ + +#ifndef HW_ACPI_GED_H +#define HW_ACPI_GED_H + +#include "hw/sysbus.h" +#include "hw/acpi/memory_hotplug.h" +#include "hw/acpi/ghes.h" +#include "qom/object.h" + +#define ACPI_POWER_BUTTON_DEVICE "PWRB" + +#define TYPE_ACPI_GED "acpi-ged" +OBJECT_DECLARE_SIMPLE_TYPE(AcpiGedState, ACPI_GED) + +#define TYPE_ACPI_GED_X86 "acpi-ged-x86" + +#define ACPI_GED_EVT_SEL_OFFSET 0x0 +#define ACPI_GED_EVT_SEL_LEN 0x4 + +#define ACPI_GED_REG_SLEEP_CTL 0x00 +#define ACPI_GED_REG_SLEEP_STS 0x01 +#define ACPI_GED_REG_RESET 0x02 +#define ACPI_GED_REG_COUNT 0x03 + +/* ACPI_GED_REG_RESET value for reset*/ +#define ACPI_GED_RESET_VALUE 0x42 + +/* ACPI_GED_REG_SLEEP_CTL.SLP_TYP value for S5 (aka poweroff) */ +#define ACPI_GED_SLP_TYP_S5 0x05 + +#define GED_DEVICE "GED" +#define AML_GED_EVT_REG "EREG" +#define AML_GED_EVT_SEL "ESEL" + +/* + * Platforms need to specify the GED event bitmap + * to describe what kind of events they want to support + * through GED. + */ +#define ACPI_GED_MEM_HOTPLUG_EVT 0x1 +#define ACPI_GED_PWR_DOWN_EVT 0x2 +#define ACPI_GED_NVDIMM_HOTPLUG_EVT 0x4 + +typedef struct GEDState { + MemoryRegion evt; + MemoryRegion regs; + uint32_t sel; +} GEDState; + +struct AcpiGedState { + SysBusDevice parent_obj; + MemHotplugState memhp_state; + MemoryRegion container_memhp; + GEDState ged_state; + uint32_t ged_event_bitmap; + qemu_irq irq; + AcpiGhesState ghes_state; +}; + +void build_ged_aml(Aml *table, const char* name, HotplugHandler *hotplug_dev, + uint32_t ged_irq, AmlRegionSpace rs, hwaddr ged_base); +void acpi_dsdt_add_power_button(Aml *scope); + +#endif diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h new file mode 100644 index 000000000..674f6958e --- /dev/null +++ b/include/hw/acpi/ghes.h @@ -0,0 +1,84 @@ +/* + * Support for generating APEI tables and recording CPER for Guests + * + * Copyright (c) 2020 HUAWEI TECHNOLOGIES CO., LTD. + * + * Author: Dongjiu Geng <gengdongjiu@huawei.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 ACPI_GHES_H +#define ACPI_GHES_H + +#include "hw/acpi/bios-linker-loader.h" + +/* + * Values for Hardware Error Notification Type field + */ +enum AcpiGhesNotifyType { + /* Polled */ + ACPI_GHES_NOTIFY_POLLED = 0, + /* External Interrupt */ + ACPI_GHES_NOTIFY_EXTERNAL = 1, + /* Local Interrupt */ + ACPI_GHES_NOTIFY_LOCAL = 2, + /* SCI */ + ACPI_GHES_NOTIFY_SCI = 3, + /* NMI */ + ACPI_GHES_NOTIFY_NMI = 4, + /* CMCI, ACPI 5.0: 18.3.2.7, Table 18-290 */ + ACPI_GHES_NOTIFY_CMCI = 5, + /* MCE, ACPI 5.0: 18.3.2.7, Table 18-290 */ + ACPI_GHES_NOTIFY_MCE = 6, + /* GPIO-Signal, ACPI 6.0: 18.3.2.7, Table 18-332 */ + ACPI_GHES_NOTIFY_GPIO = 7, + /* ARMv8 SEA, ACPI 6.1: 18.3.2.9, Table 18-345 */ + ACPI_GHES_NOTIFY_SEA = 8, + /* ARMv8 SEI, ACPI 6.1: 18.3.2.9, Table 18-345 */ + ACPI_GHES_NOTIFY_SEI = 9, + /* External Interrupt - GSIV, ACPI 6.1: 18.3.2.9, Table 18-345 */ + ACPI_GHES_NOTIFY_GSIV = 10, + /* Software Delegated Exception, ACPI 6.2: 18.3.2.9, Table 18-383 */ + ACPI_GHES_NOTIFY_SDEI = 11, + /* 12 and greater are reserved */ + ACPI_GHES_NOTIFY_RESERVED = 12 +}; + +enum { + ACPI_HEST_SRC_ID_SEA = 0, + /* future ids go here */ + ACPI_HEST_SRC_ID_RESERVED, +}; + +typedef struct AcpiGhesState { + uint64_t ghes_addr_le; + bool present; /* True if GHES is present at all on this board */ +} AcpiGhesState; + +void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker); +void acpi_build_hest(GArray *table_data, BIOSLinker *linker, + const char *oem_id, const char *oem_table_id); +void acpi_ghes_add_fw_cfg(AcpiGhesState *vms, FWCfgState *s, + GArray *hardware_errors); +int acpi_ghes_record_errors(uint8_t notify, uint64_t error_physical_addr); + +/** + * acpi_ghes_present: Report whether ACPI GHES table is present + * + * Returns: true if the system has an ACPI GHES table and it is + * safe to call acpi_ghes_record_errors() to record a memory error. + */ +bool acpi_ghes_present(void); +#endif diff --git a/include/hw/acpi/ich9.h b/include/hw/acpi/ich9.h new file mode 100644 index 000000000..7ca92843c --- /dev/null +++ b/include/hw/acpi/ich9.h @@ -0,0 +1,94 @@ +/* + * QEMU GMCH/ICH9 LPC PM Emulation + * + * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + * + * 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.1 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_ACPI_ICH9_H +#define HW_ACPI_ICH9_H + +#include "hw/acpi/acpi.h" +#include "hw/acpi/cpu_hotplug.h" +#include "hw/acpi/cpu.h" +#include "hw/acpi/pcihp.h" +#include "hw/acpi/memory_hotplug.h" +#include "hw/acpi/acpi_dev_interface.h" +#include "hw/acpi/tco.h" + +#define ACPI_PCIHP_ADDR_ICH9 0x0cc0 + +typedef struct ICH9LPCPMRegs { + /* + * In ich9 spec says that pm1_cnt register is 32bit width and + * that the upper 16bits are reserved and unused. + * PM1a_CNT_BLK = 2 in FADT so it is defined as uint16_t. + */ + ACPIREGS acpi_regs; + + MemoryRegion io; + MemoryRegion io_gpe; + MemoryRegion io_smi; + + uint32_t smi_en; + uint32_t smi_en_wmask; + uint32_t smi_sts; + + qemu_irq irq; /* SCI */ + + uint32_t pm_io_base; + Notifier powerdown_notifier; + + bool cpu_hotplug_legacy; + AcpiCpuHotplug gpe_cpu; + CPUHotplugState cpuhp_state; + + bool keep_pci_slot_hpc; + bool use_acpi_hotplug_bridge; + AcpiPciHpState acpi_pci_hotplug; + MemHotplugState acpi_memory_hotplug; + + uint8_t disable_s3; + uint8_t disable_s4; + uint8_t s4_val; + uint8_t smm_enabled; + bool smm_compat; + bool enable_tco; + TCOIORegs tco_regs; +} ICH9LPCPMRegs; + +#define ACPI_PM_PROP_TCO_ENABLED "enable_tco" + +void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm, + bool smm_enabled, + 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); + +void ich9_pm_device_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp); +void ich9_pm_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp); +void ich9_pm_device_unplug_request_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp); +void ich9_pm_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp); + +void ich9_pm_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list); +#endif /* HW_ACPI_ICH9_H */ diff --git a/include/hw/acpi/ipmi.h b/include/hw/acpi/ipmi.h new file mode 100644 index 000000000..c14ad682a --- /dev/null +++ b/include/hw/acpi/ipmi.h @@ -0,0 +1,21 @@ +/* + * QEMU IPMI ACPI handling + * + * Copyright (c) 2015,2016 Corey Minyard <cminyard@mvista.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_IPMI_H +#define HW_ACPI_IPMI_H + +#include "hw/acpi/aml-build.h" + +/* + * Add ACPI IPMI entries for all registered IPMI devices whose parent + * bus matches the given bus. The resource is the ACPI resource that + * contains the IPMI device, this is required for the I2C CRS. + */ +void build_acpi_ipmi_devices(Aml *table, BusState *bus, const char *resource); + +#endif /* HW_ACPI_IPMI_H */ diff --git a/include/hw/acpi/memory_hotplug.h b/include/hw/acpi/memory_hotplug.h new file mode 100644 index 000000000..dfe9cf3fd --- /dev/null +++ b/include/hw/acpi/memory_hotplug.h @@ -0,0 +1,57 @@ +#ifndef QEMU_HW_ACPI_MEMORY_HOTPLUG_H +#define QEMU_HW_ACPI_MEMORY_HOTPLUG_H + +#include "hw/qdev-core.h" +#include "hw/acpi/acpi.h" +#include "hw/acpi/aml-build.h" + +#define MEMORY_SLOT_SCAN_METHOD "MSCN" +#define MEMORY_DEVICES_CONTAINER "\\_SB.MHPC" +#define MEMORY_HOTPLUG_IO_LEN 24 + +/** + * 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; + +typedef struct MemHotplugState { + bool is_enabled; /* true if memory hotplug is supported */ + MemoryRegion io; + uint32_t selector; + uint32_t dev_count; + MemStatus *devs; +} MemHotplugState; + +void acpi_memory_hotplug_init(MemoryRegion *as, Object *owner, + MemHotplugState *state, hwaddr io_base); + +void acpi_memory_plug_cb(HotplugHandler *hotplug_dev, MemHotplugState *mem_st, + DeviceState *dev, Error **errp); +void acpi_memory_unplug_request_cb(HotplugHandler *hotplug_dev, + 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) \ + VMSTATE_STRUCT(memhp, state, 1, \ + vmstate_memory_hotplug, MemHotplugState) + +void acpi_memory_ospm_status(MemHotplugState *mem_st, ACPIOSTInfoList ***list); + +void build_memory_hotplug_aml(Aml *table, uint32_t nr_mem, + const char *res_root, + const char *event_handler_method, + AmlRegionSpace rs, hwaddr memhp_io_base); +#endif diff --git a/include/hw/acpi/pc-hotplug.h b/include/hw/acpi/pc-hotplug.h new file mode 100644 index 000000000..31bc9191c --- /dev/null +++ b/include/hw/acpi/pc-hotplug.h @@ -0,0 +1,34 @@ +/* + * QEMU ACPI hotplug utilities shared defines + * + * Copyright (C) 2014 Red Hat Inc + * + * Authors: + * Igor Mammedov <imammedo@redhat.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 PC_HOTPLUG_H +#define PC_HOTPLUG_H + +/* + * ONLY DEFINEs are permited in this file since it's shared + * between C and ASL code. + */ + +/* Limit for CPU arch IDs for CPU hotplug. All hotpluggable CPUs should + * have CPUClass.get_arch_id() < ACPI_CPU_HOTPLUG_ID_LIMIT. + */ +#define ACPI_CPU_HOTPLUG_ID_LIMIT 256 + +/* 256 CPU IDs, 8 bits per entry: */ +#define ACPI_GPE_PROC_LEN 32 + +#define ICH9_CPU_HOTPLUG_IO_BASE 0x0CD8 +#define PIIX4_CPU_HOTPLUG_IO_BASE 0xaf00 +#define CPU_HOTPLUG_RESOURCE_DEVICE PRES + +#define ACPI_MEMORY_HOTPLUG_BASE 0x0a00 + +#endif diff --git a/include/hw/acpi/pci.h b/include/hw/acpi/pci.h new file mode 100644 index 000000000..b5deee0a9 --- /dev/null +++ b/include/hw/acpi/pci.h @@ -0,0 +1,39 @@ +/* + * Support for generating PCI related ACPI tables and passing them to Guests + * + * Copyright (C) 2006 Fabrice Bellard + * Copyright (C) 2008-2010 Kevin O'Connor <kevin@koconnor.net> + * Copyright (C) 2013-2019 Red Hat Inc + * Copyright (C) 2019 Intel Corporation + * + * Author: Wei Yang <richardw.yang@linux.intel.com> + * Author: Michael S. Tsirkin <mst@redhat.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 HW_ACPI_PCI_H +#define HW_ACPI_PCI_H + +#include "hw/acpi/bios-linker-loader.h" + +typedef struct AcpiMcfgInfo { + uint64_t base; + uint32_t size; +} AcpiMcfgInfo; + +void build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info, + const char *oem_id, const char *oem_table_id); +Aml *aml_pci_device_dsm(void); +#endif diff --git a/include/hw/acpi/pcihp.h b/include/hw/acpi/pcihp.h new file mode 100644 index 000000000..af1a169fc --- /dev/null +++ b/include/hw/acpi/pcihp.h @@ -0,0 +1,89 @@ +/* + * QEMU<->ACPI BIOS PCI hotplug interface + * + * QEMU supports PCI hotplug via ACPI. This module + * implements the interface between QEMU and the ACPI BIOS. + * Interface specification - see docs/specs/acpi_pci_hotplug.txt + * + * Copyright (c) 2013, Red Hat Inc, Michael S. Tsirkin (mst@redhat.com) + * Copyright (c) 2006 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * 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/> + * + * Contributions after 2012-01-13 are licensed under the terms of the + * GNU GPL, version 2 or (at your option) any later version. + */ + +#ifndef HW_ACPI_PCIHP_H +#define HW_ACPI_PCIHP_H + +#include "hw/acpi/acpi.h" +#include "hw/hotplug.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; + uint32_t hotplug_enable; +} AcpiPciHpPciStatus; + +#define ACPI_PCIHP_PROP_BSEL "acpi-pcihp-bsel" +#define ACPI_PCIHP_MAX_HOTPLUG_BUS 256 +#define ACPI_PCIHP_BSEL_DEFAULT 0x0 + +typedef struct AcpiPciHpState { + AcpiPciHpPciStatus acpi_pcihp_pci_status[ACPI_PCIHP_MAX_HOTPLUG_BUS]; + uint32_t hotplug_select; + uint32_t acpi_index; + PCIBus *root; + MemoryRegion io; + bool legacy_piix; + uint16_t io_base; + uint16_t io_len; +} AcpiPciHpState; + +void acpi_pcihp_init(Object *owner, AcpiPciHpState *, PCIBus *root, + MemoryRegion *address_space_io, bool bridges_enabled, + uint16_t io_base); + +void acpi_pcihp_device_pre_plug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp); +void acpi_pcihp_device_plug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s, + DeviceState *dev, Error **errp); +void acpi_pcihp_device_unplug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s, + DeviceState *dev, Error **errp); +void acpi_pcihp_device_unplug_request_cb(HotplugHandler *hotplug_dev, + AcpiPciHpState *s, DeviceState *dev, + Error **errp); + +/* Called on reset */ +void acpi_pcihp_reset(AcpiPciHpState *s, bool acpihp_root_off); + +extern const VMStateDescription vmstate_acpi_pcihp_pci_status; + +bool vmstate_acpi_pcihp_use_acpi_index(void *opaque, int version_id); + +#define VMSTATE_PCI_HOTPLUG(pcihp, state, test_pcihp, test_acpi_index) \ + VMSTATE_UINT32_TEST(pcihp.hotplug_select, state, \ + test_pcihp), \ + VMSTATE_STRUCT_ARRAY_TEST(pcihp.acpi_pcihp_pci_status, state, \ + ACPI_PCIHP_MAX_HOTPLUG_BUS, \ + test_pcihp, 1, \ + vmstate_acpi_pcihp_pci_status, \ + AcpiPciHpPciStatus), \ + VMSTATE_UINT32_TEST(pcihp.acpi_index, state, \ + test_acpi_index) + +#endif diff --git a/include/hw/acpi/tco.h b/include/hw/acpi/tco.h new file mode 100644 index 000000000..a1e0da821 --- /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 "exec/memory.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 new file mode 100644 index 000000000..559ba6906 --- /dev/null +++ b/include/hw/acpi/tpm.h @@ -0,0 +1,216 @@ +/* + * tpm.h - TPM ACPI definitions + * + * Copyright (C) 2014 IBM Corporation + * + * Authors: + * Stefan Berger <stefanb@us.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + * Implementation of the TIS interface according to specs found at + * http://www.trustedcomputinggroup.org + * + */ +#ifndef HW_ACPI_TPM_H +#define HW_ACPI_TPM_H + +#include "qemu/units.h" +#include "hw/registerfields.h" +#include "hw/acpi/aml-build.h" +#include "sysemu/tpm.h" + +#ifdef CONFIG_TPM + +#define TPM_TIS_ADDR_BASE 0xFED40000 +#define TPM_TIS_ADDR_SIZE 0x5000 + +#define TPM_TIS_IRQ 5 + +#define TPM_TIS_NUM_LOCALITIES 5 /* per spec */ +#define TPM_TIS_LOCALITY_SHIFT 12 + +/* tis registers */ +#define TPM_TIS_REG_ACCESS 0x00 +#define TPM_TIS_REG_INT_ENABLE 0x08 +#define TPM_TIS_REG_INT_VECTOR 0x0c +#define TPM_TIS_REG_INT_STATUS 0x10 +#define TPM_TIS_REG_INTF_CAPABILITY 0x14 +#define TPM_TIS_REG_STS 0x18 +#define TPM_TIS_REG_DATA_FIFO 0x24 +#define TPM_TIS_REG_INTERFACE_ID 0x30 +#define TPM_TIS_REG_DATA_XFIFO 0x80 +#define TPM_TIS_REG_DATA_XFIFO_END 0xbc +#define TPM_TIS_REG_DID_VID 0xf00 +#define TPM_TIS_REG_RID 0xf04 + +/* vendor-specific registers */ +#define TPM_TIS_REG_DEBUG 0xf90 + +#define TPM_TIS_STS_TPM_FAMILY_MASK (0x3 << 26)/* TPM 2.0 */ +#define TPM_TIS_STS_TPM_FAMILY1_2 (0 << 26) /* TPM 2.0 */ +#define TPM_TIS_STS_TPM_FAMILY2_0 (1 << 26) /* TPM 2.0 */ +#define TPM_TIS_STS_RESET_ESTABLISHMENT_BIT (1 << 25) /* TPM 2.0 */ +#define TPM_TIS_STS_COMMAND_CANCEL (1 << 24) /* TPM 2.0 */ + +#define TPM_TIS_STS_VALID (1 << 7) +#define TPM_TIS_STS_COMMAND_READY (1 << 6) +#define TPM_TIS_STS_TPM_GO (1 << 5) +#define TPM_TIS_STS_DATA_AVAILABLE (1 << 4) +#define TPM_TIS_STS_EXPECT (1 << 3) +#define TPM_TIS_STS_SELFTEST_DONE (1 << 2) +#define TPM_TIS_STS_RESPONSE_RETRY (1 << 1) + +#define TPM_TIS_BURST_COUNT_SHIFT 8 +#define TPM_TIS_BURST_COUNT(X) \ + ((X) << TPM_TIS_BURST_COUNT_SHIFT) + +#define TPM_TIS_ACCESS_TPM_REG_VALID_STS (1 << 7) +#define TPM_TIS_ACCESS_ACTIVE_LOCALITY (1 << 5) +#define TPM_TIS_ACCESS_BEEN_SEIZED (1 << 4) +#define TPM_TIS_ACCESS_SEIZE (1 << 3) +#define TPM_TIS_ACCESS_PENDING_REQUEST (1 << 2) +#define TPM_TIS_ACCESS_REQUEST_USE (1 << 1) +#define TPM_TIS_ACCESS_TPM_ESTABLISHMENT (1 << 0) + +#define TPM_TIS_INT_ENABLED (1 << 31) +#define TPM_TIS_INT_DATA_AVAILABLE (1 << 0) +#define TPM_TIS_INT_STS_VALID (1 << 1) +#define TPM_TIS_INT_LOCALITY_CHANGED (1 << 2) +#define TPM_TIS_INT_COMMAND_READY (1 << 7) + +#define TPM_TIS_INT_POLARITY_MASK (3 << 3) +#define TPM_TIS_INT_POLARITY_LOW_LEVEL (1 << 3) + +#define TPM_TIS_INTERRUPTS_SUPPORTED (TPM_TIS_INT_LOCALITY_CHANGED | \ + TPM_TIS_INT_DATA_AVAILABLE | \ + TPM_TIS_INT_STS_VALID | \ + TPM_TIS_INT_COMMAND_READY) + +#define TPM_TIS_CAP_INTERFACE_VERSION1_3 (2 << 28) +#define TPM_TIS_CAP_INTERFACE_VERSION1_3_FOR_TPM2_0 (3 << 28) +#define TPM_TIS_CAP_DATA_TRANSFER_64B (3 << 9) +#define TPM_TIS_CAP_DATA_TRANSFER_LEGACY (0 << 9) +#define TPM_TIS_CAP_BURST_COUNT_DYNAMIC (0 << 8) +#define TPM_TIS_CAP_INTERRUPT_LOW_LEVEL (1 << 4) /* support is mandatory */ +#define TPM_TIS_CAPABILITIES_SUPPORTED1_3 \ + (TPM_TIS_CAP_INTERRUPT_LOW_LEVEL | \ + TPM_TIS_CAP_BURST_COUNT_DYNAMIC | \ + TPM_TIS_CAP_DATA_TRANSFER_64B | \ + TPM_TIS_CAP_INTERFACE_VERSION1_3 | \ + TPM_TIS_INTERRUPTS_SUPPORTED) + +#define TPM_TIS_CAPABILITIES_SUPPORTED2_0 \ + (TPM_TIS_CAP_INTERRUPT_LOW_LEVEL | \ + TPM_TIS_CAP_BURST_COUNT_DYNAMIC | \ + TPM_TIS_CAP_DATA_TRANSFER_64B | \ + TPM_TIS_CAP_INTERFACE_VERSION1_3_FOR_TPM2_0 | \ + TPM_TIS_INTERRUPTS_SUPPORTED) + +#define TPM_TIS_IFACE_ID_INTERFACE_TIS1_3 (0xf) /* TPM 2.0 */ +#define TPM_TIS_IFACE_ID_INTERFACE_FIFO (0x0) /* TPM 2.0 */ +#define TPM_TIS_IFACE_ID_INTERFACE_VER_FIFO (0 << 4) /* TPM 2.0 */ +#define TPM_TIS_IFACE_ID_CAP_5_LOCALITIES (1 << 8) /* TPM 2.0 */ +#define TPM_TIS_IFACE_ID_CAP_TIS_SUPPORTED (1 << 13) /* TPM 2.0 */ +#define TPM_TIS_IFACE_ID_INT_SEL_LOCK (1 << 19) /* TPM 2.0 */ + +#define TPM_TIS_IFACE_ID_SUPPORTED_FLAGS1_3 \ + (TPM_TIS_IFACE_ID_INTERFACE_TIS1_3 | \ + (~0u << 4)/* all of it is don't care */) + +/* if backend was a TPM 2.0: */ +#define TPM_TIS_IFACE_ID_SUPPORTED_FLAGS2_0 \ + (TPM_TIS_IFACE_ID_INTERFACE_FIFO | \ + TPM_TIS_IFACE_ID_INTERFACE_VER_FIFO | \ + TPM_TIS_IFACE_ID_CAP_5_LOCALITIES | \ + TPM_TIS_IFACE_ID_CAP_TIS_SUPPORTED) + +#define TPM_TIS_TPM_DID 0x0001 +#define TPM_TIS_TPM_VID PCI_VENDOR_ID_IBM +#define TPM_TIS_TPM_RID 0x0001 + +#define TPM_TIS_NO_DATA_BYTE 0xff + + +REG32(CRB_LOC_STATE, 0x00) + FIELD(CRB_LOC_STATE, tpmEstablished, 0, 1) + FIELD(CRB_LOC_STATE, locAssigned, 1, 1) + FIELD(CRB_LOC_STATE, activeLocality, 2, 3) + FIELD(CRB_LOC_STATE, reserved, 5, 2) + FIELD(CRB_LOC_STATE, tpmRegValidSts, 7, 1) +REG32(CRB_LOC_CTRL, 0x08) +REG32(CRB_LOC_STS, 0x0C) + FIELD(CRB_LOC_STS, Granted, 0, 1) + FIELD(CRB_LOC_STS, beenSeized, 1, 1) +REG32(CRB_INTF_ID, 0x30) + FIELD(CRB_INTF_ID, InterfaceType, 0, 4) + FIELD(CRB_INTF_ID, InterfaceVersion, 4, 4) + FIELD(CRB_INTF_ID, CapLocality, 8, 1) + FIELD(CRB_INTF_ID, CapCRBIdleBypass, 9, 1) + FIELD(CRB_INTF_ID, Reserved1, 10, 1) + FIELD(CRB_INTF_ID, CapDataXferSizeSupport, 11, 2) + FIELD(CRB_INTF_ID, CapFIFO, 13, 1) + FIELD(CRB_INTF_ID, CapCRB, 14, 1) + FIELD(CRB_INTF_ID, CapIFRes, 15, 2) + FIELD(CRB_INTF_ID, InterfaceSelector, 17, 2) + FIELD(CRB_INTF_ID, IntfSelLock, 19, 1) + FIELD(CRB_INTF_ID, Reserved2, 20, 4) + FIELD(CRB_INTF_ID, RID, 24, 8) +REG32(CRB_INTF_ID2, 0x34) + FIELD(CRB_INTF_ID2, VID, 0, 16) + FIELD(CRB_INTF_ID2, DID, 16, 16) +REG32(CRB_CTRL_EXT, 0x38) +REG32(CRB_CTRL_REQ, 0x40) +REG32(CRB_CTRL_STS, 0x44) + FIELD(CRB_CTRL_STS, tpmSts, 0, 1) + FIELD(CRB_CTRL_STS, tpmIdle, 1, 1) +REG32(CRB_CTRL_CANCEL, 0x48) +REG32(CRB_CTRL_START, 0x4C) +REG32(CRB_INT_ENABLED, 0x50) +REG32(CRB_INT_STS, 0x54) +REG32(CRB_CTRL_CMD_SIZE, 0x58) +REG32(CRB_CTRL_CMD_LADDR, 0x5C) +REG32(CRB_CTRL_CMD_HADDR, 0x60) +REG32(CRB_CTRL_RSP_SIZE, 0x64) +REG32(CRB_CTRL_RSP_ADDR, 0x68) +REG32(CRB_DATA_BUFFER, 0x80) + +#define TPM_CRB_ADDR_BASE 0xFED40000 +#define TPM_CRB_ADDR_SIZE 0x1000 +#define TPM_CRB_ADDR_CTRL (TPM_CRB_ADDR_BASE + A_CRB_CTRL_REQ) +#define TPM_CRB_R_MAX R_CRB_DATA_BUFFER + +#define TPM_LOG_AREA_MINIMUM_SIZE (64 * KiB) + +#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 +#define TPM2_START_METHOD_CRB 7 + +/* + * Physical Presence Interface + */ +#define TPM_PPI_ADDR_SIZE 0x400 +#define TPM_PPI_ADDR_BASE 0xFED45000 + +#define TPM_PPI_VERSION_NONE 0 +#define TPM_PPI_VERSION_1_30 1 + +/* whether function is blocked by BIOS settings; bits 0, 1, 2 */ +#define TPM_PPI_FUNC_NOT_IMPLEMENTED (0 << 0) +#define TPM_PPI_FUNC_BIOS_ONLY (1 << 0) +#define TPM_PPI_FUNC_BLOCKED (2 << 0) +#define TPM_PPI_FUNC_ALLOWED_USR_REQ (3 << 0) +#define TPM_PPI_FUNC_ALLOWED_USR_NOT_REQ (4 << 0) +#define TPM_PPI_FUNC_MASK (7 << 0) + +void tpm_build_ppi_acpi(TPMIf *tpm, Aml *dev); + +#endif /* CONFIG_TPM */ + +#endif /* HW_ACPI_TPM_H */ diff --git a/include/hw/acpi/utils.h b/include/hw/acpi/utils.h new file mode 100644 index 000000000..0022df027 --- /dev/null +++ b/include/hw/acpi/utils.h @@ -0,0 +1,8 @@ +#ifndef HW_ACPI_UTILS_H +#define HW_ACPI_UTILS_H + +#include "hw/nvram/fw_cfg.h" + +MemoryRegion *acpi_add_rom_blob(FWCfgCallback update, void *opaque, + GArray *blob, const char *name); +#endif diff --git a/include/hw/acpi/vmgenid.h b/include/hw/acpi/vmgenid.h new file mode 100644 index 000000000..dc8bb3433 --- /dev/null +++ b/include/hw/acpi/vmgenid.h @@ -0,0 +1,37 @@ +#ifndef ACPI_VMGENID_H +#define ACPI_VMGENID_H + +#include "hw/acpi/bios-linker-loader.h" +#include "hw/qdev-core.h" +#include "qemu/uuid.h" +#include "qom/object.h" + +#define TYPE_VMGENID "vmgenid" +#define VMGENID_GUID "guid" +#define VMGENID_GUID_FW_CFG_FILE "etc/vmgenid_guid" +#define VMGENID_ADDR_FW_CFG_FILE "etc/vmgenid_addr" + +#define VMGENID_FW_CFG_SIZE 4096 /* Occupy a page of memory */ +#define VMGENID_GUID_OFFSET 40 /* allow space for + * OVMF SDT Header Probe Supressor + */ + +OBJECT_DECLARE_SIMPLE_TYPE(VmGenIdState, VMGENID) + +struct VmGenIdState { + DeviceState parent_obj; + QemuUUID guid; /* The 128-bit GUID seen by the guest */ + uint8_t vmgenid_addr_le[8]; /* Address of the GUID (little-endian) */ +}; + +/* returns NULL unless there is exactly one device */ +static inline Object *find_vmgenid_dev(void) +{ + return object_resolve_path_type("", TYPE_VMGENID, NULL); +} + +void vmgenid_build_acpi(VmGenIdState *vms, GArray *table_data, GArray *guid, + BIOSLinker *linker, const char *oem_id); +void vmgenid_add_fw_cfg(VmGenIdState *vms, FWCfgState *s, GArray *guid); + +#endif |