mirror of https://github.com/xqemu/xqemu.git
pc, pci, tpm, virtio, vhost enhancements and fixes
A bunch of cleanups and fixes all over the place, enhancements in TPM, virtio and vhost. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJVbE3kAAoJECgfDbjSjVRphV4H/jEnq16oMP72H6xgbAIKjvrP uEx4jgkj9qGfgqLQJURPKemgzNbP+dXjd4LkIdgbUvlknCgFeKyJVPxzCCIhjc7R 5D70Aptg1CdVNaMeqsIOyJIYe0hIXQjbF7a/jtxf8nR9+kLIOpcQ200oRJtxpGVu VfzWnBj48PRXi/W03OinWYrkqeAqx0BNHRxXQ5Ylr/DxTBoJKmmp13wW/5U+Xtmi g5hDS5IF/qqrIKftisR7sDEfXENJf3ZulqP/2N8Lvufyj1lQxGkEGTKD5FDzeaj6 X0/UvUv7I2OzCbcTyeCwzF1GfZOgGceiXxopEp359SkvyoJILF7/C0Na5LY/fiw= =fckd -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging pc, pci, tpm, virtio, vhost enhancements and fixes A bunch of cleanups and fixes all over the place, enhancements in TPM, virtio and vhost. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> # gpg: Signature made Mon Jun 1 13:19:48 2015 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: (60 commits) vhost-user: add multi queue support virtio: make features 64bit wide qdev: add 64bit properties virtio-mmio: ioeventfd support hw/acpi/aml-build: Fix memory leak acpi: add aml_while() term acpi: add aml_increment() term acpi: add aml_shiftright() term acpi: add aml_shiftleft() term acpi: add aml_index() term acpi: add aml_lless() term acpi: add aml_add() term TPM2 ACPI table support tpm: Probe for connected TPM 1.2 or TPM 2 Extend TPM TIS interface to support TPM 2 Add stream ID to MSI write acpi: Simplify printing to dynamic string i386: drop FDC in pc-q35-2.4+ if neither it nor floppy drives are wanted i386/pc_q35: don't insist on board FDC if there's no default floppy i386/pc: '-drive if=floppy' should imply a board-default FDC ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
b821cbe274
|
@ -96,6 +96,20 @@ bool tpm_backend_get_tpm_established_flag(TPMBackend *s)
|
||||||
return k->ops->get_tpm_established_flag(s);
|
return k->ops->get_tpm_established_flag(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int tpm_backend_reset_tpm_established_flag(TPMBackend *s, uint8_t locty)
|
||||||
|
{
|
||||||
|
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
|
||||||
|
|
||||||
|
return k->ops->reset_tpm_established_flag(s, locty);
|
||||||
|
}
|
||||||
|
|
||||||
|
TPMVersion tpm_backend_get_tpm_version(TPMBackend *s)
|
||||||
|
{
|
||||||
|
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
|
||||||
|
|
||||||
|
return k->ops->get_tpm_version(s);
|
||||||
|
}
|
||||||
|
|
||||||
static bool tpm_backend_prop_get_opened(Object *obj, Error **errp)
|
static bool tpm_backend_prop_get_opened(Object *obj, Error **errp)
|
||||||
{
|
{
|
||||||
TPMBackend *s = TPM_BACKEND(obj);
|
TPMBackend *s = TPM_BACKEND(obj);
|
||||||
|
|
|
@ -127,6 +127,11 @@ in the ancillary data:
|
||||||
If Master is unable to send the full message or receives a wrong reply it will
|
If Master is unable to send the full message or receives a wrong reply it will
|
||||||
close the connection. An optional reconnection mechanism can be implemented.
|
close the connection. An optional reconnection mechanism can be implemented.
|
||||||
|
|
||||||
|
Multi queue support
|
||||||
|
-------------------
|
||||||
|
The protocol supports multiple queues by setting all index fields in the sent
|
||||||
|
messages to a properly calculated value.
|
||||||
|
|
||||||
Message types
|
Message types
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include "virtio-9p-coth.h"
|
#include "virtio-9p-coth.h"
|
||||||
#include "hw/virtio/virtio-access.h"
|
#include "hw/virtio/virtio-access.h"
|
||||||
|
|
||||||
static uint32_t virtio_9p_get_features(VirtIODevice *vdev, uint32_t features)
|
static uint64_t virtio_9p_get_features(VirtIODevice *vdev, uint64_t features)
|
||||||
{
|
{
|
||||||
virtio_add_feature(&features, VIRTIO_9P_MOUNT_TAG);
|
virtio_add_feature(&features, VIRTIO_9P_MOUNT_TAG);
|
||||||
return features;
|
return features;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <glib/gprintf.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
@ -59,7 +60,6 @@ static void build_append_array(GArray *array, GArray *val)
|
||||||
static void
|
static void
|
||||||
build_append_nameseg(GArray *array, const char *seg)
|
build_append_nameseg(GArray *array, const char *seg)
|
||||||
{
|
{
|
||||||
/* It would be nicer to use g_string_vprintf but it's only there in 2.22 */
|
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
len = strlen(seg);
|
len = strlen(seg);
|
||||||
|
@ -73,22 +73,12 @@ build_append_nameseg(GArray *array, const char *seg)
|
||||||
static void GCC_FMT_ATTR(2, 0)
|
static void GCC_FMT_ATTR(2, 0)
|
||||||
build_append_namestringv(GArray *array, const char *format, va_list ap)
|
build_append_namestringv(GArray *array, const char *format, va_list ap)
|
||||||
{
|
{
|
||||||
/* It would be nicer to use g_string_vprintf but it's only there in 2.22 */
|
|
||||||
char *s;
|
char *s;
|
||||||
int len;
|
|
||||||
va_list va_len;
|
|
||||||
char **segs;
|
char **segs;
|
||||||
char **segs_iter;
|
char **segs_iter;
|
||||||
int seg_count = 0;
|
int seg_count = 0;
|
||||||
|
|
||||||
va_copy(va_len, ap);
|
s = g_strdup_vprintf(format, ap);
|
||||||
len = vsnprintf(NULL, 0, format, va_len);
|
|
||||||
va_end(va_len);
|
|
||||||
len += 1;
|
|
||||||
s = g_new(typeof(*s), len);
|
|
||||||
|
|
||||||
len = vsnprintf(s, len, format, ap);
|
|
||||||
|
|
||||||
segs = g_strsplit(s, ".", 0);
|
segs = g_strsplit(s, ".", 0);
|
||||||
g_free(s);
|
g_free(s);
|
||||||
|
|
||||||
|
@ -306,6 +296,7 @@ static void aml_free(gpointer data, gpointer user_data)
|
||||||
{
|
{
|
||||||
Aml *var = data;
|
Aml *var = data;
|
||||||
build_free_array(var->buf);
|
build_free_array(var->buf);
|
||||||
|
g_free(var);
|
||||||
}
|
}
|
||||||
|
|
||||||
Aml *init_aml_allocator(void)
|
Aml *init_aml_allocator(void)
|
||||||
|
@ -465,6 +456,63 @@ Aml *aml_or(Aml *arg1, Aml *arg2)
|
||||||
return var;
|
return var;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefShiftLeft */
|
||||||
|
Aml *aml_shiftleft(Aml *arg1, Aml *count)
|
||||||
|
{
|
||||||
|
Aml *var = aml_opcode(0x79 /* ShiftLeftOp */);
|
||||||
|
aml_append(var, arg1);
|
||||||
|
aml_append(var, count);
|
||||||
|
build_append_byte(var->buf, 0x00); /* NullNameOp */
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefShiftRight */
|
||||||
|
Aml *aml_shiftright(Aml *arg1, Aml *count)
|
||||||
|
{
|
||||||
|
Aml *var = aml_opcode(0x7A /* ShiftRightOp */);
|
||||||
|
aml_append(var, arg1);
|
||||||
|
aml_append(var, count);
|
||||||
|
build_append_byte(var->buf, 0x00); /* NullNameOp */
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLLess */
|
||||||
|
Aml *aml_lless(Aml *arg1, Aml *arg2)
|
||||||
|
{
|
||||||
|
Aml *var = aml_opcode(0x95 /* LLessOp */);
|
||||||
|
aml_append(var, arg1);
|
||||||
|
aml_append(var, arg2);
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefAdd */
|
||||||
|
Aml *aml_add(Aml *arg1, Aml *arg2)
|
||||||
|
{
|
||||||
|
Aml *var = aml_opcode(0x72 /* AddOp */);
|
||||||
|
aml_append(var, arg1);
|
||||||
|
aml_append(var, arg2);
|
||||||
|
build_append_byte(var->buf, 0x00 /* NullNameOp */);
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefIncrement */
|
||||||
|
Aml *aml_increment(Aml *arg)
|
||||||
|
{
|
||||||
|
Aml *var = aml_opcode(0x75 /* IncrementOp */);
|
||||||
|
aml_append(var, arg);
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefIndex */
|
||||||
|
Aml *aml_index(Aml *arg1, Aml *idx)
|
||||||
|
{
|
||||||
|
Aml *var = aml_opcode(0x88 /* IndexOp */);
|
||||||
|
aml_append(var, arg1);
|
||||||
|
aml_append(var, idx);
|
||||||
|
build_append_byte(var->buf, 0x00 /* NullNameOp */);
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
|
||||||
/* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefNotify */
|
/* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefNotify */
|
||||||
Aml *aml_notify(Aml *arg1, Aml *arg2)
|
Aml *aml_notify(Aml *arg1, Aml *arg2)
|
||||||
{
|
{
|
||||||
|
@ -753,22 +801,15 @@ Aml *aml_create_dword_field(Aml *srcbuf, Aml *index, const char *name)
|
||||||
Aml *aml_string(const char *name_format, ...)
|
Aml *aml_string(const char *name_format, ...)
|
||||||
{
|
{
|
||||||
Aml *var = aml_opcode(0x0D /* StringPrefix */);
|
Aml *var = aml_opcode(0x0D /* StringPrefix */);
|
||||||
va_list ap, va_len;
|
va_list ap;
|
||||||
char *s;
|
char *s;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
va_start(ap, name_format);
|
va_start(ap, name_format);
|
||||||
va_copy(va_len, ap);
|
len = g_vasprintf(&s, name_format, ap);
|
||||||
len = vsnprintf(NULL, 0, name_format, va_len);
|
|
||||||
va_end(va_len);
|
|
||||||
len += 1;
|
|
||||||
s = g_new0(typeof(*s), len);
|
|
||||||
|
|
||||||
len = vsnprintf(s, len, name_format, ap);
|
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
g_array_append_vals(var->buf, s, len);
|
g_array_append_vals(var->buf, s, len + 1);
|
||||||
build_append_byte(var->buf, 0x0); /* NullChar */
|
|
||||||
g_free(s);
|
g_free(s);
|
||||||
|
|
||||||
return var;
|
return var;
|
||||||
|
|
|
@ -718,7 +718,7 @@ static void virtio_blk_set_config(VirtIODevice *vdev, const uint8_t *config)
|
||||||
aio_context_release(blk_get_aio_context(s->blk));
|
aio_context_release(blk_get_aio_context(s->blk));
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features)
|
static uint64_t virtio_blk_get_features(VirtIODevice *vdev, uint64_t features)
|
||||||
{
|
{
|
||||||
VirtIOBlock *s = VIRTIO_BLK(vdev);
|
VirtIOBlock *s = VIRTIO_BLK(vdev);
|
||||||
|
|
||||||
|
|
|
@ -498,7 +498,7 @@ static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t get_features(VirtIODevice *vdev, uint32_t features)
|
static uint64_t get_features(VirtIODevice *vdev, uint64_t features)
|
||||||
{
|
{
|
||||||
VirtIOSerial *vser;
|
VirtIOSerial *vser;
|
||||||
|
|
||||||
|
@ -973,7 +973,7 @@ static void virtio_serial_device_realize(DeviceState *dev, Error **errp)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Each port takes 2 queues, and one pair is for the control queue */
|
/* Each port takes 2 queues, and one pair is for the control queue */
|
||||||
max_supported_ports = VIRTIO_PCI_QUEUE_MAX / 2 - 1;
|
max_supported_ports = VIRTIO_QUEUE_MAX / 2 - 1;
|
||||||
|
|
||||||
if (vser->serial.max_virtserial_ports > max_supported_ports) {
|
if (vser->serial.max_virtserial_ports > max_supported_ports) {
|
||||||
error_setg(errp, "maximum ports supported: %u", max_supported_ports);
|
error_setg(errp, "maximum ports supported: %u", max_supported_ports);
|
||||||
|
|
|
@ -125,6 +125,64 @@ PropertyInfo qdev_prop_bit = {
|
||||||
.set = prop_set_bit,
|
.set = prop_set_bit,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Bit64 */
|
||||||
|
|
||||||
|
static uint64_t qdev_get_prop_mask64(Property *prop)
|
||||||
|
{
|
||||||
|
assert(prop->info == &qdev_prop_bit);
|
||||||
|
return 0x1 << prop->bitnr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bit64_prop_set(DeviceState *dev, Property *props, bool val)
|
||||||
|
{
|
||||||
|
uint64_t *p = qdev_get_prop_ptr(dev, props);
|
||||||
|
uint64_t mask = qdev_get_prop_mask64(props);
|
||||||
|
if (val) {
|
||||||
|
*p |= mask;
|
||||||
|
} else {
|
||||||
|
*p &= ~mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void prop_get_bit64(Object *obj, Visitor *v, void *opaque,
|
||||||
|
const char *name, Error **errp)
|
||||||
|
{
|
||||||
|
DeviceState *dev = DEVICE(obj);
|
||||||
|
Property *prop = opaque;
|
||||||
|
uint64_t *p = qdev_get_prop_ptr(dev, prop);
|
||||||
|
bool value = (*p & qdev_get_prop_mask64(prop)) != 0;
|
||||||
|
|
||||||
|
visit_type_bool(v, &value, name, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void prop_set_bit64(Object *obj, Visitor *v, void *opaque,
|
||||||
|
const char *name, Error **errp)
|
||||||
|
{
|
||||||
|
DeviceState *dev = DEVICE(obj);
|
||||||
|
Property *prop = opaque;
|
||||||
|
Error *local_err = NULL;
|
||||||
|
bool value;
|
||||||
|
|
||||||
|
if (dev->realized) {
|
||||||
|
qdev_prop_set_after_realize(dev, name, errp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_type_bool(v, &value, name, &local_err);
|
||||||
|
if (local_err) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bit64_prop_set(dev, prop, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
PropertyInfo qdev_prop_bit64 = {
|
||||||
|
.name = "bool",
|
||||||
|
.description = "on/off",
|
||||||
|
.get = prop_get_bit64,
|
||||||
|
.set = prop_set_bit64,
|
||||||
|
};
|
||||||
|
|
||||||
/* --- bool --- */
|
/* --- bool --- */
|
||||||
|
|
||||||
static void get_bool(Object *obj, Visitor *v, void *opaque,
|
static void get_bool(Object *obj, Visitor *v, void *opaque,
|
||||||
|
|
|
@ -9,7 +9,7 @@ obj-y += kvmvapic.o
|
||||||
obj-y += acpi-build.o
|
obj-y += acpi-build.o
|
||||||
hw/i386/acpi-build.o: hw/i386/acpi-build.c \
|
hw/i386/acpi-build.o: hw/i386/acpi-build.c \
|
||||||
hw/i386/acpi-dsdt.hex hw/i386/q35-acpi-dsdt.hex \
|
hw/i386/acpi-dsdt.hex hw/i386/q35-acpi-dsdt.hex \
|
||||||
hw/i386/ssdt-tpm.hex
|
hw/i386/ssdt-tpm.hex hw/i386/ssdt-tpm2.hex
|
||||||
|
|
||||||
iasl-option=$(shell if test -z "`$(1) $(2) 2>&1 > /dev/null`" \
|
iasl-option=$(shell if test -z "`$(1) $(2) 2>&1 > /dev/null`" \
|
||||||
; then echo "$(2)"; else echo "$(3)"; fi ;)
|
; then echo "$(2)"; else echo "$(3)"; fi ;)
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include "hw/acpi/memory_hotplug.h"
|
#include "hw/acpi/memory_hotplug.h"
|
||||||
#include "sysemu/tpm.h"
|
#include "sysemu/tpm.h"
|
||||||
#include "hw/acpi/tpm.h"
|
#include "hw/acpi/tpm.h"
|
||||||
|
#include "sysemu/tpm_backend.h"
|
||||||
|
|
||||||
/* Supported chipsets: */
|
/* Supported chipsets: */
|
||||||
#include "hw/acpi/piix4.h"
|
#include "hw/acpi/piix4.h"
|
||||||
|
@ -106,7 +107,7 @@ typedef struct AcpiPmInfo {
|
||||||
|
|
||||||
typedef struct AcpiMiscInfo {
|
typedef struct AcpiMiscInfo {
|
||||||
bool has_hpet;
|
bool has_hpet;
|
||||||
bool has_tpm;
|
TPMVersion tpm_version;
|
||||||
const unsigned char *dsdt_code;
|
const unsigned char *dsdt_code;
|
||||||
unsigned dsdt_size;
|
unsigned dsdt_size;
|
||||||
uint16_t pvpanic_port;
|
uint16_t pvpanic_port;
|
||||||
|
@ -234,7 +235,7 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
|
||||||
static void acpi_get_misc_info(AcpiMiscInfo *info)
|
static void acpi_get_misc_info(AcpiMiscInfo *info)
|
||||||
{
|
{
|
||||||
info->has_hpet = hpet_find();
|
info->has_hpet = hpet_find();
|
||||||
info->has_tpm = tpm_find();
|
info->tpm_version = tpm_get_version();
|
||||||
info->pvpanic_port = pvpanic_port();
|
info->pvpanic_port = pvpanic_port();
|
||||||
info->applesmc_io_base = applesmc_port();
|
info->applesmc_io_base = applesmc_port();
|
||||||
}
|
}
|
||||||
|
@ -414,6 +415,7 @@ build_madt(GArray *table_data, GArray *linker, AcpiCpuInfo *cpu,
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "hw/i386/ssdt-tpm.hex"
|
#include "hw/i386/ssdt-tpm.hex"
|
||||||
|
#include "hw/i386/ssdt-tpm2.hex"
|
||||||
|
|
||||||
/* Assign BSEL property to all buses. In the future, this can be changed
|
/* Assign BSEL property to all buses. In the future, this can be changed
|
||||||
* to only assign to buses that support hotplug.
|
* to only assign to buses that support hotplug.
|
||||||
|
@ -733,7 +735,7 @@ build_ssdt(GArray *table_data, GArray *linker,
|
||||||
if (misc->pvpanic_port) {
|
if (misc->pvpanic_port) {
|
||||||
scope = aml_scope("\\_SB.PCI0.ISA");
|
scope = aml_scope("\\_SB.PCI0.ISA");
|
||||||
|
|
||||||
dev = aml_device("PEVR");
|
dev = aml_device("PEVT");
|
||||||
aml_append(dev, aml_name_decl("_HID", aml_string("QEMU0001")));
|
aml_append(dev, aml_name_decl("_HID", aml_string("QEMU0001")));
|
||||||
|
|
||||||
crs = aml_resource_template();
|
crs = aml_resource_template();
|
||||||
|
@ -748,6 +750,9 @@ build_ssdt(GArray *table_data, GArray *linker,
|
||||||
aml_append(field, aml_named_field("PEPT", 8));
|
aml_append(field, aml_named_field("PEPT", 8));
|
||||||
aml_append(dev, field);
|
aml_append(dev, field);
|
||||||
|
|
||||||
|
/* device present, functioning, decoding, not shown in UI */
|
||||||
|
aml_append(dev, aml_name_decl("_STA", aml_int(0xB)));
|
||||||
|
|
||||||
method = aml_method("RDPT", 0);
|
method = aml_method("RDPT", 0);
|
||||||
aml_append(method, aml_store(aml_name("PEPT"), aml_local(0)));
|
aml_append(method, aml_store(aml_name("PEPT"), aml_local(0)));
|
||||||
aml_append(method, aml_return(aml_local(0)));
|
aml_append(method, aml_return(aml_local(0)));
|
||||||
|
@ -1026,6 +1031,25 @@ build_tpm_ssdt(GArray *table_data, GArray *linker)
|
||||||
memcpy(tpm_ptr, ssdt_tpm_aml, sizeof(ssdt_tpm_aml));
|
memcpy(tpm_ptr, ssdt_tpm_aml, sizeof(ssdt_tpm_aml));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
build_tpm2(GArray *table_data, GArray *linker)
|
||||||
|
{
|
||||||
|
Acpi20TPM2 *tpm2_ptr;
|
||||||
|
void *tpm_ptr;
|
||||||
|
|
||||||
|
tpm_ptr = acpi_data_push(table_data, sizeof(ssdt_tpm2_aml));
|
||||||
|
memcpy(tpm_ptr, ssdt_tpm2_aml, sizeof(ssdt_tpm2_aml));
|
||||||
|
|
||||||
|
tpm2_ptr = acpi_data_push(table_data, sizeof *tpm2_ptr);
|
||||||
|
|
||||||
|
tpm2_ptr->platform_class = cpu_to_le16(TPM2_ACPI_CLASS_CLIENT);
|
||||||
|
tpm2_ptr->control_area_address = cpu_to_le64(0);
|
||||||
|
tpm2_ptr->start_method = cpu_to_le32(TPM2_START_METHOD_MMIO);
|
||||||
|
|
||||||
|
build_header(linker, table_data,
|
||||||
|
(void *)tpm2_ptr, "TPM2", sizeof(*tpm2_ptr), 4);
|
||||||
|
}
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
MEM_AFFINITY_NOFLAGS = 0,
|
MEM_AFFINITY_NOFLAGS = 0,
|
||||||
MEM_AFFINITY_ENABLED = (1 << 0),
|
MEM_AFFINITY_ENABLED = (1 << 0),
|
||||||
|
@ -1340,12 +1364,21 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
|
||||||
acpi_add_table(table_offsets, tables_blob);
|
acpi_add_table(table_offsets, tables_blob);
|
||||||
build_hpet(tables_blob, tables->linker);
|
build_hpet(tables_blob, tables->linker);
|
||||||
}
|
}
|
||||||
if (misc.has_tpm) {
|
if (misc.tpm_version != TPM_VERSION_UNSPEC) {
|
||||||
acpi_add_table(table_offsets, tables_blob);
|
acpi_add_table(table_offsets, tables_blob);
|
||||||
build_tpm_tcpa(tables_blob, tables->linker, tables->tcpalog);
|
build_tpm_tcpa(tables_blob, tables->linker, tables->tcpalog);
|
||||||
|
|
||||||
acpi_add_table(table_offsets, tables_blob);
|
acpi_add_table(table_offsets, tables_blob);
|
||||||
build_tpm_ssdt(tables_blob, tables->linker);
|
switch (misc.tpm_version) {
|
||||||
|
case TPM_VERSION_1_2:
|
||||||
|
build_tpm_ssdt(tables_blob, tables->linker);
|
||||||
|
break;
|
||||||
|
case TPM_VERSION_2_0:
|
||||||
|
build_tpm2(tables_blob, tables->linker);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (guest_info->numa_nodes) {
|
if (guest_info->numa_nodes) {
|
||||||
acpi_add_table(table_offsets, tables_blob);
|
acpi_add_table(table_offsets, tables_blob);
|
||||||
|
|
49
hw/i386/pc.c
49
hw/i386/pc.c
|
@ -1395,6 +1395,7 @@ static const MemoryRegionOps ioportF0_io_ops = {
|
||||||
|
|
||||||
void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
|
void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
|
||||||
ISADevice **rtc_state,
|
ISADevice **rtc_state,
|
||||||
|
bool create_fdctrl,
|
||||||
ISADevice **floppy,
|
ISADevice **floppy,
|
||||||
bool no_vmport,
|
bool no_vmport,
|
||||||
uint32 hpet_irqs)
|
uint32 hpet_irqs)
|
||||||
|
@ -1489,8 +1490,9 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
|
||||||
|
|
||||||
for(i = 0; i < MAX_FD; i++) {
|
for(i = 0; i < MAX_FD; i++) {
|
||||||
fd[i] = drive_get(IF_FLOPPY, 0, i);
|
fd[i] = drive_get(IF_FLOPPY, 0, i);
|
||||||
|
create_fdctrl |= !!fd[i];
|
||||||
}
|
}
|
||||||
*floppy = fdctrl_init_isa(isa_bus, fd);
|
*floppy = create_fdctrl ? fdctrl_init_isa(isa_bus, fd) : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pc_nic_init(ISABus *isa_bus, PCIBus *pci_bus)
|
void pc_nic_init(ISABus *isa_bus, PCIBus *pci_bus)
|
||||||
|
@ -1543,51 +1545,6 @@ void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pc_generic_machine_class_init(ObjectClass *oc, void *data)
|
|
||||||
{
|
|
||||||
MachineClass *mc = MACHINE_CLASS(oc);
|
|
||||||
QEMUMachine *qm = data;
|
|
||||||
|
|
||||||
mc->family = qm->family;
|
|
||||||
mc->name = qm->name;
|
|
||||||
mc->alias = qm->alias;
|
|
||||||
mc->desc = qm->desc;
|
|
||||||
mc->init = qm->init;
|
|
||||||
mc->reset = qm->reset;
|
|
||||||
mc->hot_add_cpu = qm->hot_add_cpu;
|
|
||||||
mc->kvm_type = qm->kvm_type;
|
|
||||||
mc->block_default_type = qm->block_default_type;
|
|
||||||
mc->units_per_default_bus = qm->units_per_default_bus;
|
|
||||||
mc->max_cpus = qm->max_cpus;
|
|
||||||
mc->no_serial = qm->no_serial;
|
|
||||||
mc->no_parallel = qm->no_parallel;
|
|
||||||
mc->use_virtcon = qm->use_virtcon;
|
|
||||||
mc->use_sclp = qm->use_sclp;
|
|
||||||
mc->no_floppy = qm->no_floppy;
|
|
||||||
mc->no_cdrom = qm->no_cdrom;
|
|
||||||
mc->no_sdcard = qm->no_sdcard;
|
|
||||||
mc->is_default = qm->is_default;
|
|
||||||
mc->default_machine_opts = qm->default_machine_opts;
|
|
||||||
mc->default_boot_order = qm->default_boot_order;
|
|
||||||
mc->default_display = qm->default_display;
|
|
||||||
mc->compat_props = qm->compat_props;
|
|
||||||
mc->hw_version = qm->hw_version;
|
|
||||||
}
|
|
||||||
|
|
||||||
void qemu_register_pc_machine(QEMUMachine *m)
|
|
||||||
{
|
|
||||||
char *name = g_strconcat(m->name, TYPE_MACHINE_SUFFIX, NULL);
|
|
||||||
TypeInfo ti = {
|
|
||||||
.name = name,
|
|
||||||
.parent = TYPE_PC_MACHINE,
|
|
||||||
.class_init = pc_generic_machine_class_init,
|
|
||||||
.class_data = (void *)m,
|
|
||||||
};
|
|
||||||
|
|
||||||
type_register(&ti);
|
|
||||||
g_free(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pc_dimm_plug(HotplugHandler *hotplug_dev,
|
static void pc_dimm_plug(HotplugHandler *hotplug_dev,
|
||||||
DeviceState *dev, Error **errp)
|
DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
|
|
|
@ -59,6 +59,7 @@ static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 };
|
||||||
static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };
|
static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };
|
||||||
static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
|
static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
|
||||||
|
|
||||||
|
static bool pci_enabled = true;
|
||||||
static bool has_acpi_build = true;
|
static bool has_acpi_build = true;
|
||||||
static bool rsdp_in_ram = true;
|
static bool rsdp_in_ram = true;
|
||||||
static int legacy_acpi_table_size;
|
static int legacy_acpi_table_size;
|
||||||
|
@ -71,11 +72,10 @@ static bool smbios_uuid_encoded = true;
|
||||||
*/
|
*/
|
||||||
static bool gigabyte_align = true;
|
static bool gigabyte_align = true;
|
||||||
static bool has_reserved_memory = true;
|
static bool has_reserved_memory = true;
|
||||||
|
static bool kvmclock_enabled = true;
|
||||||
|
|
||||||
/* PC hardware initialisation */
|
/* PC hardware initialisation */
|
||||||
static void pc_init1(MachineState *machine,
|
static void pc_init1(MachineState *machine)
|
||||||
int pci_enabled,
|
|
||||||
int kvmclock_enabled)
|
|
||||||
{
|
{
|
||||||
PCMachineState *pc_machine = PC_MACHINE(machine);
|
PCMachineState *pc_machine = PC_MACHINE(machine);
|
||||||
MemoryRegion *system_memory = get_system_memory();
|
MemoryRegion *system_memory = get_system_memory();
|
||||||
|
@ -242,7 +242,7 @@ static void pc_init1(MachineState *machine,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* init basic PC hardware */
|
/* init basic PC hardware */
|
||||||
pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy,
|
pc_basic_device_init(isa_bus, gsi, &rtc_state, true, &floppy,
|
||||||
(pc_machine->vmport != ON_OFF_AUTO_ON), 0x4);
|
(pc_machine->vmport != ON_OFF_AUTO_ON), 0x4);
|
||||||
|
|
||||||
pc_nic_init(isa_bus, pci_bus);
|
pc_nic_init(isa_bus, pci_bus);
|
||||||
|
@ -305,11 +305,6 @@ static void pc_init1(MachineState *machine,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pc_init_pci(MachineState *machine)
|
|
||||||
{
|
|
||||||
pc_init1(machine, 1, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pc_compat_2_3(MachineState *machine)
|
static void pc_compat_2_3(MachineState *machine)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -418,76 +413,16 @@ static void pc_compat_1_2(MachineState *machine)
|
||||||
x86_cpu_compat_kvm_no_autoenable(FEAT_KVM, 1 << KVM_FEATURE_PV_EOI);
|
x86_cpu_compat_kvm_no_autoenable(FEAT_KVM, 1 << KVM_FEATURE_PV_EOI);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pc_init_pci_2_3(MachineState *machine)
|
/* PC compat function for pc-0.10 to pc-0.13 */
|
||||||
{
|
static void pc_compat_0_13(MachineState *machine)
|
||||||
pc_compat_2_3(machine);
|
|
||||||
pc_init_pci(machine);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pc_init_pci_2_2(MachineState *machine)
|
|
||||||
{
|
|
||||||
pc_compat_2_2(machine);
|
|
||||||
pc_init_pci(machine);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pc_init_pci_2_1(MachineState *machine)
|
|
||||||
{
|
|
||||||
pc_compat_2_1(machine);
|
|
||||||
pc_init_pci(machine);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pc_init_pci_2_0(MachineState *machine)
|
|
||||||
{
|
|
||||||
pc_compat_2_0(machine);
|
|
||||||
pc_init_pci(machine);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pc_init_pci_1_7(MachineState *machine)
|
|
||||||
{
|
|
||||||
pc_compat_1_7(machine);
|
|
||||||
pc_init_pci(machine);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pc_init_pci_1_6(MachineState *machine)
|
|
||||||
{
|
|
||||||
pc_compat_1_6(machine);
|
|
||||||
pc_init_pci(machine);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pc_init_pci_1_5(MachineState *machine)
|
|
||||||
{
|
|
||||||
pc_compat_1_5(machine);
|
|
||||||
pc_init_pci(machine);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pc_init_pci_1_4(MachineState *machine)
|
|
||||||
{
|
|
||||||
pc_compat_1_4(machine);
|
|
||||||
pc_init_pci(machine);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pc_init_pci_1_3(MachineState *machine)
|
|
||||||
{
|
|
||||||
pc_compat_1_3(machine);
|
|
||||||
pc_init_pci(machine);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* PC machine init function for pc-0.14 to pc-1.2 */
|
|
||||||
static void pc_init_pci_1_2(MachineState *machine)
|
|
||||||
{
|
{
|
||||||
pc_compat_1_2(machine);
|
pc_compat_1_2(machine);
|
||||||
pc_init_pci(machine);
|
kvmclock_enabled = false;
|
||||||
}
|
|
||||||
|
|
||||||
/* PC init function for pc-0.10 to pc-0.13 */
|
|
||||||
static void pc_init_pci_no_kvmclock(MachineState *machine)
|
|
||||||
{
|
|
||||||
pc_compat_1_2(machine);
|
|
||||||
pc_init1(machine, 1, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pc_init_isa(MachineState *machine)
|
static void pc_init_isa(MachineState *machine)
|
||||||
{
|
{
|
||||||
|
pci_enabled = false;
|
||||||
has_acpi_build = false;
|
has_acpi_build = false;
|
||||||
smbios_defaults = false;
|
smbios_defaults = false;
|
||||||
gigabyte_align = false;
|
gigabyte_align = false;
|
||||||
|
@ -500,7 +435,7 @@ static void pc_init_isa(MachineState *machine)
|
||||||
}
|
}
|
||||||
x86_cpu_compat_kvm_no_autoenable(FEAT_KVM, 1 << KVM_FEATURE_PV_EOI);
|
x86_cpu_compat_kvm_no_autoenable(FEAT_KVM, 1 << KVM_FEATURE_PV_EOI);
|
||||||
enable_compat_apic_id_mode();
|
enable_compat_apic_id_mode();
|
||||||
pc_init1(machine, 0, 1);
|
pc_init1(machine);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_XEN
|
#ifdef CONFIG_XEN
|
||||||
|
@ -508,7 +443,7 @@ static void pc_xen_hvm_init(MachineState *machine)
|
||||||
{
|
{
|
||||||
PCIBus *bus;
|
PCIBus *bus;
|
||||||
|
|
||||||
pc_init_pci(machine);
|
pc_init1(machine);
|
||||||
|
|
||||||
bus = pci_find_primary_bus();
|
bus = pci_find_primary_bus();
|
||||||
if (bus != NULL) {
|
if (bus != NULL) {
|
||||||
|
@ -517,118 +452,126 @@ static void pc_xen_hvm_init(MachineState *machine)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PC_I440FX_MACHINE_OPTIONS \
|
#define DEFINE_I440FX_MACHINE(suffix, name, compatfn, optionfn) \
|
||||||
PC_DEFAULT_MACHINE_OPTIONS, \
|
static void pc_init_##suffix(MachineState *machine) \
|
||||||
.family = "pc_piix", \
|
{ \
|
||||||
.desc = "Standard PC (i440FX + PIIX, 1996)", \
|
void (*compat)(MachineState *m) = (compatfn); \
|
||||||
.hot_add_cpu = pc_hot_add_cpu
|
if (compat) { \
|
||||||
|
compat(machine); \
|
||||||
|
} \
|
||||||
|
pc_init1(machine); \
|
||||||
|
} \
|
||||||
|
DEFINE_PC_MACHINE(suffix, name, pc_init_##suffix, optionfn)
|
||||||
|
|
||||||
#define PC_I440FX_2_4_MACHINE_OPTIONS \
|
static void pc_i440fx_machine_options(MachineClass *m)
|
||||||
PC_I440FX_MACHINE_OPTIONS, \
|
{
|
||||||
.default_machine_opts = "firmware=bios-256k.bin", \
|
pc_default_machine_options(m);
|
||||||
.default_display = "std"
|
m->family = "pc_piix";
|
||||||
|
m->desc = "Standard PC (i440FX + PIIX, 1996)";
|
||||||
|
m->hot_add_cpu = pc_hot_add_cpu;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pc_i440fx_2_4_machine_options(MachineClass *m)
|
||||||
|
{
|
||||||
|
pc_i440fx_machine_options(m);
|
||||||
|
m->default_machine_opts = "firmware=bios-256k.bin";
|
||||||
|
m->default_display = "std";
|
||||||
|
m->alias = "pc";
|
||||||
|
m->is_default = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_I440FX_MACHINE(v2_4, "pc-i440fx-2.4", NULL,
|
||||||
|
pc_i440fx_2_4_machine_options)
|
||||||
|
|
||||||
|
|
||||||
static QEMUMachine pc_i440fx_machine_v2_4 = {
|
static void pc_i440fx_2_3_machine_options(MachineClass *m)
|
||||||
PC_I440FX_2_4_MACHINE_OPTIONS,
|
{
|
||||||
.name = "pc-i440fx-2.4",
|
pc_i440fx_machine_options(m);
|
||||||
.alias = "pc",
|
m->alias = NULL;
|
||||||
.init = pc_init_pci,
|
m->is_default = 0;
|
||||||
.is_default = 1,
|
SET_MACHINE_COMPAT(m, PC_COMPAT_2_3);
|
||||||
};
|
}
|
||||||
|
|
||||||
#define PC_I440FX_2_3_MACHINE_OPTIONS PC_I440FX_2_4_MACHINE_OPTIONS
|
DEFINE_I440FX_MACHINE(v2_3, "pc-i440fx-2.3", pc_compat_2_3,
|
||||||
|
pc_i440fx_2_3_machine_options);
|
||||||
|
|
||||||
static QEMUMachine pc_i440fx_machine_v2_3 = {
|
|
||||||
PC_I440FX_2_3_MACHINE_OPTIONS,
|
|
||||||
.name = "pc-i440fx-2.3",
|
|
||||||
.init = pc_init_pci_2_3,
|
|
||||||
};
|
|
||||||
|
|
||||||
#define PC_I440FX_2_2_MACHINE_OPTIONS PC_I440FX_2_3_MACHINE_OPTIONS
|
static void pc_i440fx_2_2_machine_options(MachineClass *m)
|
||||||
|
{
|
||||||
|
pc_i440fx_2_3_machine_options(m);
|
||||||
|
SET_MACHINE_COMPAT(m, PC_COMPAT_2_2);
|
||||||
|
}
|
||||||
|
|
||||||
static QEMUMachine pc_i440fx_machine_v2_2 = {
|
DEFINE_I440FX_MACHINE(v2_2, "pc-i440fx-2.2", pc_compat_2_2,
|
||||||
PC_I440FX_2_2_MACHINE_OPTIONS,
|
pc_i440fx_2_2_machine_options);
|
||||||
.name = "pc-i440fx-2.2",
|
|
||||||
.init = pc_init_pci_2_2,
|
|
||||||
};
|
|
||||||
|
|
||||||
#define PC_I440FX_2_1_MACHINE_OPTIONS \
|
|
||||||
PC_I440FX_MACHINE_OPTIONS, \
|
|
||||||
.default_machine_opts = "firmware=bios-256k.bin"
|
|
||||||
|
|
||||||
static QEMUMachine pc_i440fx_machine_v2_1 = {
|
static void pc_i440fx_2_1_machine_options(MachineClass *m)
|
||||||
PC_I440FX_2_1_MACHINE_OPTIONS,
|
{
|
||||||
.name = "pc-i440fx-2.1",
|
pc_i440fx_2_2_machine_options(m);
|
||||||
.init = pc_init_pci_2_1,
|
m->default_display = NULL;
|
||||||
.compat_props = (GlobalProperty[]) {
|
SET_MACHINE_COMPAT(m, PC_COMPAT_2_1);
|
||||||
HW_COMPAT_2_1,
|
}
|
||||||
{ /* end of list */ }
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#define PC_I440FX_2_0_MACHINE_OPTIONS PC_I440FX_2_1_MACHINE_OPTIONS
|
DEFINE_I440FX_MACHINE(v2_1, "pc-i440fx-2.1", pc_compat_2_1,
|
||||||
|
pc_i440fx_2_1_machine_options);
|
||||||
|
|
||||||
static QEMUMachine pc_i440fx_machine_v2_0 = {
|
|
||||||
PC_I440FX_2_0_MACHINE_OPTIONS,
|
|
||||||
.name = "pc-i440fx-2.0",
|
|
||||||
.init = pc_init_pci_2_0,
|
|
||||||
.compat_props = (GlobalProperty[]) {
|
|
||||||
PC_COMPAT_2_0,
|
|
||||||
{ /* end of list */ }
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#define PC_I440FX_1_7_MACHINE_OPTIONS PC_I440FX_MACHINE_OPTIONS
|
|
||||||
|
|
||||||
static QEMUMachine pc_i440fx_machine_v1_7 = {
|
static void pc_i440fx_2_0_machine_options(MachineClass *m)
|
||||||
PC_I440FX_1_7_MACHINE_OPTIONS,
|
{
|
||||||
.name = "pc-i440fx-1.7",
|
pc_i440fx_2_1_machine_options(m);
|
||||||
.init = pc_init_pci_1_7,
|
SET_MACHINE_COMPAT(m, PC_COMPAT_2_0);
|
||||||
.compat_props = (GlobalProperty[]) {
|
}
|
||||||
PC_COMPAT_1_7,
|
|
||||||
{ /* end of list */ }
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#define PC_I440FX_1_6_MACHINE_OPTIONS PC_I440FX_MACHINE_OPTIONS
|
DEFINE_I440FX_MACHINE(v2_0, "pc-i440fx-2.0", pc_compat_2_0,
|
||||||
|
pc_i440fx_2_0_machine_options);
|
||||||
|
|
||||||
static QEMUMachine pc_i440fx_machine_v1_6 = {
|
|
||||||
PC_I440FX_1_6_MACHINE_OPTIONS,
|
|
||||||
.name = "pc-i440fx-1.6",
|
|
||||||
.init = pc_init_pci_1_6,
|
|
||||||
.compat_props = (GlobalProperty[]) {
|
|
||||||
PC_COMPAT_1_6,
|
|
||||||
{ /* end of list */ }
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static QEMUMachine pc_i440fx_machine_v1_5 = {
|
static void pc_i440fx_1_7_machine_options(MachineClass *m)
|
||||||
PC_I440FX_1_6_MACHINE_OPTIONS,
|
{
|
||||||
.name = "pc-i440fx-1.5",
|
pc_i440fx_2_0_machine_options(m);
|
||||||
.init = pc_init_pci_1_5,
|
m->default_machine_opts = NULL;
|
||||||
.compat_props = (GlobalProperty[]) {
|
SET_MACHINE_COMPAT(m, PC_COMPAT_1_7);
|
||||||
PC_COMPAT_1_5,
|
}
|
||||||
{ /* end of list */ }
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#define PC_I440FX_1_4_MACHINE_OPTIONS \
|
DEFINE_I440FX_MACHINE(v1_7, "pc-i440fx-1.7", pc_compat_1_7,
|
||||||
PC_I440FX_1_6_MACHINE_OPTIONS, \
|
pc_i440fx_1_7_machine_options);
|
||||||
.hot_add_cpu = NULL
|
|
||||||
|
|
||||||
|
static void pc_i440fx_1_6_machine_options(MachineClass *m)
|
||||||
|
{
|
||||||
|
pc_i440fx_1_7_machine_options(m);
|
||||||
|
SET_MACHINE_COMPAT(m, PC_COMPAT_1_6);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_I440FX_MACHINE(v1_6, "pc-i440fx-1.6", pc_compat_1_6,
|
||||||
|
pc_i440fx_1_6_machine_options);
|
||||||
|
|
||||||
|
|
||||||
|
static void pc_i440fx_1_5_machine_options(MachineClass *m)
|
||||||
|
{
|
||||||
|
pc_i440fx_1_6_machine_options(m);
|
||||||
|
SET_MACHINE_COMPAT(m, PC_COMPAT_1_5);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_I440FX_MACHINE(v1_5, "pc-i440fx-1.5", pc_compat_1_5,
|
||||||
|
pc_i440fx_1_5_machine_options);
|
||||||
|
|
||||||
|
|
||||||
|
static void pc_i440fx_1_4_machine_options(MachineClass *m)
|
||||||
|
{
|
||||||
|
pc_i440fx_1_5_machine_options(m);
|
||||||
|
m->hot_add_cpu = NULL;
|
||||||
|
SET_MACHINE_COMPAT(m, PC_COMPAT_1_4);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_I440FX_MACHINE(v1_4, "pc-i440fx-1.4", pc_compat_1_4,
|
||||||
|
pc_i440fx_1_4_machine_options);
|
||||||
|
|
||||||
static QEMUMachine pc_i440fx_machine_v1_4 = {
|
|
||||||
PC_I440FX_1_4_MACHINE_OPTIONS,
|
|
||||||
.name = "pc-i440fx-1.4",
|
|
||||||
.init = pc_init_pci_1_4,
|
|
||||||
.compat_props = (GlobalProperty[]) {
|
|
||||||
PC_COMPAT_1_4,
|
|
||||||
{ /* end of list */ }
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#define PC_COMPAT_1_3 \
|
#define PC_COMPAT_1_3 \
|
||||||
PC_COMPAT_1_4, \
|
PC_COMPAT_1_4 \
|
||||||
{\
|
{\
|
||||||
.driver = "usb-tablet",\
|
.driver = "usb-tablet",\
|
||||||
.property = "usb_version",\
|
.property = "usb_version",\
|
||||||
|
@ -645,20 +588,21 @@ static QEMUMachine pc_i440fx_machine_v1_4 = {
|
||||||
.driver = "e1000",\
|
.driver = "e1000",\
|
||||||
.property = "autonegotiation",\
|
.property = "autonegotiation",\
|
||||||
.value = "off",\
|
.value = "off",\
|
||||||
}
|
},
|
||||||
|
|
||||||
|
|
||||||
|
static void pc_i440fx_1_3_machine_options(MachineClass *m)
|
||||||
|
{
|
||||||
|
pc_i440fx_1_4_machine_options(m);
|
||||||
|
SET_MACHINE_COMPAT(m, PC_COMPAT_1_3);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_I440FX_MACHINE(v1_3, "pc-1.3", pc_compat_1_3,
|
||||||
|
pc_i440fx_1_3_machine_options);
|
||||||
|
|
||||||
static QEMUMachine pc_machine_v1_3 = {
|
|
||||||
PC_I440FX_1_4_MACHINE_OPTIONS,
|
|
||||||
.name = "pc-1.3",
|
|
||||||
.init = pc_init_pci_1_3,
|
|
||||||
.compat_props = (GlobalProperty[]) {
|
|
||||||
PC_COMPAT_1_3,
|
|
||||||
{ /* end of list */ }
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#define PC_COMPAT_1_2 \
|
#define PC_COMPAT_1_2 \
|
||||||
PC_COMPAT_1_3,\
|
PC_COMPAT_1_3 \
|
||||||
{\
|
{\
|
||||||
.driver = "nec-usb-xhci",\
|
.driver = "nec-usb-xhci",\
|
||||||
.property = "msi",\
|
.property = "msi",\
|
||||||
|
@ -683,23 +627,20 @@ static QEMUMachine pc_machine_v1_3 = {
|
||||||
.driver = "VGA",\
|
.driver = "VGA",\
|
||||||
.property = "mmio",\
|
.property = "mmio",\
|
||||||
.value = "off",\
|
.value = "off",\
|
||||||
}
|
},
|
||||||
|
|
||||||
#define PC_I440FX_1_2_MACHINE_OPTIONS \
|
static void pc_i440fx_1_2_machine_options(MachineClass *m)
|
||||||
PC_I440FX_1_4_MACHINE_OPTIONS, \
|
{
|
||||||
.init = pc_init_pci_1_2
|
pc_i440fx_1_3_machine_options(m);
|
||||||
|
SET_MACHINE_COMPAT(m, PC_COMPAT_1_2);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_I440FX_MACHINE(v1_2, "pc-1.2", pc_compat_1_2,
|
||||||
|
pc_i440fx_1_2_machine_options);
|
||||||
|
|
||||||
static QEMUMachine pc_machine_v1_2 = {
|
|
||||||
PC_I440FX_1_2_MACHINE_OPTIONS,
|
|
||||||
.name = "pc-1.2",
|
|
||||||
.compat_props = (GlobalProperty[]) {
|
|
||||||
PC_COMPAT_1_2,
|
|
||||||
{ /* end of list */ }
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#define PC_COMPAT_1_1 \
|
#define PC_COMPAT_1_1 \
|
||||||
PC_COMPAT_1_2,\
|
PC_COMPAT_1_2 \
|
||||||
{\
|
{\
|
||||||
.driver = "virtio-scsi-pci",\
|
.driver = "virtio-scsi-pci",\
|
||||||
.property = "hotplug",\
|
.property = "hotplug",\
|
||||||
|
@ -728,19 +669,20 @@ static QEMUMachine pc_machine_v1_2 = {
|
||||||
.driver = "virtio-blk-pci",\
|
.driver = "virtio-blk-pci",\
|
||||||
.property = "config-wce",\
|
.property = "config-wce",\
|
||||||
.value = "off",\
|
.value = "off",\
|
||||||
}
|
},
|
||||||
|
|
||||||
|
static void pc_i440fx_1_1_machine_options(MachineClass *m)
|
||||||
|
{
|
||||||
|
pc_i440fx_1_2_machine_options(m);
|
||||||
|
SET_MACHINE_COMPAT(m, PC_COMPAT_1_1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_I440FX_MACHINE(v1_1, "pc-1.1", pc_compat_1_2,
|
||||||
|
pc_i440fx_1_1_machine_options);
|
||||||
|
|
||||||
static QEMUMachine pc_machine_v1_1 = {
|
|
||||||
PC_I440FX_1_2_MACHINE_OPTIONS,
|
|
||||||
.name = "pc-1.1",
|
|
||||||
.compat_props = (GlobalProperty[]) {
|
|
||||||
PC_COMPAT_1_1,
|
|
||||||
{ /* end of list */ }
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#define PC_COMPAT_1_0 \
|
#define PC_COMPAT_1_0 \
|
||||||
PC_COMPAT_1_1,\
|
PC_COMPAT_1_1 \
|
||||||
{\
|
{\
|
||||||
.driver = TYPE_ISA_FDC,\
|
.driver = TYPE_ISA_FDC,\
|
||||||
.property = "check_media_rate",\
|
.property = "check_media_rate",\
|
||||||
|
@ -757,33 +699,35 @@ static QEMUMachine pc_machine_v1_1 = {
|
||||||
.driver = TYPE_USB_DEVICE,\
|
.driver = TYPE_USB_DEVICE,\
|
||||||
.property = "full-path",\
|
.property = "full-path",\
|
||||||
.value = "no",\
|
.value = "no",\
|
||||||
}
|
},
|
||||||
|
|
||||||
|
static void pc_i440fx_1_0_machine_options(MachineClass *m)
|
||||||
|
{
|
||||||
|
pc_i440fx_1_1_machine_options(m);
|
||||||
|
m->hw_version = "1.0";
|
||||||
|
SET_MACHINE_COMPAT(m, PC_COMPAT_1_0);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_I440FX_MACHINE(v1_0, "pc-1.0", pc_compat_1_2,
|
||||||
|
pc_i440fx_1_0_machine_options);
|
||||||
|
|
||||||
static QEMUMachine pc_machine_v1_0 = {
|
|
||||||
PC_I440FX_1_2_MACHINE_OPTIONS,
|
|
||||||
.name = "pc-1.0",
|
|
||||||
.compat_props = (GlobalProperty[]) {
|
|
||||||
PC_COMPAT_1_0,
|
|
||||||
{ /* end of list */ }
|
|
||||||
},
|
|
||||||
.hw_version = "1.0",
|
|
||||||
};
|
|
||||||
|
|
||||||
#define PC_COMPAT_0_15 \
|
#define PC_COMPAT_0_15 \
|
||||||
PC_COMPAT_1_0
|
PC_COMPAT_1_0
|
||||||
|
|
||||||
static QEMUMachine pc_machine_v0_15 = {
|
static void pc_i440fx_0_15_machine_options(MachineClass *m)
|
||||||
PC_I440FX_1_2_MACHINE_OPTIONS,
|
{
|
||||||
.name = "pc-0.15",
|
pc_i440fx_1_0_machine_options(m);
|
||||||
.compat_props = (GlobalProperty[]) {
|
m->hw_version = "0.15";
|
||||||
PC_COMPAT_0_15,
|
SET_MACHINE_COMPAT(m, PC_COMPAT_0_15);
|
||||||
{ /* end of list */ }
|
}
|
||||||
},
|
|
||||||
.hw_version = "0.15",
|
DEFINE_I440FX_MACHINE(v0_15, "pc-0.15", pc_compat_1_2,
|
||||||
};
|
pc_i440fx_0_15_machine_options);
|
||||||
|
|
||||||
|
|
||||||
#define PC_COMPAT_0_14 \
|
#define PC_COMPAT_0_14 \
|
||||||
PC_COMPAT_0_15,\
|
PC_COMPAT_0_15 \
|
||||||
{\
|
{\
|
||||||
.driver = "virtio-blk-pci",\
|
.driver = "virtio-blk-pci",\
|
||||||
.property = "event_idx",\
|
.property = "event_idx",\
|
||||||
|
@ -800,29 +744,29 @@ static QEMUMachine pc_machine_v0_15 = {
|
||||||
.driver = "virtio-balloon-pci",\
|
.driver = "virtio-balloon-pci",\
|
||||||
.property = "event_idx",\
|
.property = "event_idx",\
|
||||||
.value = "off",\
|
.value = "off",\
|
||||||
}
|
},{\
|
||||||
|
.driver = "qxl",\
|
||||||
static QEMUMachine pc_machine_v0_14 = {
|
.property = "revision",\
|
||||||
PC_I440FX_1_2_MACHINE_OPTIONS,
|
.value = stringify(2),\
|
||||||
.name = "pc-0.14",
|
},{\
|
||||||
.compat_props = (GlobalProperty[]) {
|
.driver = "qxl-vga",\
|
||||||
PC_COMPAT_0_14,
|
.property = "revision",\
|
||||||
{
|
.value = stringify(2),\
|
||||||
.driver = "qxl",
|
|
||||||
.property = "revision",
|
|
||||||
.value = stringify(2),
|
|
||||||
},{
|
|
||||||
.driver = "qxl-vga",
|
|
||||||
.property = "revision",
|
|
||||||
.value = stringify(2),
|
|
||||||
},
|
},
|
||||||
{ /* end of list */ }
|
|
||||||
},
|
static void pc_i440fx_0_14_machine_options(MachineClass *m)
|
||||||
.hw_version = "0.14",
|
{
|
||||||
};
|
pc_i440fx_0_15_machine_options(m);
|
||||||
|
m->hw_version = "0.14";
|
||||||
|
SET_MACHINE_COMPAT(m, PC_COMPAT_0_14);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_I440FX_MACHINE(v0_14, "pc-0.14", pc_compat_1_2,
|
||||||
|
pc_i440fx_0_14_machine_options);
|
||||||
|
|
||||||
|
|
||||||
#define PC_COMPAT_0_13 \
|
#define PC_COMPAT_0_13 \
|
||||||
PC_COMPAT_0_14,\
|
PC_COMPAT_0_14 \
|
||||||
{\
|
{\
|
||||||
.driver = TYPE_PCI_DEVICE,\
|
.driver = TYPE_PCI_DEVICE,\
|
||||||
.property = "command_serr_enable",\
|
.property = "command_serr_enable",\
|
||||||
|
@ -831,37 +775,33 @@ static QEMUMachine pc_machine_v0_14 = {
|
||||||
.driver = "AC97",\
|
.driver = "AC97",\
|
||||||
.property = "use_broken_id",\
|
.property = "use_broken_id",\
|
||||||
.value = stringify(1),\
|
.value = stringify(1),\
|
||||||
}
|
},{\
|
||||||
|
.driver = "virtio-9p-pci",\
|
||||||
#define PC_I440FX_0_13_MACHINE_OPTIONS \
|
.property = "vectors",\
|
||||||
PC_I440FX_1_2_MACHINE_OPTIONS, \
|
.value = stringify(0),\
|
||||||
.init = pc_init_pci_no_kvmclock
|
},{\
|
||||||
|
.driver = "VGA",\
|
||||||
static QEMUMachine pc_machine_v0_13 = {
|
.property = "rombar",\
|
||||||
PC_I440FX_0_13_MACHINE_OPTIONS,
|
.value = stringify(0),\
|
||||||
.name = "pc-0.13",
|
},{\
|
||||||
.compat_props = (GlobalProperty[]) {
|
.driver = "vmware-svga",\
|
||||||
PC_COMPAT_0_13,
|
.property = "rombar",\
|
||||||
{
|
.value = stringify(0),\
|
||||||
.driver = "virtio-9p-pci",
|
|
||||||
.property = "vectors",
|
|
||||||
.value = stringify(0),
|
|
||||||
},{
|
|
||||||
.driver = "VGA",
|
|
||||||
.property = "rombar",
|
|
||||||
.value = stringify(0),
|
|
||||||
},{
|
|
||||||
.driver = "vmware-svga",
|
|
||||||
.property = "rombar",
|
|
||||||
.value = stringify(0),
|
|
||||||
},
|
},
|
||||||
{ /* end of list */ }
|
|
||||||
},
|
static void pc_i440fx_0_13_machine_options(MachineClass *m)
|
||||||
.hw_version = "0.13",
|
{
|
||||||
};
|
pc_i440fx_0_14_machine_options(m);
|
||||||
|
m->hw_version = "0.13";
|
||||||
|
SET_MACHINE_COMPAT(m, PC_COMPAT_0_13);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_I440FX_MACHINE(v0_13, "pc-0.13", pc_compat_0_13,
|
||||||
|
pc_i440fx_0_13_machine_options);
|
||||||
|
|
||||||
|
|
||||||
#define PC_COMPAT_0_12 \
|
#define PC_COMPAT_0_12 \
|
||||||
PC_COMPAT_0_13,\
|
PC_COMPAT_0_13 \
|
||||||
{\
|
{\
|
||||||
.driver = "virtio-serial-pci",\
|
.driver = "virtio-serial-pci",\
|
||||||
.property = "max_ports",\
|
.property = "max_ports",\
|
||||||
|
@ -882,29 +822,21 @@ static QEMUMachine pc_machine_v0_13 = {
|
||||||
.driver = "usb-kbd",\
|
.driver = "usb-kbd",\
|
||||||
.property = "serial",\
|
.property = "serial",\
|
||||||
.value = "1",\
|
.value = "1",\
|
||||||
}
|
|
||||||
|
|
||||||
static QEMUMachine pc_machine_v0_12 = {
|
|
||||||
PC_I440FX_0_13_MACHINE_OPTIONS,
|
|
||||||
.name = "pc-0.12",
|
|
||||||
.compat_props = (GlobalProperty[]) {
|
|
||||||
PC_COMPAT_0_12,
|
|
||||||
{
|
|
||||||
.driver = "VGA",
|
|
||||||
.property = "rombar",
|
|
||||||
.value = stringify(0),
|
|
||||||
},{
|
|
||||||
.driver = "vmware-svga",
|
|
||||||
.property = "rombar",
|
|
||||||
.value = stringify(0),
|
|
||||||
},
|
},
|
||||||
{ /* end of list */ }
|
|
||||||
},
|
static void pc_i440fx_0_12_machine_options(MachineClass *m)
|
||||||
.hw_version = "0.12",
|
{
|
||||||
};
|
pc_i440fx_0_13_machine_options(m);
|
||||||
|
m->hw_version = "0.12";
|
||||||
|
SET_MACHINE_COMPAT(m, PC_COMPAT_0_12);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_I440FX_MACHINE(v0_12, "pc-0.12", pc_compat_0_13,
|
||||||
|
pc_i440fx_0_12_machine_options);
|
||||||
|
|
||||||
|
|
||||||
#define PC_COMPAT_0_11 \
|
#define PC_COMPAT_0_11 \
|
||||||
PC_COMPAT_0_12,\
|
PC_COMPAT_0_12 \
|
||||||
{\
|
{\
|
||||||
.driver = "virtio-blk-pci",\
|
.driver = "virtio-blk-pci",\
|
||||||
.property = "vectors",\
|
.property = "vectors",\
|
||||||
|
@ -913,106 +845,83 @@ static QEMUMachine pc_machine_v0_12 = {
|
||||||
.driver = TYPE_PCI_DEVICE,\
|
.driver = TYPE_PCI_DEVICE,\
|
||||||
.property = "rombar",\
|
.property = "rombar",\
|
||||||
.value = stringify(0),\
|
.value = stringify(0),\
|
||||||
}
|
},{\
|
||||||
|
.driver = "ide-drive",\
|
||||||
static QEMUMachine pc_machine_v0_11 = {
|
.property = "ver",\
|
||||||
PC_I440FX_0_13_MACHINE_OPTIONS,
|
.value = "0.11",\
|
||||||
.name = "pc-0.11",
|
},{\
|
||||||
.compat_props = (GlobalProperty[]) {
|
.driver = "scsi-disk",\
|
||||||
PC_COMPAT_0_11,
|
.property = "ver",\
|
||||||
{
|
.value = "0.11",\
|
||||||
.driver = "ide-drive",
|
|
||||||
.property = "ver",
|
|
||||||
.value = "0.11",
|
|
||||||
},{
|
|
||||||
.driver = "scsi-disk",
|
|
||||||
.property = "ver",
|
|
||||||
.value = "0.11",
|
|
||||||
},
|
},
|
||||||
{ /* end of list */ }
|
|
||||||
},
|
|
||||||
.hw_version = "0.11",
|
|
||||||
};
|
|
||||||
|
|
||||||
static QEMUMachine pc_machine_v0_10 = {
|
static void pc_i440fx_0_11_machine_options(MachineClass *m)
|
||||||
PC_I440FX_0_13_MACHINE_OPTIONS,
|
|
||||||
.name = "pc-0.10",
|
|
||||||
.compat_props = (GlobalProperty[]) {
|
|
||||||
PC_COMPAT_0_11,
|
|
||||||
{
|
|
||||||
.driver = "virtio-blk-pci",
|
|
||||||
.property = "class",
|
|
||||||
.value = stringify(PCI_CLASS_STORAGE_OTHER),
|
|
||||||
},{
|
|
||||||
.driver = "virtio-serial-pci",
|
|
||||||
.property = "class",
|
|
||||||
.value = stringify(PCI_CLASS_DISPLAY_OTHER),
|
|
||||||
},{
|
|
||||||
.driver = "virtio-net-pci",
|
|
||||||
.property = "vectors",
|
|
||||||
.value = stringify(0),
|
|
||||||
},{
|
|
||||||
.driver = "ide-drive",
|
|
||||||
.property = "ver",
|
|
||||||
.value = "0.10",
|
|
||||||
},{
|
|
||||||
.driver = "scsi-disk",
|
|
||||||
.property = "ver",
|
|
||||||
.value = "0.10",
|
|
||||||
},
|
|
||||||
{ /* end of list */ }
|
|
||||||
},
|
|
||||||
.hw_version = "0.10",
|
|
||||||
};
|
|
||||||
|
|
||||||
static QEMUMachine isapc_machine = {
|
|
||||||
PC_COMMON_MACHINE_OPTIONS,
|
|
||||||
.name = "isapc",
|
|
||||||
.desc = "ISA-only PC",
|
|
||||||
.init = pc_init_isa,
|
|
||||||
.max_cpus = 1,
|
|
||||||
.compat_props = (GlobalProperty[]) {
|
|
||||||
{ /* end of list */ }
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef CONFIG_XEN
|
|
||||||
static QEMUMachine xenfv_machine = {
|
|
||||||
PC_COMMON_MACHINE_OPTIONS,
|
|
||||||
.name = "xenfv",
|
|
||||||
.desc = "Xen Fully-virtualized PC",
|
|
||||||
.init = pc_xen_hvm_init,
|
|
||||||
.max_cpus = HVM_MAX_VCPUS,
|
|
||||||
.default_machine_opts = "accel=xen",
|
|
||||||
.hot_add_cpu = pc_hot_add_cpu,
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void pc_machine_init(void)
|
|
||||||
{
|
{
|
||||||
qemu_register_pc_machine(&pc_i440fx_machine_v2_4);
|
pc_i440fx_0_12_machine_options(m);
|
||||||
qemu_register_pc_machine(&pc_i440fx_machine_v2_3);
|
m->hw_version = "0.11";
|
||||||
qemu_register_pc_machine(&pc_i440fx_machine_v2_2);
|
SET_MACHINE_COMPAT(m, PC_COMPAT_0_11);
|
||||||
qemu_register_pc_machine(&pc_i440fx_machine_v2_1);
|
|
||||||
qemu_register_pc_machine(&pc_i440fx_machine_v2_0);
|
|
||||||
qemu_register_pc_machine(&pc_i440fx_machine_v1_7);
|
|
||||||
qemu_register_pc_machine(&pc_i440fx_machine_v1_6);
|
|
||||||
qemu_register_pc_machine(&pc_i440fx_machine_v1_5);
|
|
||||||
qemu_register_pc_machine(&pc_i440fx_machine_v1_4);
|
|
||||||
qemu_register_pc_machine(&pc_machine_v1_3);
|
|
||||||
qemu_register_pc_machine(&pc_machine_v1_2);
|
|
||||||
qemu_register_pc_machine(&pc_machine_v1_1);
|
|
||||||
qemu_register_pc_machine(&pc_machine_v1_0);
|
|
||||||
qemu_register_pc_machine(&pc_machine_v0_15);
|
|
||||||
qemu_register_pc_machine(&pc_machine_v0_14);
|
|
||||||
qemu_register_pc_machine(&pc_machine_v0_13);
|
|
||||||
qemu_register_pc_machine(&pc_machine_v0_12);
|
|
||||||
qemu_register_pc_machine(&pc_machine_v0_11);
|
|
||||||
qemu_register_pc_machine(&pc_machine_v0_10);
|
|
||||||
qemu_register_pc_machine(&isapc_machine);
|
|
||||||
#ifdef CONFIG_XEN
|
|
||||||
qemu_register_pc_machine(&xenfv_machine);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
machine_init(pc_machine_init);
|
DEFINE_I440FX_MACHINE(v0_11, "pc-0.11", pc_compat_0_13,
|
||||||
|
pc_i440fx_0_11_machine_options);
|
||||||
|
|
||||||
|
|
||||||
|
#define PC_COMPAT_0_10 \
|
||||||
|
PC_COMPAT_0_11 \
|
||||||
|
{\
|
||||||
|
.driver = "virtio-blk-pci",\
|
||||||
|
.property = "class",\
|
||||||
|
.value = stringify(PCI_CLASS_STORAGE_OTHER),\
|
||||||
|
},{\
|
||||||
|
.driver = "virtio-serial-pci",\
|
||||||
|
.property = "class",\
|
||||||
|
.value = stringify(PCI_CLASS_DISPLAY_OTHER),\
|
||||||
|
},{\
|
||||||
|
.driver = "virtio-net-pci",\
|
||||||
|
.property = "vectors",\
|
||||||
|
.value = stringify(0),\
|
||||||
|
},{\
|
||||||
|
.driver = "ide-drive",\
|
||||||
|
.property = "ver",\
|
||||||
|
.value = "0.10",\
|
||||||
|
},{\
|
||||||
|
.driver = "scsi-disk",\
|
||||||
|
.property = "ver",\
|
||||||
|
.value = "0.10",\
|
||||||
|
},
|
||||||
|
|
||||||
|
static void pc_i440fx_0_10_machine_options(MachineClass *m)
|
||||||
|
{
|
||||||
|
pc_i440fx_0_11_machine_options(m);
|
||||||
|
m->hw_version = "0.10";
|
||||||
|
SET_MACHINE_COMPAT(m, PC_COMPAT_0_10);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_I440FX_MACHINE(v0_10, "pc-0.10", pc_compat_0_13,
|
||||||
|
pc_i440fx_0_10_machine_options);
|
||||||
|
|
||||||
|
|
||||||
|
static void isapc_machine_options(MachineClass *m)
|
||||||
|
{
|
||||||
|
pc_common_machine_options(m);
|
||||||
|
m->desc = "ISA-only PC";
|
||||||
|
m->max_cpus = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_PC_MACHINE(isapc, "isapc", pc_init_isa,
|
||||||
|
isapc_machine_options);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_XEN
|
||||||
|
static void xenfv_machine_options(MachineClass *m)
|
||||||
|
{
|
||||||
|
pc_common_machine_options(m);
|
||||||
|
m->desc = "Xen Fully-virtualized PC";
|
||||||
|
m->max_cpus = HVM_MAX_VCPUS;
|
||||||
|
m->default_machine_opts = "accel=xen";
|
||||||
|
m->hot_add_cpu = pc_hot_add_cpu;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_PC_MACHINE(xenfv, "xenfv", pc_xen_hvm_init,
|
||||||
|
xenfv_machine_options);
|
||||||
|
#endif
|
||||||
|
|
233
hw/i386/pc_q35.c
233
hw/i386/pc_q35.c
|
@ -89,6 +89,7 @@ static void pc_q35_init(MachineState *machine)
|
||||||
PcGuestInfo *guest_info;
|
PcGuestInfo *guest_info;
|
||||||
ram_addr_t lowmem;
|
ram_addr_t lowmem;
|
||||||
DriveInfo *hd[MAX_SATA_PORTS];
|
DriveInfo *hd[MAX_SATA_PORTS];
|
||||||
|
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
||||||
|
|
||||||
/* Check whether RAM fits below 4G (leaving 1/2 GByte for IO memory
|
/* Check whether RAM fits below 4G (leaving 1/2 GByte for IO memory
|
||||||
* and 256 Mbytes for PCI Express Enhanced Configuration Access Mapping
|
* and 256 Mbytes for PCI Express Enhanced Configuration Access Mapping
|
||||||
|
@ -163,7 +164,6 @@ static void pc_q35_init(MachineState *machine)
|
||||||
guest_info->legacy_acpi_table_size = 0;
|
guest_info->legacy_acpi_table_size = 0;
|
||||||
|
|
||||||
if (smbios_defaults) {
|
if (smbios_defaults) {
|
||||||
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
|
||||||
/* These values are guest ABI, do not change */
|
/* These values are guest ABI, do not change */
|
||||||
smbios_set_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)",
|
smbios_set_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)",
|
||||||
mc->name, smbios_legacy_mode, smbios_uuid_encoded);
|
mc->name, smbios_legacy_mode, smbios_uuid_encoded);
|
||||||
|
@ -250,7 +250,7 @@ static void pc_q35_init(MachineState *machine)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* init basic PC hardware */
|
/* init basic PC hardware */
|
||||||
pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy,
|
pc_basic_device_init(isa_bus, gsi, &rtc_state, !mc->no_floppy, &floppy,
|
||||||
(pc_machine->vmport != ON_OFF_AUTO_ON), 0xff0104);
|
(pc_machine->vmport != ON_OFF_AUTO_ON), 0xff0104);
|
||||||
|
|
||||||
/* connect pm stuff to lpc */
|
/* connect pm stuff to lpc */
|
||||||
|
@ -366,174 +366,119 @@ static void pc_compat_1_4(MachineState *machine)
|
||||||
x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ);
|
x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pc_q35_init_2_3(MachineState *machine)
|
#define DEFINE_Q35_MACHINE(suffix, name, compatfn, optionfn) \
|
||||||
|
static void pc_init_##suffix(MachineState *machine) \
|
||||||
|
{ \
|
||||||
|
void (*compat)(MachineState *m) = (compatfn); \
|
||||||
|
if (compat) { \
|
||||||
|
compat(machine); \
|
||||||
|
} \
|
||||||
|
pc_q35_init(machine); \
|
||||||
|
} \
|
||||||
|
DEFINE_PC_MACHINE(suffix, name, pc_init_##suffix, optionfn)
|
||||||
|
|
||||||
|
|
||||||
|
static void pc_q35_machine_options(MachineClass *m)
|
||||||
{
|
{
|
||||||
pc_compat_2_3(machine);
|
pc_default_machine_options(m);
|
||||||
pc_q35_init(machine);
|
m->family = "pc_q35";
|
||||||
|
m->desc = "Standard PC (Q35 + ICH9, 2009)";
|
||||||
|
m->hot_add_cpu = pc_hot_add_cpu;
|
||||||
|
m->units_per_default_bus = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pc_q35_init_2_2(MachineState *machine)
|
static void pc_q35_2_4_machine_options(MachineClass *m)
|
||||||
{
|
{
|
||||||
pc_compat_2_2(machine);
|
pc_q35_machine_options(m);
|
||||||
pc_q35_init(machine);
|
m->default_machine_opts = "firmware=bios-256k.bin";
|
||||||
|
m->default_display = "std";
|
||||||
|
m->no_floppy = 1;
|
||||||
|
m->alias = "q35";
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pc_q35_init_2_1(MachineState *machine)
|
DEFINE_Q35_MACHINE(v2_4, "pc-q35-2.4", NULL,
|
||||||
|
pc_q35_2_4_machine_options);
|
||||||
|
|
||||||
|
|
||||||
|
static void pc_q35_2_3_machine_options(MachineClass *m)
|
||||||
{
|
{
|
||||||
pc_compat_2_1(machine);
|
pc_q35_2_4_machine_options(m);
|
||||||
pc_q35_init(machine);
|
m->alias = NULL;
|
||||||
|
SET_MACHINE_COMPAT(m, PC_COMPAT_2_3);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pc_q35_init_2_0(MachineState *machine)
|
DEFINE_Q35_MACHINE(v2_3, "pc-q35-2.3", pc_compat_2_3,
|
||||||
|
pc_q35_2_3_machine_options);
|
||||||
|
|
||||||
|
|
||||||
|
static void pc_q35_2_2_machine_options(MachineClass *m)
|
||||||
{
|
{
|
||||||
pc_compat_2_0(machine);
|
pc_q35_2_3_machine_options(m);
|
||||||
pc_q35_init(machine);
|
SET_MACHINE_COMPAT(m, PC_COMPAT_2_2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pc_q35_init_1_7(MachineState *machine)
|
DEFINE_Q35_MACHINE(v2_2, "pc-q35-2.2", pc_compat_2_2,
|
||||||
|
pc_q35_2_2_machine_options);
|
||||||
|
|
||||||
|
|
||||||
|
static void pc_q35_2_1_machine_options(MachineClass *m)
|
||||||
{
|
{
|
||||||
pc_compat_1_7(machine);
|
pc_q35_2_2_machine_options(m);
|
||||||
pc_q35_init(machine);
|
m->default_display = NULL;
|
||||||
|
SET_MACHINE_COMPAT(m, PC_COMPAT_2_1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pc_q35_init_1_6(MachineState *machine)
|
DEFINE_Q35_MACHINE(v2_1, "pc-q35-2.1", pc_compat_2_1,
|
||||||
|
pc_q35_2_1_machine_options);
|
||||||
|
|
||||||
|
|
||||||
|
static void pc_q35_2_0_machine_options(MachineClass *m)
|
||||||
{
|
{
|
||||||
pc_compat_1_6(machine);
|
pc_q35_2_1_machine_options(m);
|
||||||
pc_q35_init(machine);
|
SET_MACHINE_COMPAT(m, PC_COMPAT_2_0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pc_q35_init_1_5(MachineState *machine)
|
DEFINE_Q35_MACHINE(v2_0, "pc-q35-2.0", pc_compat_2_0,
|
||||||
|
pc_q35_2_0_machine_options);
|
||||||
|
|
||||||
|
|
||||||
|
static void pc_q35_1_7_machine_options(MachineClass *m)
|
||||||
{
|
{
|
||||||
pc_compat_1_5(machine);
|
pc_q35_2_0_machine_options(m);
|
||||||
pc_q35_init(machine);
|
m->default_machine_opts = NULL;
|
||||||
|
SET_MACHINE_COMPAT(m, PC_COMPAT_1_7);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pc_q35_init_1_4(MachineState *machine)
|
DEFINE_Q35_MACHINE(v1_7, "pc-q35-1.7", pc_compat_1_7,
|
||||||
|
pc_q35_1_7_machine_options);
|
||||||
|
|
||||||
|
|
||||||
|
static void pc_q35_1_6_machine_options(MachineClass *m)
|
||||||
{
|
{
|
||||||
pc_compat_1_4(machine);
|
pc_q35_machine_options(m);
|
||||||
pc_q35_init(machine);
|
SET_MACHINE_COMPAT(m, PC_COMPAT_1_6);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PC_Q35_MACHINE_OPTIONS \
|
DEFINE_Q35_MACHINE(v1_6, "pc-q35-1.6", pc_compat_1_6,
|
||||||
PC_DEFAULT_MACHINE_OPTIONS, \
|
pc_q35_1_6_machine_options);
|
||||||
.family = "pc_q35", \
|
|
||||||
.desc = "Standard PC (Q35 + ICH9, 2009)", \
|
|
||||||
.hot_add_cpu = pc_hot_add_cpu, \
|
|
||||||
.units_per_default_bus = 1
|
|
||||||
|
|
||||||
#define PC_Q35_2_4_MACHINE_OPTIONS \
|
|
||||||
PC_Q35_MACHINE_OPTIONS, \
|
|
||||||
.default_machine_opts = "firmware=bios-256k.bin", \
|
|
||||||
.default_display = "std"
|
|
||||||
|
|
||||||
static QEMUMachine pc_q35_machine_v2_4 = {
|
static void pc_q35_1_5_machine_options(MachineClass *m)
|
||||||
PC_Q35_2_4_MACHINE_OPTIONS,
|
|
||||||
.name = "pc-q35-2.4",
|
|
||||||
.alias = "q35",
|
|
||||||
.init = pc_q35_init,
|
|
||||||
};
|
|
||||||
|
|
||||||
#define PC_Q35_2_3_MACHINE_OPTIONS PC_Q35_2_4_MACHINE_OPTIONS
|
|
||||||
|
|
||||||
static QEMUMachine pc_q35_machine_v2_3 = {
|
|
||||||
PC_Q35_2_3_MACHINE_OPTIONS,
|
|
||||||
.name = "pc-q35-2.3",
|
|
||||||
.init = pc_q35_init_2_3,
|
|
||||||
};
|
|
||||||
|
|
||||||
#define PC_Q35_2_2_MACHINE_OPTIONS PC_Q35_2_3_MACHINE_OPTIONS
|
|
||||||
|
|
||||||
static QEMUMachine pc_q35_machine_v2_2 = {
|
|
||||||
PC_Q35_2_2_MACHINE_OPTIONS,
|
|
||||||
.name = "pc-q35-2.2",
|
|
||||||
.init = pc_q35_init_2_2,
|
|
||||||
};
|
|
||||||
|
|
||||||
#define PC_Q35_2_1_MACHINE_OPTIONS \
|
|
||||||
PC_Q35_MACHINE_OPTIONS, \
|
|
||||||
.default_machine_opts = "firmware=bios-256k.bin"
|
|
||||||
|
|
||||||
static QEMUMachine pc_q35_machine_v2_1 = {
|
|
||||||
PC_Q35_2_1_MACHINE_OPTIONS,
|
|
||||||
.name = "pc-q35-2.1",
|
|
||||||
.init = pc_q35_init_2_1,
|
|
||||||
.compat_props = (GlobalProperty[]) {
|
|
||||||
HW_COMPAT_2_1,
|
|
||||||
{ /* end of list */ }
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#define PC_Q35_2_0_MACHINE_OPTIONS PC_Q35_2_1_MACHINE_OPTIONS
|
|
||||||
|
|
||||||
static QEMUMachine pc_q35_machine_v2_0 = {
|
|
||||||
PC_Q35_2_0_MACHINE_OPTIONS,
|
|
||||||
.name = "pc-q35-2.0",
|
|
||||||
.init = pc_q35_init_2_0,
|
|
||||||
.compat_props = (GlobalProperty[]) {
|
|
||||||
PC_COMPAT_2_0,
|
|
||||||
{ /* end of list */ }
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#define PC_Q35_1_7_MACHINE_OPTIONS PC_Q35_MACHINE_OPTIONS
|
|
||||||
|
|
||||||
static QEMUMachine pc_q35_machine_v1_7 = {
|
|
||||||
PC_Q35_1_7_MACHINE_OPTIONS,
|
|
||||||
.name = "pc-q35-1.7",
|
|
||||||
.init = pc_q35_init_1_7,
|
|
||||||
.compat_props = (GlobalProperty[]) {
|
|
||||||
PC_COMPAT_1_7,
|
|
||||||
{ /* end of list */ }
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#define PC_Q35_1_6_MACHINE_OPTIONS PC_Q35_MACHINE_OPTIONS
|
|
||||||
|
|
||||||
static QEMUMachine pc_q35_machine_v1_6 = {
|
|
||||||
PC_Q35_1_6_MACHINE_OPTIONS,
|
|
||||||
.name = "pc-q35-1.6",
|
|
||||||
.init = pc_q35_init_1_6,
|
|
||||||
.compat_props = (GlobalProperty[]) {
|
|
||||||
PC_COMPAT_1_6,
|
|
||||||
{ /* end of list */ }
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static QEMUMachine pc_q35_machine_v1_5 = {
|
|
||||||
PC_Q35_1_6_MACHINE_OPTIONS,
|
|
||||||
.name = "pc-q35-1.5",
|
|
||||||
.init = pc_q35_init_1_5,
|
|
||||||
.compat_props = (GlobalProperty[]) {
|
|
||||||
PC_COMPAT_1_5,
|
|
||||||
{ /* end of list */ }
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#define PC_Q35_1_4_MACHINE_OPTIONS \
|
|
||||||
PC_Q35_1_6_MACHINE_OPTIONS, \
|
|
||||||
.hot_add_cpu = NULL
|
|
||||||
|
|
||||||
static QEMUMachine pc_q35_machine_v1_4 = {
|
|
||||||
PC_Q35_1_4_MACHINE_OPTIONS,
|
|
||||||
.name = "pc-q35-1.4",
|
|
||||||
.init = pc_q35_init_1_4,
|
|
||||||
.compat_props = (GlobalProperty[]) {
|
|
||||||
PC_COMPAT_1_4,
|
|
||||||
{ /* end of list */ }
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static void pc_q35_machine_init(void)
|
|
||||||
{
|
{
|
||||||
qemu_register_pc_machine(&pc_q35_machine_v2_4);
|
pc_q35_1_6_machine_options(m);
|
||||||
qemu_register_pc_machine(&pc_q35_machine_v2_3);
|
SET_MACHINE_COMPAT(m, PC_COMPAT_1_5);
|
||||||
qemu_register_pc_machine(&pc_q35_machine_v2_2);
|
|
||||||
qemu_register_pc_machine(&pc_q35_machine_v2_1);
|
|
||||||
qemu_register_pc_machine(&pc_q35_machine_v2_0);
|
|
||||||
qemu_register_pc_machine(&pc_q35_machine_v1_7);
|
|
||||||
qemu_register_pc_machine(&pc_q35_machine_v1_6);
|
|
||||||
qemu_register_pc_machine(&pc_q35_machine_v1_5);
|
|
||||||
qemu_register_pc_machine(&pc_q35_machine_v1_4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
machine_init(pc_q35_machine_init);
|
DEFINE_Q35_MACHINE(v1_5, "pc-q35-1.5", pc_compat_1_5,
|
||||||
|
pc_q35_1_5_machine_options);
|
||||||
|
|
||||||
|
|
||||||
|
static void pc_q35_1_4_machine_options(MachineClass *m)
|
||||||
|
{
|
||||||
|
pc_q35_1_5_machine_options(m);
|
||||||
|
m->hot_add_cpu = NULL;
|
||||||
|
SET_MACHINE_COMPAT(m, PC_COMPAT_1_4);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_Q35_MACHINE(v1_4, "pc-q35-1.4", pc_compat_1_4,
|
||||||
|
pc_q35_1_4_machine_options);
|
||||||
|
|
|
@ -25,19 +25,5 @@ DefinitionBlock (
|
||||||
0x1 // OEM Revision
|
0x1 // OEM Revision
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Scope(\_SB) {
|
#include "ssdt-tpm-common.dsl"
|
||||||
/* 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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,12 +3,12 @@ static unsigned char ssdt_tpm_aml[] = {
|
||||||
0x53,
|
0x53,
|
||||||
0x44,
|
0x44,
|
||||||
0x54,
|
0x54,
|
||||||
0x5d,
|
0x6b,
|
||||||
0x0,
|
0x0,
|
||||||
0x0,
|
0x0,
|
||||||
0x0,
|
0x0,
|
||||||
0x1,
|
0x1,
|
||||||
0x1c,
|
0x37,
|
||||||
0x42,
|
0x42,
|
||||||
0x58,
|
0x58,
|
||||||
0x50,
|
0x50,
|
||||||
|
@ -36,15 +36,26 @@ static unsigned char ssdt_tpm_aml[] = {
|
||||||
0x14,
|
0x14,
|
||||||
0x20,
|
0x20,
|
||||||
0x10,
|
0x10,
|
||||||
0x38,
|
0x46,
|
||||||
|
0x4,
|
||||||
0x5c,
|
0x5c,
|
||||||
|
0x2f,
|
||||||
|
0x3,
|
||||||
0x5f,
|
0x5f,
|
||||||
0x53,
|
0x53,
|
||||||
0x42,
|
0x42,
|
||||||
0x5f,
|
0x5f,
|
||||||
|
0x50,
|
||||||
|
0x43,
|
||||||
|
0x49,
|
||||||
|
0x30,
|
||||||
|
0x49,
|
||||||
|
0x53,
|
||||||
|
0x41,
|
||||||
|
0x5f,
|
||||||
0x5b,
|
0x5b,
|
||||||
0x82,
|
0x82,
|
||||||
0x30,
|
0x33,
|
||||||
0x54,
|
0x54,
|
||||||
0x50,
|
0x50,
|
||||||
0x4d,
|
0x4d,
|
||||||
|
@ -65,9 +76,9 @@ static unsigned char ssdt_tpm_aml[] = {
|
||||||
0x52,
|
0x52,
|
||||||
0x53,
|
0x53,
|
||||||
0x11,
|
0x11,
|
||||||
0x11,
|
0x14,
|
||||||
0xa,
|
0xa,
|
||||||
0xe,
|
0x11,
|
||||||
0x86,
|
0x86,
|
||||||
0x9,
|
0x9,
|
||||||
0x0,
|
0x0,
|
||||||
|
@ -80,6 +91,9 @@ static unsigned char ssdt_tpm_aml[] = {
|
||||||
0x50,
|
0x50,
|
||||||
0x0,
|
0x0,
|
||||||
0x0,
|
0x0,
|
||||||
|
0x22,
|
||||||
|
0x20,
|
||||||
|
0x0,
|
||||||
0x79,
|
0x79,
|
||||||
0x0,
|
0x0,
|
||||||
0x14,
|
0x14,
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* 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_tpm2_aml
|
||||||
|
|
||||||
|
DefinitionBlock (
|
||||||
|
"ssdt-tpm2.aml", // Output Filename
|
||||||
|
"SSDT", // Signature
|
||||||
|
0x01, // SSDT Compliance Revision
|
||||||
|
"BXPC", // OEMID
|
||||||
|
"BXSSDT", // TABLE ID
|
||||||
|
0x1 // OEM Revision
|
||||||
|
)
|
||||||
|
{
|
||||||
|
#include "ssdt-tpm-common.dsl"
|
||||||
|
}
|
|
@ -0,0 +1,109 @@
|
||||||
|
static unsigned char ssdt_tpm2_aml[] = {
|
||||||
|
0x53,
|
||||||
|
0x53,
|
||||||
|
0x44,
|
||||||
|
0x54,
|
||||||
|
0x6b,
|
||||||
|
0x0,
|
||||||
|
0x0,
|
||||||
|
0x0,
|
||||||
|
0x1,
|
||||||
|
0x37,
|
||||||
|
0x42,
|
||||||
|
0x58,
|
||||||
|
0x50,
|
||||||
|
0x43,
|
||||||
|
0x0,
|
||||||
|
0x0,
|
||||||
|
0x42,
|
||||||
|
0x58,
|
||||||
|
0x53,
|
||||||
|
0x53,
|
||||||
|
0x44,
|
||||||
|
0x54,
|
||||||
|
0x0,
|
||||||
|
0x0,
|
||||||
|
0x1,
|
||||||
|
0x0,
|
||||||
|
0x0,
|
||||||
|
0x0,
|
||||||
|
0x49,
|
||||||
|
0x4e,
|
||||||
|
0x54,
|
||||||
|
0x4c,
|
||||||
|
0x7,
|
||||||
|
0x11,
|
||||||
|
0x14,
|
||||||
|
0x20,
|
||||||
|
0x10,
|
||||||
|
0x46,
|
||||||
|
0x4,
|
||||||
|
0x5c,
|
||||||
|
0x2f,
|
||||||
|
0x3,
|
||||||
|
0x5f,
|
||||||
|
0x53,
|
||||||
|
0x42,
|
||||||
|
0x5f,
|
||||||
|
0x50,
|
||||||
|
0x43,
|
||||||
|
0x49,
|
||||||
|
0x30,
|
||||||
|
0x49,
|
||||||
|
0x53,
|
||||||
|
0x41,
|
||||||
|
0x5f,
|
||||||
|
0x5b,
|
||||||
|
0x82,
|
||||||
|
0x33,
|
||||||
|
0x54,
|
||||||
|
0x50,
|
||||||
|
0x4d,
|
||||||
|
0x5f,
|
||||||
|
0x8,
|
||||||
|
0x5f,
|
||||||
|
0x48,
|
||||||
|
0x49,
|
||||||
|
0x44,
|
||||||
|
0xc,
|
||||||
|
0x41,
|
||||||
|
0xd0,
|
||||||
|
0xc,
|
||||||
|
0x31,
|
||||||
|
0x8,
|
||||||
|
0x5f,
|
||||||
|
0x43,
|
||||||
|
0x52,
|
||||||
|
0x53,
|
||||||
|
0x11,
|
||||||
|
0x14,
|
||||||
|
0xa,
|
||||||
|
0x11,
|
||||||
|
0x86,
|
||||||
|
0x9,
|
||||||
|
0x0,
|
||||||
|
0x1,
|
||||||
|
0x0,
|
||||||
|
0x0,
|
||||||
|
0xd4,
|
||||||
|
0xfe,
|
||||||
|
0x0,
|
||||||
|
0x50,
|
||||||
|
0x0,
|
||||||
|
0x0,
|
||||||
|
0x22,
|
||||||
|
0x20,
|
||||||
|
0x0,
|
||||||
|
0x79,
|
||||||
|
0x0,
|
||||||
|
0x14,
|
||||||
|
0x9,
|
||||||
|
0x5f,
|
||||||
|
0x53,
|
||||||
|
0x54,
|
||||||
|
0x41,
|
||||||
|
0x0,
|
||||||
|
0xa4,
|
||||||
|
0xa,
|
||||||
|
0xf
|
||||||
|
};
|
|
@ -166,7 +166,7 @@ static void virtio_input_set_config(VirtIODevice *vdev,
|
||||||
virtio_notify_config(vdev);
|
virtio_notify_config(vdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t virtio_input_get_features(VirtIODevice *vdev, uint32_t f)
|
static uint64_t virtio_input_get_features(VirtIODevice *vdev, uint64_t f)
|
||||||
{
|
{
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,6 +157,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
|
||||||
|
|
||||||
net->dev.nvqs = 2;
|
net->dev.nvqs = 2;
|
||||||
net->dev.vqs = net->vqs;
|
net->dev.vqs = net->vqs;
|
||||||
|
net->dev.vq_index = net->nc->queue_index;
|
||||||
|
|
||||||
r = vhost_dev_init(&net->dev, options->opaque,
|
r = vhost_dev_init(&net->dev, options->opaque,
|
||||||
options->backend_type, options->force);
|
options->backend_type, options->force);
|
||||||
|
@ -267,7 +268,7 @@ static void vhost_net_stop_one(struct vhost_net *net,
|
||||||
for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
|
for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
|
||||||
const VhostOps *vhost_ops = net->dev.vhost_ops;
|
const VhostOps *vhost_ops = net->dev.vhost_ops;
|
||||||
int r = vhost_ops->vhost_call(&net->dev, VHOST_RESET_OWNER,
|
int r = vhost_ops->vhost_call(&net->dev, VHOST_RESET_OWNER,
|
||||||
NULL);
|
&file);
|
||||||
assert(r >= 0);
|
assert(r >= 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -435,7 +435,7 @@ static void virtio_net_set_queues(VirtIONet *n)
|
||||||
|
|
||||||
static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue);
|
static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue);
|
||||||
|
|
||||||
static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features)
|
static uint64_t virtio_net_get_features(VirtIODevice *vdev, uint64_t features)
|
||||||
{
|
{
|
||||||
VirtIONet *n = VIRTIO_NET(vdev);
|
VirtIONet *n = VIRTIO_NET(vdev);
|
||||||
NetClientState *nc = qemu_get_queue(n->nic);
|
NetClientState *nc = qemu_get_queue(n->nic);
|
||||||
|
@ -468,9 +468,9 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features)
|
||||||
return vhost_net_get_features(get_vhost_net(nc->peer), features);
|
return vhost_net_get_features(get_vhost_net(nc->peer), features);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t virtio_net_bad_features(VirtIODevice *vdev)
|
static uint64_t virtio_net_bad_features(VirtIODevice *vdev)
|
||||||
{
|
{
|
||||||
uint32_t features = 0;
|
uint64_t features = 0;
|
||||||
|
|
||||||
/* Linux kernel 2.6.25. It understood MAC (as everyone must),
|
/* Linux kernel 2.6.25. It understood MAC (as everyone must),
|
||||||
* but also these: */
|
* but also these: */
|
||||||
|
@ -1032,10 +1032,12 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
return -1;
|
return -1;
|
||||||
error_report("virtio-net unexpected empty queue: "
|
error_report("virtio-net unexpected empty queue: "
|
||||||
"i %zd mergeable %d offset %zd, size %zd, "
|
"i %zd mergeable %d offset %zd, size %zd, "
|
||||||
"guest hdr len %zd, host hdr len %zd guest features 0x%x",
|
"guest hdr len %zd, host hdr len %zd "
|
||||||
i, n->mergeable_rx_bufs, offset, size,
|
"guest features 0x%" PRIx64,
|
||||||
n->guest_hdr_len, n->host_hdr_len, vdev->guest_features);
|
i, n->mergeable_rx_bufs, offset, size,
|
||||||
|
n->guest_hdr_len, n->host_hdr_len,
|
||||||
|
vdev->guest_features);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1301,39 +1303,8 @@ static void virtio_net_tx_bh(void *opaque)
|
||||||
|
|
||||||
static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue)
|
static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue)
|
||||||
{
|
{
|
||||||
VirtIODevice *vdev = VIRTIO_DEVICE(n);
|
|
||||||
int i, max = multiqueue ? n->max_queues : 1;
|
|
||||||
|
|
||||||
n->multiqueue = multiqueue;
|
n->multiqueue = multiqueue;
|
||||||
|
|
||||||
for (i = 2; i < n->max_queues * 2 + 1; i++) {
|
|
||||||
virtio_del_queue(vdev, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 1; i < max; i++) {
|
|
||||||
n->vqs[i].rx_vq = virtio_add_queue(vdev, 256, virtio_net_handle_rx);
|
|
||||||
if (n->vqs[i].tx_timer) {
|
|
||||||
n->vqs[i].tx_vq =
|
|
||||||
virtio_add_queue(vdev, 256, virtio_net_handle_tx_timer);
|
|
||||||
n->vqs[i].tx_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
|
|
||||||
virtio_net_tx_timer,
|
|
||||||
&n->vqs[i]);
|
|
||||||
} else {
|
|
||||||
n->vqs[i].tx_vq =
|
|
||||||
virtio_add_queue(vdev, 256, virtio_net_handle_tx_bh);
|
|
||||||
n->vqs[i].tx_bh = qemu_bh_new(virtio_net_tx_bh, &n->vqs[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
n->vqs[i].tx_waiting = 0;
|
|
||||||
n->vqs[i].n = n;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Note: Minux Guests (version 3.2.1) use ctrl vq but don't ack
|
|
||||||
* VIRTIO_NET_F_CTRL_VQ. Create ctrl vq unconditionally to avoid
|
|
||||||
* breaking them.
|
|
||||||
*/
|
|
||||||
n->ctrl_vq = virtio_add_queue(vdev, 64, virtio_net_handle_ctrl);
|
|
||||||
|
|
||||||
virtio_net_set_queues(n);
|
virtio_net_set_queues(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1549,7 +1520,7 @@ static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx,
|
||||||
vdev, idx, mask);
|
vdev, idx, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void virtio_net_set_config_size(VirtIONet *n, uint32_t host_features)
|
static void virtio_net_set_config_size(VirtIONet *n, uint64_t host_features)
|
||||||
{
|
{
|
||||||
int i, config_size = 0;
|
int i, config_size = 0;
|
||||||
virtio_add_feature(&host_features, VIRTIO_NET_F_MAC);
|
virtio_add_feature(&host_features, VIRTIO_NET_F_MAC);
|
||||||
|
@ -1586,17 +1557,15 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
|
||||||
virtio_init(vdev, "virtio-net", VIRTIO_ID_NET, n->config_size);
|
virtio_init(vdev, "virtio-net", VIRTIO_ID_NET, n->config_size);
|
||||||
|
|
||||||
n->max_queues = MAX(n->nic_conf.peers.queues, 1);
|
n->max_queues = MAX(n->nic_conf.peers.queues, 1);
|
||||||
if (n->max_queues * 2 + 1 > VIRTIO_PCI_QUEUE_MAX) {
|
if (n->max_queues * 2 + 1 > VIRTIO_QUEUE_MAX) {
|
||||||
error_setg(errp, "Invalid number of queues (= %" PRIu32 "), "
|
error_setg(errp, "Invalid number of queues (= %" PRIu32 "), "
|
||||||
"must be a positive integer less than %d.",
|
"must be a positive integer less than %d.",
|
||||||
n->max_queues, (VIRTIO_PCI_QUEUE_MAX - 1) / 2);
|
n->max_queues, (VIRTIO_QUEUE_MAX - 1) / 2);
|
||||||
virtio_cleanup(vdev);
|
virtio_cleanup(vdev);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
n->vqs = g_malloc0(sizeof(VirtIONetQueue) * n->max_queues);
|
n->vqs = g_malloc0(sizeof(VirtIONetQueue) * n->max_queues);
|
||||||
n->vqs[0].rx_vq = virtio_add_queue(vdev, 256, virtio_net_handle_rx);
|
|
||||||
n->curr_queues = 1;
|
n->curr_queues = 1;
|
||||||
n->vqs[0].n = n;
|
|
||||||
n->tx_timeout = n->net_conf.txtimer;
|
n->tx_timeout = n->net_conf.txtimer;
|
||||||
|
|
||||||
if (n->net_conf.tx && strcmp(n->net_conf.tx, "timer")
|
if (n->net_conf.tx && strcmp(n->net_conf.tx, "timer")
|
||||||
|
@ -1607,16 +1576,24 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
|
||||||
error_report("Defaulting to \"bh\"");
|
error_report("Defaulting to \"bh\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n->net_conf.tx && !strcmp(n->net_conf.tx, "timer")) {
|
for (i = 0; i < n->max_queues; i++) {
|
||||||
n->vqs[0].tx_vq = virtio_add_queue(vdev, 256,
|
n->vqs[i].rx_vq = virtio_add_queue(vdev, 256, virtio_net_handle_rx);
|
||||||
virtio_net_handle_tx_timer);
|
if (n->net_conf.tx && !strcmp(n->net_conf.tx, "timer")) {
|
||||||
n->vqs[0].tx_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, virtio_net_tx_timer,
|
n->vqs[i].tx_vq =
|
||||||
&n->vqs[0]);
|
virtio_add_queue(vdev, 256, virtio_net_handle_tx_timer);
|
||||||
} else {
|
n->vqs[i].tx_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
|
||||||
n->vqs[0].tx_vq = virtio_add_queue(vdev, 256,
|
virtio_net_tx_timer,
|
||||||
virtio_net_handle_tx_bh);
|
&n->vqs[i]);
|
||||||
n->vqs[0].tx_bh = qemu_bh_new(virtio_net_tx_bh, &n->vqs[0]);
|
} else {
|
||||||
|
n->vqs[i].tx_vq =
|
||||||
|
virtio_add_queue(vdev, 256, virtio_net_handle_tx_bh);
|
||||||
|
n->vqs[i].tx_bh = qemu_bh_new(virtio_net_tx_bh, &n->vqs[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
n->vqs[i].tx_waiting = 0;
|
||||||
|
n->vqs[i].n = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
n->ctrl_vq = virtio_add_queue(vdev, 64, virtio_net_handle_ctrl);
|
n->ctrl_vq = virtio_add_queue(vdev, 64, virtio_net_handle_ctrl);
|
||||||
qemu_macaddr_default_if_unset(&n->nic_conf.macaddr);
|
qemu_macaddr_default_if_unset(&n->nic_conf.macaddr);
|
||||||
memcpy(&n->mac[0], &n->nic_conf.macaddr, sizeof(n->mac));
|
memcpy(&n->mac[0], &n->nic_conf.macaddr, sizeof(n->mac));
|
||||||
|
|
10
hw/pci/msi.c
10
hw/pci/msi.c
|
@ -291,8 +291,16 @@ void msi_notify(PCIDevice *dev, unsigned int vector)
|
||||||
"notify vector 0x%x"
|
"notify vector 0x%x"
|
||||||
" address: 0x%"PRIx64" data: 0x%"PRIx32"\n",
|
" address: 0x%"PRIx64" data: 0x%"PRIx32"\n",
|
||||||
vector, msg.address, msg.data);
|
vector, msg.address, msg.data);
|
||||||
|
msi_send_message(dev, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void msi_send_message(PCIDevice *dev, MSIMessage msg)
|
||||||
|
{
|
||||||
|
MemTxAttrs attrs = {};
|
||||||
|
|
||||||
|
attrs.stream_id = (pci_bus_num(dev->bus) << 8) | dev->devfn;
|
||||||
address_space_stl_le(&dev->bus_master_as, msg.address, msg.data,
|
address_space_stl_le(&dev->bus_master_as, msg.address, msg.data,
|
||||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
attrs, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Normally called by pci_default_write_config(). */
|
/* Normally called by pci_default_write_config(). */
|
||||||
|
|
|
@ -443,8 +443,7 @@ void msix_notify(PCIDevice *dev, unsigned vector)
|
||||||
|
|
||||||
msg = msix_get_message(dev, vector);
|
msg = msix_get_message(dev, vector);
|
||||||
|
|
||||||
address_space_stl_le(&dev->bus_master_as, msg.address, msg.data,
|
msi_send_message(dev, msg);
|
||||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void msix_reset(PCIDevice *dev)
|
void msix_reset(PCIDevice *dev)
|
||||||
|
|
|
@ -1815,15 +1815,21 @@ static const TypeInfo spapr_machine_info = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define SPAPR_COMPAT_2_3 \
|
||||||
|
HW_COMPAT_2_3
|
||||||
|
|
||||||
#define SPAPR_COMPAT_2_2 \
|
#define SPAPR_COMPAT_2_2 \
|
||||||
|
SPAPR_COMPAT_2_3 \
|
||||||
|
HW_COMPAT_2_2 \
|
||||||
{\
|
{\
|
||||||
.driver = TYPE_SPAPR_PCI_HOST_BRIDGE,\
|
.driver = TYPE_SPAPR_PCI_HOST_BRIDGE,\
|
||||||
.property = "mem_win_size",\
|
.property = "mem_win_size",\
|
||||||
.value = "0x20000000",\
|
.value = "0x20000000",\
|
||||||
}
|
},
|
||||||
|
|
||||||
#define SPAPR_COMPAT_2_1 \
|
#define SPAPR_COMPAT_2_1 \
|
||||||
SPAPR_COMPAT_2_2
|
SPAPR_COMPAT_2_2 \
|
||||||
|
HW_COMPAT_2_1
|
||||||
|
|
||||||
static void spapr_compat_2_3(Object *obj)
|
static void spapr_compat_2_3(Object *obj)
|
||||||
{
|
{
|
||||||
|
@ -1861,8 +1867,7 @@ static void spapr_machine_2_1_class_init(ObjectClass *oc, void *data)
|
||||||
{
|
{
|
||||||
MachineClass *mc = MACHINE_CLASS(oc);
|
MachineClass *mc = MACHINE_CLASS(oc);
|
||||||
static GlobalProperty compat_props[] = {
|
static GlobalProperty compat_props[] = {
|
||||||
HW_COMPAT_2_1,
|
SPAPR_COMPAT_2_1
|
||||||
SPAPR_COMPAT_2_1,
|
|
||||||
{ /* end of list */ }
|
{ /* end of list */ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1881,7 +1886,7 @@ static const TypeInfo spapr_machine_2_1_info = {
|
||||||
static void spapr_machine_2_2_class_init(ObjectClass *oc, void *data)
|
static void spapr_machine_2_2_class_init(ObjectClass *oc, void *data)
|
||||||
{
|
{
|
||||||
static GlobalProperty compat_props[] = {
|
static GlobalProperty compat_props[] = {
|
||||||
SPAPR_COMPAT_2_2,
|
SPAPR_COMPAT_2_2
|
||||||
{ /* end of list */ }
|
{ /* end of list */ }
|
||||||
};
|
};
|
||||||
MachineClass *mc = MACHINE_CLASS(oc);
|
MachineClass *mc = MACHINE_CLASS(oc);
|
||||||
|
|
|
@ -45,6 +45,8 @@
|
||||||
do { } while (0)
|
do { } while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define VIRTIO_S390_QUEUE_MAX 64
|
||||||
|
|
||||||
static void virtio_s390_bus_new(VirtioBusState *bus, size_t bus_size,
|
static void virtio_s390_bus_new(VirtioBusState *bus, size_t bus_size,
|
||||||
VirtIOS390Device *dev);
|
VirtIOS390Device *dev);
|
||||||
|
|
||||||
|
@ -139,8 +141,6 @@ static void s390_virtio_device_init(VirtIOS390Device *dev,
|
||||||
|
|
||||||
bus->dev_offs += dev_len;
|
bus->dev_offs += dev_len;
|
||||||
|
|
||||||
dev->host_features = virtio_bus_get_vdev_features(&dev->bus,
|
|
||||||
dev->host_features);
|
|
||||||
s390_virtio_device_sync(dev);
|
s390_virtio_device_sync(dev);
|
||||||
s390_virtio_reset_idx(dev);
|
s390_virtio_reset_idx(dev);
|
||||||
if (dev->qdev.hotplugged) {
|
if (dev->qdev.hotplugged) {
|
||||||
|
@ -354,7 +354,7 @@ static ram_addr_t s390_virtio_device_num_vq(VirtIOS390Device *dev)
|
||||||
VirtIODevice *vdev = dev->vdev;
|
VirtIODevice *vdev = dev->vdev;
|
||||||
int num_vq;
|
int num_vq;
|
||||||
|
|
||||||
for (num_vq = 0; num_vq < VIRTIO_PCI_QUEUE_MAX; num_vq++) {
|
for (num_vq = 0; num_vq < VIRTIO_S390_QUEUE_MAX; num_vq++) {
|
||||||
if (!virtio_queue_get_num(vdev, num_vq)) {
|
if (!virtio_queue_get_num(vdev, num_vq)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -433,7 +433,8 @@ void s390_virtio_device_sync(VirtIOS390Device *dev)
|
||||||
cur_offs += num_vq * VIRTIO_VQCONFIG_LEN;
|
cur_offs += num_vq * VIRTIO_VQCONFIG_LEN;
|
||||||
|
|
||||||
/* Sync feature bitmap */
|
/* Sync feature bitmap */
|
||||||
address_space_stl_le(&address_space_memory, cur_offs, dev->host_features,
|
address_space_stl_le(&address_space_memory, cur_offs,
|
||||||
|
dev->vdev->host_features,
|
||||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||||
|
|
||||||
dev->feat_offs = cur_offs + dev->feat_len;
|
dev->feat_offs = cur_offs + dev->feat_len;
|
||||||
|
@ -476,7 +477,7 @@ VirtIOS390Device *s390_virtio_bus_find_vring(VirtIOS390Bus *bus,
|
||||||
QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
|
QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
|
||||||
VirtIOS390Device *dev = (VirtIOS390Device *)kid->child;
|
VirtIOS390Device *dev = (VirtIOS390Device *)kid->child;
|
||||||
|
|
||||||
for(i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
|
for (i = 0; i < VIRTIO_S390_QUEUE_MAX; i++) {
|
||||||
if (!virtio_queue_get_addr(dev->vdev, i))
|
if (!virtio_queue_get_addr(dev->vdev, i))
|
||||||
break;
|
break;
|
||||||
if (virtio_queue_get_addr(dev->vdev, i) == mem) {
|
if (virtio_queue_get_addr(dev->vdev, i) == mem) {
|
||||||
|
@ -528,10 +529,17 @@ static void virtio_s390_notify(DeviceState *d, uint16_t vector)
|
||||||
s390_virtio_irq(0, token);
|
s390_virtio_irq(0, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned virtio_s390_get_features(DeviceState *d)
|
static void virtio_s390_device_plugged(DeviceState *d, Error **errp)
|
||||||
{
|
{
|
||||||
VirtIOS390Device *dev = to_virtio_s390_device(d);
|
VirtIOS390Device *dev = to_virtio_s390_device(d);
|
||||||
return dev->host_features;
|
VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
|
||||||
|
int n = virtio_get_num_queues(vdev);
|
||||||
|
|
||||||
|
if (n > VIRTIO_S390_QUEUE_MAX) {
|
||||||
|
error_setg(errp, "The nubmer of virtqueues %d "
|
||||||
|
"exceeds s390 limit %d", n,
|
||||||
|
VIRTIO_S390_QUEUE_MAX);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************** S390 Virtio Bus Device Descriptions *******************/
|
/**************** S390 Virtio Bus Device Descriptions *******************/
|
||||||
|
@ -626,16 +634,10 @@ static void s390_virtio_busdev_reset(DeviceState *dev)
|
||||||
virtio_reset(_dev->vdev);
|
virtio_reset(_dev->vdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Property virtio_s390_properties[] = {
|
|
||||||
DEFINE_VIRTIO_COMMON_FEATURES(VirtIOS390Device, host_features),
|
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
|
||||||
};
|
|
||||||
|
|
||||||
static void virtio_s390_device_class_init(ObjectClass *klass, void *data)
|
static void virtio_s390_device_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
|
|
||||||
dc->props = virtio_s390_properties;
|
|
||||||
dc->realize = s390_virtio_busdev_realize;
|
dc->realize = s390_virtio_busdev_realize;
|
||||||
dc->bus_type = TYPE_S390_VIRTIO_BUS;
|
dc->bus_type = TYPE_S390_VIRTIO_BUS;
|
||||||
dc->reset = s390_virtio_busdev_reset;
|
dc->reset = s390_virtio_busdev_reset;
|
||||||
|
@ -733,7 +735,7 @@ static void virtio_s390_bus_class_init(ObjectClass *klass, void *data)
|
||||||
BusClass *bus_class = BUS_CLASS(klass);
|
BusClass *bus_class = BUS_CLASS(klass);
|
||||||
bus_class->max_dev = 1;
|
bus_class->max_dev = 1;
|
||||||
k->notify = virtio_s390_notify;
|
k->notify = virtio_s390_notify;
|
||||||
k->get_features = virtio_s390_get_features;
|
k->device_plugged = virtio_s390_device_plugged;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo virtio_s390_bus_info = {
|
static const TypeInfo virtio_s390_bus_info = {
|
||||||
|
|
|
@ -92,7 +92,6 @@ struct VirtIOS390Device {
|
||||||
ram_addr_t feat_offs;
|
ram_addr_t feat_offs;
|
||||||
uint8_t feat_len;
|
uint8_t feat_len;
|
||||||
VirtIODevice *vdev;
|
VirtIODevice *vdev;
|
||||||
uint32_t host_features;
|
|
||||||
VirtioBusState bus;
|
VirtioBusState bus;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@ static int virtio_ccw_hcall_notify(const uint64_t *args)
|
||||||
if (!sch || !css_subch_visible(sch)) {
|
if (!sch || !css_subch_visible(sch)) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (queue >= VIRTIO_PCI_QUEUE_MAX) {
|
if (queue >= VIRTIO_CCW_QUEUE_MAX) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
virtio_queue_notify(virtio_ccw_get_vdev(sch), queue);
|
virtio_queue_notify(virtio_ccw_get_vdev(sch), queue);
|
||||||
|
|
|
@ -170,7 +170,7 @@ static void virtio_ccw_start_ioeventfd(VirtioCcwDevice *dev)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
vdev = virtio_bus_get_device(&dev->bus);
|
vdev = virtio_bus_get_device(&dev->bus);
|
||||||
for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
|
for (n = 0; n < VIRTIO_CCW_QUEUE_MAX; n++) {
|
||||||
if (!virtio_queue_get_num(vdev, n)) {
|
if (!virtio_queue_get_num(vdev, n)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -205,7 +205,7 @@ static void virtio_ccw_stop_ioeventfd(VirtioCcwDevice *dev)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
vdev = virtio_bus_get_device(&dev->bus);
|
vdev = virtio_bus_get_device(&dev->bus);
|
||||||
for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
|
for (n = 0; n < VIRTIO_CCW_QUEUE_MAX; n++) {
|
||||||
if (!virtio_queue_get_num(vdev, n)) {
|
if (!virtio_queue_get_num(vdev, n)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -266,7 +266,7 @@ static int virtio_ccw_set_vqs(SubchDev *sch, uint64_t addr, uint32_t align,
|
||||||
{
|
{
|
||||||
VirtIODevice *vdev = virtio_ccw_get_vdev(sch);
|
VirtIODevice *vdev = virtio_ccw_get_vdev(sch);
|
||||||
|
|
||||||
if (index >= VIRTIO_PCI_QUEUE_MAX) {
|
if (index >= VIRTIO_CCW_QUEUE_MAX) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,7 +291,7 @@ static int virtio_ccw_set_vqs(SubchDev *sch, uint64_t addr, uint32_t align,
|
||||||
virtio_queue_set_vector(vdev, index, index);
|
virtio_queue_set_vector(vdev, index, index);
|
||||||
}
|
}
|
||||||
/* tell notify handler in case of config change */
|
/* tell notify handler in case of config change */
|
||||||
vdev->config_vector = VIRTIO_PCI_QUEUE_MAX;
|
vdev->config_vector = VIRTIO_CCW_QUEUE_MAX;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,8 +381,8 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
|
||||||
+ sizeof(features.features),
|
+ sizeof(features.features),
|
||||||
MEMTXATTRS_UNSPECIFIED,
|
MEMTXATTRS_UNSPECIFIED,
|
||||||
NULL);
|
NULL);
|
||||||
if (features.index < ARRAY_SIZE(dev->host_features)) {
|
if (features.index == 0) {
|
||||||
features.features = dev->host_features[features.index];
|
features.features = vdev->host_features;
|
||||||
} else {
|
} else {
|
||||||
/* Return zeroes if the guest supports more feature bits. */
|
/* Return zeroes if the guest supports more feature bits. */
|
||||||
features.features = 0;
|
features.features = 0;
|
||||||
|
@ -417,7 +417,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
|
||||||
ccw.cda,
|
ccw.cda,
|
||||||
MEMTXATTRS_UNSPECIFIED,
|
MEMTXATTRS_UNSPECIFIED,
|
||||||
NULL);
|
NULL);
|
||||||
if (features.index < ARRAY_SIZE(dev->host_features)) {
|
if (features.index == 0) {
|
||||||
virtio_set_features(vdev, features.features);
|
virtio_set_features(vdev, features.features);
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
|
@ -573,7 +573,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
|
||||||
ccw.cda,
|
ccw.cda,
|
||||||
MEMTXATTRS_UNSPECIFIED,
|
MEMTXATTRS_UNSPECIFIED,
|
||||||
NULL);
|
NULL);
|
||||||
if (vq_config.index >= VIRTIO_PCI_QUEUE_MAX) {
|
if (vq_config.index >= VIRTIO_CCW_QUEUE_MAX) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -896,44 +896,17 @@ static void virtio_ccw_balloon_realize(VirtioCcwDevice *ccw_dev, Error **errp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void balloon_ccw_stats_get_all(Object *obj, struct Visitor *v,
|
|
||||||
void *opaque, const char *name,
|
|
||||||
Error **errp)
|
|
||||||
{
|
|
||||||
VirtIOBalloonCcw *dev = opaque;
|
|
||||||
object_property_get(OBJECT(&dev->vdev), v, "guest-stats", errp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void balloon_ccw_stats_get_poll_interval(Object *obj, struct Visitor *v,
|
|
||||||
void *opaque, const char *name,
|
|
||||||
Error **errp)
|
|
||||||
{
|
|
||||||
VirtIOBalloonCcw *dev = opaque;
|
|
||||||
object_property_get(OBJECT(&dev->vdev), v, "guest-stats-polling-interval",
|
|
||||||
errp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void balloon_ccw_stats_set_poll_interval(Object *obj, struct Visitor *v,
|
|
||||||
void *opaque, const char *name,
|
|
||||||
Error **errp)
|
|
||||||
{
|
|
||||||
VirtIOBalloonCcw *dev = opaque;
|
|
||||||
object_property_set(OBJECT(&dev->vdev), v, "guest-stats-polling-interval",
|
|
||||||
errp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void virtio_ccw_balloon_instance_init(Object *obj)
|
static void virtio_ccw_balloon_instance_init(Object *obj)
|
||||||
{
|
{
|
||||||
VirtIOBalloonCcw *dev = VIRTIO_BALLOON_CCW(obj);
|
VirtIOBalloonCcw *dev = VIRTIO_BALLOON_CCW(obj);
|
||||||
|
|
||||||
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
|
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
|
||||||
TYPE_VIRTIO_BALLOON);
|
TYPE_VIRTIO_BALLOON);
|
||||||
object_property_add(obj, "guest-stats", "guest statistics",
|
object_property_add_alias(obj, "guest-stats", OBJECT(&dev->vdev),
|
||||||
balloon_ccw_stats_get_all, NULL, NULL, dev, NULL);
|
"guest-stats", &error_abort);
|
||||||
|
object_property_add_alias(obj, "guest-stats-polling-interval",
|
||||||
object_property_add(obj, "guest-stats-polling-interval", "int",
|
OBJECT(&dev->vdev),
|
||||||
balloon_ccw_stats_get_poll_interval,
|
"guest-stats-polling-interval", &error_abort);
|
||||||
balloon_ccw_stats_set_poll_interval,
|
|
||||||
NULL, dev, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void virtio_ccw_scsi_realize(VirtioCcwDevice *ccw_dev, Error **errp)
|
static void virtio_ccw_scsi_realize(VirtioCcwDevice *ccw_dev, Error **errp)
|
||||||
|
@ -1052,7 +1025,7 @@ static void virtio_ccw_notify(DeviceState *d, uint16_t vector)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vector < VIRTIO_PCI_QUEUE_MAX) {
|
if (vector < VIRTIO_CCW_QUEUE_MAX) {
|
||||||
if (!dev->indicators) {
|
if (!dev->indicators) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1098,14 +1071,6 @@ static void virtio_ccw_notify(DeviceState *d, uint16_t vector)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned virtio_ccw_get_features(DeviceState *d)
|
|
||||||
{
|
|
||||||
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
|
|
||||||
|
|
||||||
/* Only the first 32 feature bits are used. */
|
|
||||||
return dev->host_features[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
static void virtio_ccw_reset(DeviceState *d)
|
static void virtio_ccw_reset(DeviceState *d)
|
||||||
{
|
{
|
||||||
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
|
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
|
||||||
|
@ -1413,19 +1378,22 @@ static int virtio_ccw_load_config(DeviceState *d, QEMUFile *f)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is called by virtio-bus just after the device is plugged. */
|
/* This is called by virtio-bus just after the device is plugged. */
|
||||||
static void virtio_ccw_device_plugged(DeviceState *d)
|
static void virtio_ccw_device_plugged(DeviceState *d, Error **errp)
|
||||||
{
|
{
|
||||||
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
|
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
|
||||||
|
VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
|
||||||
SubchDev *sch = dev->sch;
|
SubchDev *sch = dev->sch;
|
||||||
|
int n = virtio_get_num_queues(vdev);
|
||||||
|
|
||||||
|
if (virtio_get_num_queues(vdev) > VIRTIO_CCW_QUEUE_MAX) {
|
||||||
|
error_setg(errp, "The nubmer of virtqueues %d "
|
||||||
|
"exceeds ccw limit %d", n,
|
||||||
|
VIRTIO_CCW_QUEUE_MAX);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
sch->id.cu_model = virtio_bus_get_vdev_id(&dev->bus);
|
sch->id.cu_model = virtio_bus_get_vdev_id(&dev->bus);
|
||||||
|
|
||||||
/* Only the first 32 feature bits are used. */
|
|
||||||
virtio_add_feature(&dev->host_features[0], VIRTIO_F_NOTIFY_ON_EMPTY);
|
|
||||||
virtio_add_feature(&dev->host_features[0], VIRTIO_F_BAD_FEATURE);
|
|
||||||
dev->host_features[0] = virtio_bus_get_vdev_features(&dev->bus,
|
|
||||||
dev->host_features[0]);
|
|
||||||
|
|
||||||
css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid,
|
css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid,
|
||||||
d->hotplugged, 1);
|
d->hotplugged, 1);
|
||||||
}
|
}
|
||||||
|
@ -1675,16 +1643,10 @@ static void virtio_ccw_busdev_unplug(HotplugHandler *hotplug_dev,
|
||||||
object_unparent(OBJECT(dev));
|
object_unparent(OBJECT(dev));
|
||||||
}
|
}
|
||||||
|
|
||||||
static Property virtio_ccw_properties[] = {
|
|
||||||
DEFINE_VIRTIO_COMMON_FEATURES(VirtioCcwDevice, host_features[0]),
|
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
|
||||||
};
|
|
||||||
|
|
||||||
static void virtio_ccw_device_class_init(ObjectClass *klass, void *data)
|
static void virtio_ccw_device_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
|
|
||||||
dc->props = virtio_ccw_properties;
|
|
||||||
dc->realize = virtio_ccw_busdev_realize;
|
dc->realize = virtio_ccw_busdev_realize;
|
||||||
dc->exit = virtio_ccw_busdev_exit;
|
dc->exit = virtio_ccw_busdev_exit;
|
||||||
dc->bus_type = TYPE_VIRTUAL_CSS_BUS;
|
dc->bus_type = TYPE_VIRTUAL_CSS_BUS;
|
||||||
|
@ -1749,7 +1711,6 @@ static void virtio_ccw_bus_class_init(ObjectClass *klass, void *data)
|
||||||
|
|
||||||
bus_class->max_dev = 1;
|
bus_class->max_dev = 1;
|
||||||
k->notify = virtio_ccw_notify;
|
k->notify = virtio_ccw_notify;
|
||||||
k->get_features = virtio_ccw_get_features;
|
|
||||||
k->vmstate_change = virtio_ccw_vmstate_change;
|
k->vmstate_change = virtio_ccw_vmstate_change;
|
||||||
k->query_guest_notifiers = virtio_ccw_query_guest_notifiers;
|
k->query_guest_notifiers = virtio_ccw_query_guest_notifiers;
|
||||||
k->set_host_notifier = virtio_ccw_set_host_notifier;
|
k->set_host_notifier = virtio_ccw_set_host_notifier;
|
||||||
|
|
|
@ -68,9 +68,6 @@ typedef struct VirtIOCCWDeviceClass {
|
||||||
int (*exit)(VirtioCcwDevice *dev);
|
int (*exit)(VirtioCcwDevice *dev);
|
||||||
} VirtIOCCWDeviceClass;
|
} VirtIOCCWDeviceClass;
|
||||||
|
|
||||||
/* Change here if we want to support more feature bits. */
|
|
||||||
#define VIRTIO_CCW_FEATURE_SIZE 1
|
|
||||||
|
|
||||||
/* Performance improves when virtqueue kick processing is decoupled from the
|
/* Performance improves when virtqueue kick processing is decoupled from the
|
||||||
* vcpu thread using ioeventfd for some devices. */
|
* vcpu thread using ioeventfd for some devices. */
|
||||||
#define VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT 1
|
#define VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT 1
|
||||||
|
@ -88,7 +85,6 @@ struct VirtioCcwDevice {
|
||||||
DeviceState parent_obj;
|
DeviceState parent_obj;
|
||||||
SubchDev *sch;
|
SubchDev *sch;
|
||||||
char *bus_id;
|
char *bus_id;
|
||||||
uint32_t host_features[VIRTIO_CCW_FEATURE_SIZE];
|
|
||||||
VirtioBusState bus;
|
VirtioBusState bus;
|
||||||
bool ioeventfd_started;
|
bool ioeventfd_started;
|
||||||
bool ioeventfd_disabled;
|
bool ioeventfd_disabled;
|
||||||
|
|
|
@ -151,8 +151,8 @@ static void vhost_scsi_stop(VHostSCSI *s)
|
||||||
vhost_dev_disable_notifiers(&s->dev, vdev);
|
vhost_dev_disable_notifiers(&s->dev, vdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t vhost_scsi_get_features(VirtIODevice *vdev,
|
static uint64_t vhost_scsi_get_features(VirtIODevice *vdev,
|
||||||
uint32_t features)
|
uint64_t features)
|
||||||
{
|
{
|
||||||
VHostSCSI *s = VHOST_SCSI(vdev);
|
VHostSCSI *s = VHOST_SCSI(vdev);
|
||||||
|
|
||||||
|
|
|
@ -628,8 +628,8 @@ static void virtio_scsi_set_config(VirtIODevice *vdev,
|
||||||
vs->cdb_size = virtio_ldl_p(vdev, &scsiconf->cdb_size);
|
vs->cdb_size = virtio_ldl_p(vdev, &scsiconf->cdb_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t virtio_scsi_get_features(VirtIODevice *vdev,
|
static uint64_t virtio_scsi_get_features(VirtIODevice *vdev,
|
||||||
uint32_t requested_features)
|
uint64_t requested_features)
|
||||||
{
|
{
|
||||||
VirtIOSCSI *s = VIRTIO_SCSI(vdev);
|
VirtIOSCSI *s = VIRTIO_SCSI(vdev);
|
||||||
|
|
||||||
|
@ -830,10 +830,10 @@ void virtio_scsi_common_realize(DeviceState *dev, Error **errp,
|
||||||
sizeof(VirtIOSCSIConfig));
|
sizeof(VirtIOSCSIConfig));
|
||||||
|
|
||||||
if (s->conf.num_queues == 0 ||
|
if (s->conf.num_queues == 0 ||
|
||||||
s->conf.num_queues > VIRTIO_PCI_QUEUE_MAX - 2) {
|
s->conf.num_queues > VIRTIO_QUEUE_MAX - 2) {
|
||||||
error_setg(errp, "Invalid number of queues (= %" PRIu32 "), "
|
error_setg(errp, "Invalid number of queues (= %" PRIu32 "), "
|
||||||
"must be a positive integer less than %d.",
|
"must be a positive integer less than %d.",
|
||||||
s->conf.num_queues, VIRTIO_PCI_QUEUE_MAX - 2);
|
s->conf.num_queues, VIRTIO_QUEUE_MAX - 2);
|
||||||
virtio_cleanup(vdev);
|
virtio_cleanup(vdev);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
common-obj-$(CONFIG_TPM_TIS) += tpm_tis.o
|
common-obj-$(CONFIG_TPM_TIS) += tpm_tis.o
|
||||||
common-obj-$(CONFIG_TPM_PASSTHROUGH) += tpm_passthrough.o
|
common-obj-$(CONFIG_TPM_PASSTHROUGH) += tpm_passthrough.o tpm_util.o
|
||||||
|
|
|
@ -29,6 +29,7 @@ struct TPMState {
|
||||||
|
|
||||||
char *backend;
|
char *backend;
|
||||||
TPMBackend *be_driver;
|
TPMBackend *be_driver;
|
||||||
|
TPMVersion be_tpm_version;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TPM(obj) OBJECT_CHECK(TPMState, (obj), TYPE_TPM_TIS)
|
#define TPM(obj) OBJECT_CHECK(TPMState, (obj), TYPE_TPM_TIS)
|
||||||
|
@ -65,4 +66,10 @@ struct tpm_resp_hdr {
|
||||||
#define TPM_ORD_ContinueSelfTest 0x53
|
#define TPM_ORD_ContinueSelfTest 0x53
|
||||||
#define TPM_ORD_GetTicks 0xf1
|
#define TPM_ORD_GetTicks 0xf1
|
||||||
|
|
||||||
|
|
||||||
|
/* TPM2 defines */
|
||||||
|
#define TPM2_ST_NO_SESSIONS 0x8001
|
||||||
|
|
||||||
|
#define TPM2_CC_ReadClock 0x00000181
|
||||||
|
|
||||||
#endif /* TPM_TPM_INT_H */
|
#endif /* TPM_TPM_INT_H */
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "hw/i386/pc.h"
|
#include "hw/i386/pc.h"
|
||||||
#include "sysemu/tpm_backend_int.h"
|
#include "sysemu/tpm_backend_int.h"
|
||||||
#include "tpm_tis.h"
|
#include "tpm_tis.h"
|
||||||
|
#include "tpm_util.h"
|
||||||
|
|
||||||
#define DEBUG_TPM 0
|
#define DEBUG_TPM 0
|
||||||
|
|
||||||
|
@ -69,6 +70,8 @@ struct TPMPassthruState {
|
||||||
bool tpm_op_canceled;
|
bool tpm_op_canceled;
|
||||||
int cancel_fd;
|
int cancel_fd;
|
||||||
bool had_startup_error;
|
bool had_startup_error;
|
||||||
|
|
||||||
|
TPMVersion tpm_version;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct TPMPassthruState TPMPassthruState;
|
typedef struct TPMPassthruState TPMPassthruState;
|
||||||
|
@ -267,6 +270,13 @@ static bool tpm_passthrough_get_tpm_established_flag(TPMBackend *tb)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int tpm_passthrough_reset_tpm_established_flag(TPMBackend *tb,
|
||||||
|
uint8_t locty)
|
||||||
|
{
|
||||||
|
/* only a TPM 2.0 will support this */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static bool tpm_passthrough_get_startup_error(TPMBackend *tb)
|
static bool tpm_passthrough_get_startup_error(TPMBackend *tb)
|
||||||
{
|
{
|
||||||
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
|
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
|
||||||
|
@ -324,56 +334,11 @@ static const char *tpm_passthrough_create_desc(void)
|
||||||
return "Passthrough TPM backend driver";
|
return "Passthrough TPM backend driver";
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static TPMVersion tpm_passthrough_get_tpm_version(TPMBackend *tb)
|
||||||
* A basic test of a TPM device. We expect a well formatted response header
|
|
||||||
* (error response is fine) within one second.
|
|
||||||
*/
|
|
||||||
static int tpm_passthrough_test_tpmdev(int fd)
|
|
||||||
{
|
{
|
||||||
struct tpm_req_hdr req = {
|
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
|
||||||
.tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
|
|
||||||
.len = cpu_to_be32(sizeof(req)),
|
|
||||||
.ordinal = cpu_to_be32(TPM_ORD_GetTicks),
|
|
||||||
};
|
|
||||||
struct tpm_resp_hdr *resp;
|
|
||||||
fd_set readfds;
|
|
||||||
int n;
|
|
||||||
struct timeval tv = {
|
|
||||||
.tv_sec = 1,
|
|
||||||
.tv_usec = 0,
|
|
||||||
};
|
|
||||||
unsigned char buf[1024];
|
|
||||||
|
|
||||||
n = write(fd, &req, sizeof(req));
|
return tpm_pt->tpm_version;
|
||||||
if (n < 0) {
|
|
||||||
return errno;
|
|
||||||
}
|
|
||||||
if (n != sizeof(req)) {
|
|
||||||
return EFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
FD_ZERO(&readfds);
|
|
||||||
FD_SET(fd, &readfds);
|
|
||||||
|
|
||||||
/* wait for a second */
|
|
||||||
n = select(fd + 1, &readfds, NULL, NULL, &tv);
|
|
||||||
if (n != 1) {
|
|
||||||
return errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
n = read(fd, &buf, sizeof(buf));
|
|
||||||
if (n < sizeof(struct tpm_resp_hdr)) {
|
|
||||||
return EFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
resp = (struct tpm_resp_hdr *)buf;
|
|
||||||
/* check the header */
|
|
||||||
if (be16_to_cpu(resp->tag) != TPM_TAG_RSP_COMMAND ||
|
|
||||||
be32_to_cpu(resp->len) != n) {
|
|
||||||
return EBADMSG;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -443,7 +408,7 @@ static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb)
|
||||||
goto err_free_parameters;
|
goto err_free_parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tpm_passthrough_test_tpmdev(tpm_pt->tpm_fd)) {
|
if (tpm_util_test_tpmdev(tpm_pt->tpm_fd, &tpm_pt->tpm_version)) {
|
||||||
error_report("'%s' is not a TPM device.",
|
error_report("'%s' is not a TPM device.",
|
||||||
tpm_pt->tpm_dev);
|
tpm_pt->tpm_dev);
|
||||||
goto err_close_tpmdev;
|
goto err_close_tpmdev;
|
||||||
|
@ -540,6 +505,8 @@ static const TPMDriverOps tpm_passthrough_driver = {
|
||||||
.deliver_request = tpm_passthrough_deliver_request,
|
.deliver_request = tpm_passthrough_deliver_request,
|
||||||
.cancel_cmd = tpm_passthrough_cancel_cmd,
|
.cancel_cmd = tpm_passthrough_cancel_cmd,
|
||||||
.get_tpm_established_flag = tpm_passthrough_get_tpm_established_flag,
|
.get_tpm_established_flag = tpm_passthrough_get_tpm_established_flag,
|
||||||
|
.reset_tpm_established_flag = tpm_passthrough_reset_tpm_established_flag,
|
||||||
|
.get_tpm_version = tpm_passthrough_get_tpm_version,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void tpm_passthrough_inst_init(Object *obj)
|
static void tpm_passthrough_inst_init(Object *obj)
|
||||||
|
|
119
hw/tpm/tpm_tis.c
119
hw/tpm/tpm_tis.c
|
@ -17,6 +17,9 @@
|
||||||
* supports version 1.3, 21 March 2013
|
* supports version 1.3, 21 March 2013
|
||||||
* In the developers menu choose the PC Client section then find the TIS
|
* In the developers menu choose the PC Client section then find the TIS
|
||||||
* specification.
|
* specification.
|
||||||
|
*
|
||||||
|
* TPM TIS for TPM 2 implementation following TCG PC Client Platform
|
||||||
|
* TPM Profile (PTP) Specification, Familiy 2.0, Revision 00.43
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "sysemu/tpm_backend.h"
|
#include "sysemu/tpm_backend.h"
|
||||||
|
@ -29,6 +32,7 @@
|
||||||
#include "tpm_tis.h"
|
#include "tpm_tis.h"
|
||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
#include "qemu/main-loop.h"
|
#include "qemu/main-loop.h"
|
||||||
|
#include "sysemu/tpm_backend.h"
|
||||||
|
|
||||||
#define DEBUG_TIS 0
|
#define DEBUG_TIS 0
|
||||||
|
|
||||||
|
@ -49,6 +53,7 @@
|
||||||
#define TPM_TIS_REG_INTF_CAPABILITY 0x14
|
#define TPM_TIS_REG_INTF_CAPABILITY 0x14
|
||||||
#define TPM_TIS_REG_STS 0x18
|
#define TPM_TIS_REG_STS 0x18
|
||||||
#define TPM_TIS_REG_DATA_FIFO 0x24
|
#define TPM_TIS_REG_DATA_FIFO 0x24
|
||||||
|
#define TPM_TIS_REG_INTERFACE_ID 0x30
|
||||||
#define TPM_TIS_REG_DATA_XFIFO 0x80
|
#define TPM_TIS_REG_DATA_XFIFO 0x80
|
||||||
#define TPM_TIS_REG_DATA_XFIFO_END 0xbc
|
#define TPM_TIS_REG_DATA_XFIFO_END 0xbc
|
||||||
#define TPM_TIS_REG_DID_VID 0xf00
|
#define TPM_TIS_REG_DID_VID 0xf00
|
||||||
|
@ -57,6 +62,12 @@
|
||||||
/* vendor-specific registers */
|
/* vendor-specific registers */
|
||||||
#define TPM_TIS_REG_DEBUG 0xf90
|
#define TPM_TIS_REG_DEBUG 0xf90
|
||||||
|
|
||||||
|
#define TPM_TIS_STS_TPM_FAMILY_MASK (0x3 << 26)/* TPM 2.0 */
|
||||||
|
#define TPM_TIS_STS_TPM_FAMILY1_2 (0 << 26) /* TPM 2.0 */
|
||||||
|
#define TPM_TIS_STS_TPM_FAMILY2_0 (1 << 26) /* TPM 2.0 */
|
||||||
|
#define TPM_TIS_STS_RESET_ESTABLISHMENT_BIT (1 << 25) /* TPM 2.0 */
|
||||||
|
#define TPM_TIS_STS_COMMAND_CANCEL (1 << 24) /* TPM 2.0 */
|
||||||
|
|
||||||
#define TPM_TIS_STS_VALID (1 << 7)
|
#define TPM_TIS_STS_VALID (1 << 7)
|
||||||
#define TPM_TIS_STS_COMMAND_READY (1 << 6)
|
#define TPM_TIS_STS_COMMAND_READY (1 << 6)
|
||||||
#define TPM_TIS_STS_TPM_GO (1 << 5)
|
#define TPM_TIS_STS_TPM_GO (1 << 5)
|
||||||
|
@ -102,15 +113,42 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define TPM_TIS_CAP_INTERFACE_VERSION1_3 (2 << 28)
|
#define TPM_TIS_CAP_INTERFACE_VERSION1_3 (2 << 28)
|
||||||
|
#define TPM_TIS_CAP_INTERFACE_VERSION1_3_FOR_TPM2_0 (3 << 28)
|
||||||
#define TPM_TIS_CAP_DATA_TRANSFER_64B (3 << 9)
|
#define TPM_TIS_CAP_DATA_TRANSFER_64B (3 << 9)
|
||||||
#define TPM_TIS_CAP_DATA_TRANSFER_LEGACY (0 << 9)
|
#define TPM_TIS_CAP_DATA_TRANSFER_LEGACY (0 << 9)
|
||||||
#define TPM_TIS_CAP_BURST_COUNT_DYNAMIC (0 << 8)
|
#define TPM_TIS_CAP_BURST_COUNT_DYNAMIC (0 << 8)
|
||||||
#define TPM_TIS_CAP_INTERRUPT_LOW_LEVEL (1 << 4) /* support is mandatory */
|
#define TPM_TIS_CAP_INTERRUPT_LOW_LEVEL (1 << 4) /* support is mandatory */
|
||||||
#define TPM_TIS_CAPABILITIES_SUPPORTED (TPM_TIS_CAP_INTERRUPT_LOW_LEVEL | \
|
#define TPM_TIS_CAPABILITIES_SUPPORTED1_3 \
|
||||||
TPM_TIS_CAP_BURST_COUNT_DYNAMIC | \
|
(TPM_TIS_CAP_INTERRUPT_LOW_LEVEL | \
|
||||||
TPM_TIS_CAP_DATA_TRANSFER_64B | \
|
TPM_TIS_CAP_BURST_COUNT_DYNAMIC | \
|
||||||
TPM_TIS_CAP_INTERFACE_VERSION1_3 | \
|
TPM_TIS_CAP_DATA_TRANSFER_64B | \
|
||||||
TPM_TIS_INTERRUPTS_SUPPORTED)
|
TPM_TIS_CAP_INTERFACE_VERSION1_3 | \
|
||||||
|
TPM_TIS_INTERRUPTS_SUPPORTED)
|
||||||
|
|
||||||
|
#define TPM_TIS_CAPABILITIES_SUPPORTED2_0 \
|
||||||
|
(TPM_TIS_CAP_INTERRUPT_LOW_LEVEL | \
|
||||||
|
TPM_TIS_CAP_BURST_COUNT_DYNAMIC | \
|
||||||
|
TPM_TIS_CAP_DATA_TRANSFER_64B | \
|
||||||
|
TPM_TIS_CAP_INTERFACE_VERSION1_3_FOR_TPM2_0 | \
|
||||||
|
TPM_TIS_INTERRUPTS_SUPPORTED)
|
||||||
|
|
||||||
|
#define TPM_TIS_IFACE_ID_INTERFACE_TIS1_3 (0xf) /* TPM 2.0 */
|
||||||
|
#define TPM_TIS_IFACE_ID_INTERFACE_FIFO (0x0) /* TPM 2.0 */
|
||||||
|
#define TPM_TIS_IFACE_ID_INTERFACE_VER_FIFO (0 << 4) /* TPM 2.0 */
|
||||||
|
#define TPM_TIS_IFACE_ID_CAP_5_LOCALITIES (1 << 8) /* TPM 2.0 */
|
||||||
|
#define TPM_TIS_IFACE_ID_CAP_TIS_SUPPORTED (1 << 13) /* TPM 2.0 */
|
||||||
|
#define TPM_TIS_IFACE_ID_INT_SEL_LOCK (1 << 19) /* TPM 2.0 */
|
||||||
|
|
||||||
|
#define TPM_TIS_IFACE_ID_SUPPORTED_FLAGS1_3 \
|
||||||
|
(TPM_TIS_IFACE_ID_INTERFACE_TIS1_3 | \
|
||||||
|
(~0 << 4)/* all of it is don't care */)
|
||||||
|
|
||||||
|
/* if backend was a TPM 2.0: */
|
||||||
|
#define TPM_TIS_IFACE_ID_SUPPORTED_FLAGS2_0 \
|
||||||
|
(TPM_TIS_IFACE_ID_INTERFACE_FIFO | \
|
||||||
|
TPM_TIS_IFACE_ID_INTERFACE_VER_FIFO | \
|
||||||
|
TPM_TIS_IFACE_ID_CAP_5_LOCALITIES | \
|
||||||
|
TPM_TIS_IFACE_ID_CAP_TIS_SUPPORTED)
|
||||||
|
|
||||||
#define TPM_TIS_TPM_DID 0x0001
|
#define TPM_TIS_TPM_DID 0x0001
|
||||||
#define TPM_TIS_TPM_VID PCI_VENDOR_ID_IBM
|
#define TPM_TIS_TPM_VID PCI_VENDOR_ID_IBM
|
||||||
|
@ -154,7 +192,8 @@ static void tpm_tis_show_buffer(const TPMSizedBuffer *sb, const char *string)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the given flags in the STS register by clearing the register but
|
* Set the given flags in the STS register by clearing the register but
|
||||||
* preserving the SELFTEST_DONE flag and then setting the new flags.
|
* preserving the SELFTEST_DONE and TPM_FAMILY_MASK flags and then setting
|
||||||
|
* the new flags.
|
||||||
*
|
*
|
||||||
* The SELFTEST_DONE flag is acquired from the backend that determines it by
|
* The SELFTEST_DONE flag is acquired from the backend that determines it by
|
||||||
* peeking into TPM commands.
|
* peeking into TPM commands.
|
||||||
|
@ -166,7 +205,7 @@ static void tpm_tis_show_buffer(const TPMSizedBuffer *sb, const char *string)
|
||||||
*/
|
*/
|
||||||
static void tpm_tis_sts_set(TPMLocality *l, uint32_t flags)
|
static void tpm_tis_sts_set(TPMLocality *l, uint32_t flags)
|
||||||
{
|
{
|
||||||
l->sts &= TPM_TIS_STS_SELFTEST_DONE;
|
l->sts &= TPM_TIS_STS_SELFTEST_DONE | TPM_TIS_STS_TPM_FAMILY_MASK;
|
||||||
l->sts |= flags;
|
l->sts |= flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -489,7 +528,17 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
|
||||||
val = tis->loc[locty].ints;
|
val = tis->loc[locty].ints;
|
||||||
break;
|
break;
|
||||||
case TPM_TIS_REG_INTF_CAPABILITY:
|
case TPM_TIS_REG_INTF_CAPABILITY:
|
||||||
val = TPM_TIS_CAPABILITIES_SUPPORTED;
|
switch (s->be_tpm_version) {
|
||||||
|
case TPM_VERSION_UNSPEC:
|
||||||
|
val = 0;
|
||||||
|
break;
|
||||||
|
case TPM_VERSION_1_2:
|
||||||
|
val = TPM_TIS_CAPABILITIES_SUPPORTED1_3;
|
||||||
|
break;
|
||||||
|
case TPM_VERSION_2_0:
|
||||||
|
val = TPM_TIS_CAPABILITIES_SUPPORTED2_0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case TPM_TIS_REG_STS:
|
case TPM_TIS_REG_STS:
|
||||||
if (tis->active_locty == locty) {
|
if (tis->active_locty == locty) {
|
||||||
|
@ -536,6 +585,9 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
|
||||||
shift = 0; /* no more adjustments */
|
shift = 0; /* no more adjustments */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case TPM_TIS_REG_INTERFACE_ID:
|
||||||
|
val = tis->loc[locty].iface_id;
|
||||||
|
break;
|
||||||
case TPM_TIS_REG_DID_VID:
|
case TPM_TIS_REG_DID_VID:
|
||||||
val = (TPM_TIS_TPM_DID << 16) | TPM_TIS_TPM_VID;
|
val = (TPM_TIS_TPM_DID << 16) | TPM_TIS_TPM_VID;
|
||||||
break;
|
break;
|
||||||
|
@ -736,6 +788,25 @@ static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s->be_tpm_version == TPM_VERSION_2_0) {
|
||||||
|
/* some flags that are only supported for TPM 2 */
|
||||||
|
if (val & TPM_TIS_STS_COMMAND_CANCEL) {
|
||||||
|
if (tis->loc[locty].state == TPM_TIS_STATE_EXECUTION) {
|
||||||
|
/*
|
||||||
|
* request the backend to cancel. Some backends may not
|
||||||
|
* support it
|
||||||
|
*/
|
||||||
|
tpm_backend_cancel_cmd(s->be_driver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (val & TPM_TIS_STS_RESET_ESTABLISHMENT_BIT) {
|
||||||
|
if (locty == 3 || locty == 4) {
|
||||||
|
tpm_backend_reset_tpm_established_flag(s->be_driver, locty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val &= (TPM_TIS_STS_COMMAND_READY | TPM_TIS_STS_TPM_GO |
|
val &= (TPM_TIS_STS_COMMAND_READY | TPM_TIS_STS_TPM_GO |
|
||||||
TPM_TIS_STS_RESPONSE_RETRY);
|
TPM_TIS_STS_RESPONSE_RETRY);
|
||||||
|
|
||||||
|
@ -860,6 +931,13 @@ static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case TPM_TIS_REG_INTERFACE_ID:
|
||||||
|
if (val & TPM_TIS_IFACE_ID_INT_SEL_LOCK) {
|
||||||
|
for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) {
|
||||||
|
tis->loc[l].iface_id |= TPM_TIS_IFACE_ID_INT_SEL_LOCK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -884,6 +962,16 @@ static int tpm_tis_do_startup_tpm(TPMState *s)
|
||||||
return tpm_backend_startup_tpm(s->be_driver);
|
return tpm_backend_startup_tpm(s->be_driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the TPMVersion of the backend device being used
|
||||||
|
*/
|
||||||
|
TPMVersion tpm_tis_get_tpm_version(Object *obj)
|
||||||
|
{
|
||||||
|
TPMState *s = TPM(obj);
|
||||||
|
|
||||||
|
return tpm_backend_get_tpm_version(s->be_driver);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function is called when the machine starts, resets or due to
|
* This function is called when the machine starts, resets or due to
|
||||||
* S3 resume.
|
* S3 resume.
|
||||||
|
@ -894,6 +982,8 @@ static void tpm_tis_reset(DeviceState *dev)
|
||||||
TPMTISEmuState *tis = &s->s.tis;
|
TPMTISEmuState *tis = &s->s.tis;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
|
s->be_tpm_version = tpm_backend_get_tpm_version(s->be_driver);
|
||||||
|
|
||||||
tpm_backend_reset(s->be_driver);
|
tpm_backend_reset(s->be_driver);
|
||||||
|
|
||||||
tis->active_locty = TPM_TIS_NO_LOCALITY;
|
tis->active_locty = TPM_TIS_NO_LOCALITY;
|
||||||
|
@ -902,7 +992,18 @@ static void tpm_tis_reset(DeviceState *dev)
|
||||||
|
|
||||||
for (c = 0; c < TPM_TIS_NUM_LOCALITIES; c++) {
|
for (c = 0; c < TPM_TIS_NUM_LOCALITIES; c++) {
|
||||||
tis->loc[c].access = TPM_TIS_ACCESS_TPM_REG_VALID_STS;
|
tis->loc[c].access = TPM_TIS_ACCESS_TPM_REG_VALID_STS;
|
||||||
tis->loc[c].sts = 0;
|
switch (s->be_tpm_version) {
|
||||||
|
case TPM_VERSION_UNSPEC:
|
||||||
|
break;
|
||||||
|
case TPM_VERSION_1_2:
|
||||||
|
tis->loc[c].sts = TPM_TIS_STS_TPM_FAMILY1_2;
|
||||||
|
tis->loc[c].iface_id = TPM_TIS_IFACE_ID_SUPPORTED_FLAGS1_3;
|
||||||
|
break;
|
||||||
|
case TPM_VERSION_2_0:
|
||||||
|
tis->loc[c].sts = TPM_TIS_STS_TPM_FAMILY2_0;
|
||||||
|
tis->loc[c].iface_id = TPM_TIS_IFACE_ID_SUPPORTED_FLAGS2_0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
tis->loc[c].inte = TPM_TIS_INT_POLARITY_LOW_LEVEL;
|
tis->loc[c].inte = TPM_TIS_INT_POLARITY_LOW_LEVEL;
|
||||||
tis->loc[c].ints = 0;
|
tis->loc[c].ints = 0;
|
||||||
tis->loc[c].state = TPM_TIS_STATE_IDLE;
|
tis->loc[c].state = TPM_TIS_STATE_IDLE;
|
||||||
|
|
|
@ -42,6 +42,7 @@ typedef struct TPMLocality {
|
||||||
TPMTISState state;
|
TPMTISState state;
|
||||||
uint8_t access;
|
uint8_t access;
|
||||||
uint32_t sts;
|
uint32_t sts;
|
||||||
|
uint32_t iface_id;
|
||||||
uint32_t inte;
|
uint32_t inte;
|
||||||
uint32_t ints;
|
uint32_t ints;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
/*
|
||||||
|
* TPM utility functions
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 - 2015 IBM Corporation
|
||||||
|
* Authors:
|
||||||
|
* Stefan Berger <stefanb@us.ibm.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "tpm_util.h"
|
||||||
|
#include "tpm_int.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A basic test of a TPM device. We expect a well formatted response header
|
||||||
|
* (error response is fine) within one second.
|
||||||
|
*/
|
||||||
|
static int tpm_util_test(int fd,
|
||||||
|
unsigned char *request,
|
||||||
|
size_t requestlen,
|
||||||
|
uint16_t *return_tag)
|
||||||
|
{
|
||||||
|
struct tpm_resp_hdr *resp;
|
||||||
|
fd_set readfds;
|
||||||
|
int n;
|
||||||
|
struct timeval tv = {
|
||||||
|
.tv_sec = 1,
|
||||||
|
.tv_usec = 0,
|
||||||
|
};
|
||||||
|
unsigned char buf[1024];
|
||||||
|
|
||||||
|
n = write(fd, request, requestlen);
|
||||||
|
if (n < 0) {
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
if (n != requestlen) {
|
||||||
|
return EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
FD_ZERO(&readfds);
|
||||||
|
FD_SET(fd, &readfds);
|
||||||
|
|
||||||
|
/* wait for a second */
|
||||||
|
n = select(fd + 1, &readfds, NULL, NULL, &tv);
|
||||||
|
if (n != 1) {
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = read(fd, &buf, sizeof(buf));
|
||||||
|
if (n < sizeof(struct tpm_resp_hdr)) {
|
||||||
|
return EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
resp = (struct tpm_resp_hdr *)buf;
|
||||||
|
/* check the header */
|
||||||
|
if (be32_to_cpu(resp->len) != n) {
|
||||||
|
return EBADMSG;
|
||||||
|
}
|
||||||
|
|
||||||
|
*return_tag = be16_to_cpu(resp->tag);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Probe for the TPM device in the back
|
||||||
|
* Returns 0 on success with the version of the probed TPM set, 1 on failure.
|
||||||
|
*/
|
||||||
|
int tpm_util_test_tpmdev(int tpm_fd, TPMVersion *tpm_version)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Sending a TPM1.2 command to a TPM2 should return a TPM1.2
|
||||||
|
* header (tag = 0xc4) and error code (TPM_BADTAG = 0x1e)
|
||||||
|
*
|
||||||
|
* Sending a TPM2 command to a TPM 2 will give a TPM 2 tag in the
|
||||||
|
* header.
|
||||||
|
* Sending a TPM2 command to a TPM 1.2 will give a TPM 1.2 tag
|
||||||
|
* in the header and an error code.
|
||||||
|
*/
|
||||||
|
const struct tpm_req_hdr test_req = {
|
||||||
|
.tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
|
||||||
|
.len = cpu_to_be32(sizeof(test_req)),
|
||||||
|
.ordinal = cpu_to_be32(TPM_ORD_GetTicks),
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct tpm_req_hdr test_req_tpm2 = {
|
||||||
|
.tag = cpu_to_be16(TPM2_ST_NO_SESSIONS),
|
||||||
|
.len = cpu_to_be32(sizeof(test_req_tpm2)),
|
||||||
|
.ordinal = cpu_to_be32(TPM2_CC_ReadClock),
|
||||||
|
};
|
||||||
|
uint16_t return_tag;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Send TPM 2 command */
|
||||||
|
ret = tpm_util_test(tpm_fd, (unsigned char *)&test_req_tpm2,
|
||||||
|
sizeof(test_req_tpm2), &return_tag);
|
||||||
|
/* TPM 2 would respond with a tag of TPM2_ST_NO_SESSIONS */
|
||||||
|
if (!ret && return_tag == TPM2_ST_NO_SESSIONS) {
|
||||||
|
*tpm_version = TPM_VERSION_2_0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send TPM 1.2 command */
|
||||||
|
ret = tpm_util_test(tpm_fd, (unsigned char *)&test_req,
|
||||||
|
sizeof(test_req), &return_tag);
|
||||||
|
if (!ret && return_tag == TPM_TAG_RSP_COMMAND) {
|
||||||
|
*tpm_version = TPM_VERSION_1_2;
|
||||||
|
/* this is a TPM 1.2 */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*tpm_version = TPM_VERSION_UNSPEC;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* TPM utility functions
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 - 2015 IBM Corporation
|
||||||
|
* Authors:
|
||||||
|
* Stefan Berger <stefanb@us.ibm.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
#ifndef TPM_TPM_UTILS_H
|
||||||
|
#define TPM_TPM_UTILS_H
|
||||||
|
|
||||||
|
#include "sysemu/tpm_backend.h"
|
||||||
|
|
||||||
|
int tpm_util_test_tpmdev(int tpm_fd, TPMVersion *tpm_version);
|
||||||
|
|
||||||
|
#endif /* TPM_TPM_UTILS_H */
|
|
@ -210,7 +210,12 @@ static int vhost_user_call(struct vhost_dev *dev, unsigned long int request,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VHOST_SET_OWNER:
|
case VHOST_SET_OWNER:
|
||||||
|
break;
|
||||||
|
|
||||||
case VHOST_RESET_OWNER:
|
case VHOST_RESET_OWNER:
|
||||||
|
memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
|
||||||
|
msg.state.index += dev->vq_index;
|
||||||
|
msg.size = sizeof(m.state);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VHOST_SET_MEM_TABLE:
|
case VHOST_SET_MEM_TABLE:
|
||||||
|
@ -253,17 +258,20 @@ static int vhost_user_call(struct vhost_dev *dev, unsigned long int request,
|
||||||
case VHOST_SET_VRING_NUM:
|
case VHOST_SET_VRING_NUM:
|
||||||
case VHOST_SET_VRING_BASE:
|
case VHOST_SET_VRING_BASE:
|
||||||
memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
|
memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
|
||||||
|
msg.state.index += dev->vq_index;
|
||||||
msg.size = sizeof(m.state);
|
msg.size = sizeof(m.state);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VHOST_GET_VRING_BASE:
|
case VHOST_GET_VRING_BASE:
|
||||||
memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
|
memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
|
||||||
|
msg.state.index += dev->vq_index;
|
||||||
msg.size = sizeof(m.state);
|
msg.size = sizeof(m.state);
|
||||||
need_reply = 1;
|
need_reply = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VHOST_SET_VRING_ADDR:
|
case VHOST_SET_VRING_ADDR:
|
||||||
memcpy(&msg.addr, arg, sizeof(struct vhost_vring_addr));
|
memcpy(&msg.addr, arg, sizeof(struct vhost_vring_addr));
|
||||||
|
msg.addr.index += dev->vq_index;
|
||||||
msg.size = sizeof(m.addr);
|
msg.size = sizeof(m.addr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -271,7 +279,7 @@ static int vhost_user_call(struct vhost_dev *dev, unsigned long int request,
|
||||||
case VHOST_SET_VRING_CALL:
|
case VHOST_SET_VRING_CALL:
|
||||||
case VHOST_SET_VRING_ERR:
|
case VHOST_SET_VRING_ERR:
|
||||||
file = arg;
|
file = arg;
|
||||||
msg.u64 = file->index & VHOST_USER_VRING_IDX_MASK;
|
msg.u64 = (file->index + dev->vq_index) & VHOST_USER_VRING_IDX_MASK;
|
||||||
msg.size = sizeof(m.u64);
|
msg.size = sizeof(m.u64);
|
||||||
if (ioeventfd_enabled() && file->fd > 0) {
|
if (ioeventfd_enabled() && file->fd > 0) {
|
||||||
fds[fd_num++] = file->fd;
|
fds[fd_num++] = file->fd;
|
||||||
|
@ -313,6 +321,7 @@ static int vhost_user_call(struct vhost_dev *dev, unsigned long int request,
|
||||||
error_report("Received bad msg size.");
|
error_report("Received bad msg size.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
msg.state.index -= dev->vq_index;
|
||||||
memcpy(arg, &msg.state, sizeof(struct vhost_vring_state));
|
memcpy(arg, &msg.state, sizeof(struct vhost_vring_state));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -310,7 +310,7 @@ static void virtio_balloon_set_config(VirtIODevice *vdev,
|
||||||
trace_virtio_balloon_set_config(dev->actual, oldactual);
|
trace_virtio_balloon_set_config(dev->actual, oldactual);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t virtio_balloon_get_features(VirtIODevice *vdev, uint32_t f)
|
static uint64_t virtio_balloon_get_features(VirtIODevice *vdev, uint64_t f)
|
||||||
{
|
{
|
||||||
f |= (1 << VIRTIO_BALLOON_F_STATS_VQ);
|
f |= (1 << VIRTIO_BALLOON_F_STATS_VQ);
|
||||||
return f;
|
return f;
|
||||||
|
@ -396,14 +396,6 @@ static void virtio_balloon_device_realize(DeviceState *dev, Error **errp)
|
||||||
|
|
||||||
register_savevm(dev, "virtio-balloon", -1, 1,
|
register_savevm(dev, "virtio-balloon", -1, 1,
|
||||||
virtio_balloon_save, virtio_balloon_load, s);
|
virtio_balloon_save, virtio_balloon_load, s);
|
||||||
|
|
||||||
object_property_add(OBJECT(dev), "guest-stats", "guest statistics",
|
|
||||||
balloon_stats_get_all, NULL, NULL, s, NULL);
|
|
||||||
|
|
||||||
object_property_add(OBJECT(dev), "guest-stats-polling-interval", "int",
|
|
||||||
balloon_stats_get_poll_interval,
|
|
||||||
balloon_stats_set_poll_interval,
|
|
||||||
NULL, s, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void virtio_balloon_device_unrealize(DeviceState *dev, Error **errp)
|
static void virtio_balloon_device_unrealize(DeviceState *dev, Error **errp)
|
||||||
|
@ -417,6 +409,19 @@ static void virtio_balloon_device_unrealize(DeviceState *dev, Error **errp)
|
||||||
virtio_cleanup(vdev);
|
virtio_cleanup(vdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void virtio_balloon_instance_init(Object *obj)
|
||||||
|
{
|
||||||
|
VirtIOBalloon *s = VIRTIO_BALLOON(obj);
|
||||||
|
|
||||||
|
object_property_add(obj, "guest-stats", "guest statistics",
|
||||||
|
balloon_stats_get_all, NULL, NULL, s, NULL);
|
||||||
|
|
||||||
|
object_property_add(obj, "guest-stats-polling-interval", "int",
|
||||||
|
balloon_stats_get_poll_interval,
|
||||||
|
balloon_stats_set_poll_interval,
|
||||||
|
NULL, s, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static Property virtio_balloon_properties[] = {
|
static Property virtio_balloon_properties[] = {
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
};
|
};
|
||||||
|
@ -441,6 +446,7 @@ static const TypeInfo virtio_balloon_info = {
|
||||||
.name = TYPE_VIRTIO_BALLOON,
|
.name = TYPE_VIRTIO_BALLOON,
|
||||||
.parent = TYPE_VIRTIO_DEVICE,
|
.parent = TYPE_VIRTIO_DEVICE,
|
||||||
.instance_size = sizeof(VirtIOBalloon),
|
.instance_size = sizeof(VirtIOBalloon),
|
||||||
|
.instance_init = virtio_balloon_instance_init,
|
||||||
.class_init = virtio_balloon_class_init,
|
.class_init = virtio_balloon_class_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -38,19 +38,23 @@ do { printf("virtio_bus: " fmt , ## __VA_ARGS__); } while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* A VirtIODevice is being plugged */
|
/* A VirtIODevice is being plugged */
|
||||||
int virtio_bus_device_plugged(VirtIODevice *vdev)
|
void virtio_bus_device_plugged(VirtIODevice *vdev, Error **errp)
|
||||||
{
|
{
|
||||||
DeviceState *qdev = DEVICE(vdev);
|
DeviceState *qdev = DEVICE(vdev);
|
||||||
BusState *qbus = BUS(qdev_get_parent_bus(qdev));
|
BusState *qbus = BUS(qdev_get_parent_bus(qdev));
|
||||||
VirtioBusState *bus = VIRTIO_BUS(qbus);
|
VirtioBusState *bus = VIRTIO_BUS(qbus);
|
||||||
VirtioBusClass *klass = VIRTIO_BUS_GET_CLASS(bus);
|
VirtioBusClass *klass = VIRTIO_BUS_GET_CLASS(bus);
|
||||||
|
VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
|
||||||
|
|
||||||
DPRINTF("%s: plug device.\n", qbus->name);
|
DPRINTF("%s: plug device.\n", qbus->name);
|
||||||
|
|
||||||
if (klass->device_plugged != NULL) {
|
if (klass->device_plugged != NULL) {
|
||||||
klass->device_plugged(qbus->parent);
|
klass->device_plugged(qbus->parent, errp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
/* Get the features of the plugged device. */
|
||||||
|
assert(vdc->get_features != NULL);
|
||||||
|
vdev->host_features = vdc->get_features(vdev, vdev->host_features);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset the virtio_bus */
|
/* Reset the virtio_bus */
|
||||||
|
@ -96,19 +100,6 @@ size_t virtio_bus_get_vdev_config_len(VirtioBusState *bus)
|
||||||
return vdev->config_len;
|
return vdev->config_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the features of the plugged device. */
|
|
||||||
uint32_t virtio_bus_get_vdev_features(VirtioBusState *bus,
|
|
||||||
uint32_t requested_features)
|
|
||||||
{
|
|
||||||
VirtIODevice *vdev = virtio_bus_get_device(bus);
|
|
||||||
VirtioDeviceClass *k;
|
|
||||||
|
|
||||||
assert(vdev != NULL);
|
|
||||||
k = VIRTIO_DEVICE_GET_CLASS(vdev);
|
|
||||||
assert(k->get_features != NULL);
|
|
||||||
return k->get_features(vdev, requested_features);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get bad features of the plugged device. */
|
/* Get bad features of the plugged device. */
|
||||||
uint32_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus)
|
uint32_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus)
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,7 +22,9 @@
|
||||||
#include "hw/sysbus.h"
|
#include "hw/sysbus.h"
|
||||||
#include "hw/virtio/virtio.h"
|
#include "hw/virtio/virtio.h"
|
||||||
#include "qemu/host-utils.h"
|
#include "qemu/host-utils.h"
|
||||||
|
#include "sysemu/kvm.h"
|
||||||
#include "hw/virtio/virtio-bus.h"
|
#include "hw/virtio/virtio-bus.h"
|
||||||
|
#include "qemu/error-report.h"
|
||||||
|
|
||||||
/* #define DEBUG_VIRTIO_MMIO */
|
/* #define DEBUG_VIRTIO_MMIO */
|
||||||
|
|
||||||
|
@ -80,15 +82,102 @@ typedef struct {
|
||||||
SysBusDevice parent_obj;
|
SysBusDevice parent_obj;
|
||||||
MemoryRegion iomem;
|
MemoryRegion iomem;
|
||||||
qemu_irq irq;
|
qemu_irq irq;
|
||||||
uint32_t host_features;
|
|
||||||
/* Guest accessible state needing migration and reset */
|
/* Guest accessible state needing migration and reset */
|
||||||
uint32_t host_features_sel;
|
uint32_t host_features_sel;
|
||||||
uint32_t guest_features_sel;
|
uint32_t guest_features_sel;
|
||||||
uint32_t guest_page_shift;
|
uint32_t guest_page_shift;
|
||||||
/* virtio-bus */
|
/* virtio-bus */
|
||||||
VirtioBusState bus;
|
VirtioBusState bus;
|
||||||
|
bool ioeventfd_disabled;
|
||||||
|
bool ioeventfd_started;
|
||||||
} VirtIOMMIOProxy;
|
} VirtIOMMIOProxy;
|
||||||
|
|
||||||
|
static int virtio_mmio_set_host_notifier_internal(VirtIOMMIOProxy *proxy,
|
||||||
|
int n, bool assign,
|
||||||
|
bool set_handler)
|
||||||
|
{
|
||||||
|
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
|
||||||
|
VirtQueue *vq = virtio_get_queue(vdev, n);
|
||||||
|
EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
|
||||||
|
int r = 0;
|
||||||
|
|
||||||
|
if (assign) {
|
||||||
|
r = event_notifier_init(notifier, 1);
|
||||||
|
if (r < 0) {
|
||||||
|
error_report("%s: unable to init event notifier: %d",
|
||||||
|
__func__, r);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
virtio_queue_set_host_notifier_fd_handler(vq, true, set_handler);
|
||||||
|
memory_region_add_eventfd(&proxy->iomem, VIRTIO_MMIO_QUEUENOTIFY, 4,
|
||||||
|
true, n, notifier);
|
||||||
|
} else {
|
||||||
|
memory_region_del_eventfd(&proxy->iomem, VIRTIO_MMIO_QUEUENOTIFY, 4,
|
||||||
|
true, n, notifier);
|
||||||
|
virtio_queue_set_host_notifier_fd_handler(vq, false, false);
|
||||||
|
event_notifier_cleanup(notifier);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virtio_mmio_start_ioeventfd(VirtIOMMIOProxy *proxy)
|
||||||
|
{
|
||||||
|
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
|
||||||
|
int n, r;
|
||||||
|
|
||||||
|
if (!kvm_eventfds_enabled() ||
|
||||||
|
proxy->ioeventfd_disabled ||
|
||||||
|
proxy->ioeventfd_started) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
|
||||||
|
if (!virtio_queue_get_num(vdev, n)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = virtio_mmio_set_host_notifier_internal(proxy, n, true, true);
|
||||||
|
if (r < 0) {
|
||||||
|
goto assign_error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
proxy->ioeventfd_started = true;
|
||||||
|
return;
|
||||||
|
|
||||||
|
assign_error:
|
||||||
|
while (--n >= 0) {
|
||||||
|
if (!virtio_queue_get_num(vdev, n)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = virtio_mmio_set_host_notifier_internal(proxy, n, false, false);
|
||||||
|
assert(r >= 0);
|
||||||
|
}
|
||||||
|
proxy->ioeventfd_started = false;
|
||||||
|
error_report("%s: failed. Fallback to a userspace (slower).", __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virtio_mmio_stop_ioeventfd(VirtIOMMIOProxy *proxy)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
int n;
|
||||||
|
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
|
||||||
|
|
||||||
|
if (!proxy->ioeventfd_started) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
|
||||||
|
if (!virtio_queue_get_num(vdev, n)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = virtio_mmio_set_host_notifier_internal(proxy, n, false, false);
|
||||||
|
assert(r >= 0);
|
||||||
|
}
|
||||||
|
proxy->ioeventfd_started = false;
|
||||||
|
}
|
||||||
|
|
||||||
static uint64_t virtio_mmio_read(void *opaque, hwaddr offset, unsigned size)
|
static uint64_t virtio_mmio_read(void *opaque, hwaddr offset, unsigned size)
|
||||||
{
|
{
|
||||||
VirtIOMMIOProxy *proxy = (VirtIOMMIOProxy *)opaque;
|
VirtIOMMIOProxy *proxy = (VirtIOMMIOProxy *)opaque;
|
||||||
|
@ -147,7 +236,7 @@ static uint64_t virtio_mmio_read(void *opaque, hwaddr offset, unsigned size)
|
||||||
if (proxy->host_features_sel) {
|
if (proxy->host_features_sel) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return proxy->host_features;
|
return vdev->host_features;
|
||||||
case VIRTIO_MMIO_QUEUENUMMAX:
|
case VIRTIO_MMIO_QUEUENUMMAX:
|
||||||
if (!virtio_queue_get_num(vdev, vdev->queue_sel)) {
|
if (!virtio_queue_get_num(vdev, vdev->queue_sel)) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -237,7 +326,7 @@ static void virtio_mmio_write(void *opaque, hwaddr offset, uint64_t value,
|
||||||
proxy->guest_page_shift);
|
proxy->guest_page_shift);
|
||||||
break;
|
break;
|
||||||
case VIRTIO_MMIO_QUEUESEL:
|
case VIRTIO_MMIO_QUEUESEL:
|
||||||
if (value < VIRTIO_PCI_QUEUE_MAX) {
|
if (value < VIRTIO_QUEUE_MAX) {
|
||||||
vdev->queue_sel = value;
|
vdev->queue_sel = value;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -257,7 +346,7 @@ static void virtio_mmio_write(void *opaque, hwaddr offset, uint64_t value,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case VIRTIO_MMIO_QUEUENOTIFY:
|
case VIRTIO_MMIO_QUEUENOTIFY:
|
||||||
if (value < VIRTIO_PCI_QUEUE_MAX) {
|
if (value < VIRTIO_QUEUE_MAX) {
|
||||||
virtio_queue_notify(vdev, value);
|
virtio_queue_notify(vdev, value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -266,7 +355,16 @@ static void virtio_mmio_write(void *opaque, hwaddr offset, uint64_t value,
|
||||||
virtio_update_irq(vdev);
|
virtio_update_irq(vdev);
|
||||||
break;
|
break;
|
||||||
case VIRTIO_MMIO_STATUS:
|
case VIRTIO_MMIO_STATUS:
|
||||||
|
if (!(value & VIRTIO_CONFIG_S_DRIVER_OK)) {
|
||||||
|
virtio_mmio_stop_ioeventfd(proxy);
|
||||||
|
}
|
||||||
|
|
||||||
virtio_set_status(vdev, value & 0xff);
|
virtio_set_status(vdev, value & 0xff);
|
||||||
|
|
||||||
|
if (value & VIRTIO_CONFIG_S_DRIVER_OK) {
|
||||||
|
virtio_mmio_start_ioeventfd(proxy);
|
||||||
|
}
|
||||||
|
|
||||||
if (vdev->status == 0) {
|
if (vdev->status == 0) {
|
||||||
virtio_reset(vdev);
|
virtio_reset(vdev);
|
||||||
}
|
}
|
||||||
|
@ -306,13 +404,6 @@ static void virtio_mmio_update_irq(DeviceState *opaque, uint16_t vector)
|
||||||
qemu_set_irq(proxy->irq, level);
|
qemu_set_irq(proxy->irq, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int virtio_mmio_get_features(DeviceState *opaque)
|
|
||||||
{
|
|
||||||
VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
|
|
||||||
|
|
||||||
return proxy->host_features;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int virtio_mmio_load_config(DeviceState *opaque, QEMUFile *f)
|
static int virtio_mmio_load_config(DeviceState *opaque, QEMUFile *f)
|
||||||
{
|
{
|
||||||
VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
|
VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
|
||||||
|
@ -336,24 +427,94 @@ static void virtio_mmio_reset(DeviceState *d)
|
||||||
{
|
{
|
||||||
VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
|
VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
|
||||||
|
|
||||||
|
virtio_mmio_stop_ioeventfd(proxy);
|
||||||
virtio_bus_reset(&proxy->bus);
|
virtio_bus_reset(&proxy->bus);
|
||||||
proxy->host_features_sel = 0;
|
proxy->host_features_sel = 0;
|
||||||
proxy->guest_features_sel = 0;
|
proxy->guest_features_sel = 0;
|
||||||
proxy->guest_page_shift = 0;
|
proxy->guest_page_shift = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* virtio-mmio device */
|
static int virtio_mmio_set_guest_notifier(DeviceState *d, int n, bool assign,
|
||||||
|
bool with_irqfd)
|
||||||
|
{
|
||||||
|
VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
|
||||||
|
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
|
||||||
|
VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
|
||||||
|
VirtQueue *vq = virtio_get_queue(vdev, n);
|
||||||
|
EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
|
||||||
|
|
||||||
/* This is called by virtio-bus just after the device is plugged. */
|
if (assign) {
|
||||||
static void virtio_mmio_device_plugged(DeviceState *opaque)
|
int r = event_notifier_init(notifier, 0);
|
||||||
|
if (r < 0) {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
virtio_queue_set_guest_notifier_fd_handler(vq, true, with_irqfd);
|
||||||
|
} else {
|
||||||
|
virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd);
|
||||||
|
event_notifier_cleanup(notifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vdc->guest_notifier_mask) {
|
||||||
|
vdc->guest_notifier_mask(vdev, n, !assign);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int virtio_mmio_set_guest_notifiers(DeviceState *d, int nvqs,
|
||||||
|
bool assign)
|
||||||
|
{
|
||||||
|
VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
|
||||||
|
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
|
||||||
|
/* TODO: need to check if kvm-arm supports irqfd */
|
||||||
|
bool with_irqfd = false;
|
||||||
|
int r, n;
|
||||||
|
|
||||||
|
nvqs = MIN(nvqs, VIRTIO_QUEUE_MAX);
|
||||||
|
|
||||||
|
for (n = 0; n < nvqs; n++) {
|
||||||
|
if (!virtio_queue_get_num(vdev, n)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = virtio_mmio_set_guest_notifier(d, n, assign, with_irqfd);
|
||||||
|
if (r < 0) {
|
||||||
|
goto assign_error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
assign_error:
|
||||||
|
/* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */
|
||||||
|
assert(assign);
|
||||||
|
while (--n >= 0) {
|
||||||
|
virtio_mmio_set_guest_notifier(d, n, !assign, false);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int virtio_mmio_set_host_notifier(DeviceState *opaque, int n,
|
||||||
|
bool assign)
|
||||||
{
|
{
|
||||||
VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
|
VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
|
||||||
|
|
||||||
virtio_add_feature(&proxy->host_features, VIRTIO_F_NOTIFY_ON_EMPTY);
|
/* Stop using ioeventfd for virtqueue kick if the device starts using host
|
||||||
proxy->host_features = virtio_bus_get_vdev_features(&proxy->bus,
|
* notifiers. This makes it easy to avoid stepping on each others' toes.
|
||||||
proxy->host_features);
|
*/
|
||||||
|
proxy->ioeventfd_disabled = assign;
|
||||||
|
if (assign) {
|
||||||
|
virtio_mmio_stop_ioeventfd(proxy);
|
||||||
|
}
|
||||||
|
/* We don't need to start here: it's not needed because backend
|
||||||
|
* currently only stops on status change away from ok,
|
||||||
|
* reset, vmstop and such. If we do add code to start here,
|
||||||
|
* need to check vmstate, device state etc. */
|
||||||
|
return virtio_mmio_set_host_notifier_internal(proxy, n, assign, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* virtio-mmio device */
|
||||||
|
|
||||||
static void virtio_mmio_realizefn(DeviceState *d, Error **errp)
|
static void virtio_mmio_realizefn(DeviceState *d, Error **errp)
|
||||||
{
|
{
|
||||||
VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
|
VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
|
||||||
|
@ -367,16 +528,10 @@ static void virtio_mmio_realizefn(DeviceState *d, Error **errp)
|
||||||
sysbus_init_mmio(sbd, &proxy->iomem);
|
sysbus_init_mmio(sbd, &proxy->iomem);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Property virtio_mmio_properties[] = {
|
|
||||||
DEFINE_VIRTIO_COMMON_FEATURES(VirtIOMMIOProxy, host_features),
|
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
|
||||||
};
|
|
||||||
|
|
||||||
static void virtio_mmio_class_init(ObjectClass *klass, void *data)
|
static void virtio_mmio_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
|
|
||||||
dc->props = virtio_mmio_properties;
|
|
||||||
dc->realize = virtio_mmio_realizefn;
|
dc->realize = virtio_mmio_realizefn;
|
||||||
dc->reset = virtio_mmio_reset;
|
dc->reset = virtio_mmio_reset;
|
||||||
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
||||||
|
@ -399,8 +554,8 @@ static void virtio_mmio_bus_class_init(ObjectClass *klass, void *data)
|
||||||
k->notify = virtio_mmio_update_irq;
|
k->notify = virtio_mmio_update_irq;
|
||||||
k->save_config = virtio_mmio_save_config;
|
k->save_config = virtio_mmio_save_config;
|
||||||
k->load_config = virtio_mmio_load_config;
|
k->load_config = virtio_mmio_load_config;
|
||||||
k->get_features = virtio_mmio_get_features;
|
k->set_host_notifier = virtio_mmio_set_host_notifier;
|
||||||
k->device_plugged = virtio_mmio_device_plugged;
|
k->set_guest_notifiers = virtio_mmio_set_guest_notifiers;
|
||||||
k->has_variable_vring_alignment = true;
|
k->has_variable_vring_alignment = true;
|
||||||
bus_class->max_dev = 1;
|
bus_class->max_dev = 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,7 +171,7 @@ static void virtio_pci_start_ioeventfd(VirtIOPCIProxy *proxy)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
|
for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
|
||||||
if (!virtio_queue_get_num(vdev, n)) {
|
if (!virtio_queue_get_num(vdev, n)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -207,7 +207,7 @@ static void virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
|
for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
|
||||||
if (!virtio_queue_get_num(vdev, n)) {
|
if (!virtio_queue_get_num(vdev, n)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -243,11 +243,11 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
|
||||||
virtio_queue_set_addr(vdev, vdev->queue_sel, pa);
|
virtio_queue_set_addr(vdev, vdev->queue_sel, pa);
|
||||||
break;
|
break;
|
||||||
case VIRTIO_PCI_QUEUE_SEL:
|
case VIRTIO_PCI_QUEUE_SEL:
|
||||||
if (val < VIRTIO_PCI_QUEUE_MAX)
|
if (val < VIRTIO_QUEUE_MAX)
|
||||||
vdev->queue_sel = val;
|
vdev->queue_sel = val;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_PCI_QUEUE_NOTIFY:
|
case VIRTIO_PCI_QUEUE_NOTIFY:
|
||||||
if (val < VIRTIO_PCI_QUEUE_MAX) {
|
if (val < VIRTIO_QUEUE_MAX) {
|
||||||
virtio_queue_notify(vdev, val);
|
virtio_queue_notify(vdev, val);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -306,7 +306,7 @@ static uint32_t virtio_ioport_read(VirtIOPCIProxy *proxy, uint32_t addr)
|
||||||
|
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
case VIRTIO_PCI_HOST_FEATURES:
|
case VIRTIO_PCI_HOST_FEATURES:
|
||||||
ret = proxy->host_features;
|
ret = vdev->host_features;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_PCI_GUEST_FEATURES:
|
case VIRTIO_PCI_GUEST_FEATURES:
|
||||||
ret = vdev->guest_features;
|
ret = vdev->guest_features;
|
||||||
|
@ -434,12 +434,6 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned virtio_pci_get_features(DeviceState *d)
|
|
||||||
{
|
|
||||||
VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
|
|
||||||
return proxy->host_features;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int kvm_virtio_pci_vq_vector_use(VirtIOPCIProxy *proxy,
|
static int kvm_virtio_pci_vq_vector_use(VirtIOPCIProxy *proxy,
|
||||||
unsigned int queue_no,
|
unsigned int queue_no,
|
||||||
unsigned int vector,
|
unsigned int vector,
|
||||||
|
@ -750,7 +744,7 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign)
|
||||||
bool with_irqfd = msix_enabled(&proxy->pci_dev) &&
|
bool with_irqfd = msix_enabled(&proxy->pci_dev) &&
|
||||||
kvm_msi_via_irqfd_enabled();
|
kvm_msi_via_irqfd_enabled();
|
||||||
|
|
||||||
nvqs = MIN(nvqs, VIRTIO_PCI_QUEUE_MAX);
|
nvqs = MIN(nvqs, VIRTIO_QUEUE_MAX);
|
||||||
|
|
||||||
/* When deassigning, pass a consistent nvqs value
|
/* When deassigning, pass a consistent nvqs value
|
||||||
* to avoid leaking notifiers.
|
* to avoid leaking notifiers.
|
||||||
|
@ -918,12 +912,13 @@ static int virtio_pci_query_nvectors(DeviceState *d)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is called by virtio-bus just after the device is plugged. */
|
/* This is called by virtio-bus just after the device is plugged. */
|
||||||
static void virtio_pci_device_plugged(DeviceState *d)
|
static void virtio_pci_device_plugged(DeviceState *d, Error **errp)
|
||||||
{
|
{
|
||||||
VirtIOPCIProxy *proxy = VIRTIO_PCI(d);
|
VirtIOPCIProxy *proxy = VIRTIO_PCI(d);
|
||||||
VirtioBusState *bus = &proxy->bus;
|
VirtioBusState *bus = &proxy->bus;
|
||||||
uint8_t *config;
|
uint8_t *config;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
|
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
|
||||||
|
|
||||||
config = proxy->pci_dev.config;
|
config = proxy->pci_dev.config;
|
||||||
if (proxy->class_code) {
|
if (proxy->class_code) {
|
||||||
|
@ -958,10 +953,7 @@ static void virtio_pci_device_plugged(DeviceState *d)
|
||||||
proxy->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD;
|
proxy->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtio_add_feature(&proxy->host_features, VIRTIO_F_NOTIFY_ON_EMPTY);
|
virtio_add_feature(&vdev->host_features, VIRTIO_F_BAD_FEATURE);
|
||||||
virtio_add_feature(&proxy->host_features, VIRTIO_F_BAD_FEATURE);
|
|
||||||
proxy->host_features = virtio_bus_get_vdev_features(bus,
|
|
||||||
proxy->host_features);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void virtio_pci_device_unplugged(DeviceState *d)
|
static void virtio_pci_device_unplugged(DeviceState *d)
|
||||||
|
@ -999,7 +991,6 @@ static void virtio_pci_reset(DeviceState *qdev)
|
||||||
static Property virtio_pci_properties[] = {
|
static Property virtio_pci_properties[] = {
|
||||||
DEFINE_PROP_BIT("virtio-pci-bus-master-bug-migration", VirtIOPCIProxy, flags,
|
DEFINE_PROP_BIT("virtio-pci-bus-master-bug-migration", VirtIOPCIProxy, flags,
|
||||||
VIRTIO_PCI_FLAG_BUS_MASTER_BUG_MIGRATION_BIT, false),
|
VIRTIO_PCI_FLAG_BUS_MASTER_BUG_MIGRATION_BIT, false),
|
||||||
DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
|
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1207,32 +1198,6 @@ static const TypeInfo vhost_scsi_pci_info = {
|
||||||
|
|
||||||
/* virtio-balloon-pci */
|
/* virtio-balloon-pci */
|
||||||
|
|
||||||
static void balloon_pci_stats_get_all(Object *obj, struct Visitor *v,
|
|
||||||
void *opaque, const char *name,
|
|
||||||
Error **errp)
|
|
||||||
{
|
|
||||||
VirtIOBalloonPCI *dev = opaque;
|
|
||||||
object_property_get(OBJECT(&dev->vdev), v, "guest-stats", errp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void balloon_pci_stats_get_poll_interval(Object *obj, struct Visitor *v,
|
|
||||||
void *opaque, const char *name,
|
|
||||||
Error **errp)
|
|
||||||
{
|
|
||||||
VirtIOBalloonPCI *dev = opaque;
|
|
||||||
object_property_get(OBJECT(&dev->vdev), v, "guest-stats-polling-interval",
|
|
||||||
errp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void balloon_pci_stats_set_poll_interval(Object *obj, struct Visitor *v,
|
|
||||||
void *opaque, const char *name,
|
|
||||||
Error **errp)
|
|
||||||
{
|
|
||||||
VirtIOBalloonPCI *dev = opaque;
|
|
||||||
object_property_set(OBJECT(&dev->vdev), v, "guest-stats-polling-interval",
|
|
||||||
errp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Property virtio_balloon_pci_properties[] = {
|
static Property virtio_balloon_pci_properties[] = {
|
||||||
DEFINE_PROP_UINT32("class", VirtIOPCIProxy, class_code, 0),
|
DEFINE_PROP_UINT32("class", VirtIOPCIProxy, class_code, 0),
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
|
@ -1269,16 +1234,14 @@ static void virtio_balloon_pci_class_init(ObjectClass *klass, void *data)
|
||||||
static void virtio_balloon_pci_instance_init(Object *obj)
|
static void virtio_balloon_pci_instance_init(Object *obj)
|
||||||
{
|
{
|
||||||
VirtIOBalloonPCI *dev = VIRTIO_BALLOON_PCI(obj);
|
VirtIOBalloonPCI *dev = VIRTIO_BALLOON_PCI(obj);
|
||||||
|
|
||||||
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
|
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
|
||||||
TYPE_VIRTIO_BALLOON);
|
TYPE_VIRTIO_BALLOON);
|
||||||
object_property_add(obj, "guest-stats", "guest statistics",
|
object_property_add_alias(obj, "guest-stats", OBJECT(&dev->vdev),
|
||||||
balloon_pci_stats_get_all, NULL, NULL, dev,
|
"guest-stats", &error_abort);
|
||||||
NULL);
|
object_property_add_alias(obj, "guest-stats-polling-interval",
|
||||||
|
OBJECT(&dev->vdev),
|
||||||
object_property_add(obj, "guest-stats-polling-interval", "int",
|
"guest-stats-polling-interval", &error_abort);
|
||||||
balloon_pci_stats_get_poll_interval,
|
|
||||||
balloon_pci_stats_set_poll_interval,
|
|
||||||
NULL, dev, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo virtio_balloon_pci_info = {
|
static const TypeInfo virtio_balloon_pci_info = {
|
||||||
|
@ -1497,7 +1460,6 @@ static void virtio_pci_bus_class_init(ObjectClass *klass, void *data)
|
||||||
k->load_config = virtio_pci_load_config;
|
k->load_config = virtio_pci_load_config;
|
||||||
k->save_queue = virtio_pci_save_queue;
|
k->save_queue = virtio_pci_save_queue;
|
||||||
k->load_queue = virtio_pci_load_queue;
|
k->load_queue = virtio_pci_load_queue;
|
||||||
k->get_features = virtio_pci_get_features;
|
|
||||||
k->query_guest_notifiers = virtio_pci_query_guest_notifiers;
|
k->query_guest_notifiers = virtio_pci_query_guest_notifiers;
|
||||||
k->set_host_notifier = virtio_pci_set_host_notifier;
|
k->set_host_notifier = virtio_pci_set_host_notifier;
|
||||||
k->set_guest_notifiers = virtio_pci_set_guest_notifiers;
|
k->set_guest_notifiers = virtio_pci_set_guest_notifiers;
|
||||||
|
|
|
@ -91,7 +91,6 @@ struct VirtIOPCIProxy {
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
uint32_t class_code;
|
uint32_t class_code;
|
||||||
uint32_t nvectors;
|
uint32_t nvectors;
|
||||||
uint32_t host_features;
|
|
||||||
bool ioeventfd_disabled;
|
bool ioeventfd_disabled;
|
||||||
bool ioeventfd_started;
|
bool ioeventfd_started;
|
||||||
VirtIOIRQFD *vector_irqfd;
|
VirtIOIRQFD *vector_irqfd;
|
||||||
|
|
|
@ -99,7 +99,7 @@ static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
|
||||||
virtio_rng_process(vrng);
|
virtio_rng_process(vrng);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t get_features(VirtIODevice *vdev, uint32_t f)
|
static uint64_t get_features(VirtIODevice *vdev, uint64_t f)
|
||||||
{
|
{
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
|
@ -600,7 +600,7 @@ void virtio_reset(void *opaque)
|
||||||
vdev->config_vector = VIRTIO_NO_VECTOR;
|
vdev->config_vector = VIRTIO_NO_VECTOR;
|
||||||
virtio_notify_vector(vdev, vdev->config_vector);
|
virtio_notify_vector(vdev, vdev->config_vector);
|
||||||
|
|
||||||
for(i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
|
for(i = 0; i < VIRTIO_QUEUE_MAX; i++) {
|
||||||
vdev->vq[i].vring.desc = 0;
|
vdev->vq[i].vring.desc = 0;
|
||||||
vdev->vq[i].vring.avail = 0;
|
vdev->vq[i].vring.avail = 0;
|
||||||
vdev->vq[i].vring.used = 0;
|
vdev->vq[i].vring.used = 0;
|
||||||
|
@ -746,10 +746,23 @@ int virtio_queue_get_num(VirtIODevice *vdev, int n)
|
||||||
return vdev->vq[n].vring.num;
|
return vdev->vq[n].vring.num;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int virtio_get_num_queues(VirtIODevice *vdev)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
|
||||||
|
if (!virtio_queue_get_num(vdev, i)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
int virtio_queue_get_id(VirtQueue *vq)
|
int virtio_queue_get_id(VirtQueue *vq)
|
||||||
{
|
{
|
||||||
VirtIODevice *vdev = vq->vdev;
|
VirtIODevice *vdev = vq->vdev;
|
||||||
assert(vq >= &vdev->vq[0] && vq < &vdev->vq[VIRTIO_PCI_QUEUE_MAX]);
|
assert(vq >= &vdev->vq[0] && vq < &vdev->vq[VIRTIO_QUEUE_MAX]);
|
||||||
return vq - &vdev->vq[0];
|
return vq - &vdev->vq[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -785,7 +798,7 @@ void virtio_queue_notify(VirtIODevice *vdev, int n)
|
||||||
|
|
||||||
uint16_t virtio_queue_vector(VirtIODevice *vdev, int n)
|
uint16_t virtio_queue_vector(VirtIODevice *vdev, int n)
|
||||||
{
|
{
|
||||||
return n < VIRTIO_PCI_QUEUE_MAX ? vdev->vq[n].vector :
|
return n < VIRTIO_QUEUE_MAX ? vdev->vq[n].vector :
|
||||||
VIRTIO_NO_VECTOR;
|
VIRTIO_NO_VECTOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -793,7 +806,7 @@ void virtio_queue_set_vector(VirtIODevice *vdev, int n, uint16_t vector)
|
||||||
{
|
{
|
||||||
VirtQueue *vq = &vdev->vq[n];
|
VirtQueue *vq = &vdev->vq[n];
|
||||||
|
|
||||||
if (n < VIRTIO_PCI_QUEUE_MAX) {
|
if (n < VIRTIO_QUEUE_MAX) {
|
||||||
if (vdev->vector_queues &&
|
if (vdev->vector_queues &&
|
||||||
vdev->vq[n].vector != VIRTIO_NO_VECTOR) {
|
vdev->vq[n].vector != VIRTIO_NO_VECTOR) {
|
||||||
QLIST_REMOVE(vq, node);
|
QLIST_REMOVE(vq, node);
|
||||||
|
@ -811,12 +824,12 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
|
for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
|
||||||
if (vdev->vq[i].vring.num == 0)
|
if (vdev->vq[i].vring.num == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == VIRTIO_PCI_QUEUE_MAX || queue_size > VIRTQUEUE_MAX_SIZE)
|
if (i == VIRTIO_QUEUE_MAX || queue_size > VIRTQUEUE_MAX_SIZE)
|
||||||
abort();
|
abort();
|
||||||
|
|
||||||
vdev->vq[i].vring.num = queue_size;
|
vdev->vq[i].vring.num = queue_size;
|
||||||
|
@ -828,7 +841,7 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
|
||||||
|
|
||||||
void virtio_del_queue(VirtIODevice *vdev, int n)
|
void virtio_del_queue(VirtIODevice *vdev, int n)
|
||||||
{
|
{
|
||||||
if (n < 0 || n >= VIRTIO_PCI_QUEUE_MAX) {
|
if (n < 0 || n >= VIRTIO_QUEUE_MAX) {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -893,6 +906,13 @@ static bool virtio_device_endian_needed(void *opaque)
|
||||||
return vdev->device_endian != virtio_default_endian();
|
return vdev->device_endian != virtio_default_endian();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool virtio_64bit_features_needed(void *opaque)
|
||||||
|
{
|
||||||
|
VirtIODevice *vdev = opaque;
|
||||||
|
|
||||||
|
return (vdev->host_features >> 32) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const VMStateDescription vmstate_virtio_device_endian = {
|
static const VMStateDescription vmstate_virtio_device_endian = {
|
||||||
.name = "virtio/device_endian",
|
.name = "virtio/device_endian",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
|
@ -903,6 +923,16 @@ static const VMStateDescription vmstate_virtio_device_endian = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const VMStateDescription vmstate_virtio_64bit_features = {
|
||||||
|
.name = "virtio/64bit_features",
|
||||||
|
.version_id = 1,
|
||||||
|
.minimum_version_id = 1,
|
||||||
|
.fields = (VMStateField[]) {
|
||||||
|
VMSTATE_UINT64(guest_features, VirtIODevice),
|
||||||
|
VMSTATE_END_OF_LIST()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static const VMStateDescription vmstate_virtio = {
|
static const VMStateDescription vmstate_virtio = {
|
||||||
.name = "virtio",
|
.name = "virtio",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
|
@ -916,6 +946,10 @@ static const VMStateDescription vmstate_virtio = {
|
||||||
.vmsd = &vmstate_virtio_device_endian,
|
.vmsd = &vmstate_virtio_device_endian,
|
||||||
.needed = &virtio_device_endian_needed
|
.needed = &virtio_device_endian_needed
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.vmsd = &vmstate_virtio_64bit_features,
|
||||||
|
.needed = &virtio_64bit_features_needed
|
||||||
|
},
|
||||||
{ 0 }
|
{ 0 }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -925,6 +959,7 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f)
|
||||||
BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
|
BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
|
||||||
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
|
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
|
||||||
VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
|
VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
|
||||||
|
uint32_t guest_features_lo = (vdev->guest_features & 0xffffffff);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (k->save_config) {
|
if (k->save_config) {
|
||||||
|
@ -934,18 +969,18 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f)
|
||||||
qemu_put_8s(f, &vdev->status);
|
qemu_put_8s(f, &vdev->status);
|
||||||
qemu_put_8s(f, &vdev->isr);
|
qemu_put_8s(f, &vdev->isr);
|
||||||
qemu_put_be16s(f, &vdev->queue_sel);
|
qemu_put_be16s(f, &vdev->queue_sel);
|
||||||
qemu_put_be32s(f, &vdev->guest_features);
|
qemu_put_be32s(f, &guest_features_lo);
|
||||||
qemu_put_be32(f, vdev->config_len);
|
qemu_put_be32(f, vdev->config_len);
|
||||||
qemu_put_buffer(f, vdev->config, vdev->config_len);
|
qemu_put_buffer(f, vdev->config, vdev->config_len);
|
||||||
|
|
||||||
for (i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
|
for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
|
||||||
if (vdev->vq[i].vring.num == 0)
|
if (vdev->vq[i].vring.num == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_put_be32(f, i);
|
qemu_put_be32(f, i);
|
||||||
|
|
||||||
for (i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
|
for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
|
||||||
if (vdev->vq[i].vring.num == 0)
|
if (vdev->vq[i].vring.num == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -970,13 +1005,10 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f)
|
||||||
|
|
||||||
int virtio_set_features(VirtIODevice *vdev, uint32_t val)
|
int virtio_set_features(VirtIODevice *vdev, uint32_t val)
|
||||||
{
|
{
|
||||||
BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
|
|
||||||
VirtioBusClass *vbusk = VIRTIO_BUS_GET_CLASS(qbus);
|
|
||||||
VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
|
VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
|
||||||
uint32_t supported_features = vbusk->get_features(qbus->parent);
|
bool bad = (val & ~(vdev->host_features)) != 0;
|
||||||
bool bad = (val & ~supported_features) != 0;
|
|
||||||
|
|
||||||
val &= supported_features;
|
val &= vdev->host_features;
|
||||||
if (k->set_features) {
|
if (k->set_features) {
|
||||||
k->set_features(vdev, val);
|
k->set_features(vdev, val);
|
||||||
}
|
}
|
||||||
|
@ -990,7 +1022,6 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
|
||||||
int32_t config_len;
|
int32_t config_len;
|
||||||
uint32_t num;
|
uint32_t num;
|
||||||
uint32_t features;
|
uint32_t features;
|
||||||
uint32_t supported_features;
|
|
||||||
BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
|
BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
|
||||||
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
|
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
|
||||||
VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
|
VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
|
||||||
|
@ -1010,17 +1041,11 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
|
||||||
qemu_get_8s(f, &vdev->status);
|
qemu_get_8s(f, &vdev->status);
|
||||||
qemu_get_8s(f, &vdev->isr);
|
qemu_get_8s(f, &vdev->isr);
|
||||||
qemu_get_be16s(f, &vdev->queue_sel);
|
qemu_get_be16s(f, &vdev->queue_sel);
|
||||||
if (vdev->queue_sel >= VIRTIO_PCI_QUEUE_MAX) {
|
if (vdev->queue_sel >= VIRTIO_QUEUE_MAX) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
qemu_get_be32s(f, &features);
|
qemu_get_be32s(f, &features);
|
||||||
|
|
||||||
if (virtio_set_features(vdev, features) < 0) {
|
|
||||||
supported_features = k->get_features(qbus->parent);
|
|
||||||
error_report("Features 0x%x unsupported. Allowed features: 0x%x",
|
|
||||||
features, supported_features);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
config_len = qemu_get_be32(f);
|
config_len = qemu_get_be32(f);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1037,7 +1062,7 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
|
||||||
|
|
||||||
num = qemu_get_be32(f);
|
num = qemu_get_be32(f);
|
||||||
|
|
||||||
if (num > VIRTIO_PCI_QUEUE_MAX) {
|
if (num > VIRTIO_QUEUE_MAX) {
|
||||||
error_report("Invalid number of PCI queues: 0x%x", num);
|
error_report("Invalid number of PCI queues: 0x%x", num);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1086,6 +1111,28 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
|
||||||
vdev->device_endian = virtio_default_endian();
|
vdev->device_endian = virtio_default_endian();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (virtio_64bit_features_needed(vdev)) {
|
||||||
|
/*
|
||||||
|
* Subsection load filled vdev->guest_features. Run them
|
||||||
|
* through virtio_set_features to sanity-check them against
|
||||||
|
* host_features.
|
||||||
|
*/
|
||||||
|
uint64_t features64 = vdev->guest_features;
|
||||||
|
if (virtio_set_features(vdev, features64) < 0) {
|
||||||
|
error_report("Features 0x%" PRIx64 " unsupported. "
|
||||||
|
"Allowed features: 0x%" PRIx64,
|
||||||
|
features64, vdev->host_features);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (virtio_set_features(vdev, features) < 0) {
|
||||||
|
error_report("Features 0x%x unsupported. "
|
||||||
|
"Allowed features: 0x%" PRIx64,
|
||||||
|
features, vdev->host_features);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < num; i++) {
|
for (i = 0; i < num; i++) {
|
||||||
if (vdev->vq[i].pa) {
|
if (vdev->vq[i].pa) {
|
||||||
uint16_t nheads;
|
uint16_t nheads;
|
||||||
|
@ -1163,9 +1210,9 @@ void virtio_init(VirtIODevice *vdev, const char *name,
|
||||||
vdev->isr = 0;
|
vdev->isr = 0;
|
||||||
vdev->queue_sel = 0;
|
vdev->queue_sel = 0;
|
||||||
vdev->config_vector = VIRTIO_NO_VECTOR;
|
vdev->config_vector = VIRTIO_NO_VECTOR;
|
||||||
vdev->vq = g_malloc0(sizeof(VirtQueue) * VIRTIO_PCI_QUEUE_MAX);
|
vdev->vq = g_malloc0(sizeof(VirtQueue) * VIRTIO_QUEUE_MAX);
|
||||||
vdev->vm_running = runstate_is_running();
|
vdev->vm_running = runstate_is_running();
|
||||||
for (i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
|
for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
|
||||||
vdev->vq[i].vector = VIRTIO_NO_VECTOR;
|
vdev->vq[i].vector = VIRTIO_NO_VECTOR;
|
||||||
vdev->vq[i].vdev = vdev;
|
vdev->vq[i].vdev = vdev;
|
||||||
vdev->vq[i].queue_index = i;
|
vdev->vq[i].queue_index = i;
|
||||||
|
@ -1328,7 +1375,12 @@ static void virtio_device_realize(DeviceState *dev, Error **errp)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtio_bus_device_plugged(vdev);
|
|
||||||
|
virtio_bus_device_plugged(vdev, &err);
|
||||||
|
if (err != NULL) {
|
||||||
|
error_propagate(errp, err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void virtio_device_unrealize(DeviceState *dev, Error **errp)
|
static void virtio_device_unrealize(DeviceState *dev, Error **errp)
|
||||||
|
@ -1351,6 +1403,11 @@ static void virtio_device_unrealize(DeviceState *dev, Error **errp)
|
||||||
vdev->bus_name = NULL;
|
vdev->bus_name = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Property virtio_properties[] = {
|
||||||
|
DEFINE_VIRTIO_COMMON_FEATURES(VirtIODevice, host_features),
|
||||||
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
|
};
|
||||||
|
|
||||||
static void virtio_device_class_init(ObjectClass *klass, void *data)
|
static void virtio_device_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
/* Set the default value here. */
|
/* Set the default value here. */
|
||||||
|
@ -1359,6 +1416,7 @@ static void virtio_device_class_init(ObjectClass *klass, void *data)
|
||||||
dc->realize = virtio_device_realize;
|
dc->realize = virtio_device_realize;
|
||||||
dc->unrealize = virtio_device_unrealize;
|
dc->unrealize = virtio_device_unrealize;
|
||||||
dc->bus_type = TYPE_VIRTIO_BUS;
|
dc->bus_type = TYPE_VIRTIO_BUS;
|
||||||
|
dc->props = virtio_properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo virtio_device_info = {
|
static const TypeInfo virtio_device_info = {
|
||||||
|
|
|
@ -33,6 +33,8 @@ typedef struct MemTxAttrs {
|
||||||
unsigned int secure:1;
|
unsigned int secure:1;
|
||||||
/* Memory access is usermode (unprivileged) */
|
/* Memory access is usermode (unprivileged) */
|
||||||
unsigned int user:1;
|
unsigned int user:1;
|
||||||
|
/* Stream ID (for MSI for example) */
|
||||||
|
unsigned int stream_id:16;
|
||||||
} MemTxAttrs;
|
} MemTxAttrs;
|
||||||
|
|
||||||
/* Bus masters which don't specify any attributes will get this,
|
/* Bus masters which don't specify any attributes will get this,
|
||||||
|
|
|
@ -450,6 +450,9 @@ typedef struct AcpiTableMcfg AcpiTableMcfg;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TCPA Description Table
|
* TCPA Description Table
|
||||||
|
*
|
||||||
|
* Following Level 00, Rev 00.37 of specs:
|
||||||
|
* http://www.trustedcomputinggroup.org/resources/tcg_acpi_specification
|
||||||
*/
|
*/
|
||||||
struct Acpi20Tcpa {
|
struct Acpi20Tcpa {
|
||||||
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
|
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
|
||||||
|
@ -459,6 +462,21 @@ struct Acpi20Tcpa {
|
||||||
} QEMU_PACKED;
|
} QEMU_PACKED;
|
||||||
typedef struct Acpi20Tcpa Acpi20Tcpa;
|
typedef struct Acpi20Tcpa Acpi20Tcpa;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TPM2
|
||||||
|
*
|
||||||
|
* Following Level 00, Rev 00.37 of specs:
|
||||||
|
* http://www.trustedcomputinggroup.org/resources/tcg_acpi_specification
|
||||||
|
*/
|
||||||
|
struct Acpi20TPM2 {
|
||||||
|
ACPI_TABLE_HEADER_DEF
|
||||||
|
uint16_t platform_class;
|
||||||
|
uint16_t reserved;
|
||||||
|
uint64_t control_area_address;
|
||||||
|
uint32_t start_method;
|
||||||
|
} QEMU_PACKED;
|
||||||
|
typedef struct Acpi20TPM2 Acpi20TPM2;
|
||||||
|
|
||||||
/* DMAR - DMA Remapping table r2.2 */
|
/* DMAR - DMA Remapping table r2.2 */
|
||||||
struct AcpiTableDmar {
|
struct AcpiTableDmar {
|
||||||
ACPI_TABLE_HEADER_DEF
|
ACPI_TABLE_HEADER_DEF
|
||||||
|
|
|
@ -202,6 +202,12 @@ Aml *aml_arg(int pos);
|
||||||
Aml *aml_store(Aml *val, Aml *target);
|
Aml *aml_store(Aml *val, Aml *target);
|
||||||
Aml *aml_and(Aml *arg1, Aml *arg2);
|
Aml *aml_and(Aml *arg1, Aml *arg2);
|
||||||
Aml *aml_or(Aml *arg1, Aml *arg2);
|
Aml *aml_or(Aml *arg1, Aml *arg2);
|
||||||
|
Aml *aml_shiftleft(Aml *arg1, Aml *count);
|
||||||
|
Aml *aml_shiftright(Aml *arg1, Aml *count);
|
||||||
|
Aml *aml_lless(Aml *arg1, Aml *arg2);
|
||||||
|
Aml *aml_add(Aml *arg1, Aml *arg2);
|
||||||
|
Aml *aml_increment(Aml *arg);
|
||||||
|
Aml *aml_index(Aml *arg1, Aml *idx);
|
||||||
Aml *aml_notify(Aml *arg1, Aml *arg2);
|
Aml *aml_notify(Aml *arg1, Aml *arg2);
|
||||||
Aml *aml_call1(const char *method, Aml *arg1);
|
Aml *aml_call1(const char *method, Aml *arg1);
|
||||||
Aml *aml_call2(const char *method, Aml *arg1, Aml *arg2);
|
Aml *aml_call2(const char *method, Aml *arg1, Aml *arg2);
|
||||||
|
@ -260,6 +266,7 @@ Aml *aml_device(const char *name_format, ...) GCC_FMT_ATTR(1, 2);
|
||||||
Aml *aml_method(const char *name, int arg_count);
|
Aml *aml_method(const char *name, int arg_count);
|
||||||
Aml *aml_if(Aml *predicate);
|
Aml *aml_if(Aml *predicate);
|
||||||
Aml *aml_else(void);
|
Aml *aml_else(void);
|
||||||
|
Aml *aml_while(Aml *predicate);
|
||||||
Aml *aml_package(uint8_t num_elements);
|
Aml *aml_package(uint8_t num_elements);
|
||||||
Aml *aml_buffer(int buffer_size, uint8_t *byte_list);
|
Aml *aml_buffer(int buffer_size, uint8_t *byte_list);
|
||||||
Aml *aml_resource_template(void);
|
Aml *aml_resource_template(void);
|
||||||
|
|
|
@ -26,4 +26,9 @@
|
||||||
#define TPM_TCPA_ACPI_CLASS_CLIENT 0
|
#define TPM_TCPA_ACPI_CLASS_CLIENT 0
|
||||||
#define TPM_TCPA_ACPI_CLASS_SERVER 1
|
#define TPM_TCPA_ACPI_CLASS_SERVER 1
|
||||||
|
|
||||||
|
#define TPM2_ACPI_CLASS_CLIENT 0
|
||||||
|
#define TPM2_ACPI_CLASS_SERVER 1
|
||||||
|
|
||||||
|
#define TPM2_START_METHOD_MMIO 6
|
||||||
|
|
||||||
#endif /* HW_ACPI_TPM_H */
|
#endif /* HW_ACPI_TPM_H */
|
||||||
|
|
|
@ -19,31 +19,18 @@ typedef void QEMUMachineHotAddCPUFunc(const int64_t id, Error **errp);
|
||||||
typedef int QEMUMachineGetKvmtypeFunc(const char *arg);
|
typedef int QEMUMachineGetKvmtypeFunc(const char *arg);
|
||||||
|
|
||||||
struct QEMUMachine {
|
struct QEMUMachine {
|
||||||
const char *family; /* NULL iff @name identifies a standalone machtype */
|
|
||||||
const char *name;
|
const char *name;
|
||||||
const char *alias;
|
|
||||||
const char *desc;
|
const char *desc;
|
||||||
QEMUMachineInitFunc *init;
|
QEMUMachineInitFunc *init;
|
||||||
QEMUMachineResetFunc *reset;
|
|
||||||
QEMUMachineHotAddCPUFunc *hot_add_cpu;
|
|
||||||
QEMUMachineGetKvmtypeFunc *kvm_type;
|
QEMUMachineGetKvmtypeFunc *kvm_type;
|
||||||
BlockInterfaceType block_default_type;
|
BlockInterfaceType block_default_type;
|
||||||
int units_per_default_bus;
|
|
||||||
int max_cpus;
|
int max_cpus;
|
||||||
unsigned int no_serial:1,
|
unsigned int
|
||||||
no_parallel:1,
|
|
||||||
use_virtcon:1,
|
|
||||||
use_sclp:1,
|
|
||||||
no_floppy:1,
|
|
||||||
no_cdrom:1,
|
|
||||||
no_sdcard:1,
|
no_sdcard:1,
|
||||||
has_dynamic_sysbus:1;
|
has_dynamic_sysbus:1;
|
||||||
int is_default;
|
int is_default;
|
||||||
const char *default_machine_opts;
|
const char *default_machine_opts;
|
||||||
const char *default_boot_order;
|
const char *default_boot_order;
|
||||||
const char *default_display;
|
|
||||||
GlobalProperty *compat_props;
|
|
||||||
const char *hw_version;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void memory_region_allocate_system_memory(MemoryRegion *mr, Object *owner,
|
void memory_region_allocate_system_memory(MemoryRegion *mr, Object *owner,
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
#ifndef HW_COMPAT_H
|
#ifndef HW_COMPAT_H
|
||||||
#define HW_COMPAT_H
|
#define HW_COMPAT_H
|
||||||
|
|
||||||
|
#define HW_COMPAT_2_3 \
|
||||||
|
/* empty */
|
||||||
|
|
||||||
|
#define HW_COMPAT_2_2 \
|
||||||
|
/* empty */
|
||||||
|
|
||||||
#define HW_COMPAT_2_1 \
|
#define HW_COMPAT_2_1 \
|
||||||
{\
|
{\
|
||||||
.driver = "intel-hda",\
|
.driver = "intel-hda",\
|
||||||
|
@ -30,6 +36,6 @@
|
||||||
.driver = "virtio-pci",\
|
.driver = "virtio-pci",\
|
||||||
.property = "virtio-pci-bus-master-bug-migration",\
|
.property = "virtio-pci-bus-master-bug-migration",\
|
||||||
.value = "on",\
|
.value = "on",\
|
||||||
}
|
},
|
||||||
|
|
||||||
#endif /* HW_COMPAT_H */
|
#endif /* HW_COMPAT_H */
|
||||||
|
|
|
@ -73,8 +73,6 @@ typedef struct PCMachineClass PCMachineClass;
|
||||||
#define PC_MACHINE_CLASS(klass) \
|
#define PC_MACHINE_CLASS(klass) \
|
||||||
OBJECT_CLASS_CHECK(PCMachineClass, (klass), TYPE_PC_MACHINE)
|
OBJECT_CLASS_CHECK(PCMachineClass, (klass), TYPE_PC_MACHINE)
|
||||||
|
|
||||||
void qemu_register_pc_machine(QEMUMachine *m);
|
|
||||||
|
|
||||||
/* PC-style peripherals (also used by other machines). */
|
/* PC-style peripherals (also used by other machines). */
|
||||||
|
|
||||||
typedef struct PcPciInfo {
|
typedef struct PcPciInfo {
|
||||||
|
@ -199,6 +197,7 @@ qemu_irq *pc_allocate_cpu_irq(void);
|
||||||
DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus);
|
DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus);
|
||||||
void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
|
void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
|
||||||
ISADevice **rtc_state,
|
ISADevice **rtc_state,
|
||||||
|
bool create_fdctrl,
|
||||||
ISADevice **floppy,
|
ISADevice **floppy,
|
||||||
bool no_vmport,
|
bool no_vmport,
|
||||||
uint32 hpet_irqs);
|
uint32 hpet_irqs);
|
||||||
|
@ -295,8 +294,19 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t);
|
||||||
int e820_get_num_entries(void);
|
int e820_get_num_entries(void);
|
||||||
bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
|
bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
|
||||||
|
|
||||||
|
#define PC_COMPAT_2_3 \
|
||||||
|
HW_COMPAT_2_3
|
||||||
|
|
||||||
|
#define PC_COMPAT_2_2 \
|
||||||
|
PC_COMPAT_2_3 \
|
||||||
|
HW_COMPAT_2_2
|
||||||
|
|
||||||
|
#define PC_COMPAT_2_1 \
|
||||||
|
PC_COMPAT_2_2 \
|
||||||
|
HW_COMPAT_2_1
|
||||||
|
|
||||||
#define PC_COMPAT_2_0 \
|
#define PC_COMPAT_2_0 \
|
||||||
HW_COMPAT_2_1, \
|
PC_COMPAT_2_1 \
|
||||||
{\
|
{\
|
||||||
.driver = "virtio-scsi-pci",\
|
.driver = "virtio-scsi-pci",\
|
||||||
.property = "any_layout",\
|
.property = "any_layout",\
|
||||||
|
@ -353,10 +363,10 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
|
||||||
.driver = "ioh3420",\
|
.driver = "ioh3420",\
|
||||||
.property = COMPAT_PROP_PCP,\
|
.property = COMPAT_PROP_PCP,\
|
||||||
.value = "off",\
|
.value = "off",\
|
||||||
}
|
},
|
||||||
|
|
||||||
#define PC_COMPAT_1_7 \
|
#define PC_COMPAT_1_7 \
|
||||||
PC_COMPAT_2_0, \
|
PC_COMPAT_2_0 \
|
||||||
{\
|
{\
|
||||||
.driver = TYPE_USB_DEVICE,\
|
.driver = TYPE_USB_DEVICE,\
|
||||||
.property = "msos-desc",\
|
.property = "msos-desc",\
|
||||||
|
@ -371,10 +381,10 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
|
||||||
.driver = "hpet",\
|
.driver = "hpet",\
|
||||||
.property = HPET_INTCAP,\
|
.property = HPET_INTCAP,\
|
||||||
.value = stringify(4),\
|
.value = stringify(4),\
|
||||||
}
|
},
|
||||||
|
|
||||||
#define PC_COMPAT_1_6 \
|
#define PC_COMPAT_1_6 \
|
||||||
PC_COMPAT_1_7, \
|
PC_COMPAT_1_7 \
|
||||||
{\
|
{\
|
||||||
.driver = "e1000",\
|
.driver = "e1000",\
|
||||||
.property = "mitigation",\
|
.property = "mitigation",\
|
||||||
|
@ -395,10 +405,10 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
|
||||||
.driver = "q35-pcihost",\
|
.driver = "q35-pcihost",\
|
||||||
.property = "short_root_bus",\
|
.property = "short_root_bus",\
|
||||||
.value = stringify(1),\
|
.value = stringify(1),\
|
||||||
}
|
},
|
||||||
|
|
||||||
#define PC_COMPAT_1_5 \
|
#define PC_COMPAT_1_5 \
|
||||||
PC_COMPAT_1_6, \
|
PC_COMPAT_1_6 \
|
||||||
{\
|
{\
|
||||||
.driver = "Conroe-" TYPE_X86_CPU,\
|
.driver = "Conroe-" TYPE_X86_CPU,\
|
||||||
.property = "model",\
|
.property = "model",\
|
||||||
|
@ -439,31 +449,31 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
|
||||||
.driver = "q35-pcihost",\
|
.driver = "q35-pcihost",\
|
||||||
.property = "short_root_bus",\
|
.property = "short_root_bus",\
|
||||||
.value = stringify(0),\
|
.value = stringify(0),\
|
||||||
}
|
},
|
||||||
|
|
||||||
#define PC_COMPAT_1_4 \
|
#define PC_COMPAT_1_4 \
|
||||||
PC_COMPAT_1_5, \
|
PC_COMPAT_1_5 \
|
||||||
{\
|
{\
|
||||||
.driver = "scsi-hd",\
|
.driver = "scsi-hd",\
|
||||||
.property = "discard_granularity",\
|
.property = "discard_granularity",\
|
||||||
.value = stringify(0),\
|
.value = stringify(0),\
|
||||||
},{\
|
},{\
|
||||||
.driver = "scsi-cd",\
|
.driver = "scsi-cd",\
|
||||||
.property = "discard_granularity",\
|
.property = "discard_granularity",\
|
||||||
.value = stringify(0),\
|
.value = stringify(0),\
|
||||||
},{\
|
},{\
|
||||||
.driver = "scsi-disk",\
|
.driver = "scsi-disk",\
|
||||||
.property = "discard_granularity",\
|
.property = "discard_granularity",\
|
||||||
.value = stringify(0),\
|
.value = stringify(0),\
|
||||||
},{\
|
},{\
|
||||||
.driver = "ide-hd",\
|
.driver = "ide-hd",\
|
||||||
.property = "discard_granularity",\
|
.property = "discard_granularity",\
|
||||||
.value = stringify(0),\
|
.value = stringify(0),\
|
||||||
},{\
|
},{\
|
||||||
.driver = "ide-cd",\
|
.driver = "ide-cd",\
|
||||||
.property = "discard_granularity",\
|
.property = "discard_granularity",\
|
||||||
.value = stringify(0),\
|
.value = stringify(0),\
|
||||||
},{\
|
},{\
|
||||||
.driver = "ide-drive",\
|
.driver = "ide-drive",\
|
||||||
.property = "discard_granularity",\
|
.property = "discard_granularity",\
|
||||||
.value = stringify(0),\
|
.value = stringify(0),\
|
||||||
|
@ -471,7 +481,7 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
|
||||||
.driver = "virtio-blk-pci",\
|
.driver = "virtio-blk-pci",\
|
||||||
.property = "discard_granularity",\
|
.property = "discard_granularity",\
|
||||||
.value = stringify(0),\
|
.value = stringify(0),\
|
||||||
},{\
|
},{\
|
||||||
.driver = "virtio-serial-pci",\
|
.driver = "virtio-serial-pci",\
|
||||||
.property = "vectors",\
|
.property = "vectors",\
|
||||||
/* DEV_NVECTORS_UNSPECIFIED as a uint32_t string */\
|
/* DEV_NVECTORS_UNSPECIFIED as a uint32_t string */\
|
||||||
|
@ -504,14 +514,45 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
|
||||||
.driver = "486-" TYPE_X86_CPU,\
|
.driver = "486-" TYPE_X86_CPU,\
|
||||||
.property = "model",\
|
.property = "model",\
|
||||||
.value = stringify(0),\
|
.value = stringify(0),\
|
||||||
}
|
},
|
||||||
|
|
||||||
#define PC_COMMON_MACHINE_OPTIONS \
|
static inline void pc_common_machine_options(MachineClass *m)
|
||||||
.default_boot_order = "cad"
|
{
|
||||||
|
m->default_boot_order = "cad";
|
||||||
|
}
|
||||||
|
|
||||||
#define PC_DEFAULT_MACHINE_OPTIONS \
|
static inline void pc_default_machine_options(MachineClass *m)
|
||||||
PC_COMMON_MACHINE_OPTIONS, \
|
{
|
||||||
.hot_add_cpu = pc_hot_add_cpu, \
|
pc_common_machine_options(m);
|
||||||
.max_cpus = 255
|
m->hot_add_cpu = pc_hot_add_cpu;
|
||||||
|
m->max_cpus = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEFINE_PC_MACHINE(suffix, namestr, initfn, optsfn) \
|
||||||
|
static void pc_machine_##suffix##_class_init(ObjectClass *oc, void *data) \
|
||||||
|
{ \
|
||||||
|
MachineClass *mc = MACHINE_CLASS(oc); \
|
||||||
|
optsfn(mc); \
|
||||||
|
mc->name = namestr; \
|
||||||
|
mc->init = initfn; \
|
||||||
|
} \
|
||||||
|
static const TypeInfo pc_machine_type_##suffix = { \
|
||||||
|
.name = namestr TYPE_MACHINE_SUFFIX, \
|
||||||
|
.parent = TYPE_PC_MACHINE, \
|
||||||
|
.class_init = pc_machine_##suffix##_class_init, \
|
||||||
|
}; \
|
||||||
|
static void pc_machine_init_##suffix(void) \
|
||||||
|
{ \
|
||||||
|
type_register(&pc_machine_type_##suffix); \
|
||||||
|
} \
|
||||||
|
machine_init(pc_machine_init_##suffix)
|
||||||
|
|
||||||
|
#define SET_MACHINE_COMPAT(m, COMPAT) do { \
|
||||||
|
static GlobalProperty props[] = { \
|
||||||
|
COMPAT \
|
||||||
|
{ /* end of list */ } \
|
||||||
|
}; \
|
||||||
|
(m)->compat_props = props; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -39,6 +39,7 @@ int msi_init(struct PCIDevice *dev, uint8_t offset,
|
||||||
void msi_uninit(struct PCIDevice *dev);
|
void msi_uninit(struct PCIDevice *dev);
|
||||||
void msi_reset(PCIDevice *dev);
|
void msi_reset(PCIDevice *dev);
|
||||||
void msi_notify(PCIDevice *dev, unsigned int vector);
|
void msi_notify(PCIDevice *dev, unsigned int vector);
|
||||||
|
void msi_send_message(PCIDevice *dev, MSIMessage msg);
|
||||||
void msi_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int len);
|
void msi_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int len);
|
||||||
unsigned int msi_nr_vectors_allocated(const PCIDevice *dev);
|
unsigned int msi_nr_vectors_allocated(const PCIDevice *dev);
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
/*** qdev-properties.c ***/
|
/*** qdev-properties.c ***/
|
||||||
|
|
||||||
extern PropertyInfo qdev_prop_bit;
|
extern PropertyInfo qdev_prop_bit;
|
||||||
|
extern PropertyInfo qdev_prop_bit64;
|
||||||
extern PropertyInfo qdev_prop_bool;
|
extern PropertyInfo qdev_prop_bool;
|
||||||
extern PropertyInfo qdev_prop_uint8;
|
extern PropertyInfo qdev_prop_uint8;
|
||||||
extern PropertyInfo qdev_prop_uint16;
|
extern PropertyInfo qdev_prop_uint16;
|
||||||
|
@ -50,6 +51,15 @@ extern PropertyInfo qdev_prop_arraylen;
|
||||||
.qtype = QTYPE_QBOOL, \
|
.qtype = QTYPE_QBOOL, \
|
||||||
.defval = (bool)_defval, \
|
.defval = (bool)_defval, \
|
||||||
}
|
}
|
||||||
|
#define DEFINE_PROP_BIT64(_name, _state, _field, _bit, _defval) { \
|
||||||
|
.name = (_name), \
|
||||||
|
.info = &(qdev_prop_bit), \
|
||||||
|
.bitnr = (_bit), \
|
||||||
|
.offset = offsetof(_state, _field) \
|
||||||
|
+ type_check(uint64_t, typeof_field(_state, _field)), \
|
||||||
|
.qtype = QTYPE_QBOOL, \
|
||||||
|
.defval = (bool)_defval, \
|
||||||
|
}
|
||||||
|
|
||||||
#define DEFINE_PROP_BOOL(_name, _state, _field, _defval) { \
|
#define DEFINE_PROP_BOOL(_name, _state, _field, _defval) { \
|
||||||
.name = (_name), \
|
.name = (_name), \
|
||||||
|
|
|
@ -17,10 +17,13 @@
|
||||||
#include "hw/s390x/adapter.h"
|
#include "hw/s390x/adapter.h"
|
||||||
#include "hw/virtio/virtio.h"
|
#include "hw/virtio/virtio.h"
|
||||||
|
|
||||||
|
#define ADAPTER_ROUTES_MAX_GSI 64
|
||||||
|
#define VIRTIO_CCW_QUEUE_MAX ADAPTER_ROUTES_MAX_GSI
|
||||||
|
|
||||||
typedef struct AdapterRoutes {
|
typedef struct AdapterRoutes {
|
||||||
AdapterInfo adapter;
|
AdapterInfo adapter;
|
||||||
int num_routes;
|
int num_routes;
|
||||||
int gsi[VIRTIO_PCI_QUEUE_MAX];
|
int gsi[ADAPTER_ROUTES_MAX_GSI];
|
||||||
} AdapterRoutes;
|
} AdapterRoutes;
|
||||||
|
|
||||||
#define TYPE_S390_FLIC_COMMON "s390-flic"
|
#define TYPE_S390_FLIC_COMMON "s390-flic"
|
||||||
|
|
|
@ -47,7 +47,6 @@ typedef struct VirtioBusClass {
|
||||||
int (*load_config)(DeviceState *d, QEMUFile *f);
|
int (*load_config)(DeviceState *d, QEMUFile *f);
|
||||||
int (*load_queue)(DeviceState *d, int n, QEMUFile *f);
|
int (*load_queue)(DeviceState *d, int n, QEMUFile *f);
|
||||||
int (*load_done)(DeviceState *d, QEMUFile *f);
|
int (*load_done)(DeviceState *d, QEMUFile *f);
|
||||||
unsigned (*get_features)(DeviceState *d);
|
|
||||||
bool (*query_guest_notifiers)(DeviceState *d);
|
bool (*query_guest_notifiers)(DeviceState *d);
|
||||||
int (*set_guest_notifiers)(DeviceState *d, int nvqs, bool assign);
|
int (*set_guest_notifiers)(DeviceState *d, int nvqs, bool assign);
|
||||||
int (*set_host_notifier)(DeviceState *d, int n, bool assigned);
|
int (*set_host_notifier)(DeviceState *d, int n, bool assigned);
|
||||||
|
@ -56,7 +55,7 @@ typedef struct VirtioBusClass {
|
||||||
* transport independent init function.
|
* transport independent init function.
|
||||||
* This is called by virtio-bus just after the device is plugged.
|
* This is called by virtio-bus just after the device is plugged.
|
||||||
*/
|
*/
|
||||||
void (*device_plugged)(DeviceState *d);
|
void (*device_plugged)(DeviceState *d, Error **errp);
|
||||||
/*
|
/*
|
||||||
* transport independent exit function.
|
* transport independent exit function.
|
||||||
* This is called by virtio-bus just before the device is unplugged.
|
* This is called by virtio-bus just before the device is unplugged.
|
||||||
|
@ -75,7 +74,7 @@ struct VirtioBusState {
|
||||||
BusState parent_obj;
|
BusState parent_obj;
|
||||||
};
|
};
|
||||||
|
|
||||||
int virtio_bus_device_plugged(VirtIODevice *vdev);
|
void virtio_bus_device_plugged(VirtIODevice *vdev, Error **errp);
|
||||||
void virtio_bus_reset(VirtioBusState *bus);
|
void virtio_bus_reset(VirtioBusState *bus);
|
||||||
void virtio_bus_device_unplugged(VirtIODevice *bus);
|
void virtio_bus_device_unplugged(VirtIODevice *bus);
|
||||||
/* Get the device id of the plugged device. */
|
/* Get the device id of the plugged device. */
|
||||||
|
|
|
@ -48,7 +48,7 @@ typedef struct VirtQueueElement
|
||||||
struct iovec out_sg[VIRTQUEUE_MAX_SIZE];
|
struct iovec out_sg[VIRTQUEUE_MAX_SIZE];
|
||||||
} VirtQueueElement;
|
} VirtQueueElement;
|
||||||
|
|
||||||
#define VIRTIO_PCI_QUEUE_MAX 64
|
#define VIRTIO_QUEUE_MAX 1024
|
||||||
|
|
||||||
#define VIRTIO_NO_VECTOR 0xffff
|
#define VIRTIO_NO_VECTOR 0xffff
|
||||||
|
|
||||||
|
@ -73,7 +73,8 @@ struct VirtIODevice
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
uint8_t isr;
|
uint8_t isr;
|
||||||
uint16_t queue_sel;
|
uint16_t queue_sel;
|
||||||
uint32_t guest_features;
|
uint64_t guest_features;
|
||||||
|
uint64_t host_features;
|
||||||
size_t config_len;
|
size_t config_len;
|
||||||
void *config;
|
void *config;
|
||||||
uint16_t config_vector;
|
uint16_t config_vector;
|
||||||
|
@ -95,8 +96,8 @@ typedef struct VirtioDeviceClass {
|
||||||
/* This is what a VirtioDevice must implement */
|
/* This is what a VirtioDevice must implement */
|
||||||
DeviceRealize realize;
|
DeviceRealize realize;
|
||||||
DeviceUnrealize unrealize;
|
DeviceUnrealize unrealize;
|
||||||
uint32_t (*get_features)(VirtIODevice *vdev, uint32_t requested_features);
|
uint64_t (*get_features)(VirtIODevice *vdev, uint64_t requested_features);
|
||||||
uint32_t (*bad_features)(VirtIODevice *vdev);
|
uint64_t (*bad_features)(VirtIODevice *vdev);
|
||||||
void (*set_features)(VirtIODevice *vdev, uint32_t val);
|
void (*set_features)(VirtIODevice *vdev, uint32_t val);
|
||||||
void (*get_config)(VirtIODevice *vdev, uint8_t *config);
|
void (*get_config)(VirtIODevice *vdev, uint8_t *config);
|
||||||
void (*set_config)(VirtIODevice *vdev, const uint8_t *config);
|
void (*set_config)(VirtIODevice *vdev, const uint8_t *config);
|
||||||
|
@ -175,6 +176,7 @@ void virtio_queue_set_addr(VirtIODevice *vdev, int n, hwaddr addr);
|
||||||
hwaddr virtio_queue_get_addr(VirtIODevice *vdev, int n);
|
hwaddr virtio_queue_get_addr(VirtIODevice *vdev, int n);
|
||||||
void virtio_queue_set_num(VirtIODevice *vdev, int n, int num);
|
void virtio_queue_set_num(VirtIODevice *vdev, int n, int num);
|
||||||
int virtio_queue_get_num(VirtIODevice *vdev, int n);
|
int virtio_queue_get_num(VirtIODevice *vdev, int n);
|
||||||
|
int virtio_get_num_queues(VirtIODevice *vdev);
|
||||||
void virtio_queue_set_align(VirtIODevice *vdev, int n, int align);
|
void virtio_queue_set_align(VirtIODevice *vdev, int n, int align);
|
||||||
void virtio_queue_notify(VirtIODevice *vdev, int n);
|
void virtio_queue_notify(VirtIODevice *vdev, int n);
|
||||||
uint16_t virtio_queue_vector(VirtIODevice *vdev, int n);
|
uint16_t virtio_queue_vector(VirtIODevice *vdev, int n);
|
||||||
|
@ -193,10 +195,12 @@ typedef struct VirtIOSCSIConf VirtIOSCSIConf;
|
||||||
typedef struct VirtIORNGConf VirtIORNGConf;
|
typedef struct VirtIORNGConf VirtIORNGConf;
|
||||||
|
|
||||||
#define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \
|
#define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \
|
||||||
DEFINE_PROP_BIT("indirect_desc", _state, _field, \
|
DEFINE_PROP_BIT64("indirect_desc", _state, _field, \
|
||||||
VIRTIO_RING_F_INDIRECT_DESC, true), \
|
VIRTIO_RING_F_INDIRECT_DESC, true), \
|
||||||
DEFINE_PROP_BIT("event_idx", _state, _field, \
|
DEFINE_PROP_BIT64("event_idx", _state, _field, \
|
||||||
VIRTIO_RING_F_EVENT_IDX, true)
|
VIRTIO_RING_F_EVENT_IDX, true), \
|
||||||
|
DEFINE_PROP_BIT64("notify_on_empty", _state, _field, \
|
||||||
|
VIRTIO_F_NOTIFY_ON_EMPTY, true)
|
||||||
|
|
||||||
hwaddr virtio_queue_get_desc_addr(VirtIODevice *vdev, int n);
|
hwaddr virtio_queue_get_desc_addr(VirtIODevice *vdev, int n);
|
||||||
hwaddr virtio_queue_get_avail_addr(VirtIODevice *vdev, int n);
|
hwaddr virtio_queue_get_avail_addr(VirtIODevice *vdev, int n);
|
||||||
|
@ -223,21 +227,21 @@ void virtio_irq(VirtQueue *vq);
|
||||||
VirtQueue *virtio_vector_first_queue(VirtIODevice *vdev, uint16_t vector);
|
VirtQueue *virtio_vector_first_queue(VirtIODevice *vdev, uint16_t vector);
|
||||||
VirtQueue *virtio_vector_next_queue(VirtQueue *vq);
|
VirtQueue *virtio_vector_next_queue(VirtQueue *vq);
|
||||||
|
|
||||||
static inline void virtio_add_feature(uint32_t *features, unsigned int fbit)
|
static inline void virtio_add_feature(uint64_t *features, unsigned int fbit)
|
||||||
{
|
{
|
||||||
assert(fbit < 32);
|
assert(fbit < 64);
|
||||||
*features |= (1 << fbit);
|
*features |= (1 << fbit);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void virtio_clear_feature(uint32_t *features, unsigned int fbit)
|
static inline void virtio_clear_feature(uint64_t *features, unsigned int fbit)
|
||||||
{
|
{
|
||||||
assert(fbit < 32);
|
assert(fbit < 64);
|
||||||
*features &= ~(1 << fbit);
|
*features &= ~(1 << fbit);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool __virtio_has_feature(uint32_t features, unsigned int fbit)
|
static inline bool __virtio_has_feature(uint64_t features, unsigned int fbit)
|
||||||
{
|
{
|
||||||
assert(fbit < 32);
|
assert(fbit < 64);
|
||||||
return !!(features & (1 << fbit));
|
return !!(features & (1 << fbit));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,11 +20,24 @@ int tpm_config_parse(QemuOptsList *opts_list, const char *optarg);
|
||||||
int tpm_init(void);
|
int tpm_init(void);
|
||||||
void tpm_cleanup(void);
|
void tpm_cleanup(void);
|
||||||
|
|
||||||
|
typedef enum TPMVersion {
|
||||||
|
TPM_VERSION_UNSPEC = 0,
|
||||||
|
TPM_VERSION_1_2 = 1,
|
||||||
|
TPM_VERSION_2_0 = 2,
|
||||||
|
} TPMVersion;
|
||||||
|
|
||||||
|
TPMVersion tpm_tis_get_tpm_version(Object *obj);
|
||||||
|
|
||||||
#define TYPE_TPM_TIS "tpm-tis"
|
#define TYPE_TPM_TIS "tpm-tis"
|
||||||
|
|
||||||
static inline bool tpm_find(void)
|
static inline TPMVersion tpm_get_version(void)
|
||||||
{
|
{
|
||||||
return object_resolve_path_type("", TYPE_TPM_TIS, NULL);
|
Object *obj = object_resolve_path_type("", TYPE_TPM_TIS, NULL);
|
||||||
|
|
||||||
|
if (obj) {
|
||||||
|
return tpm_tis_get_tpm_version(obj);
|
||||||
|
}
|
||||||
|
return TPM_VERSION_UNSPEC;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* QEMU_TPM_H */
|
#endif /* QEMU_TPM_H */
|
||||||
|
|
|
@ -88,6 +88,10 @@ struct TPMDriverOps {
|
||||||
void (*cancel_cmd)(TPMBackend *t);
|
void (*cancel_cmd)(TPMBackend *t);
|
||||||
|
|
||||||
bool (*get_tpm_established_flag)(TPMBackend *t);
|
bool (*get_tpm_established_flag)(TPMBackend *t);
|
||||||
|
|
||||||
|
int (*reset_tpm_established_flag)(TPMBackend *t, uint8_t locty);
|
||||||
|
|
||||||
|
TPMVersion (*get_tpm_version)(TPMBackend *t);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -191,6 +195,15 @@ void tpm_backend_cancel_cmd(TPMBackend *s);
|
||||||
*/
|
*/
|
||||||
bool tpm_backend_get_tpm_established_flag(TPMBackend *s);
|
bool tpm_backend_get_tpm_established_flag(TPMBackend *s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tpm_backend_reset_tpm_established_flag:
|
||||||
|
* @s: the backend
|
||||||
|
* @locty: the locality number
|
||||||
|
*
|
||||||
|
* Reset the TPM establishment flag.
|
||||||
|
*/
|
||||||
|
int tpm_backend_reset_tpm_established_flag(TPMBackend *s, uint8_t locty);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tpm_backend_open:
|
* tpm_backend_open:
|
||||||
* @s: the backend to open
|
* @s: the backend to open
|
||||||
|
@ -201,6 +214,16 @@ bool tpm_backend_get_tpm_established_flag(TPMBackend *s);
|
||||||
*/
|
*/
|
||||||
void tpm_backend_open(TPMBackend *s, Error **errp);
|
void tpm_backend_open(TPMBackend *s, Error **errp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tpm_backend_get_tpm_version:
|
||||||
|
* @s: the backend to call into
|
||||||
|
*
|
||||||
|
* Get the TPM Version that is emulated at the backend.
|
||||||
|
*
|
||||||
|
* Returns TPMVersion.
|
||||||
|
*/
|
||||||
|
TPMVersion tpm_backend_get_tpm_version(TPMBackend *s);
|
||||||
|
|
||||||
TPMBackend *qemu_find_tpm(const char *id);
|
TPMBackend *qemu_find_tpm(const char *id);
|
||||||
|
|
||||||
const TPMDriverOps *tpm_get_backend_driver(const char *type);
|
const TPMDriverOps *tpm_get_backend_driver(const char *type);
|
||||||
|
|
|
@ -121,35 +121,39 @@ static void net_vhost_user_event(void *opaque, int event)
|
||||||
case CHR_EVENT_OPENED:
|
case CHR_EVENT_OPENED:
|
||||||
vhost_user_start(s);
|
vhost_user_start(s);
|
||||||
net_vhost_link_down(s, false);
|
net_vhost_link_down(s, false);
|
||||||
error_report("chardev \"%s\" went up", s->chr->label);
|
error_report("chardev \"%s\" went up", s->nc.info_str);
|
||||||
break;
|
break;
|
||||||
case CHR_EVENT_CLOSED:
|
case CHR_EVENT_CLOSED:
|
||||||
net_vhost_link_down(s, true);
|
net_vhost_link_down(s, true);
|
||||||
vhost_user_stop(s);
|
vhost_user_stop(s);
|
||||||
error_report("chardev \"%s\" went down", s->chr->label);
|
error_report("chardev \"%s\" went down", s->nc.info_str);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int net_vhost_user_init(NetClientState *peer, const char *device,
|
static int net_vhost_user_init(NetClientState *peer, const char *device,
|
||||||
const char *name, CharDriverState *chr)
|
const char *name, CharDriverState *chr,
|
||||||
|
uint32_t queues)
|
||||||
{
|
{
|
||||||
NetClientState *nc;
|
NetClientState *nc;
|
||||||
VhostUserState *s;
|
VhostUserState *s;
|
||||||
|
int i;
|
||||||
|
|
||||||
nc = qemu_new_net_client(&net_vhost_user_info, peer, device, name);
|
for (i = 0; i < queues; i++) {
|
||||||
|
nc = qemu_new_net_client(&net_vhost_user_info, peer, device, name);
|
||||||
|
|
||||||
snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user to %s",
|
snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user%d to %s",
|
||||||
chr->label);
|
i, chr->label);
|
||||||
|
|
||||||
s = DO_UPCAST(VhostUserState, nc, nc);
|
s = DO_UPCAST(VhostUserState, nc, nc);
|
||||||
|
|
||||||
/* We don't provide a receive callback */
|
/* We don't provide a receive callback */
|
||||||
s->nc.receive_disabled = 1;
|
s->nc.receive_disabled = 1;
|
||||||
s->chr = chr;
|
s->chr = chr;
|
||||||
|
s->nc.queue_index = i;
|
||||||
qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event, s);
|
|
||||||
|
|
||||||
|
qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event, s);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,6 +230,7 @@ int net_init_vhost_user(const NetClientOptions *opts, const char *name,
|
||||||
NetClientState *peer, Error **errp)
|
NetClientState *peer, Error **errp)
|
||||||
{
|
{
|
||||||
/* FIXME error_setg(errp, ...) on failure */
|
/* FIXME error_setg(errp, ...) on failure */
|
||||||
|
uint32_t queues;
|
||||||
const NetdevVhostUserOptions *vhost_user_opts;
|
const NetdevVhostUserOptions *vhost_user_opts;
|
||||||
CharDriverState *chr;
|
CharDriverState *chr;
|
||||||
|
|
||||||
|
@ -244,6 +249,12 @@ int net_init_vhost_user(const NetClientOptions *opts, const char *name,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* number of queues for multiqueue */
|
||||||
|
if (vhost_user_opts->has_queues) {
|
||||||
|
queues = vhost_user_opts->queues;
|
||||||
|
} else {
|
||||||
|
queues = 1;
|
||||||
|
}
|
||||||
|
|
||||||
return net_vhost_user_init(peer, "vhost_user", name, chr);
|
return net_vhost_user_init(peer, "vhost_user", name, chr, queues);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2444,12 +2444,16 @@
|
||||||
#
|
#
|
||||||
# @vhostforce: #optional vhost on for non-MSIX virtio guests (default: false).
|
# @vhostforce: #optional vhost on for non-MSIX virtio guests (default: false).
|
||||||
#
|
#
|
||||||
|
# @queues: #optional number of queues to be created for multiqueue vhost-user
|
||||||
|
# (default: 1) (Since 2.4)
|
||||||
|
#
|
||||||
# Since 2.1
|
# Since 2.1
|
||||||
##
|
##
|
||||||
{ 'struct': 'NetdevVhostUserOptions',
|
{ 'struct': 'NetdevVhostUserOptions',
|
||||||
'data': {
|
'data': {
|
||||||
'chardev': 'str',
|
'chardev': 'str',
|
||||||
'*vhostforce': 'bool' } }
|
'*vhostforce': 'bool',
|
||||||
|
'*queues': 'uint32' } }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @NetClientOptions
|
# @NetClientOptions
|
||||||
|
|
|
@ -1955,13 +1955,14 @@ The hubport netdev lets you connect a NIC to a QEMU "vlan" instead of a single
|
||||||
netdev. @code{-net} and @code{-device} with parameter @option{vlan} create the
|
netdev. @code{-net} and @code{-device} with parameter @option{vlan} create the
|
||||||
required hub automatically.
|
required hub automatically.
|
||||||
|
|
||||||
@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off]
|
@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off][,queues=n]
|
||||||
|
|
||||||
Establish a vhost-user netdev, backed by a chardev @var{id}. The chardev should
|
Establish a vhost-user netdev, backed by a chardev @var{id}. The chardev should
|
||||||
be a unix domain socket backed one. The vhost-user uses a specifically defined
|
be a unix domain socket backed one. The vhost-user uses a specifically defined
|
||||||
protocol to pass vhost ioctl replacement messages to an application on the other
|
protocol to pass vhost ioctl replacement messages to an application on the other
|
||||||
end of the socket. On non-MSIX guests, the feature can be forced with
|
end of the socket. On non-MSIX guests, the feature can be forced with
|
||||||
@var{vhostforce}.
|
@var{vhostforce}. Use 'queues=@var{n}' to specify the number of queues to
|
||||||
|
be created for multiqueue vhost-user.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
@example
|
@example
|
||||||
|
|
15
vl.c
15
vl.c
|
@ -1314,32 +1314,17 @@ static void machine_class_init(ObjectClass *oc, void *data)
|
||||||
{
|
{
|
||||||
MachineClass *mc = MACHINE_CLASS(oc);
|
MachineClass *mc = MACHINE_CLASS(oc);
|
||||||
QEMUMachine *qm = data;
|
QEMUMachine *qm = data;
|
||||||
|
|
||||||
mc->family = qm->family;
|
|
||||||
mc->name = qm->name;
|
mc->name = qm->name;
|
||||||
mc->alias = qm->alias;
|
|
||||||
mc->desc = qm->desc;
|
mc->desc = qm->desc;
|
||||||
mc->init = qm->init;
|
mc->init = qm->init;
|
||||||
mc->reset = qm->reset;
|
|
||||||
mc->hot_add_cpu = qm->hot_add_cpu;
|
|
||||||
mc->kvm_type = qm->kvm_type;
|
mc->kvm_type = qm->kvm_type;
|
||||||
mc->block_default_type = qm->block_default_type;
|
mc->block_default_type = qm->block_default_type;
|
||||||
mc->units_per_default_bus = qm->units_per_default_bus;
|
|
||||||
mc->max_cpus = qm->max_cpus;
|
mc->max_cpus = qm->max_cpus;
|
||||||
mc->no_serial = qm->no_serial;
|
|
||||||
mc->no_parallel = qm->no_parallel;
|
|
||||||
mc->use_virtcon = qm->use_virtcon;
|
|
||||||
mc->use_sclp = qm->use_sclp;
|
|
||||||
mc->no_floppy = qm->no_floppy;
|
|
||||||
mc->no_cdrom = qm->no_cdrom;
|
|
||||||
mc->no_sdcard = qm->no_sdcard;
|
mc->no_sdcard = qm->no_sdcard;
|
||||||
mc->has_dynamic_sysbus = qm->has_dynamic_sysbus;
|
mc->has_dynamic_sysbus = qm->has_dynamic_sysbus;
|
||||||
mc->is_default = qm->is_default;
|
mc->is_default = qm->is_default;
|
||||||
mc->default_machine_opts = qm->default_machine_opts;
|
mc->default_machine_opts = qm->default_machine_opts;
|
||||||
mc->default_boot_order = qm->default_boot_order;
|
mc->default_boot_order = qm->default_boot_order;
|
||||||
mc->default_display = qm->default_display;
|
|
||||||
mc->compat_props = qm->compat_props;
|
|
||||||
mc->hw_version = qm->hw_version;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int qemu_register_machine(QEMUMachine *m)
|
int qemu_register_machine(QEMUMachine *m)
|
||||||
|
|
Loading…
Reference in New Issue