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

pci, pc, virtio: fixes, features

tpm physical presence interface
rsc support in virtio net
ivshmem is removed
misc cleanups and fixes all over the place

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

# gpg: Signature made Fri 18 Jan 2019 02:11:11 GMT
# gpg:                using RSA key 281F0DB8D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg:                 aka "Michael S. Tsirkin <mst@redhat.com>"
# Primary key fingerprint: 0270 606B 6F3C DF3D 0B17  0970 C350 3912 AFBE 8E67
#      Subkey fingerprint: 5D09 FD08 71C8 F85B 94CA  8A0D 281F 0DB8 D28D 5469

* remotes/mst/tags/for_upstream: (49 commits)
  migration: Use strnlen() for fixed-size string
  migration: Fix stringop-truncation warning
  hw/acpi: Use QEMU_NONSTRING for non NUL-terminated arrays
  block/sheepdog: Use QEMU_NONSTRING for non NUL-terminated arrays
  qemu/compiler: Define QEMU_NONSTRING
  acpi: update expected files
  hw: acpi: Fix memory hotplug AML generation error
  tpm: clear RAM when "memory overwrite" requested
  acpi: add ACPI memory clear interface
  acpi: build TPM Physical Presence interface
  acpi: expose TPM/PPI configuration parameters to firmware via fw_cfg
  tpm: allocate/map buffer for TPM Physical Presence interface
  tpm: add a "ppi" boolean property
  hw/misc/edu: add msi_uninit() for pci_edu_uninit()
  virtio: Make disable-legacy/disable-modern compat properties optional
  globals: Allow global properties to be optional
  virtio: virtio 9p really requires CONFIG_VIRTFS to work
  virtio: split virtio crypto bits from virtio-pci.h
  virtio: split virtio gpu bits from virtio-pci.h
  virtio: split virtio serial bits from virtio-pci
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell
2019-01-18 14:58:58 +00:00
71 changed files with 3103 additions and 1638 deletions
+1 -1
View File
@@ -1224,7 +1224,7 @@ static int find_vdi_name(BDRVSheepdogState *s, const char *filename,
SheepdogVdiReq hdr;
SheepdogVdiRsp *rsp = (SheepdogVdiRsp *)&hdr;
unsigned int wlen, rlen = 0;
char buf[SD_MAX_VDI_LEN + SD_MAX_VDI_TAG_LEN];
char buf[SD_MAX_VDI_LEN + SD_MAX_VDI_TAG_LEN] QEMU_NONSTRING;
fd = connect_to_sdog(s, errp);
if (fd < 0) {
+2 -1
View File
@@ -1,7 +1,7 @@
CONFIG_VHOST_USER_SCSI=$(call land,$(CONFIG_VHOST_USER),$(CONFIG_LINUX))
CONFIG_VHOST_USER_BLK=$(call land,$(CONFIG_VHOST_USER),$(CONFIG_LINUX))
CONFIG_VIRTIO=y
CONFIG_VIRTIO_9P=y
CONFIG_VIRTIO_9P=$(CONFIG_VIRTFS)
CONFIG_VIRTIO_BALLOON=y
CONFIG_VIRTIO_BLK=y
CONFIG_VIRTIO_CRYPTO=y
@@ -12,3 +12,4 @@ CONFIG_VIRTIO_RNG=y
CONFIG_SCSI=y
CONFIG_VIRTIO_SCSI=y
CONFIG_VIRTIO_SERIAL=y
CONFIG_VIRTIO_INPUT_HOST=$(CONFIG_LINUX)
+6 -2
View File
@@ -17,12 +17,16 @@ get interrupted by its peers.
There are two basic configurations:
- Just shared memory: -device ivshmem-plain,memdev=HMB,...
- Just shared memory:
-device ivshmem-plain,memdev=HMB,...
This uses host memory backend HMB. It should have option "share"
set.
- Shared memory plus interrupts: -device ivshmem,chardev=CHR,vectors=N,...
- Shared memory plus interrupts:
-device ivshmem-doorbell,chardev=CHR,vectors=N,...
An ivshmem server must already be running on the host. The device
connects to the server's UNIX domain socket via character device
+104
View File
@@ -34,6 +34,25 @@ The CRB interface makes a memory mapped IO region in the area 0xfed40000 -
QEMU files related to TPM CRB interface:
- hw/tpm/tpm_crb.c
= fw_cfg interface =
The bios/firmware may read the "etc/tpm/config" fw_cfg entry for
configuring the guest appropriately.
The entry of 6 bytes has the following content, in little-endian:
#define TPM_VERSION_UNSPEC 0
#define TPM_VERSION_1_2 1
#define TPM_VERSION_2_0 2
#define TPM_PPI_VERSION_NONE 0
#define TPM_PPI_VERSION_1_30 1
struct FwCfgTPMConfig {
uint32_t tpmppi_address; /* PPI memory location */
uint8_t tpm_version; /* TPM version */
uint8_t tpmppi_version; /* PPI version */
};
= ACPI Interface =
@@ -57,6 +76,91 @@ URL:
https://trustedcomputinggroup.org/tcg-acpi-specification/
== ACPI PPI Interface ==
QEMU supports the Physical Presence Interface (PPI) for TPM 1.2 and TPM 2. This
interface requires ACPI and firmware support. The specification can be found at
the following URL:
https://trustedcomputinggroup.org/resource/tcg-physical-presence-interface-specification/
PPI enables a system administrator (root) to request a modification to the
TPM upon reboot. The PPI specification defines the operation requests and the
actions the firmware has to take. The system administrator passes the operation
request number to the firmware through an ACPI interface which writes this
number to a memory location that the firmware knows. Upon reboot, the firmware
finds the number and sends commands to the the TPM. The firmware writes the TPM
result code and the operation request number to a memory location that ACPI can
read from and pass the result on to the administrator.
The PPI specification defines a set of mandatory and optional operations for
the firmware to implement. The ACPI interface also allows an administrator to
list the supported operations. In QEMU the ACPI code is generated by QEMU, yet
the firmware needs to implement support on a per-operations basis, and
different firmwares may support a different subset. Therefore, QEMU introduces
the virtual memory device for PPI where the firmware can indicate which
operations it supports and ACPI can enable the ones that are supported and
disable all others. This interface lies in main memory and has the following
layout:
+----------+--------+--------+-------------------------------------------+
| Field | Length | Offset | Description |
+----------+--------+--------+-------------------------------------------+
| func | 0x100 | 0x000 | Firmware sets values for each supported |
| | | | operation. See defined values below. |
+----------+--------+--------+-------------------------------------------+
| ppin | 0x1 | 0x100 | SMI interrupt to use. Set by firmware. |
| | | | Not supported. |
+----------+--------+--------+-------------------------------------------+
| ppip | 0x4 | 0x101 | ACPI function index to pass to SMM code. |
| | | | Set by ACPI. Not supported. |
+----------+--------+--------+-------------------------------------------+
| pprp | 0x4 | 0x105 | Result of last executed operation. Set by |
| | | | firmware. See function index 5 for values.|
+----------+--------+--------+-------------------------------------------+
| pprq | 0x4 | 0x109 | Operation request number to execute. See |
| | | | 'Physical Presence Interface Operation |
| | | | Summary' tables in specs. Set by ACPI. |
+----------+--------+--------+-------------------------------------------+
| pprm | 0x4 | 0x10d | Operation request optional parameter. |
| | | | Values depend on operation. Set by ACPI. |
+----------+--------+--------+-------------------------------------------+
| lppr | 0x4 | 0x111 | Last executed operation request number. |
| | | | Copied from pprq field by firmware. |
+----------+--------+--------+-------------------------------------------+
| fret | 0x4 | 0x115 | Result code from SMM function. |
| | | | Not supported. |
+----------+--------+--------+-------------------------------------------+
| res1 | 0x40 | 0x119 | Reserved for future use |
+----------+--------+--------+-------------------------------------------+
| next_step| 0x1 | 0x159 | Operation to execute after reboot by |
| | | | firmware. Used by firmware. |
+----------+--------+--------+-------------------------------------------+
| movv | 0x1 | 0x15a | Memory overwrite variable |
+----------+--------+--------+-------------------------------------------+
The following values are supported for the 'func' field. They correspond
to the values used by ACPI function index 8.
+----------+-------------------------------------------------------------+
| value | Description |
+----------+-------------------------------------------------------------+
| 0 | Operation is not implemented. |
+----------+-------------------------------------------------------------+
| 1 | Operation is only accessible through firmware. |
+----------+-------------------------------------------------------------+
| 2 | Operation is blocked for OS by firmware configuration. |
+----------+-------------------------------------------------------------+
| 3 | Operation is allowed and physically present user required. |
+----------+-------------------------------------------------------------+
| 4 | Operation is allowed and physically present user is not |
| | required. |
+----------+-------------------------------------------------------------+
The location of the table is given by the fw_cfg tpmppi_address field.
The PPI memory region size is 0x400 (TPM_PPI_ADDR_SIZE) to leave
enough room for future updates.
QEMU files related to TPM ACPI tables:
- hw/i386/acpi-build.c
+1
View File
@@ -11,6 +11,7 @@ common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o
common-obj-y += acpi_interface.o
common-obj-y += bios-linker-loader.o
common-obj-y += aml-build.o
common-obj-$(CONFIG_TPM) += tpm.o
common-obj-$(CONFIG_IPMI) += ipmi.o
common-obj-$(call lnot,$(CONFIG_IPMI)) += ipmi-stub.o
+8 -4
View File
@@ -35,14 +35,18 @@
struct acpi_table_header {
uint16_t _length; /* our length, not actual part of the hdr */
/* allows easier parsing for fw_cfg clients */
char sig[4]; /* ACPI signature (4 ASCII characters) */
char sig[4]
QEMU_NONSTRING; /* ACPI signature (4 ASCII characters) */
uint32_t length; /* Length of table, in bytes, including header */
uint8_t revision; /* ACPI Specification minor version # */
uint8_t checksum; /* To make sum of entire table == 0 */
char oem_id[6]; /* OEM identification */
char oem_table_id[8]; /* OEM table identification */
char oem_id[6]
QEMU_NONSTRING; /* OEM identification */
char oem_table_id[8]
QEMU_NONSTRING; /* OEM table identification */
uint32_t oem_revision; /* OEM revision number */
char asl_compiler_id[4]; /* ASL compiler vendor ID */
char asl_compiler_id[4]
QEMU_NONSTRING; /* ASL compiler vendor ID */
uint32_t asl_compiler_revision; /* ASL compiler revision number */
} QEMU_PACKED;
+5 -5
View File
@@ -686,15 +686,15 @@ void build_memory_hotplug_aml(Aml *table, uint32_t nr_mem,
method = aml_method("_OST", 3, AML_NOTSERIALIZED);
s = MEMORY_SLOT_OST_METHOD;
aml_append(method, aml_return(aml_call4(
s, aml_name("_UID"), aml_arg(0), aml_arg(1), aml_arg(2)
)));
aml_append(method,
aml_call4(s, aml_name("_UID"), aml_arg(0),
aml_arg(1), aml_arg(2)));
aml_append(dev, method);
method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
s = MEMORY_SLOT_EJECT_METHOD;
aml_append(method, aml_return(aml_call2(
s, aml_name("_UID"), aml_arg(0))));
aml_append(method,
aml_call2(s, aml_name("_UID"), aml_arg(0)));
aml_append(dev, method);
aml_append(dev_container, dev);
+459
View File
@@ -0,0 +1,459 @@
/* Support for generating ACPI TPM tables
*
* Copyright (C) 2018 IBM, Corp.
* Copyright (C) 2018 Red Hat Inc
*
* 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 "qemu/osdep.h"
#include "qapi/error.h"
#include "hw/acpi/tpm.h"
void tpm_build_ppi_acpi(TPMIf *tpm, Aml *dev)
{
Aml *method, *field, *ifctx, *ifctx2, *ifctx3, *func_mask,
*not_implemented, *pak, *tpm2, *tpm3, *pprm, *pprq, *zero, *one;
if (!object_property_get_bool(OBJECT(tpm), "ppi", &error_abort)) {
return;
}
zero = aml_int(0);
one = aml_int(1);
func_mask = aml_int(TPM_PPI_FUNC_MASK);
not_implemented = aml_int(TPM_PPI_FUNC_NOT_IMPLEMENTED);
/*
* TPP2 is for the registers that ACPI code used to pass
* the PPI code and parameter (PPRQ, PPRM) to the firmware.
*/
aml_append(dev,
aml_operation_region("TPP2", AML_SYSTEM_MEMORY,
aml_int(TPM_PPI_ADDR_BASE + 0x100),
0x5A));
field = aml_field("TPP2", AML_ANY_ACC, AML_NOLOCK, AML_PRESERVE);
aml_append(field, aml_named_field("PPIN", 8));
aml_append(field, aml_named_field("PPIP", 32));
aml_append(field, aml_named_field("PPRP", 32));
aml_append(field, aml_named_field("PPRQ", 32));
aml_append(field, aml_named_field("PPRM", 32));
aml_append(field, aml_named_field("LPPR", 32));
aml_append(dev, field);
pprq = aml_name("PPRQ");
pprm = aml_name("PPRM");
aml_append(dev,
aml_operation_region(
"TPP3", AML_SYSTEM_MEMORY,
aml_int(TPM_PPI_ADDR_BASE +
0x15a /* movv, docs/specs/tpm.txt */),
0x1));
field = aml_field("TPP3", AML_BYTE_ACC, AML_NOLOCK, AML_PRESERVE);
aml_append(field, aml_named_field("MOVV", 8));
aml_append(dev, field);
/*
* DerefOf in Windows is broken with SYSTEM_MEMORY. Use a dynamic
* operation region inside of a method for getting FUNC[op].
*/
method = aml_method("TPFN", 1, AML_SERIALIZED);
{
Aml *op = aml_arg(0);
ifctx = aml_if(aml_lgreater_equal(op, aml_int(0x100)));
{
aml_append(ifctx, aml_return(zero));
}
aml_append(method, ifctx);
aml_append(method,
aml_operation_region("TPP1", AML_SYSTEM_MEMORY,
aml_add(aml_int(TPM_PPI_ADDR_BASE), op, NULL), 0x1));
field = aml_field("TPP1", AML_BYTE_ACC, AML_NOLOCK, AML_PRESERVE);
aml_append(field, aml_named_field("TPPF", 8));
aml_append(method, field);
aml_append(method, aml_return(aml_name("TPPF")));
}
aml_append(dev, method);
/*
* Use global TPM2 & TPM3 variables to workaround Windows ACPI bug
* when returning packages.
*/
pak = aml_package(2);
aml_append(pak, zero);
aml_append(pak, zero);
aml_append(dev, aml_name_decl("TPM2", pak));
tpm2 = aml_name("TPM2");
pak = aml_package(3);
aml_append(pak, zero);
aml_append(pak, zero);
aml_append(pak, zero);
aml_append(dev, aml_name_decl("TPM3", pak));
tpm3 = aml_name("TPM3");
method = aml_method("_DSM", 4, AML_SERIALIZED);
{
uint8_t zerobyte[1] = { 0 };
Aml *function, *arguments, *rev, *op, *op_arg, *op_flags, *uuid;
uuid = aml_arg(0);
rev = aml_arg(1);
function = aml_arg(2);
arguments = aml_arg(3);
op = aml_local(0);
op_flags = aml_local(1);
/* Physical Presence Interface */
ifctx = aml_if(
aml_equal(uuid,
aml_touuid("3DDDFAA6-361B-4EB4-A424-8D10089D1653")));
{
/* standard DSM query function */
ifctx2 = aml_if(aml_equal(function, zero));
{
uint8_t byte_list[2] = { 0xff, 0x01 }; /* functions 1-8 */
aml_append(ifctx2,
aml_return(aml_buffer(sizeof(byte_list),
byte_list)));
}
aml_append(ifctx, ifctx2);
/*
* PPI 1.0: 2.1.1 Get Physical Presence Interface Version
*
* Arg 2 (Integer): Function Index = 1
* Arg 3 (Package): Arguments = Empty Package
* Returns: Type: String
*/
ifctx2 = aml_if(aml_equal(function, one));
{
aml_append(ifctx2, aml_return(aml_string("1.3")));
}
aml_append(ifctx, ifctx2);
/*
* PPI 1.0: 2.1.3 Submit TPM Operation Request to Pre-OS Environment
*
* Arg 2 (Integer): Function Index = 2
* Arg 3 (Package): Arguments = Package: Type: Integer
* Operation Value of the Request
* Returns: Type: Integer
* 0: Success
* 1: Operation Value of the Request Not Supported
* 2: General Failure
*/
ifctx2 = aml_if(aml_equal(function, aml_int(2)));
{
/* get opcode */
aml_append(ifctx2,
aml_store(aml_derefof(aml_index(arguments,
zero)), op));
/* get opcode flags */
aml_append(ifctx2,
aml_store(aml_call1("TPFN", op), op_flags));
/* if func[opcode] & TPM_PPI_FUNC_NOT_IMPLEMENTED */
ifctx3 = aml_if(
aml_equal(
aml_and(op_flags, func_mask, NULL),
not_implemented));
{
/* 1: Operation Value of the Request Not Supported */
aml_append(ifctx3, aml_return(one));
}
aml_append(ifctx2, ifctx3);
aml_append(ifctx2, aml_store(op, pprq));
aml_append(ifctx2, aml_store(zero, pprm));
/* 0: success */
aml_append(ifctx2, aml_return(zero));
}
aml_append(ifctx, ifctx2);
/*
* PPI 1.0: 2.1.4 Get Pending TPM Operation Requested By the OS
*
* Arg 2 (Integer): Function Index = 3
* Arg 3 (Package): Arguments = Empty Package
* Returns: Type: Package of Integers
* Integer 1: Function Return code
* 0: Success
* 1: General Failure
* Integer 2: Pending operation requested by the OS
* 0: None
* >0: Operation Value of the Pending Request
* Integer 3: Optional argument to pending operation
* requested by the OS
* 0: None
* >0: Argument Value of the Pending Request
*/
ifctx2 = aml_if(aml_equal(function, aml_int(3)));
{
/*
* Revision ID of 1, no integer parameter beyond
* parameter two are expected
*/
ifctx3 = aml_if(aml_equal(rev, one));
{
/* TPM2[1] = PPRQ */
aml_append(ifctx3,
aml_store(pprq, aml_index(tpm2, one)));
aml_append(ifctx3, aml_return(tpm2));
}
aml_append(ifctx2, ifctx3);
/*
* A return value of {0, 23, 1} indicates that
* operation 23 with argument 1 is pending.
*/
ifctx3 = aml_if(aml_equal(rev, aml_int(2)));
{
/* TPM3[1] = PPRQ */
aml_append(ifctx3,
aml_store(pprq, aml_index(tpm3, one)));
/* TPM3[2] = PPRM */
aml_append(ifctx3,
aml_store(pprm, aml_index(tpm3, aml_int(2))));
aml_append(ifctx3, aml_return(tpm3));
}
aml_append(ifctx2, ifctx3);
}
aml_append(ifctx, ifctx2);
/*
* PPI 1.0: 2.1.5 Get Platform-Specific Action to Transition to
* Pre-OS Environment
*
* Arg 2 (Integer): Function Index = 4
* Arg 3 (Package): Arguments = Empty Package
* Returns: Type: Integer
* 0: None
* 1: Shutdown
* 2: Reboot
* 3: OS Vendor-specific
*/
ifctx2 = aml_if(aml_equal(function, aml_int(4)));
{
/* reboot */
aml_append(ifctx2, aml_return(aml_int(2)));
}
aml_append(ifctx, ifctx2);
/*
* PPI 1.0: 2.1.6 Return TPM Operation Response to OS Environment
*
* Arg 2 (Integer): Function Index = 5
* Arg 3 (Package): Arguments = Empty Package
* Returns: Type: Package of Integer
* Integer 1: Function Return code
* 0: Success
* 1: General Failure
* Integer 2: Most recent operation request
* 0: None
* >0: Operation Value of the most recent request
* Integer 3: Response to the most recent operation request
* 0: Success
* 0x00000001..0x00000FFF: Corresponding TPM
* error code
* 0xFFFFFFF0: User Abort or timeout of dialog
* 0xFFFFFFF1: firmware Failure
*/
ifctx2 = aml_if(aml_equal(function, aml_int(5)));
{
/* TPM3[1] = LPPR */
aml_append(ifctx2,
aml_store(aml_name("LPPR"),
aml_index(tpm3, one)));
/* TPM3[2] = PPRP */
aml_append(ifctx2,
aml_store(aml_name("PPRP"),
aml_index(tpm3, aml_int(2))));
aml_append(ifctx2, aml_return(tpm3));
}
aml_append(ifctx, ifctx2);
/*
* PPI 1.0: 2.1.7 Submit preferred user language
*
* Arg 2 (Integer): Function Index = 6
* Arg 3 (Package): Arguments = String Package
* Preferred language code
* Returns: Type: Integer
* Function Return Code
* 3: Not implemented
*/
ifctx2 = aml_if(aml_equal(function, aml_int(6)));
{
/* 3 = not implemented */
aml_append(ifctx2, aml_return(aml_int(3)));
}
aml_append(ifctx, ifctx2);
/*
* PPI 1.1: 2.1.7 Submit TPM Operation Request to
* Pre-OS Environment 2
*
* Arg 2 (Integer): Function Index = 7
* Arg 3 (Package): Arguments = Package: Type: Integer
* Integer 1: Operation Value of the Request
* Integer 2: Argument for Operation (optional)
* Returns: Type: Integer
* 0: Success
* 1: Not Implemented
* 2: General Failure
* 3: Operation blocked by current firmware settings
*/
ifctx2 = aml_if(aml_equal(function, aml_int(7)));
{
/* get opcode */
aml_append(ifctx2, aml_store(aml_derefof(aml_index(arguments,
zero)),
op));
/* get opcode flags */
aml_append(ifctx2, aml_store(aml_call1("TPFN", op),
op_flags));
/* if func[opcode] & TPM_PPI_FUNC_NOT_IMPLEMENTED */
ifctx3 = aml_if(
aml_equal(
aml_and(op_flags, func_mask, NULL),
not_implemented));
{
/* 1: not implemented */
aml_append(ifctx3, aml_return(one));
}
aml_append(ifctx2, ifctx3);
/* if func[opcode] & TPM_PPI_FUNC_BLOCKED */
ifctx3 = aml_if(
aml_equal(
aml_and(op_flags, func_mask, NULL),
aml_int(TPM_PPI_FUNC_BLOCKED)));
{
/* 3: blocked by firmware */
aml_append(ifctx3, aml_return(aml_int(3)));
}
aml_append(ifctx2, ifctx3);
/* revision to integer */
ifctx3 = aml_if(aml_equal(rev, one));
{
/* revision 1 */
/* PPRQ = op */
aml_append(ifctx3, aml_store(op, pprq));
/* no argument, PPRM = 0 */
aml_append(ifctx3, aml_store(zero, pprm));
}
aml_append(ifctx2, ifctx3);
ifctx3 = aml_if(aml_equal(rev, aml_int(2)));
{
/* revision 2 */
/* PPRQ = op */
op_arg = aml_derefof(aml_index(arguments, one));
aml_append(ifctx3, aml_store(op, pprq));
/* PPRM = arg3[1] */
aml_append(ifctx3, aml_store(op_arg, pprm));
}
aml_append(ifctx2, ifctx3);
/* 0: success */
aml_append(ifctx2, aml_return(zero));
}
aml_append(ifctx, ifctx2);
/*
* PPI 1.1: 2.1.8 Get User Confirmation Status for Operation
*
* Arg 2 (Integer): Function Index = 8
* Arg 3 (Package): Arguments = Package: Type: Integer
* Operation Value that may need user confirmation
* Returns: Type: Integer
* 0: Not implemented
* 1: Firmware only
* 2: Blocked for OS by firmware configuration
* 3: Allowed and physically present user required
* 4: Allowed and physically present user not required
*/
ifctx2 = aml_if(aml_equal(function, aml_int(8)));
{
/* get opcode */
aml_append(ifctx2,
aml_store(aml_derefof(aml_index(arguments,
zero)),
op));
/* get opcode flags */
aml_append(ifctx2, aml_store(aml_call1("TPFN", op),
op_flags));
/* return confirmation status code */
aml_append(ifctx2,
aml_return(
aml_and(op_flags, func_mask, NULL)));
}
aml_append(ifctx, ifctx2);
aml_append(ifctx, aml_return(aml_buffer(1, zerobyte)));
}
aml_append(method, ifctx);
/*
* "TCG Platform Reset Attack Mitigation Specification 1.00",
* Chapter 6 "ACPI _DSM Function"
*/
ifctx = aml_if(
aml_equal(uuid,
aml_touuid("376054ED-CC13-4675-901C-4756D7F2D45D")));
{
/* standard DSM query function */
ifctx2 = aml_if(aml_equal(function, zero));
{
uint8_t byte_list[1] = { 0x03 }; /* functions 1-2 supported */
aml_append(ifctx2,
aml_return(aml_buffer(sizeof(byte_list),
byte_list)));
}
aml_append(ifctx, ifctx2);
/*
* TCG Platform Reset Attack Mitigation Specification 1.0 Ch.6
*
* Arg 2 (Integer): Function Index = 1
* Arg 3 (Package): Arguments = Package: Type: Integer
* Operation Value of the Request
* Returns: Type: Integer
* 0: Success
* 1: General Failure
*/
ifctx2 = aml_if(aml_equal(function, one));
{
aml_append(ifctx2,
aml_store(aml_derefof(aml_index(arguments, zero)),
op));
{
aml_append(ifctx2, aml_store(op, aml_name("MOVV")));
/* 0: success */
aml_append(ifctx2, aml_return(zero));
}
}
aml_append(ifctx, ifctx2);
}
aml_append(method, ifctx);
}
aml_append(dev, method);
}
+5 -2
View File
@@ -250,6 +250,7 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp)
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VHostUserBlk *s = VHOST_USER_BLK(vdev);
VhostUserState *user;
struct vhost_virtqueue *vqs = NULL;
int i, ret;
if (!s->chardev.chr) {
@@ -288,6 +289,7 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp)
s->dev.vqs = g_new(struct vhost_virtqueue, s->dev.nvqs);
s->dev.vq_index = 0;
s->dev.backend_features = 0;
vqs = s->dev.vqs;
vhost_dev_set_config_notifier(&s->dev, &blk_ops);
@@ -314,7 +316,7 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp)
vhost_err:
vhost_dev_cleanup(&s->dev);
virtio_err:
g_free(s->dev.vqs);
g_free(vqs);
virtio_cleanup(vdev);
vhost_user_cleanup(user);
@@ -326,10 +328,11 @@ static void vhost_user_blk_device_unrealize(DeviceState *dev, Error **errp)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VHostUserBlk *s = VHOST_USER_BLK(dev);
struct vhost_virtqueue *vqs = s->dev.vqs;
vhost_user_blk_set_status(vdev, 0);
vhost_dev_cleanup(&s->dev);
g_free(s->dev.vqs);
g_free(vqs);
virtio_cleanup(vdev);
if (s->vhost_user) {
+5 -2
View File
@@ -28,6 +28,8 @@ GlobalProperty hw_compat_3_1[] = {
{ "pcie-root-port", "x-width", "1" },
{ "memory-backend-file", "x-use-canonical-path-for-ramblock-id", "true" },
{ "memory-backend-memfd", "x-use-canonical-path-for-ramblock-id", "true" },
{ "tpm-crb", "ppi", "false" },
{ "tpm-tis", "ppi", "false" },
};
const size_t hw_compat_3_1_len = G_N_ELEMENTS(hw_compat_3_1);
@@ -91,8 +93,9 @@ const size_t hw_compat_2_7_len = G_N_ELEMENTS(hw_compat_2_7);
GlobalProperty hw_compat_2_6[] = {
{ "virtio-mmio", "format_transport_address", "off" },
{ "virtio-pci", "disable-modern", "on" },
{ "virtio-pci", "disable-legacy", "off" },
/* Optional because not all virtio-pci devices support legacy mode */
{ "virtio-pci", "disable-modern", "on", .optional = true },
{ "virtio-pci", "disable-legacy", "off", .optional = true },
};
const size_t hw_compat_2_6_len = G_N_ELEMENTS(hw_compat_2_6);
+14
View File
@@ -19,6 +19,20 @@
#include "hw/virtio/virtio-pci.h"
#include "hw/virtio/virtio-gpu.h"
typedef struct VirtIOGPUPCI VirtIOGPUPCI;
/*
* virtio-gpu-pci: This extends VirtioPCIProxy.
*/
#define TYPE_VIRTIO_GPU_PCI "virtio-gpu-pci"
#define VIRTIO_GPU_PCI(obj) \
OBJECT_CHECK(VirtIOGPUPCI, (obj), TYPE_VIRTIO_GPU_PCI)
struct VirtIOGPUPCI {
VirtIOPCIProxy parent_obj;
VirtIOGPU vdev;
};
static Property virtio_gpu_pci_properties[] = {
DEFINE_VIRTIO_GPU_PCI_PROPERTIES(VirtIOPCIProxy),
DEFINE_PROP_END_OF_LIST(),
+1
View File
@@ -3,6 +3,7 @@
#include "hw/pci/pci.h"
#include "vga_int.h"
#include "hw/virtio/virtio-pci.h"
#include "hw/virtio/virtio-gpu.h"
#include "qapi/error.h"
/*
+27 -2
View File
@@ -119,6 +119,12 @@ typedef struct AcpiBuildPciBusHotplugState {
bool pcihp_bridge_en;
} AcpiBuildPciBusHotplugState;
typedef struct FwCfgTPMConfig {
uint32_t tpmppi_address;
uint8_t tpm_version;
uint8_t tpmppi_version;
} QEMU_PACKED FwCfgTPMConfig;
static void init_common_fadt_data(Object *o, AcpiFadtData *data)
{
uint32_t io = object_property_get_uint(o, ACPI_PM_PROP_PM_IO_BASE, NULL);
@@ -1796,6 +1802,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
uint32_t nr_mem = machine->ram_slots;
int root_bus_limit = 0xFF;
PCIBus *bus = NULL;
TPMIf *tpm = tpm_find();
int i;
dsdt = init_aml_allocator();
@@ -2133,7 +2140,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
/* Scan all PCI buses. Generate tables to support hotplug. */
build_append_pci_bus_devices(scope, bus, pm->pcihp_bridge_en);
if (TPM_IS_TIS(tpm_find())) {
if (TPM_IS_TIS(tpm)) {
dev = aml_device("ISA.TPM");
aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C31")));
aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
@@ -2147,6 +2154,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
*/
/* aml_append(crs, aml_irq_no_flags(TPM_TIS_IRQ)); */
aml_append(dev, aml_name_decl("_CRS", crs));
tpm_build_ppi_acpi(tpm, dev);
aml_append(scope, dev);
}
@@ -2154,7 +2164,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
}
}
if (TPM_IS_CRB(tpm_find())) {
if (TPM_IS_CRB(tpm)) {
dev = aml_device("TPM");
aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
crs = aml_resource_template();
@@ -2166,6 +2176,8 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
aml_append(method, aml_return(aml_int(0x0f)));
aml_append(dev, method);
tpm_build_ppi_acpi(tpm, dev);
aml_append(sb_scope, dev);
}
@@ -2847,6 +2859,8 @@ void acpi_setup(void)
AcpiBuildTables tables;
AcpiBuildState *build_state;
Object *vmgenid_dev;
TPMIf *tpm;
static FwCfgTPMConfig tpm_config;
if (!pcms->fw_cfg) {
ACPI_BUILD_DPRINTF("No fw cfg. Bailing out.\n");
@@ -2881,6 +2895,17 @@ void acpi_setup(void)
fw_cfg_add_file(pcms->fw_cfg, ACPI_BUILD_TPMLOG_FILE,
tables.tcpalog->data, acpi_data_len(tables.tcpalog));
tpm = tpm_find();
if (tpm && object_property_get_bool(OBJECT(tpm), "ppi", &error_abort)) {
tpm_config = (FwCfgTPMConfig) {
.tpmppi_address = cpu_to_le32(TPM_PPI_ADDR_BASE),
.tpm_version = tpm_get_version(tpm),
.tpmppi_version = TPM_PPI_VERSION_1_30
};
fw_cfg_add_file(pcms->fw_cfg, "etc/tpm/config",
&tpm_config, sizeof tpm_config);
}
vmgenid_dev = find_vmgenid_dev();
if (vmgenid_dev) {
vmgenid_add_fw_cfg(VMGENID(vmgenid_dev), pcms->fw_cfg,
-1
View File
@@ -715,7 +715,6 @@ static void pc_i440fx_1_2_machine_options(MachineClass *m)
PC_CPU_MODEL_IDS("1.2.0")
{ "nec-usb-xhci", "msi", "off" },
{ "nec-usb-xhci", "msix", "off" },
{ "ivshmem", "use64", "0" },
{ "qxl", "revision", "3" },
{ "qxl-vga", "revision", "3" },
{ "VGA", "mmio", "off" },
+1
View File
@@ -377,6 +377,7 @@ static void pci_edu_uninit(PCIDevice *pdev)
qemu_mutex_destroy(&edu->thr_mutex);
timer_del(&edu->dma_timer);
msi_uninit(pdev);
}
static void edu_obj_uint64(Object *obj, Visitor *v, const char *name,
+5 -205
View File
@@ -112,13 +112,6 @@ typedef struct IVShmemState {
/* migration stuff */
OnOffAuto master;
Error *migration_blocker;
/* legacy cruft */
char *role;
char *shmobj;
char *sizearg;
size_t legacy_size;
uint32_t not_legacy_32bit;
} IVShmemState;
/* registers for the Inter-VM shared memory device */
@@ -529,17 +522,6 @@ static void process_msg_shmem(IVShmemState *s, int fd, Error **errp)
size = buf.st_size;
/* Legacy cruft */
if (s->legacy_size != SIZE_MAX) {
if (size < s->legacy_size) {
error_setg(errp, "server sent only %zd bytes of shared memory",
(size_t)buf.st_size);
close(fd);
return;
}
size = s->legacy_size;
}
/* mmap the region and map into the BAR2 */
memory_region_init_ram_from_fd(&s->server_bar2, OBJECT(s),
"ivshmem.bar2", size, true, fd, &local_err);
@@ -882,8 +864,6 @@ static void ivshmem_common_realize(PCIDevice *dev, Error **errp)
IVShmemState *s = IVSHMEM_COMMON(dev);
Error *err = NULL;
uint8_t *pci_conf;
uint8_t attr = PCI_BASE_ADDRESS_SPACE_MEMORY |
PCI_BASE_ADDRESS_MEM_PREFETCH;
Error *local_err = NULL;
/* IRQFD requires MSI */
@@ -903,10 +883,6 @@ static void ivshmem_common_realize(PCIDevice *dev, Error **errp)
pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY,
&s->ivshmem_mmio);
if (s->not_legacy_32bit) {
attr |= PCI_BASE_ADDRESS_MEM_TYPE_64;
}
if (s->hostmem != NULL) {
IVSHMEM_DPRINTF("using hostmem\n");
@@ -964,7 +940,11 @@ static void ivshmem_common_realize(PCIDevice *dev, Error **errp)
}
vmstate_register_ram(s->ivshmem_bar2, DEVICE(s));
pci_register_bar(PCI_DEVICE(s), 2, attr, s->ivshmem_bar2);
pci_register_bar(PCI_DEVICE(s), 2,
PCI_BASE_ADDRESS_SPACE_MEMORY |
PCI_BASE_ADDRESS_MEM_PREFETCH |
PCI_BASE_ADDRESS_MEM_TYPE_64,
s->ivshmem_bar2);
}
static void ivshmem_exit(PCIDevice *dev)
@@ -1084,13 +1064,6 @@ static Property ivshmem_plain_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
static void ivshmem_plain_init(Object *obj)
{
IVShmemState *s = IVSHMEM_PLAIN(obj);
s->not_legacy_32bit = 1;
}
static void ivshmem_plain_realize(PCIDevice *dev, Error **errp)
{
IVShmemState *s = IVSHMEM_COMMON(dev);
@@ -1122,7 +1095,6 @@ static const TypeInfo ivshmem_plain_info = {
.name = TYPE_IVSHMEM_PLAIN,
.parent = TYPE_IVSHMEM_COMMON,
.instance_size = sizeof(IVShmemState),
.instance_init = ivshmem_plain_init,
.class_init = ivshmem_plain_class_init,
};
@@ -1155,8 +1127,6 @@ static void ivshmem_doorbell_init(Object *obj)
IVShmemState *s = IVSHMEM_DOORBELL(obj);
s->features |= (1 << IVSHMEM_MSI);
s->legacy_size = SIZE_MAX; /* whatever the server sends */
s->not_legacy_32bit = 1;
}
static void ivshmem_doorbell_realize(PCIDevice *dev, Error **errp)
@@ -1189,181 +1159,11 @@ static const TypeInfo ivshmem_doorbell_info = {
.class_init = ivshmem_doorbell_class_init,
};
static int ivshmem_load_old(QEMUFile *f, void *opaque, int version_id)
{
IVShmemState *s = opaque;
PCIDevice *pdev = PCI_DEVICE(s);
int ret;
IVSHMEM_DPRINTF("ivshmem_load_old\n");
if (version_id != 0) {
return -EINVAL;
}
ret = ivshmem_pre_load(s);
if (ret) {
return ret;
}
ret = pci_device_load(pdev, f);
if (ret) {
return ret;
}
if (ivshmem_has_feature(s, IVSHMEM_MSI)) {
msix_load(pdev, f);
ivshmem_msix_vector_use(s);
} else {
s->intrstatus = qemu_get_be32(f);
s->intrmask = qemu_get_be32(f);
}
return 0;
}
static bool test_msix(void *opaque, int version_id)
{
IVShmemState *s = opaque;
return ivshmem_has_feature(s, IVSHMEM_MSI);
}
static bool test_no_msix(void *opaque, int version_id)
{
return !test_msix(opaque, version_id);
}
static const VMStateDescription ivshmem_vmsd = {
.name = "ivshmem",
.version_id = 1,
.minimum_version_id = 1,
.pre_load = ivshmem_pre_load,
.post_load = ivshmem_post_load,
.fields = (VMStateField[]) {
VMSTATE_PCI_DEVICE(parent_obj, IVShmemState),
VMSTATE_MSIX_TEST(parent_obj, IVShmemState, test_msix),
VMSTATE_UINT32_TEST(intrstatus, IVShmemState, test_no_msix),
VMSTATE_UINT32_TEST(intrmask, IVShmemState, test_no_msix),
VMSTATE_END_OF_LIST()
},
.load_state_old = ivshmem_load_old,
.minimum_version_id_old = 0
};
static Property ivshmem_properties[] = {
DEFINE_PROP_CHR("chardev", IVShmemState, server_chr),
DEFINE_PROP_STRING("size", IVShmemState, sizearg),
DEFINE_PROP_UINT32("vectors", IVShmemState, vectors, 1),
DEFINE_PROP_BIT("ioeventfd", IVShmemState, features, IVSHMEM_IOEVENTFD,
false),
DEFINE_PROP_BIT("msi", IVShmemState, features, IVSHMEM_MSI, true),
DEFINE_PROP_STRING("shm", IVShmemState, shmobj),
DEFINE_PROP_STRING("role", IVShmemState, role),
DEFINE_PROP_UINT32("use64", IVShmemState, not_legacy_32bit, 1),
DEFINE_PROP_END_OF_LIST(),
};
static void desugar_shm(IVShmemState *s)
{
Object *obj;
char *path;
obj = object_new("memory-backend-file");
path = g_strdup_printf("/dev/shm/%s", s->shmobj);
object_property_set_str(obj, path, "mem-path", &error_abort);
g_free(path);
object_property_set_int(obj, s->legacy_size, "size", &error_abort);
object_property_set_bool(obj, true, "share", &error_abort);
object_property_add_child(OBJECT(s), "internal-shm-backend", obj,
&error_abort);
object_unref(obj);
user_creatable_complete(USER_CREATABLE(obj), &error_abort);
s->hostmem = MEMORY_BACKEND(obj);
}
static void ivshmem_realize(PCIDevice *dev, Error **errp)
{
IVShmemState *s = IVSHMEM_COMMON(dev);
if (!qtest_enabled()) {
warn_report("ivshmem is deprecated, please use ivshmem-plain"
" or ivshmem-doorbell instead");
}
if (qemu_chr_fe_backend_connected(&s->server_chr) + !!s->shmobj != 1) {
error_setg(errp, "You must specify either 'shm' or 'chardev'");
return;
}
if (s->sizearg == NULL) {
s->legacy_size = 4 * MiB; /* 4 MB default */
} else {
int ret;
uint64_t size;
ret = qemu_strtosz_MiB(s->sizearg, NULL, &size);
if (ret < 0 || (size_t)size != size || !is_power_of_2(size)) {
error_setg(errp, "Invalid size %s", s->sizearg);
return;
}
s->legacy_size = size;
}
/* check that role is reasonable */
if (s->role) {
if (strncmp(s->role, "peer", 5) == 0) {
s->master = ON_OFF_AUTO_OFF;
} else if (strncmp(s->role, "master", 7) == 0) {
s->master = ON_OFF_AUTO_ON;
} else {
error_setg(errp, "'role' must be 'peer' or 'master'");
return;
}
} else {
s->master = ON_OFF_AUTO_AUTO;
}
if (s->shmobj) {
desugar_shm(s);
}
/*
* Note: we don't use INTx with IVSHMEM_MSI at all, so this is a
* bald-faced lie then. But it's a backwards compatible lie.
*/
pci_config_set_interrupt_pin(dev->config, 1);
ivshmem_common_realize(dev, errp);
}
static void ivshmem_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
k->realize = ivshmem_realize;
k->revision = 0;
dc->desc = "Inter-VM shared memory (legacy)";
dc->props = ivshmem_properties;
dc->vmsd = &ivshmem_vmsd;
}
static const TypeInfo ivshmem_info = {
.name = TYPE_IVSHMEM,
.parent = TYPE_IVSHMEM_COMMON,
.instance_size = sizeof(IVShmemState),
.class_init = ivshmem_class_init,
};
static void ivshmem_register_types(void)
{
type_register_static(&ivshmem_common_info);
type_register_static(&ivshmem_plain_info);
type_register_static(&ivshmem_doorbell_info);
type_register_static(&ivshmem_info);
}
type_init(ivshmem_register_types)
+666 -1
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -345,7 +345,7 @@ int msix_init_exclusive_bar(PCIDevice *dev, unsigned short nentries,
char *name;
uint32_t bar_size = 4096;
uint32_t bar_pba_offset = bar_size / 2;
uint32_t bar_pba_size = (nentries / 8 + 1) * 8;
uint32_t bar_pba_size = QEMU_ALIGN_UP(nentries, 64) / 8;
/*
* Migration compatibility dictates that this remains a 4k
+17 -8
View File
@@ -391,10 +391,10 @@ static void pcie_cap_slot_event(PCIDevice *dev, PCIExpressHotPlugEvent event)
}
static void pcie_cap_slot_plug_common(PCIDevice *hotplug_dev, DeviceState *dev,
uint8_t **exp_cap, Error **errp)
Error **errp)
{
*exp_cap = hotplug_dev->config + hotplug_dev->exp.exp_cap;
uint16_t sltsta = pci_get_word(*exp_cap + PCI_EXP_SLTSTA);
uint8_t *exp_cap = hotplug_dev->config + hotplug_dev->exp.exp_cap;
uint16_t sltsta = pci_get_word(exp_cap + PCI_EXP_SLTSTA);
PCIE_DEV_PRINTF(PCI_DEVICE(dev), "hotplug state: 0x%x\n", sltsta);
if (sltsta & PCI_EXP_SLTSTA_EIS) {
@@ -405,14 +405,19 @@ static void pcie_cap_slot_plug_common(PCIDevice *hotplug_dev, DeviceState *dev,
}
}
void pcie_cap_slot_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
pcie_cap_slot_plug_common(PCI_DEVICE(hotplug_dev), dev, errp);
}
void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
uint8_t *exp_cap;
PCIDevice *hotplug_pdev = PCI_DEVICE(hotplug_dev);
uint8_t *exp_cap = hotplug_pdev->config + hotplug_pdev->exp.exp_cap;
PCIDevice *pci_dev = PCI_DEVICE(dev);
pcie_cap_slot_plug_common(PCI_DEVICE(hotplug_dev), dev, &exp_cap, errp);
/* Don't send event when device is enabled during qemu machine creation:
* it is present on boot, no hotplug event is necessary. We do send an
* event when the device is disabled later. */
@@ -458,11 +463,15 @@ static void pcie_unplug_device(PCIBus *bus, PCIDevice *dev, void *opaque)
void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
uint8_t *exp_cap;
Error *local_err = NULL;
PCIDevice *pci_dev = PCI_DEVICE(dev);
PCIBus *bus = pci_get_bus(pci_dev);
pcie_cap_slot_plug_common(PCI_DEVICE(hotplug_dev), dev, &exp_cap, errp);
pcie_cap_slot_plug_common(PCI_DEVICE(hotplug_dev), dev, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
/* In case user cancel the operation of multi-function hot-add,
* remove the function that is unexposed to guest individually,
+1
View File
@@ -154,6 +154,7 @@ static void pcie_slot_class_init(ObjectClass *oc, void *data)
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
dc->props = pcie_slot_props;
hc->pre_plug = pcie_cap_slot_pre_plug_cb;
hc->plug = pcie_cap_slot_plug_cb;
hc->unplug = pcie_cap_slot_unplug_cb;
hc->unplug_request = pcie_cap_slot_unplug_request_cb;

Some files were not shown because too many files have changed in this diff Show More