From e8388e92e3bb6dbdd69ada6d7939e06e15875eeb Mon Sep 17 00:00:00 2001 From: Suraj Jitindar Singh Date: Tue, 13 Feb 2018 04:12:23 +0100 Subject: [PATCH 06/15] target/ppc/kvm: Add cap_ppc_safe_[cache/bounds_check/indirect_branch] RH-Author: Suraj Jitindar Singh Message-id: <1518495150-24134-3-git-send-email-sursingh@redhat.com> Patchwork-id: 78984 O-Subject: [RHEL7.5 qemu-kvm-rhev PATCH 2/9] target/ppc/kvm: Add cap_ppc_safe_[cache/bounds_check/indirect_branch] Bugzilla: 1532050 RH-Acked-by: David Gibson RH-Acked-by: Laurent Vivier RH-Acked-by: Thomas Huth From: Suraj Jitindar Singh Add three new kvm capabilities used to represent the level of host support for three corresponding workarounds. Host support for each of the capabilities is queried through the new ioctl KVM_PPC_GET_CPU_CHAR which returns four uint64 quantities. The first two, character and behaviour, represent the available characteristics of the cpu and the behaviour of the cpu respectively. The second two, c_mask and b_mask, represent the mask of known bits for the character and beheviour dwords respectively. Signed-off-by: Suraj Jitindar Singh Reviewed-by: David Gibson [dwg: Correct some compile errors due to name change in final kernel patch version] Signed-off-by: David Gibson (cherry picked from commit 8acc2ae5e91681ceda3ff4cf946ebf163f6012e9) Signed-off-by: Miroslav Rezanina Conflicts: target/ppc/kvm.c Minor massage required due to lack of commit downstream: 2e9c10eb (ppc: spapr: use generic cpu_model parsing) Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1532050 Signed-off-by: Suraj Jitindar Singh --- include/hw/ppc/spapr.h | 12 +++++++++++ target/ppc/kvm.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++ target/ppc/kvm_ppc.h | 18 ++++++++++++++++ 3 files changed, 88 insertions(+) diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 7156a70..6090f3d 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -297,6 +297,18 @@ struct sPAPRMachineState { #define H_DABRX_KERNEL (1ULL<<(63-62)) #define H_DABRX_USER (1ULL<<(63-63)) +/* Values for KVM_PPC_GET_CPU_CHAR & H_GET_CPU_CHARACTERISTICS */ +#define H_CPU_CHAR_SPEC_BAR_ORI31 PPC_BIT(0) +#define H_CPU_CHAR_BCCTRL_SERIALISED PPC_BIT(1) +#define H_CPU_CHAR_L1D_FLUSH_ORI30 PPC_BIT(2) +#define H_CPU_CHAR_L1D_FLUSH_TRIG2 PPC_BIT(3) +#define H_CPU_CHAR_L1D_THREAD_PRIV PPC_BIT(4) +#define H_CPU_CHAR_HON_BRANCH_HINTS PPC_BIT(5) +#define H_CPU_CHAR_THR_RECONF_TRIG PPC_BIT(6) +#define H_CPU_BEHAV_FAVOUR_SECURITY PPC_BIT(0) +#define H_CPU_BEHAV_L1D_FLUSH_PR PPC_BIT(1) +#define H_CPU_BEHAV_BNDS_CHK_SPEC_BAR PPC_BIT(2) + /* Each control block has to be on a 4K boundary */ #define H_CB_ALIGNMENT 4096 diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index ce7e2ec..7a7bc3b 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -92,6 +92,9 @@ static int cap_mmu_radix; static int cap_mmu_hash_v3; static int cap_resize_hpt; static int cap_ppc_pvr_compat; +static int cap_ppc_safe_cache; +static int cap_ppc_safe_bounds_check; +static int cap_ppc_safe_indirect_branch; static uint32_t debug_inst_opcode; @@ -124,6 +127,7 @@ static bool kvmppc_is_pr(KVMState *ks) } static int kvm_ppc_register_host_cpu_type(void); +static void kvmppc_get_cpu_characteristics(KVMState *s); int kvm_arch_init(MachineState *ms, KVMState *s) { @@ -150,6 +154,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) cap_mmu_radix = kvm_vm_check_extension(s, KVM_CAP_PPC_MMU_RADIX); cap_mmu_hash_v3 = kvm_vm_check_extension(s, KVM_CAP_PPC_MMU_HASH_V3); cap_resize_hpt = kvm_vm_check_extension(s, KVM_CAP_SPAPR_RESIZE_HPT); + kvmppc_get_cpu_characteristics(s); /* * Note: setting it to false because there is not such capability * in KVM at this moment. @@ -2473,6 +2478,59 @@ bool kvmppc_has_cap_mmu_hash_v3(void) return cap_mmu_hash_v3; } +static void kvmppc_get_cpu_characteristics(KVMState *s) +{ + struct kvm_ppc_cpu_char c; + int ret; + + /* Assume broken */ + cap_ppc_safe_cache = 0; + cap_ppc_safe_bounds_check = 0; + cap_ppc_safe_indirect_branch = 0; + + ret = kvm_vm_check_extension(s, KVM_CAP_PPC_GET_CPU_CHAR); + if (!ret) { + return; + } + ret = kvm_vm_ioctl(s, KVM_PPC_GET_CPU_CHAR, &c); + if (ret < 0) { + return; + } + /* Parse and set cap_ppc_safe_cache */ + if (~c.behaviour & c.behaviour_mask & H_CPU_BEHAV_L1D_FLUSH_PR) { + cap_ppc_safe_cache = 2; + } else if ((c.character & c.character_mask & H_CPU_CHAR_L1D_THREAD_PRIV) && + (c.character & c.character_mask + & (H_CPU_CHAR_L1D_FLUSH_ORI30 | H_CPU_CHAR_L1D_FLUSH_TRIG2))) { + cap_ppc_safe_cache = 1; + } + /* Parse and set cap_ppc_safe_bounds_check */ + if (~c.behaviour & c.behaviour_mask & H_CPU_BEHAV_BNDS_CHK_SPEC_BAR) { + cap_ppc_safe_bounds_check = 2; + } else if (c.character & c.character_mask & H_CPU_CHAR_SPEC_BAR_ORI31) { + cap_ppc_safe_bounds_check = 1; + } + /* Parse and set cap_ppc_safe_indirect_branch */ + if (c.character & H_CPU_CHAR_BCCTRL_SERIALISED) { + cap_ppc_safe_indirect_branch = 2; + } +} + +int kvmppc_get_cap_safe_cache(void) +{ + return cap_ppc_safe_cache; +} + +int kvmppc_get_cap_safe_bounds_check(void) +{ + return cap_ppc_safe_bounds_check; +} + +int kvmppc_get_cap_safe_indirect_branch(void) +{ + return cap_ppc_safe_indirect_branch; +} + PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void) { uint32_t host_pvr = mfpvr(); diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h index e6711fc..9da92a9 100644 --- a/target/ppc/kvm_ppc.h +++ b/target/ppc/kvm_ppc.h @@ -62,6 +62,9 @@ bool kvmppc_has_cap_fixup_hcalls(void); bool kvmppc_has_cap_htm(void); bool kvmppc_has_cap_mmu_radix(void); bool kvmppc_has_cap_mmu_hash_v3(void); +int kvmppc_get_cap_safe_cache(void); +int kvmppc_get_cap_safe_bounds_check(void); +int kvmppc_get_cap_safe_indirect_branch(void); int kvmppc_enable_hwrng(void); int kvmppc_put_books_sregs(PowerPCCPU *cpu); PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void); @@ -299,6 +302,21 @@ static inline bool kvmppc_has_cap_mmu_hash_v3(void) return false; } +static inline int kvmppc_get_cap_safe_cache(void) +{ + return 0; +} + +static inline int kvmppc_get_cap_safe_bounds_check(void) +{ + return 0; +} + +static inline int kvmppc_get_cap_safe_indirect_branch(void) +{ + return 0; +} + static inline int kvmppc_enable_hwrng(void) { return -1; -- 1.8.3.1