aboutsummaryrefslogtreecommitdiff
path: root/hw/ppc/spapr_caps.c
diff options
context:
space:
mode:
authorNicholas Piggin <npiggin@gmail.com>2023-05-16 02:02:16 +1000
committerDaniel Henrique Barboza <danielhb413@gmail.com>2023-05-28 07:13:54 -0300
commitccc5a4c5e108775667ffc25182cd2ba2326ac979 (patch)
treedfd3caaf7382d24d54fa94b1e561fa2b2d68d3e1 /hw/ppc/spapr_caps.c
parent4ee5d2817ff18d10be887853d5e966247f0a0c30 (diff)
spapr: Add SPAPR_CAP_AIL_MODE_3 for AIL mode 3 support for H_SET_MODE hcall
The behaviour of the Address Translation Mode on Interrupt resource is not consistently supported by all CPU versions or all KVM versions: KVM HV does not support mode 2, and does not support mode 3 on POWER7 or early POWER9 processesors. KVM PR only supports mode 0. TCG supports all modes (0, 2, 3) on CPUs with support for the corresonding LPCR[AIL] mode. This leads to inconsistencies in guest behaviour and could cause problems migrating guests. This was not noticable for Linux guests for a long time because the kernel only uses modes 0 and 3, and it used to consider AIL-3 to be advisory in that it would always keep the AIL-0 vectors around, so it did not matter whether or not interrupts were delivered according to the AIL mode. Recent Linux guests depend on AIL mode 3 working as specified in order to support the SCV facility interrupt. If AIL-3 can not be provided, then H_SET_MODE must return an error to Linux so it can disable the SCV facility (failure to do so can lead to userspace being able to crash the guest kernel). Add the ail-mode-3 capability to specify that AIL-3 is supported. AIL-0 is implied as the baseline, and AIL-2 is no longer supported by spapr. AIL-2 is not known to be used by any software, but support in TCG could be restored with an ail-mode-2 capability quite easily if a regression is reported. Modify the H_SET_MODE Address Translation Mode on Interrupt resource handler to check capabilities and correctly return error if not supported. KVM has a cap to advertise support for AIL-3. Reviewed-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Message-Id: <20230515160216.394612-1-npiggin@gmail.com> Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
Diffstat (limited to 'hw/ppc/spapr_caps.c')
-rw-r--r--hw/ppc/spapr_caps.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index b4283055c1..3fd45a6dec 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -614,6 +614,33 @@ static void cap_rpt_invalidate_apply(SpaprMachineState *spapr,
}
}
+static void cap_ail_mode_3_apply(SpaprMachineState *spapr,
+ uint8_t val, Error **errp)
+{
+ ERRP_GUARD();
+ PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+
+ if (!val) {
+ return;
+ }
+
+ if (tcg_enabled()) {
+ /* AIL-3 is only supported on POWER8 and above CPUs. */
+ if (!(pcc->insns_flags2 & PPC2_ISA207S)) {
+ error_setg(errp, "TCG only supports cap-ail-mode-3 on POWER8 and later CPUs");
+ error_append_hint(errp, "Try appending -machine cap-ail-mode-3=off\n");
+ return;
+ }
+ } else if (kvm_enabled()) {
+ if (!kvmppc_supports_ail_3()) {
+ error_setg(errp, "KVM implementation does not support cap-ail-mode-3");
+ error_append_hint(errp, "Try appending -machine cap-ail-mode-3=off\n");
+ return;
+ }
+ }
+}
+
SpaprCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
[SPAPR_CAP_HTM] = {
.name = "htm",
@@ -731,6 +758,15 @@ SpaprCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
.type = "bool",
.apply = cap_rpt_invalidate_apply,
},
+ [SPAPR_CAP_AIL_MODE_3] = {
+ .name = "ail-mode-3",
+ .description = "Alternate Interrupt Location (AIL) mode 3 support",
+ .index = SPAPR_CAP_AIL_MODE_3,
+ .get = spapr_cap_get_bool,
+ .set = spapr_cap_set_bool,
+ .type = "bool",
+ .apply = cap_ail_mode_3_apply,
+ },
};
static SpaprCapabilities default_caps_with_cpu(SpaprMachineState *spapr,
@@ -750,6 +786,7 @@ static SpaprCapabilities default_caps_with_cpu(SpaprMachineState *spapr,
0, spapr->max_compat_pvr)) {
caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF;
caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
+ caps.caps[SPAPR_CAP_AIL_MODE_3] = SPAPR_CAP_OFF;
}
if (!ppc_type_check_compat(cputype, CPU_POWERPC_LOGICAL_2_06_PLUS,