CCA planes provides new parameters to the VMM: - num_aux_planes defines the number of extra planes - rtt_tree_pp controls whether each plane has it's own page table tree, of if they share one tree. Signed-off-by: Steven Price --- arch/arm64/include/uapi/asm/kvm.h | 12 +++++ arch/arm64/kvm/rme.c | 77 +++++++++++++++++++++++++++++-- 2 files changed, 86 insertions(+), 3 deletions(-) diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index 9b5d67ecbc5e..1d83da0f3aaa 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -440,6 +440,8 @@ enum { /* List of configuration items accepted for KVM_CAP_ARM_RME_CONFIG_REALM */ #define ARM_RME_CONFIG_RPV 0 #define ARM_RME_CONFIG_HASH_ALGO 1 +#define ARM_RME_CONFIG_NUM_AUX_PLANES 2 +#define ARM_RME_CONFIG_RTT_TREE_PP 3 #define ARM_RME_CONFIG_HASH_ALGO_SHA256 0 #define ARM_RME_CONFIG_HASH_ALGO_SHA512 1 @@ -459,6 +461,16 @@ struct arm_rme_config { __u32 hash_algo; }; + /* cfg == ARM_RME_CONFIG_NUM_AUX_PLANES */ + struct { + __u32 num_aux_planes; + }; + + /* cfg == ARM_RME_CONFIG_RTT_TREE_PP */ + struct { + __u32 rtt_tree_pp; + }; + /* Fix the size of the union */ __u8 reserved[256]; }; diff --git a/arch/arm64/kvm/rme.c b/arch/arm64/kvm/rme.c index 6cb938957510..fca305da1843 100644 --- a/arch/arm64/kvm/rme.c +++ b/arch/arm64/kvm/rme.c @@ -43,6 +43,28 @@ bool kvm_rme_supports_sve(void) return rme_has_feature(RMI_FEATURE_REGISTER_0_SVE_EN); } +static bool kvm_rme_supports_rtt_tree_single(void) +{ + int i = u64_get_bits(rmm_feat_reg0, RMI_FEATURE_REGISTER_0_RTT_PLANE); + + switch (i) { + case RMI_RTT_PLANE_AUX: + return false; + case RMI_RTT_PLANE_AUX_SINGLE: + case RMI_RTT_PLANE_SINGLE: + return true; + default: + WARN(1, "Unknown encoding for RMI_FEATURE_REGISTER_0_RTT_PLANE: %#x", i); + } + return false; +} + +static unsigned int rme_get_max_num_aux_planes(void) +{ + return u64_get_bits(rmm_feat_reg0, + RMI_FEATURE_REGISTER_0_MAX_NUM_AUX_PLANES); +} + static int rmi_check_version(void) { struct arm_smccc_res res; @@ -1077,6 +1099,14 @@ int realm_map_protected(struct realm *realm, return -ENXIO; } +static unsigned long pi_index_to_s2tte(unsigned long idx) +{ + return FIELD_PREP(BIT(PTE_PI_IDX_0), (idx >> 0) & 1) | + FIELD_PREP(BIT(PTE_PI_IDX_1), (idx >> 1) & 1) | + FIELD_PREP(BIT(PTE_PI_IDX_2), (idx >> 2) & 1) | + FIELD_PREP(BIT(PTE_PI_IDX_3), (idx >> 3) & 1); +} + int realm_map_non_secure(struct realm *realm, unsigned long ipa, kvm_pfn_t pfn, @@ -1101,9 +1131,17 @@ int realm_map_non_secure(struct realm *realm, * so for now we permit both read and write. */ unsigned long desc = phys | - PTE_S2_MEMATTR(MT_S2_FWB_NORMAL) | - KVM_PTE_LEAF_ATTR_LO_S2_S2AP_R | - KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W; + PTE_S2_MEMATTR(MT_S2_FWB_NORMAL); + /* + * FIXME: Read+Write permissions for now, and no support yet + * for setting RMI_REALM_PARAM_FLAG1_RTT_S2AP_ENCODING + */ + if (1) + desc |= KVM_PTE_LEAF_ATTR_LO_S2_S2AP_R | + KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W; + else + desc |= pi_index_to_s2tte(RMI_BASE_PERM_RW_INDEX); + ret = rmi_rtt_map_unprotected(rd, ipa, map_level, desc); if (RMI_RETURN_STATUS(ret) == RMI_ERROR_RTT) { @@ -1653,6 +1691,33 @@ static int config_realm_hash_algo(struct realm *realm, return 0; } +static int config_num_aux_planes(struct realm *realm, + struct arm_rme_config *cfg) +{ + if (cfg->num_aux_planes > rme_get_max_num_aux_planes()) + return -EINVAL; + + realm->num_aux_planes = cfg->num_aux_planes; + realm->params->num_aux_planes = cfg->num_aux_planes; + + return 0; +} + +static int config_rtt_tree_pp(struct realm *realm, + struct arm_rme_config *cfg) +{ + if (!kvm_rme_supports_rtt_tree_single() && !cfg->rtt_tree_pp) + return -EINVAL; + + realm->rtt_tree_pp = !!cfg->rtt_tree_pp; + if (realm->rtt_tree_pp) + realm->params->flags1 |= RMI_REALM_PARAM_FLAG1_RTT_TREE_PP; + else + realm->params->flags1 &= ~RMI_REALM_PARAM_FLAG1_RTT_TREE_PP; + + return 0; +} + static int kvm_rme_config_realm(struct kvm *kvm, struct kvm_enable_cap *cap) { struct arm_rme_config cfg; @@ -1672,6 +1737,12 @@ static int kvm_rme_config_realm(struct kvm *kvm, struct kvm_enable_cap *cap) case ARM_RME_CONFIG_HASH_ALGO: r = config_realm_hash_algo(realm, &cfg); break; + case ARM_RME_CONFIG_NUM_AUX_PLANES: + r = config_num_aux_planes(realm, &cfg); + break; + case ARM_RME_CONFIG_RTT_TREE_PP: + r = config_rtt_tree_pp(realm, &cfg); + break; default: r = -EINVAL; } -- 2.43.0