mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
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:
+1
-1
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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
@@ -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,
|
||||
|
||||
@@ -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" },
|
||||
|
||||
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -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
@@ -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,
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user