|
|
4a2fec |
From dde06ffd66bbc8aa9232dd2c0b849c074d9fcd06 Mon Sep 17 00:00:00 2001
|
|
|
4a2fec |
From: David Gibson <dgibson@redhat.com>
|
|
|
4a2fec |
Date: Fri, 19 Jan 2018 02:34:41 +0100
|
|
|
4a2fec |
Subject: [PATCH 13/21] hw/ppc/spapr_caps: Rework spapr_caps to use uint8
|
|
|
4a2fec |
internal representation
|
|
|
4a2fec |
|
|
|
4a2fec |
RH-Author: David Gibson <dgibson@redhat.com>
|
|
|
4a2fec |
Message-id: <20180119023442.28577-7-dgibson@redhat.com>
|
|
|
4a2fec |
Patchwork-id: 78674
|
|
|
4a2fec |
O-Subject: [RHEL-7.5 qemu-kvm-rhev PATCH 6/7] hw/ppc/spapr_caps: Rework spapr_caps to use uint8 internal representation
|
|
|
4a2fec |
Bugzilla: 1523414
|
|
|
4a2fec |
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
|
|
|
4a2fec |
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
|
|
4a2fec |
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
4a2fec |
|
|
|
4a2fec |
From: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
|
|
|
4a2fec |
|
|
|
4a2fec |
Currently spapr_caps are tied to boolean values (on or off). This patch
|
|
|
4a2fec |
reworks the caps so that they can have any uint8 value. This allows more
|
|
|
4a2fec |
capabilities with various values to be represented in the same way
|
|
|
4a2fec |
internally. Capabilities are numbered in ascending order. The internal
|
|
|
4a2fec |
representation of capability values is an array of uint8s in the
|
|
|
4a2fec |
sPAPRMachineState, indexed by capability number.
|
|
|
4a2fec |
|
|
|
4a2fec |
Capabilities can have their own name, description, options, getter and
|
|
|
4a2fec |
setter functions, type and allow functions. They also each have their own
|
|
|
4a2fec |
section in the migration stream. Capabilities are only migrated if they
|
|
|
4a2fec |
were explictly set on the command line, with the assumption that
|
|
|
4a2fec |
otherwise the default will match.
|
|
|
4a2fec |
|
|
|
4a2fec |
On migration we ensure that the capability value on the destination
|
|
|
4a2fec |
is greater than or equal to the capability value from the source. So
|
|
|
4a2fec |
long at this remains the case then the migration is considered
|
|
|
4a2fec |
compatible and allowed to continue.
|
|
|
4a2fec |
|
|
|
4a2fec |
This patch implements generic getter and setter functions for boolean
|
|
|
4a2fec |
capabilities. It also converts the existings cap-htm, cap-vsx and
|
|
|
4a2fec |
cap-dfp capabilities to this new format.
|
|
|
4a2fec |
|
|
|
4a2fec |
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
|
|
|
4a2fec |
(cherry picked from commit 4e5fe3688e23d61b45cc549ff1322aff8f50ef45)
|
|
|
4a2fec |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
4a2fec |
|
|
|
4a2fec |
Conflicts:
|
|
|
4a2fec |
hw/ppc/spapr.c
|
|
|
4a2fec |
include/hw/ppc/spapr.h
|
|
|
4a2fec |
|
|
|
4a2fec |
Some trivial contextual conflicts. Also conflicts due to difference
|
|
|
4a2fec |
between upstream and downstream machine type versions. Converted to
|
|
|
4a2fec |
apply to relevant downstream versions.
|
|
|
4a2fec |
|
|
|
4a2fec |
Again needed adjustment to the pre_save function because its return
|
|
|
4a2fec |
type has been changed upstream, but not downstream.
|
|
|
4a2fec |
|
|
|
4a2fec |
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1523414
|
|
|
4a2fec |
|
|
|
4a2fec |
Signed-off-by: David Gibson <dgibson@redhat.com>
|
|
|
4a2fec |
---
|
|
|
4a2fec |
hw/ppc/spapr.c | 38 ++++--
|
|
|
4a2fec |
hw/ppc/spapr_caps.c | 321 +++++++++++++++++++++++++------------------------
|
|
|
4a2fec |
include/hw/ppc/spapr.h | 45 +++----
|
|
|
4a2fec |
3 files changed, 218 insertions(+), 186 deletions(-)
|
|
|
4a2fec |
|
|
|
4a2fec |
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
|
|
|
4a2fec |
index 41cb2fa..66227c3 100644
|
|
|
4a2fec |
--- a/hw/ppc/spapr.c
|
|
|
4a2fec |
+++ b/hw/ppc/spapr.c
|
|
|
4a2fec |
@@ -320,7 +320,7 @@ static void spapr_populate_pa_features(sPAPRMachineState *spapr,
|
|
|
4a2fec |
*/
|
|
|
4a2fec |
pa_features[3] |= 0x20;
|
|
|
4a2fec |
}
|
|
|
4a2fec |
- if (spapr_has_cap(spapr, SPAPR_CAP_HTM) && pa_size > 24) {
|
|
|
4a2fec |
+ if ((spapr_get_cap(spapr, SPAPR_CAP_HTM) != 0) && pa_size > 24) {
|
|
|
4a2fec |
pa_features[24] |= 0x80; /* Transactional memory support */
|
|
|
4a2fec |
}
|
|
|
4a2fec |
if (legacy_guest && pa_size > 40) {
|
|
|
4a2fec |
@@ -566,7 +566,7 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
|
|
|
4a2fec |
*
|
|
|
4a2fec |
* Only CPUs for which we create core types in spapr_cpu_core.c
|
|
|
4a2fec |
* are possible, and all of those have VMX */
|
|
|
4a2fec |
- if (spapr_has_cap(spapr, SPAPR_CAP_VSX)) {
|
|
|
4a2fec |
+ if (spapr_get_cap(spapr, SPAPR_CAP_VSX) != 0) {
|
|
|
4a2fec |
_FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 2)));
|
|
|
4a2fec |
} else {
|
|
|
4a2fec |
_FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 1)));
|
|
|
4a2fec |
@@ -575,7 +575,7 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
|
|
|
4a2fec |
/* Advertise DFP (Decimal Floating Point) if available
|
|
|
4a2fec |
* 0 / no property == no DFP
|
|
|
4a2fec |
* 1 == DFP available */
|
|
|
4a2fec |
- if (spapr_has_cap(spapr, SPAPR_CAP_DFP)) {
|
|
|
4a2fec |
+ if (spapr_get_cap(spapr, SPAPR_CAP_DFP) != 0) {
|
|
|
4a2fec |
_FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1)));
|
|
|
4a2fec |
}
|
|
|
4a2fec |
|
|
|
4a2fec |
@@ -1544,6 +1544,18 @@ static bool spapr_vga_init(PCIBus *pci_bus, Error **errp)
|
|
|
4a2fec |
}
|
|
|
4a2fec |
}
|
|
|
4a2fec |
|
|
|
4a2fec |
+static int spapr_pre_load(void *opaque)
|
|
|
4a2fec |
+{
|
|
|
4a2fec |
+ int rc;
|
|
|
4a2fec |
+
|
|
|
4a2fec |
+ rc = spapr_caps_pre_load(opaque);
|
|
|
4a2fec |
+ if (rc) {
|
|
|
4a2fec |
+ return rc;
|
|
|
4a2fec |
+ }
|
|
|
4a2fec |
+
|
|
|
4a2fec |
+ return 0;
|
|
|
4a2fec |
+}
|
|
|
4a2fec |
+
|
|
|
4a2fec |
static int spapr_post_load(void *opaque, int version_id)
|
|
|
4a2fec |
{
|
|
|
4a2fec |
sPAPRMachineState *spapr = (sPAPRMachineState *)opaque;
|
|
|
4a2fec |
@@ -1585,6 +1597,11 @@ static int spapr_post_load(void *opaque, int version_id)
|
|
|
4a2fec |
return err;
|
|
|
4a2fec |
}
|
|
|
4a2fec |
|
|
|
4a2fec |
+static void spapr_pre_save(void *opaque)
|
|
|
4a2fec |
+{
|
|
|
4a2fec |
+ spapr_caps_pre_save(opaque);
|
|
|
4a2fec |
+}
|
|
|
4a2fec |
+
|
|
|
4a2fec |
static bool version_before_3(void *opaque, int version_id)
|
|
|
4a2fec |
{
|
|
|
4a2fec |
return version_id < 3;
|
|
|
4a2fec |
@@ -1705,7 +1722,9 @@ static const VMStateDescription vmstate_spapr = {
|
|
|
4a2fec |
.name = "spapr",
|
|
|
4a2fec |
.version_id = 3,
|
|
|
4a2fec |
.minimum_version_id = 1,
|
|
|
4a2fec |
+ .pre_load = spapr_pre_load,
|
|
|
4a2fec |
.post_load = spapr_post_load,
|
|
|
4a2fec |
+ .pre_save = spapr_pre_save,
|
|
|
4a2fec |
.fields = (VMStateField[]) {
|
|
|
4a2fec |
/* used to be @next_irq */
|
|
|
4a2fec |
VMSTATE_UNUSED_BUFFER(version_before_3, 0, 4),
|
|
|
4a2fec |
@@ -1720,7 +1739,9 @@ static const VMStateDescription vmstate_spapr = {
|
|
|
4a2fec |
&vmstate_spapr_ov5_cas,
|
|
|
4a2fec |
&vmstate_spapr_patb_entry,
|
|
|
4a2fec |
&vmstate_spapr_pending_events,
|
|
|
4a2fec |
- &vmstate_spapr_caps,
|
|
|
4a2fec |
+ &vmstate_spapr_cap_htm,
|
|
|
4a2fec |
+ &vmstate_spapr_cap_vsx,
|
|
|
4a2fec |
+ &vmstate_spapr_cap_dfp,
|
|
|
4a2fec |
NULL
|
|
|
4a2fec |
}
|
|
|
4a2fec |
};
|
|
|
4a2fec |
@@ -2279,8 +2300,6 @@ static void ppc_spapr_init(MachineState *machine)
|
|
|
4a2fec |
char *filename;
|
|
|
4a2fec |
Error *resize_hpt_err = NULL;
|
|
|
4a2fec |
|
|
|
4a2fec |
- spapr_caps_validate(spapr, &error_fatal);
|
|
|
4a2fec |
-
|
|
|
4a2fec |
msi_nonbroken = true;
|
|
|
4a2fec |
|
|
|
4a2fec |
QLIST_INIT(&spapr->phbs);
|
|
|
4a2fec |
@@ -3650,7 +3669,9 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
|
|
|
4a2fec |
mc->numa_mem_align_shift = 28;
|
|
|
4a2fec |
smc->has_power9_support = true;
|
|
|
4a2fec |
|
|
|
4a2fec |
- smc->default_caps = spapr_caps(SPAPR_CAP_VSX | SPAPR_CAP_DFP);
|
|
|
4a2fec |
+ smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF;
|
|
|
4a2fec |
+ smc->default_caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_ON;
|
|
|
4a2fec |
+ smc->default_caps.caps[SPAPR_CAP_DFP] = SPAPR_CAP_ON;
|
|
|
4a2fec |
spapr_caps_add_properties(smc, &error_abort);
|
|
|
4a2fec |
}
|
|
|
4a2fec |
|
|
|
4a2fec |
@@ -4056,8 +4077,7 @@ static void spapr_machine_rhel740_class_options(MachineClass *mc)
|
|
|
4a2fec |
smc->has_power9_support = false;
|
|
|
4a2fec |
smc->pre_2_10_has_unused_icps = true;
|
|
|
4a2fec |
smc->resize_hpt_default = SPAPR_RESIZE_HPT_DISABLED;
|
|
|
4a2fec |
- smc->default_caps = spapr_caps(SPAPR_CAP_HTM | SPAPR_CAP_VSX
|
|
|
4a2fec |
- | SPAPR_CAP_DFP);
|
|
|
4a2fec |
+ smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_ON;
|
|
|
4a2fec |
}
|
|
|
4a2fec |
|
|
|
4a2fec |
DEFINE_SPAPR_MACHINE(rhel740, "rhel7.4.0", false);
|
|
|
4a2fec |
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
|
|
|
4a2fec |
index 2b67ac2..f95a785 100644
|
|
|
4a2fec |
--- a/hw/ppc/spapr_caps.c
|
|
|
4a2fec |
+++ b/hw/ppc/spapr_caps.c
|
|
|
4a2fec |
@@ -35,18 +35,51 @@
|
|
|
4a2fec |
typedef struct sPAPRCapabilityInfo {
|
|
|
4a2fec |
const char *name;
|
|
|
4a2fec |
const char *description;
|
|
|
4a2fec |
- uint64_t flag;
|
|
|
4a2fec |
+ const char *options; /* valid capability values */
|
|
|
4a2fec |
+ int index;
|
|
|
4a2fec |
|
|
|
4a2fec |
+ /* Getter and Setter Function Pointers */
|
|
|
4a2fec |
+ ObjectPropertyAccessor *get;
|
|
|
4a2fec |
+ ObjectPropertyAccessor *set;
|
|
|
4a2fec |
+ const char *type;
|
|
|
4a2fec |
/* Make sure the virtual hardware can support this capability */
|
|
|
4a2fec |
- void (*allow)(sPAPRMachineState *spapr, Error **errp);
|
|
|
4a2fec |
-
|
|
|
4a2fec |
- /* If possible, tell the virtual hardware not to allow the cap to
|
|
|
4a2fec |
- * be used at all */
|
|
|
4a2fec |
- void (*disallow)(sPAPRMachineState *spapr, Error **errp);
|
|
|
4a2fec |
+ void (*apply)(sPAPRMachineState *spapr, uint8_t val, Error **errp);
|
|
|
4a2fec |
} sPAPRCapabilityInfo;
|
|
|
4a2fec |
|
|
|
4a2fec |
-static void cap_htm_allow(sPAPRMachineState *spapr, Error **errp)
|
|
|
4a2fec |
+static void spapr_cap_get_bool(Object *obj, Visitor *v, const char *name,
|
|
|
4a2fec |
+ void *opaque, Error **errp)
|
|
|
4a2fec |
+{
|
|
|
4a2fec |
+ sPAPRCapabilityInfo *cap = opaque;
|
|
|
4a2fec |
+ sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
|
|
|
4a2fec |
+ bool value = spapr_get_cap(spapr, cap->index) == SPAPR_CAP_ON;
|
|
|
4a2fec |
+
|
|
|
4a2fec |
+ visit_type_bool(v, name, &value, errp);
|
|
|
4a2fec |
+}
|
|
|
4a2fec |
+
|
|
|
4a2fec |
+static void spapr_cap_set_bool(Object *obj, Visitor *v, const char *name,
|
|
|
4a2fec |
+ void *opaque, Error **errp)
|
|
|
4a2fec |
+{
|
|
|
4a2fec |
+ sPAPRCapabilityInfo *cap = opaque;
|
|
|
4a2fec |
+ sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
|
|
|
4a2fec |
+ bool value;
|
|
|
4a2fec |
+ Error *local_err = NULL;
|
|
|
4a2fec |
+
|
|
|
4a2fec |
+ visit_type_bool(v, name, &value, &local_err);
|
|
|
4a2fec |
+ if (local_err) {
|
|
|
4a2fec |
+ error_propagate(errp, local_err);
|
|
|
4a2fec |
+ return;
|
|
|
4a2fec |
+ }
|
|
|
4a2fec |
+
|
|
|
4a2fec |
+ spapr->cmd_line_caps[cap->index] = true;
|
|
|
4a2fec |
+ spapr->eff.caps[cap->index] = value ? SPAPR_CAP_ON : SPAPR_CAP_OFF;
|
|
|
4a2fec |
+}
|
|
|
4a2fec |
+
|
|
|
4a2fec |
+static void cap_htm_apply(sPAPRMachineState *spapr, uint8_t val, Error **errp)
|
|
|
4a2fec |
{
|
|
|
4a2fec |
+ if (!val) {
|
|
|
4a2fec |
+ /* TODO: We don't support disabling htm yet */
|
|
|
4a2fec |
+ return;
|
|
|
4a2fec |
+ }
|
|
|
4a2fec |
if (tcg_enabled()) {
|
|
|
4a2fec |
error_setg(errp,
|
|
|
4a2fec |
"No Transactional Memory support in TCG, try cap-htm=off");
|
|
|
4a2fec |
@@ -57,11 +90,15 @@ static void cap_htm_allow(sPAPRMachineState *spapr, Error **errp)
|
|
|
4a2fec |
}
|
|
|
4a2fec |
}
|
|
|
4a2fec |
|
|
|
4a2fec |
-static void cap_vsx_allow(sPAPRMachineState *spapr, Error **errp)
|
|
|
4a2fec |
+static void cap_vsx_apply(sPAPRMachineState *spapr, uint8_t val, Error **errp)
|
|
|
4a2fec |
{
|
|
|
4a2fec |
PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
|
|
|
4a2fec |
CPUPPCState *env = &cpu->env;
|
|
|
4a2fec |
|
|
|
4a2fec |
+ if (!val) {
|
|
|
4a2fec |
+ /* TODO: We don't support disabling vsx yet */
|
|
|
4a2fec |
+ return;
|
|
|
4a2fec |
+ }
|
|
|
4a2fec |
/* Allowable CPUs in spapr_cpu_core.c should already have gotten
|
|
|
4a2fec |
* rid of anything that doesn't do VMX */
|
|
|
4a2fec |
g_assert(env->insns_flags & PPC_ALTIVEC);
|
|
|
4a2fec |
@@ -70,37 +107,51 @@ static void cap_vsx_allow(sPAPRMachineState *spapr, Error **errp)
|
|
|
4a2fec |
}
|
|
|
4a2fec |
}
|
|
|
4a2fec |
|
|
|
4a2fec |
-static void cap_dfp_allow(sPAPRMachineState *spapr, Error **errp)
|
|
|
4a2fec |
+static void cap_dfp_apply(sPAPRMachineState *spapr, uint8_t val, Error **errp)
|
|
|
4a2fec |
{
|
|
|
4a2fec |
PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
|
|
|
4a2fec |
CPUPPCState *env = &cpu->env;
|
|
|
4a2fec |
|
|
|
4a2fec |
+ if (!val) {
|
|
|
4a2fec |
+ /* TODO: We don't support disabling dfp yet */
|
|
|
4a2fec |
+ return;
|
|
|
4a2fec |
+ }
|
|
|
4a2fec |
if (!(env->insns_flags2 & PPC2_DFP)) {
|
|
|
4a2fec |
error_setg(errp, "DFP support not available, try cap-dfp=off");
|
|
|
4a2fec |
}
|
|
|
4a2fec |
}
|
|
|
4a2fec |
|
|
|
4a2fec |
-static sPAPRCapabilityInfo capability_table[] = {
|
|
|
4a2fec |
- {
|
|
|
4a2fec |
+
|
|
|
4a2fec |
+sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
|
|
|
4a2fec |
+ [SPAPR_CAP_HTM] = {
|
|
|
4a2fec |
.name = "htm",
|
|
|
4a2fec |
.description = "Allow Hardware Transactional Memory (HTM)",
|
|
|
4a2fec |
- .flag = SPAPR_CAP_HTM,
|
|
|
4a2fec |
- .allow = cap_htm_allow,
|
|
|
4a2fec |
- /* TODO: add cap_htm_disallow */
|
|
|
4a2fec |
+ .options = "",
|
|
|
4a2fec |
+ .index = SPAPR_CAP_HTM,
|
|
|
4a2fec |
+ .get = spapr_cap_get_bool,
|
|
|
4a2fec |
+ .set = spapr_cap_set_bool,
|
|
|
4a2fec |
+ .type = "bool",
|
|
|
4a2fec |
+ .apply = cap_htm_apply,
|
|
|
4a2fec |
},
|
|
|
4a2fec |
- {
|
|
|
4a2fec |
+ [SPAPR_CAP_VSX] = {
|
|
|
4a2fec |
.name = "vsx",
|
|
|
4a2fec |
.description = "Allow Vector Scalar Extensions (VSX)",
|
|
|
4a2fec |
- .flag = SPAPR_CAP_VSX,
|
|
|
4a2fec |
- .allow = cap_vsx_allow,
|
|
|
4a2fec |
- /* TODO: add cap_vsx_disallow */
|
|
|
4a2fec |
+ .options = "",
|
|
|
4a2fec |
+ .index = SPAPR_CAP_VSX,
|
|
|
4a2fec |
+ .get = spapr_cap_get_bool,
|
|
|
4a2fec |
+ .set = spapr_cap_set_bool,
|
|
|
4a2fec |
+ .type = "bool",
|
|
|
4a2fec |
+ .apply = cap_vsx_apply,
|
|
|
4a2fec |
},
|
|
|
4a2fec |
- {
|
|
|
4a2fec |
+ [SPAPR_CAP_DFP] = {
|
|
|
4a2fec |
.name = "dfp",
|
|
|
4a2fec |
.description = "Allow Decimal Floating Point (DFP)",
|
|
|
4a2fec |
- .flag = SPAPR_CAP_DFP,
|
|
|
4a2fec |
- .allow = cap_dfp_allow,
|
|
|
4a2fec |
- /* TODO: add cap_dfp_disallow */
|
|
|
4a2fec |
+ .options = "",
|
|
|
4a2fec |
+ .index = SPAPR_CAP_DFP,
|
|
|
4a2fec |
+ .get = spapr_cap_get_bool,
|
|
|
4a2fec |
+ .set = spapr_cap_set_bool,
|
|
|
4a2fec |
+ .type = "bool",
|
|
|
4a2fec |
+ .apply = cap_dfp_apply,
|
|
|
4a2fec |
},
|
|
|
4a2fec |
};
|
|
|
4a2fec |
|
|
|
4a2fec |
@@ -115,23 +166,33 @@ static sPAPRCapabilities default_caps_with_cpu(sPAPRMachineState *spapr,
|
|
|
4a2fec |
|
|
|
4a2fec |
if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_07,
|
|
|
4a2fec |
0, spapr->max_compat_pvr)) {
|
|
|
4a2fec |
- caps.mask &= ~SPAPR_CAP_HTM;
|
|
|
4a2fec |
+ caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF;
|
|
|
4a2fec |
}
|
|
|
4a2fec |
|
|
|
4a2fec |
if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_06,
|
|
|
4a2fec |
0, spapr->max_compat_pvr)) {
|
|
|
4a2fec |
- caps.mask &= ~SPAPR_CAP_VSX;
|
|
|
4a2fec |
- caps.mask &= ~SPAPR_CAP_DFP;
|
|
|
4a2fec |
+ caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_OFF;
|
|
|
4a2fec |
+ caps.caps[SPAPR_CAP_DFP] = SPAPR_CAP_OFF;
|
|
|
4a2fec |
}
|
|
|
4a2fec |
|
|
|
4a2fec |
return caps;
|
|
|
4a2fec |
}
|
|
|
4a2fec |
|
|
|
4a2fec |
-static bool spapr_caps_needed(void *opaque)
|
|
|
4a2fec |
+int spapr_caps_pre_load(void *opaque)
|
|
|
4a2fec |
{
|
|
|
4a2fec |
sPAPRMachineState *spapr = opaque;
|
|
|
4a2fec |
|
|
|
4a2fec |
- return (spapr->forced_caps.mask != 0) || (spapr->forbidden_caps.mask != 0);
|
|
|
4a2fec |
+ /* Set to default so we can tell if this came in with the migration */
|
|
|
4a2fec |
+ spapr->mig = spapr->def;
|
|
|
4a2fec |
+ return 0;
|
|
|
4a2fec |
+}
|
|
|
4a2fec |
+
|
|
|
4a2fec |
+int spapr_caps_pre_save(void *opaque)
|
|
|
4a2fec |
+{
|
|
|
4a2fec |
+ sPAPRMachineState *spapr = opaque;
|
|
|
4a2fec |
+
|
|
|
4a2fec |
+ spapr->mig = spapr->eff;
|
|
|
4a2fec |
+ return 0;
|
|
|
4a2fec |
}
|
|
|
4a2fec |
|
|
|
4a2fec |
/* This has to be called from the top-level spapr post_load, not the
|
|
|
4a2fec |
@@ -140,175 +201,121 @@ static bool spapr_caps_needed(void *opaque)
|
|
|
4a2fec |
* caps on the destination */
|
|
|
4a2fec |
int spapr_caps_post_migration(sPAPRMachineState *spapr)
|
|
|
4a2fec |
{
|
|
|
4a2fec |
- uint64_t allcaps = 0;
|
|
|
4a2fec |
int i;
|
|
|
4a2fec |
bool ok = true;
|
|
|
4a2fec |
- sPAPRCapabilities dstcaps = spapr->effective_caps;
|
|
|
4a2fec |
+ sPAPRCapabilities dstcaps = spapr->eff;
|
|
|
4a2fec |
sPAPRCapabilities srccaps;
|
|
|
4a2fec |
|
|
|
4a2fec |
srccaps = default_caps_with_cpu(spapr, first_cpu);
|
|
|
4a2fec |
- srccaps.mask |= spapr->mig_forced_caps.mask;
|
|
|
4a2fec |
- srccaps.mask &= ~spapr->mig_forbidden_caps.mask;
|
|
|
4a2fec |
+ for (i = 0; i < SPAPR_CAP_NUM; i++) {
|
|
|
4a2fec |
+ /* If not default value then assume came in with the migration */
|
|
|
4a2fec |
+ if (spapr->mig.caps[i] != spapr->def.caps[i]) {
|
|
|
4a2fec |
+ srccaps.caps[i] = spapr->mig.caps[i];
|
|
|
4a2fec |
+ }
|
|
|
4a2fec |
+ }
|
|
|
4a2fec |
|
|
|
4a2fec |
- for (i = 0; i < ARRAY_SIZE(capability_table); i++) {
|
|
|
4a2fec |
+ for (i = 0; i < SPAPR_CAP_NUM; i++) {
|
|
|
4a2fec |
sPAPRCapabilityInfo *info = &capability_table[i];
|
|
|
4a2fec |
|
|
|
4a2fec |
- allcaps |= info->flag;
|
|
|
4a2fec |
-
|
|
|
4a2fec |
- if ((srccaps.mask & info->flag) && !(dstcaps.mask & info->flag)) {
|
|
|
4a2fec |
- error_report("cap-%s=on in incoming stream, but off in destination",
|
|
|
4a2fec |
- info->name);
|
|
|
4a2fec |
+ if (srccaps.caps[i] > dstcaps.caps[i]) {
|
|
|
4a2fec |
+ error_report("cap-%s higher level (%d) in incoming stream than on destination (%d)",
|
|
|
4a2fec |
+ info->name, srccaps.caps[i], dstcaps.caps[i]);
|
|
|
4a2fec |
ok = false;
|
|
|
4a2fec |
}
|
|
|
4a2fec |
|
|
|
4a2fec |
- if (!(srccaps.mask & info->flag) && (dstcaps.mask & info->flag)) {
|
|
|
4a2fec |
- warn_report("cap-%s=off in incoming stream, but on in destination",
|
|
|
4a2fec |
- info->name);
|
|
|
4a2fec |
+ if (srccaps.caps[i] < dstcaps.caps[i]) {
|
|
|
4a2fec |
+ warn_report("cap-%s lower level (%d) in incoming stream than on destination (%d)",
|
|
|
4a2fec |
+ info->name, srccaps.caps[i], dstcaps.caps[i]);
|
|
|
4a2fec |
}
|
|
|
4a2fec |
}
|
|
|
4a2fec |
|
|
|
4a2fec |
- if (spapr->mig_forced_caps.mask & ~allcaps) {
|
|
|
4a2fec |
- error_report(
|
|
|
4a2fec |
- "Unknown capabilities 0x%"PRIx64" enabled in incoming stream",
|
|
|
4a2fec |
- spapr->mig_forced_caps.mask & ~allcaps);
|
|
|
4a2fec |
- ok = false;
|
|
|
4a2fec |
- }
|
|
|
4a2fec |
- if (spapr->mig_forbidden_caps.mask & ~allcaps) {
|
|
|
4a2fec |
- warn_report(
|
|
|
4a2fec |
- "Unknown capabilities 0x%"PRIx64" disabled in incoming stream",
|
|
|
4a2fec |
- spapr->mig_forbidden_caps.mask & ~allcaps);
|
|
|
4a2fec |
- }
|
|
|
4a2fec |
-
|
|
|
4a2fec |
return ok ? 0 : -EINVAL;
|
|
|
4a2fec |
}
|
|
|
4a2fec |
|
|
|
4a2fec |
-static void spapr_caps_pre_save(void *opaque)
|
|
|
4a2fec |
+static bool spapr_cap_htm_needed(void *opaque)
|
|
|
4a2fec |
{
|
|
|
4a2fec |
sPAPRMachineState *spapr = opaque;
|
|
|
4a2fec |
|
|
|
4a2fec |
- spapr->mig_forced_caps = spapr->forced_caps;
|
|
|
4a2fec |
- spapr->mig_forbidden_caps = spapr->forbidden_caps;
|
|
|
4a2fec |
+ return spapr->cmd_line_caps[SPAPR_CAP_HTM] &&
|
|
|
4a2fec |
+ (spapr->eff.caps[SPAPR_CAP_HTM] != spapr->def.caps[SPAPR_CAP_HTM]);
|
|
|
4a2fec |
}
|
|
|
4a2fec |
|
|
|
4a2fec |
-static int spapr_caps_pre_load(void *opaque)
|
|
|
4a2fec |
+const VMStateDescription vmstate_spapr_cap_htm = {
|
|
|
4a2fec |
+ .name = "spapr/cap/htm",
|
|
|
4a2fec |
+ .version_id = 1,
|
|
|
4a2fec |
+ .minimum_version_id = 1,
|
|
|
4a2fec |
+ .needed = spapr_cap_htm_needed,
|
|
|
4a2fec |
+ .fields = (VMStateField[]) {
|
|
|
4a2fec |
+ VMSTATE_UINT8(mig.caps[SPAPR_CAP_HTM], sPAPRMachineState),
|
|
|
4a2fec |
+ VMSTATE_END_OF_LIST()
|
|
|
4a2fec |
+ },
|
|
|
4a2fec |
+};
|
|
|
4a2fec |
+
|
|
|
4a2fec |
+static bool spapr_cap_vsx_needed(void *opaque)
|
|
|
4a2fec |
{
|
|
|
4a2fec |
sPAPRMachineState *spapr = opaque;
|
|
|
4a2fec |
|
|
|
4a2fec |
- spapr->mig_forced_caps = spapr_caps(0);
|
|
|
4a2fec |
- spapr->mig_forbidden_caps = spapr_caps(0);
|
|
|
4a2fec |
- return 0;
|
|
|
4a2fec |
+ return spapr->cmd_line_caps[SPAPR_CAP_VSX] &&
|
|
|
4a2fec |
+ (spapr->eff.caps[SPAPR_CAP_VSX] != spapr->def.caps[SPAPR_CAP_VSX]);
|
|
|
4a2fec |
}
|
|
|
4a2fec |
|
|
|
4a2fec |
-const VMStateDescription vmstate_spapr_caps = {
|
|
|
4a2fec |
- .name = "spapr/caps",
|
|
|
4a2fec |
+const VMStateDescription vmstate_spapr_cap_vsx = {
|
|
|
4a2fec |
+ .name = "spapr/cap/vsx",
|
|
|
4a2fec |
.version_id = 1,
|
|
|
4a2fec |
.minimum_version_id = 1,
|
|
|
4a2fec |
- .needed = spapr_caps_needed,
|
|
|
4a2fec |
- .pre_save = spapr_caps_pre_save,
|
|
|
4a2fec |
- .pre_load = spapr_caps_pre_load,
|
|
|
4a2fec |
+ .needed = spapr_cap_vsx_needed,
|
|
|
4a2fec |
.fields = (VMStateField[]) {
|
|
|
4a2fec |
- VMSTATE_UINT64(mig_forced_caps.mask, sPAPRMachineState),
|
|
|
4a2fec |
- VMSTATE_UINT64(mig_forbidden_caps.mask, sPAPRMachineState),
|
|
|
4a2fec |
+ VMSTATE_UINT8(mig.caps[SPAPR_CAP_VSX], sPAPRMachineState),
|
|
|
4a2fec |
VMSTATE_END_OF_LIST()
|
|
|
4a2fec |
},
|
|
|
4a2fec |
};
|
|
|
4a2fec |
|
|
|
4a2fec |
-void spapr_caps_reset(sPAPRMachineState *spapr)
|
|
|
4a2fec |
-{
|
|
|
4a2fec |
- Error *local_err = NULL;
|
|
|
4a2fec |
- sPAPRCapabilities caps;
|
|
|
4a2fec |
- int i;
|
|
|
4a2fec |
-
|
|
|
4a2fec |
- /* First compute the actual set of caps we're running with.. */
|
|
|
4a2fec |
- caps = default_caps_with_cpu(spapr, first_cpu);
|
|
|
4a2fec |
-
|
|
|
4a2fec |
- /* Remove unnecessary forced/forbidden bits (this will help us
|
|
|
4a2fec |
- * with migration) */
|
|
|
4a2fec |
- spapr->forced_caps.mask &= ~caps.mask;
|
|
|
4a2fec |
- spapr->forbidden_caps.mask &= caps.mask;
|
|
|
4a2fec |
-
|
|
|
4a2fec |
- caps.mask |= spapr->forced_caps.mask;
|
|
|
4a2fec |
- caps.mask &= ~spapr->forbidden_caps.mask;
|
|
|
4a2fec |
-
|
|
|
4a2fec |
- spapr->effective_caps = caps;
|
|
|
4a2fec |
-
|
|
|
4a2fec |
- /* .. then apply those caps to the virtual hardware */
|
|
|
4a2fec |
-
|
|
|
4a2fec |
- for (i = 0; i < ARRAY_SIZE(capability_table); i++) {
|
|
|
4a2fec |
- sPAPRCapabilityInfo *info = &capability_table[i];
|
|
|
4a2fec |
-
|
|
|
4a2fec |
- if (spapr->effective_caps.mask & info->flag) {
|
|
|
4a2fec |
- /* Failure to allow a cap is fatal - if the guest doesn't
|
|
|
4a2fec |
- * have it, we'll be supplying an incorrect environment */
|
|
|
4a2fec |
- if (info->allow) {
|
|
|
4a2fec |
- info->allow(spapr, &error_fatal);
|
|
|
4a2fec |
- }
|
|
|
4a2fec |
- } else {
|
|
|
4a2fec |
- /* Failure to enforce a cap is only a warning. The guest
|
|
|
4a2fec |
- * shouldn't be using it, since it's not advertised, so it
|
|
|
4a2fec |
- * doesn't get to complain about weird behaviour if it
|
|
|
4a2fec |
- * goes ahead anyway */
|
|
|
4a2fec |
- if (info->disallow) {
|
|
|
4a2fec |
- info->disallow(spapr, &local_err);
|
|
|
4a2fec |
- }
|
|
|
4a2fec |
- if (local_err) {
|
|
|
4a2fec |
- warn_report_err(local_err);
|
|
|
4a2fec |
- local_err = NULL;
|
|
|
4a2fec |
- }
|
|
|
4a2fec |
- }
|
|
|
4a2fec |
- }
|
|
|
4a2fec |
-}
|
|
|
4a2fec |
-
|
|
|
4a2fec |
-static void spapr_cap_get(Object *obj, Visitor *v, const char *name,
|
|
|
4a2fec |
- void *opaque, Error **errp)
|
|
|
4a2fec |
+static bool spapr_cap_dfp_needed(void *opaque)
|
|
|
4a2fec |
{
|
|
|
4a2fec |
- sPAPRCapabilityInfo *cap = opaque;
|
|
|
4a2fec |
- sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
|
|
|
4a2fec |
- bool value = spapr_has_cap(spapr, cap->flag);
|
|
|
4a2fec |
-
|
|
|
4a2fec |
- /* TODO: Could this get called before effective_caps is finalized
|
|
|
4a2fec |
- * in spapr_caps_reset()? */
|
|
|
4a2fec |
+ sPAPRMachineState *spapr = opaque;
|
|
|
4a2fec |
|
|
|
4a2fec |
- visit_type_bool(v, name, &value, errp);
|
|
|
4a2fec |
+ return spapr->cmd_line_caps[SPAPR_CAP_DFP] &&
|
|
|
4a2fec |
+ (spapr->eff.caps[SPAPR_CAP_DFP] != spapr->def.caps[SPAPR_CAP_DFP]);
|
|
|
4a2fec |
}
|
|
|
4a2fec |
|
|
|
4a2fec |
-static void spapr_cap_set(Object *obj, Visitor *v, const char *name,
|
|
|
4a2fec |
- void *opaque, Error **errp)
|
|
|
4a2fec |
-{
|
|
|
4a2fec |
- sPAPRCapabilityInfo *cap = opaque;
|
|
|
4a2fec |
- sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
|
|
|
4a2fec |
- bool value;
|
|
|
4a2fec |
- Error *local_err = NULL;
|
|
|
4a2fec |
-
|
|
|
4a2fec |
- visit_type_bool(v, name, &value, &local_err);
|
|
|
4a2fec |
- if (local_err) {
|
|
|
4a2fec |
- error_propagate(errp, local_err);
|
|
|
4a2fec |
- return;
|
|
|
4a2fec |
- }
|
|
|
4a2fec |
-
|
|
|
4a2fec |
- if (value) {
|
|
|
4a2fec |
- spapr->forced_caps.mask |= cap->flag;
|
|
|
4a2fec |
- } else {
|
|
|
4a2fec |
- spapr->forbidden_caps.mask |= cap->flag;
|
|
|
4a2fec |
- }
|
|
|
4a2fec |
-}
|
|
|
4a2fec |
+const VMStateDescription vmstate_spapr_cap_dfp = {
|
|
|
4a2fec |
+ .name = "spapr/cap/dfp",
|
|
|
4a2fec |
+ .version_id = 1,
|
|
|
4a2fec |
+ .minimum_version_id = 1,
|
|
|
4a2fec |
+ .needed = spapr_cap_dfp_needed,
|
|
|
4a2fec |
+ .fields = (VMStateField[]) {
|
|
|
4a2fec |
+ VMSTATE_UINT8(mig.caps[SPAPR_CAP_DFP], sPAPRMachineState),
|
|
|
4a2fec |
+ VMSTATE_END_OF_LIST()
|
|
|
4a2fec |
+ },
|
|
|
4a2fec |
+};
|
|
|
4a2fec |
|
|
|
4a2fec |
-void spapr_caps_validate(sPAPRMachineState *spapr, Error **errp)
|
|
|
4a2fec |
+void spapr_caps_reset(sPAPRMachineState *spapr)
|
|
|
4a2fec |
{
|
|
|
4a2fec |
- uint64_t allcaps = 0;
|
|
|
4a2fec |
+ sPAPRCapabilities default_caps;
|
|
|
4a2fec |
int i;
|
|
|
4a2fec |
|
|
|
4a2fec |
- for (i = 0; i < ARRAY_SIZE(capability_table); i++) {
|
|
|
4a2fec |
- g_assert((allcaps & capability_table[i].flag) == 0);
|
|
|
4a2fec |
- allcaps |= capability_table[i].flag;
|
|
|
4a2fec |
+ /* First compute the actual set of caps we're running with.. */
|
|
|
4a2fec |
+ default_caps = default_caps_with_cpu(spapr, first_cpu);
|
|
|
4a2fec |
+
|
|
|
4a2fec |
+ for (i = 0; i < SPAPR_CAP_NUM; i++) {
|
|
|
4a2fec |
+ /* Store the defaults */
|
|
|
4a2fec |
+ spapr->def.caps[i] = default_caps.caps[i];
|
|
|
4a2fec |
+ /* If not set on the command line then apply the default value */
|
|
|
4a2fec |
+ if (!spapr->cmd_line_caps[i]) {
|
|
|
4a2fec |
+ spapr->eff.caps[i] = default_caps.caps[i];
|
|
|
4a2fec |
+ }
|
|
|
4a2fec |
}
|
|
|
4a2fec |
|
|
|
4a2fec |
- g_assert((spapr->forced_caps.mask & ~allcaps) == 0);
|
|
|
4a2fec |
- g_assert((spapr->forbidden_caps.mask & ~allcaps) == 0);
|
|
|
4a2fec |
+ /* .. then apply those caps to the virtual hardware */
|
|
|
4a2fec |
+
|
|
|
4a2fec |
+ for (i = 0; i < SPAPR_CAP_NUM; i++) {
|
|
|
4a2fec |
+ sPAPRCapabilityInfo *info = &capability_table[i];
|
|
|
4a2fec |
|
|
|
4a2fec |
- if (spapr->forced_caps.mask & spapr->forbidden_caps.mask) {
|
|
|
4a2fec |
- error_setg(errp, "Some sPAPR capabilities set both on and off");
|
|
|
4a2fec |
- return;
|
|
|
4a2fec |
+ /*
|
|
|
4a2fec |
+ * If the apply function can't set the desired level and thinks it's
|
|
|
4a2fec |
+ * fatal, it should cause that.
|
|
|
4a2fec |
+ */
|
|
|
4a2fec |
+ info->apply(spapr, spapr->eff.caps[i], &error_fatal);
|
|
|
4a2fec |
}
|
|
|
4a2fec |
}
|
|
|
4a2fec |
|
|
|
4a2fec |
@@ -321,17 +328,19 @@ void spapr_caps_add_properties(sPAPRMachineClass *smc, Error **errp)
|
|
|
4a2fec |
for (i = 0; i < ARRAY_SIZE(capability_table); i++) {
|
|
|
4a2fec |
sPAPRCapabilityInfo *cap = &capability_table[i];
|
|
|
4a2fec |
const char *name = g_strdup_printf("cap-%s", cap->name);
|
|
|
4a2fec |
+ char *desc;
|
|
|
4a2fec |
|
|
|
4a2fec |
- object_class_property_add(klass, name, "bool",
|
|
|
4a2fec |
- spapr_cap_get, spapr_cap_set, NULL,
|
|
|
4a2fec |
- cap, &local_err);
|
|
|
4a2fec |
+ object_class_property_add(klass, name, cap->type,
|
|
|
4a2fec |
+ cap->get, cap->set,
|
|
|
4a2fec |
+ NULL, cap, &local_err);
|
|
|
4a2fec |
if (local_err) {
|
|
|
4a2fec |
error_propagate(errp, local_err);
|
|
|
4a2fec |
return;
|
|
|
4a2fec |
}
|
|
|
4a2fec |
|
|
|
4a2fec |
- object_class_property_set_description(klass, name, cap->description,
|
|
|
4a2fec |
- &local_err);
|
|
|
4a2fec |
+ desc = g_strdup_printf("%s%s", cap->description, cap->options);
|
|
|
4a2fec |
+ object_class_property_set_description(klass, name, desc, &local_err);
|
|
|
4a2fec |
+ g_free(desc);
|
|
|
4a2fec |
if (local_err) {
|
|
|
4a2fec |
error_propagate(errp, local_err);
|
|
|
4a2fec |
return;
|
|
|
4a2fec |
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
|
|
|
4a2fec |
index df767c3..7156a70 100644
|
|
|
4a2fec |
--- a/include/hw/ppc/spapr.h
|
|
|
4a2fec |
+++ b/include/hw/ppc/spapr.h
|
|
|
4a2fec |
@@ -54,20 +54,25 @@ typedef enum {
|
|
|
4a2fec |
* Capabilities
|
|
|
4a2fec |
*/
|
|
|
4a2fec |
|
|
|
4a2fec |
-/* These bits go in the migration stream, so they can't be reassigned */
|
|
|
4a2fec |
-
|
|
|
4a2fec |
/* Hardware Transactional Memory */
|
|
|
4a2fec |
-#define SPAPR_CAP_HTM 0x0000000000000001ULL
|
|
|
4a2fec |
-
|
|
|
4a2fec |
+#define SPAPR_CAP_HTM 0x00
|
|
|
4a2fec |
/* Vector Scalar Extensions */
|
|
|
4a2fec |
-#define SPAPR_CAP_VSX 0x0000000000000002ULL
|
|
|
4a2fec |
-
|
|
|
4a2fec |
+#define SPAPR_CAP_VSX 0x01
|
|
|
4a2fec |
/* Decimal Floating Point */
|
|
|
4a2fec |
-#define SPAPR_CAP_DFP 0x0000000000000004ULL
|
|
|
4a2fec |
+#define SPAPR_CAP_DFP 0x02
|
|
|
4a2fec |
+/* Num Caps */
|
|
|
4a2fec |
+#define SPAPR_CAP_NUM (SPAPR_CAP_DFP + 1)
|
|
|
4a2fec |
+
|
|
|
4a2fec |
+/*
|
|
|
4a2fec |
+ * Capability Values
|
|
|
4a2fec |
+ */
|
|
|
4a2fec |
+/* Bool Caps */
|
|
|
4a2fec |
+#define SPAPR_CAP_OFF 0x00
|
|
|
4a2fec |
+#define SPAPR_CAP_ON 0x01
|
|
|
4a2fec |
|
|
|
4a2fec |
typedef struct sPAPRCapabilities sPAPRCapabilities;
|
|
|
4a2fec |
struct sPAPRCapabilities {
|
|
|
4a2fec |
- uint64_t mask;
|
|
|
4a2fec |
+ uint8_t caps[SPAPR_CAP_NUM];
|
|
|
4a2fec |
};
|
|
|
4a2fec |
|
|
|
4a2fec |
/**
|
|
|
4a2fec |
@@ -151,9 +156,8 @@ struct sPAPRMachineState {
|
|
|
4a2fec |
|
|
|
4a2fec |
const char *icp_type;
|
|
|
4a2fec |
|
|
|
4a2fec |
- sPAPRCapabilities forced_caps, forbidden_caps;
|
|
|
4a2fec |
- sPAPRCapabilities mig_forced_caps, mig_forbidden_caps;
|
|
|
4a2fec |
- sPAPRCapabilities effective_caps;
|
|
|
4a2fec |
+ bool cmd_line_caps[SPAPR_CAP_NUM];
|
|
|
4a2fec |
+ sPAPRCapabilities def, eff, mig;
|
|
|
4a2fec |
};
|
|
|
4a2fec |
|
|
|
4a2fec |
#define H_SUCCESS 0
|
|
|
4a2fec |
@@ -732,24 +736,23 @@ void spapr_do_system_reset_on_cpu(CPUState *cs, run_on_cpu_data arg);
|
|
|
4a2fec |
|
|
|
4a2fec |
#define HTAB_SIZE(spapr) (1ULL << ((spapr)->htab_shift))
|
|
|
4a2fec |
|
|
|
4a2fec |
+
|
|
|
4a2fec |
+int spapr_caps_pre_load(void *opaque);
|
|
|
4a2fec |
+int spapr_caps_pre_save(void *opaque);
|
|
|
4a2fec |
+
|
|
|
4a2fec |
/*
|
|
|
4a2fec |
* Handling of optional capabilities
|
|
|
4a2fec |
*/
|
|
|
4a2fec |
-extern const VMStateDescription vmstate_spapr_caps;
|
|
|
4a2fec |
-
|
|
|
4a2fec |
-static inline sPAPRCapabilities spapr_caps(uint64_t mask)
|
|
|
4a2fec |
-{
|
|
|
4a2fec |
- sPAPRCapabilities caps = { mask };
|
|
|
4a2fec |
- return caps;
|
|
|
4a2fec |
-}
|
|
|
4a2fec |
+extern const VMStateDescription vmstate_spapr_cap_htm;
|
|
|
4a2fec |
+extern const VMStateDescription vmstate_spapr_cap_vsx;
|
|
|
4a2fec |
+extern const VMStateDescription vmstate_spapr_cap_dfp;
|
|
|
4a2fec |
|
|
|
4a2fec |
-static inline bool spapr_has_cap(sPAPRMachineState *spapr, uint64_t cap)
|
|
|
4a2fec |
+static inline uint8_t spapr_get_cap(sPAPRMachineState *spapr, int cap)
|
|
|
4a2fec |
{
|
|
|
4a2fec |
- return !!(spapr->effective_caps.mask & cap);
|
|
|
4a2fec |
+ return spapr->eff.caps[cap];
|
|
|
4a2fec |
}
|
|
|
4a2fec |
|
|
|
4a2fec |
void spapr_caps_reset(sPAPRMachineState *spapr);
|
|
|
4a2fec |
-void spapr_caps_validate(sPAPRMachineState *spapr, Error **errp);
|
|
|
4a2fec |
void spapr_caps_add_properties(sPAPRMachineClass *smc, Error **errp);
|
|
|
4a2fec |
int spapr_caps_post_migration(sPAPRMachineState *spapr);
|
|
|
4a2fec |
|
|
|
4a2fec |
--
|
|
|
4a2fec |
1.8.3.1
|
|
|
4a2fec |
|