pci, pc fixes, features

A bunch of bugfixes - these will make sense for 2.1.1
 
 ACPI support for TPM and partial ARI support for PCIE.
 
 Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABAgAGBQJT+mRDAAoJECgfDbjSjVRpNisIAIU4TriYRVG6gQBGIatvdJdg
 +2ZAiJEAiUQlCIfBvyofwmpiVjkrnFlinmbBeuoSOxTFtuHjFxW+N8uAD93/OiNj
 wHsruVz5ReHov3l3SWQBYkJAEFCYw0yKXPqMkqFj9Y5Dq2uWv+IcceJsBwCn+LQI
 WtEoYtJMhcmAove27tioT7yhEL7x7pF3StMDX9gjRpml4KxA2himgPcrkyq6wjDk
 Qg3zNEQNpehLkHJLFHEGzwrYUgY2xSfAl7dUCQ+pVXttaEion49/KclBz0aWkt0U
 QUQCELCfeRf9Od3Gh4IDUIjTJyBhBtNnJo5+YcK6yYu/JsaVJ1hTSnDtqCq7udo=
 =FjrT
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging

pci, pc fixes, features

A bunch of bugfixes - these will make sense for 2.1.1

ACPI support for TPM and partial ARI support for PCIE.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

# gpg: Signature made Sun 24 Aug 2014 23:16:35 BST using RSA key ID D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg:                 aka "Michael S. Tsirkin <mst@redhat.com>"

* remotes/mst/tags/for_upstream:
  pcie: fix trailing whitespace
  ioh3420: Enable ARI forwarding
  ioh3420: Remove obsoleted, unused ioh3420_init function
  pcie: Rename the pcie_cap_ari_* functions to pcie_cap_arifwd_*
  pcie: Fix incorrect write to the ari capability next function field
  ssdt-tpm: add generated hex file to git
  Add ACPI tables for TPM
  pc: reserve more memory for ACPI for new machine types
  pcihp: fix possible array out of bounds
  pci_bridge: manually destroy memory regions within PCIBridgeWindows
  hostmem: set MPOL_MF_MOVE

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2014-08-25 18:49:25 +01:00
commit a44a12b78a
19 changed files with 270 additions and 48 deletions

View file

@ -295,7 +295,7 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
/* ensure policy won't be ignored in case memory is preallocated
* before mbind(). note: MPOL_MF_STRICT is ignored on hugepages so
* this doesn't catch hugepage case. */
unsigned flags = MPOL_MF_STRICT;
unsigned flags = MPOL_MF_STRICT | MPOL_MF_MOVE;
/* check for invalid host-nodes and policies and give more verbose
* error messages than mbind(). */

View file

@ -231,7 +231,7 @@ static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size)
uint32_t val = 0;
int bsel = s->hotplug_select;
if (bsel < 0 || bsel > ACPI_PCIHP_MAX_HOTPLUG_BUS) {
if (bsel < 0 || bsel >= ACPI_PCIHP_MAX_HOTPLUG_BUS) {
return 0;
}

View file

@ -10,7 +10,8 @@ obj-y += bios-linker-loader.o
hw/i386/acpi-build.o: hw/i386/acpi-build.c hw/i386/acpi-dsdt.hex \
hw/i386/ssdt-proc.hex hw/i386/ssdt-pcihp.hex hw/i386/ssdt-misc.hex \
hw/i386/acpi-dsdt.hex hw/i386/q35-acpi-dsdt.hex \
hw/i386/q35-acpi-dsdt.hex hw/i386/ssdt-mem.hex
hw/i386/q35-acpi-dsdt.hex hw/i386/ssdt-mem.hex \
hw/i386/ssdt-tpm.hex
iasl-option=$(shell if test -z "`$(1) $(2) 2>&1 > /dev/null`" \
; then echo "$(2)"; else echo "$(3)"; fi ;)

View file

@ -40,6 +40,8 @@
#include "hw/loader.h"
#include "hw/isa/isa.h"
#include "hw/acpi/memory_hotplug.h"
#include "sysemu/tpm.h"
#include "hw/acpi/tpm.h"
/* Supported chipsets: */
#include "hw/acpi/piix4.h"
@ -88,6 +90,7 @@ typedef struct AcpiPmInfo {
typedef struct AcpiMiscInfo {
bool has_hpet;
bool has_tpm;
DECLARE_BITMAP(slot_hotplug_enable, PCI_SLOT_MAX);
const unsigned char *dsdt_code;
unsigned dsdt_size;
@ -210,6 +213,7 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
static void acpi_get_misc_info(AcpiMiscInfo *info)
{
info->has_hpet = hpet_find();
info->has_tpm = tpm_find();
info->pvpanic_port = pvpanic_port();
}
@ -698,6 +702,7 @@ static inline char acpi_get_hex(uint32_t val)
#include "hw/i386/ssdt-misc.hex"
#include "hw/i386/ssdt-pcihp.hex"
#include "hw/i386/ssdt-tpm.hex"
static void
build_append_notify_method(GArray *device, const char *name,
@ -1201,6 +1206,39 @@ build_hpet(GArray *table_data, GArray *linker)
(void *)hpet, "HPET", sizeof(*hpet), 1);
}
static void
build_tpm_tcpa(GArray *table_data, GArray *linker)
{
Acpi20Tcpa *tcpa = acpi_data_push(table_data, sizeof *tcpa);
/* the log area will come right after the TCPA table */
uint64_t log_area_start_address = acpi_data_len(table_data);
tcpa->platform_class = cpu_to_le16(TPM_TCPA_ACPI_CLASS_CLIENT);
tcpa->log_area_minimum_length = cpu_to_le32(TPM_LOG_AREA_MINIMUM_SIZE);
tcpa->log_area_start_address = cpu_to_le64(log_area_start_address);
/* log area start address to be filled by Guest linker */
bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
ACPI_BUILD_TABLE_FILE,
table_data, &tcpa->log_area_start_address,
sizeof(tcpa->log_area_start_address));
build_header(linker, table_data,
(void *)tcpa, "TCPA", sizeof(*tcpa), 2);
/* now only get the log area and with that modify table_data */
acpi_data_push(table_data, TPM_LOG_AREA_MINIMUM_SIZE);
}
static void
build_tpm_ssdt(GArray *table_data, GArray *linker)
{
void *tpm_ptr;
tpm_ptr = acpi_data_push(table_data, sizeof(ssdt_tpm_aml));
memcpy(tpm_ptr, ssdt_tpm_aml, sizeof(ssdt_tpm_aml));
}
typedef enum {
MEM_AFFINITY_NOFLAGS = 0,
MEM_AFFINITY_ENABLED = (1 << 0),
@ -1531,6 +1569,13 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
acpi_add_table(table_offsets, tables->table_data);
build_hpet(tables->table_data, tables->linker);
}
if (misc.has_tpm) {
acpi_add_table(table_offsets, tables->table_data);
build_tpm_tcpa(tables->table_data, tables->linker);
acpi_add_table(table_offsets, tables->table_data);
build_tpm_ssdt(tables->table_data, tables->linker);
}
if (guest_info->numa_nodes) {
acpi_add_table(table_offsets, tables->table_data);
build_srat(tables->table_data, tables->linker, &cpu, guest_info);

View file

@ -314,4 +314,15 @@ struct AcpiTableMcfg {
} QEMU_PACKED;
typedef struct AcpiTableMcfg AcpiTableMcfg;
/*
* TCPA Description Table
*/
struct Acpi20Tcpa {
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
uint16_t platform_class;
uint32_t log_area_minimum_length;
uint64_t log_area_start_address;
} QEMU_PACKED;
typedef struct Acpi20Tcpa Acpi20Tcpa;
#endif

View file

@ -73,7 +73,12 @@
#endif
/* Leave a chunk of memory at the top of RAM for the BIOS ACPI tables. */
#define ACPI_DATA_SIZE 0x10000
unsigned acpi_data_size = 0x20000;
void pc_set_legacy_acpi_data_size(void)
{
acpi_data_size = 0x10000;
}
#define BIOS_CFG_IOPORT 0x510
#define FW_CFG_ACPI_TABLES (FW_CFG_ARCH_LOCAL + 0)
#define FW_CFG_SMBIOS_ENTRIES (FW_CFG_ARCH_LOCAL + 1)
@ -811,8 +816,9 @@ static void load_linux(FWCfgState *fw_cfg,
initrd_max = 0x37ffffff;
}
if (initrd_max >= max_ram_size-ACPI_DATA_SIZE)
initrd_max = max_ram_size-ACPI_DATA_SIZE-1;
if (initrd_max >= max_ram_size - acpi_data_size) {
initrd_max = max_ram_size - acpi_data_size - 1;
}
fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_ADDR, cmdline_addr);
fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, strlen(kernel_cmdline)+1);

View file

@ -323,6 +323,7 @@ static void pc_compat_2_0(MachineState *machine)
legacy_acpi_table_size = 6652;
smbios_legacy_mode = true;
has_reserved_memory = false;
pc_set_legacy_acpi_data_size();
}
static void pc_compat_1_7(MachineState *machine)

View file

@ -280,6 +280,7 @@ static void pc_compat_2_0(MachineState *machine)
{
smbios_legacy_mode = true;
has_reserved_memory = false;
pc_set_legacy_acpi_data_size();
}
static void pc_compat_1_7(MachineState *machine)

43
hw/i386/ssdt-tpm.dsl Normal file
View file

@ -0,0 +1,43 @@
/*
* 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/>.
*/
#include "hw/acpi/tpm.h"
ACPI_EXTRACT_ALL_CODE ssdt_tpm_aml
DefinitionBlock (
"ssdt-tpm.aml", // Output Filename
"SSDT", // Signature
0x01, // SSDT Compliance Revision
"BXPC", // OEMID
"BXSSDT", // TABLE ID
0x1 // OEM Revision
)
{
Scope(\_SB) {
/* TPM with emulated TPM TIS interface */
Device (TPM) {
Name (_HID, EisaID ("PNP0C31"))
Name (_CRS, ResourceTemplate ()
{
Memory32Fixed (ReadWrite, TPM_TIS_ADDR_BASE, TPM_TIS_ADDR_SIZE)
// older Linux tpm_tis drivers do not work with IRQ
//IRQNoFlags () {TPM_TIS_IRQ}
})
Method (_STA, 0, NotSerialized) {
Return (0x0F)
}
}
}
}

View file

@ -0,0 +1,95 @@
static unsigned char ssdt_tpm_aml[] = {
0x53,
0x53,
0x44,
0x54,
0x5d,
0x0,
0x0,
0x0,
0x1,
0xf,
0x42,
0x58,
0x50,
0x43,
0x0,
0x0,
0x42,
0x58,
0x53,
0x53,
0x44,
0x54,
0x0,
0x0,
0x1,
0x0,
0x0,
0x0,
0x49,
0x4e,
0x54,
0x4c,
0x15,
0x11,
0x13,
0x20,
0x10,
0x38,
0x5c,
0x5f,
0x53,
0x42,
0x5f,
0x5b,
0x82,
0x30,
0x54,
0x50,
0x4d,
0x5f,
0x8,
0x5f,
0x48,
0x49,
0x44,
0xc,
0x41,
0xd0,
0xc,
0x31,
0x8,
0x5f,
0x43,
0x52,
0x53,
0x11,
0x11,
0xa,
0xe,
0x86,
0x9,
0x0,
0x1,
0x0,
0x0,
0xd4,
0xfe,
0x0,
0x50,
0x0,
0x0,
0x79,
0x0,
0x14,
0x9,
0x5f,
0x53,
0x54,
0x41,
0x0,
0xa4,
0xa,
0xf
};

View file

@ -85,6 +85,7 @@ static void ioh3420_reset(DeviceState *qdev)
pcie_cap_root_reset(d);
pcie_cap_deverr_reset(d);
pcie_cap_slot_reset(d);
pcie_cap_arifwd_reset(d);
pcie_aer_root_reset(d);
pci_bridge_reset(qdev);
pci_bridge_disable_base_limit(d);
@ -118,6 +119,8 @@ static int ioh3420_initfn(PCIDevice *d)
if (rc < 0) {
goto err_msi;
}
pcie_cap_arifwd_init(d);
pcie_cap_deverr_init(d);
pcie_cap_slot_init(d, s->slot);
pcie_chassis_create(s->chassis);
@ -156,30 +159,6 @@ static void ioh3420_exitfn(PCIDevice *d)
pci_bridge_exitfn(d);
}
PCIESlot *ioh3420_init(PCIBus *bus, int devfn, bool multifunction,
const char *bus_name, pci_map_irq_fn map_irq,
uint8_t port, uint8_t chassis, uint16_t slot)
{
PCIDevice *d;
PCIBridge *br;
DeviceState *qdev;
d = pci_create_multifunction(bus, devfn, multifunction, "ioh3420");
if (!d) {
return NULL;
}
br = PCI_BRIDGE(d);
qdev = DEVICE(d);
pci_bridge_map_irq(br, bus_name, map_irq);
qdev_prop_set_uint8(qdev, "port", port);
qdev_prop_set_uint8(qdev, "chassis", chassis);
qdev_prop_set_uint16(qdev, "slot", slot);
qdev_init_nofail(qdev);
return PCIE_SLOT(d);
}
static Property ioh3420_props[] = {
DEFINE_PROP_BIT(COMPAT_PROP_PCP, PCIDevice, cap_present,
QEMU_PCIE_SLTCAP_PCP_BITNR, true),

View file

@ -50,7 +50,7 @@ static void xio3130_downstream_reset(DeviceState *qdev)
pcie_cap_deverr_reset(d);
pcie_cap_slot_reset(d);
pcie_cap_ari_reset(d);
pcie_cap_arifwd_reset(d);
pci_bridge_reset(qdev);
}
@ -91,7 +91,7 @@ static int xio3130_downstream_initfn(PCIDevice *d)
if (rc < 0) {
goto err_pcie_cap;
}
pcie_cap_ari_init(d);
pcie_cap_arifwd_init(d);
rc = pcie_aer_init(d, XIO3130_AER_OFFSET);
if (rc < 0) {
goto err;

View file

@ -219,6 +219,12 @@ static void pci_bridge_region_del(PCIBridge *br, PCIBridgeWindows *w)
static void pci_bridge_region_cleanup(PCIBridge *br, PCIBridgeWindows *w)
{
object_unparent(OBJECT(&w->alias_io));
object_unparent(OBJECT(&w->alias_mem));
object_unparent(OBJECT(&w->alias_pref_mem));
object_unparent(OBJECT(&w->alias_vga[QEMU_PCI_VGA_IO_LO]));
object_unparent(OBJECT(&w->alias_vga[QEMU_PCI_VGA_IO_HI]));
object_unparent(OBJECT(&w->alias_vga[QEMU_PCI_VGA_MEM]));
g_free(w);
}

View file

@ -497,9 +497,10 @@ void pcie_cap_flr_write_config(PCIDevice *dev,
}
}
/* Alternative Routing-ID Interpretation (ARI) */
/* ari forwarding support for down stream port */
void pcie_cap_ari_init(PCIDevice *dev)
/* Alternative Routing-ID Interpretation (ARI)
* forwarding support for root and downstream ports
*/
void pcie_cap_arifwd_init(PCIDevice *dev)
{
uint32_t pos = dev->exp.exp_cap;
pci_long_test_and_set_mask(dev->config + pos + PCI_EXP_DEVCAP2,
@ -508,13 +509,13 @@ void pcie_cap_ari_init(PCIDevice *dev)
PCI_EXP_DEVCTL2_ARI);
}
void pcie_cap_ari_reset(PCIDevice *dev)
void pcie_cap_arifwd_reset(PCIDevice *dev)
{
uint8_t *devctl2 = dev->config + dev->exp.exp_cap + PCI_EXP_DEVCTL2;
pci_long_test_and_clear_mask(devctl2, PCI_EXP_DEVCTL2_ARI);
}
bool pcie_cap_is_ari_enabled(const PCIDevice *dev)
bool pcie_cap_is_arifwd_enabled(const PCIDevice *dev)
{
if (!pci_is_express(dev)) {
return false;
@ -630,5 +631,5 @@ void pcie_ari_init(PCIDevice *dev, uint16_t offset, uint16_t nextfn)
{
pcie_add_capability(dev, PCI_EXT_CAP_ID_ARI, PCI_ARI_VER,
offset, PCI_ARI_SIZEOF);
pci_set_long(dev->config + offset + PCI_ARI_CAP, PCI_ARI_CAP_NFN(nextfn));
pci_set_long(dev->config + offset + PCI_ARI_CAP, (nextfn & 0xff) << 8);
}

View file

@ -18,23 +18,17 @@
#define TPM_TPM_TIS_H
#include "hw/isa/isa.h"
#include "hw/acpi/tpm.h"
#include "qemu-common.h"
#define TPM_TIS_ADDR_BASE 0xFED40000
#define TPM_TIS_NUM_LOCALITIES 5 /* per spec */
#define TPM_TIS_LOCALITY_SHIFT 12
#define TPM_TIS_NO_LOCALITY 0xff
#define TPM_TIS_IS_VALID_LOCTY(x) ((x) < TPM_TIS_NUM_LOCALITIES)
#define TPM_TIS_IRQ 5
#define TPM_TIS_BUFFER_MAX 4096
#define TYPE_TPM_TIS "tpm-tis"
typedef enum {
TPM_TIS_STATE_IDLE = 0,
TPM_TIS_STATE_READY,

29
include/hw/acpi/tpm.h Normal file
View file

@ -0,0 +1,29 @@
/*
* tpm.h - TPM ACPI definitions
*
* Copyright (C) 2014 IBM Corporation
*
* Authors:
* Stefan Berger <stefanb@us.ibm.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*
* Implementation of the TIS interface according to specs found at
* http://www.trustedcomputinggroup.org
*
*/
#ifndef HW_ACPI_TPM_H
#define HW_ACPI_TPM_H
#define TPM_TIS_ADDR_BASE 0xFED40000
#define TPM_TIS_ADDR_SIZE 0x5000
#define TPM_TIS_IRQ 5
#define TPM_LOG_AREA_MINIMUM_SIZE (64 * 1024)
#define TPM_TCPA_ACPI_CLASS_CLIENT 0
#define TPM_TCPA_ACPI_CLASS_SERVER 1
#endif /* HW_ACPI_TPM_H */

View file

@ -176,6 +176,8 @@ void pc_acpi_init(const char *default_dsdt);
PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size,
ram_addr_t above_4g_mem_size);
void pc_set_legacy_acpi_data_size(void);
#define PCI_HOST_PROP_PCI_HOLE_START "pci-hole-start"
#define PCI_HOST_PROP_PCI_HOLE_END "pci-hole-end"
#define PCI_HOST_PROP_PCI_HOLE64_START "pci-hole64-start"

View file

@ -103,9 +103,10 @@ void pcie_cap_flr_init(PCIDevice *dev);
void pcie_cap_flr_write_config(PCIDevice *dev,
uint32_t addr, uint32_t val, int len);
void pcie_cap_ari_init(PCIDevice *dev);
void pcie_cap_ari_reset(PCIDevice *dev);
bool pcie_cap_is_ari_enabled(const PCIDevice *dev);
/* ARI forwarding capability and control */
void pcie_cap_arifwd_init(PCIDevice *dev);
void pcie_cap_arifwd_reset(PCIDevice *dev);
bool pcie_cap_is_arifwd_enabled(const PCIDevice *dev);
/* PCI express extended capability helper functions */
uint16_t pcie_find_capability(PCIDevice *dev, uint16_t cap_id);

View file

@ -20,4 +20,11 @@ int tpm_config_parse(QemuOptsList *opts_list, const char *optarg);
int tpm_init(void);
void tpm_cleanup(void);
#define TYPE_TPM_TIS "tpm-tis"
static inline bool tpm_find(void)
{
return object_resolve_path_type("", TYPE_TPM_TIS, NULL);
}
#endif /* QEMU_TPM_H */