KVM: arm64: Add support for hypercall services selection
Subsystems (5)
v7 cover KVM: arm64: Add support for hypercall services selection
Hello,
Continuing the discussion from [1], the series tries to add support for the userspace to elect the hypercall services that it wishes to expose to the guest, rather than the guest discovering them unconditionally. The idea employed by the series was taken from
[1] as suggested by Marc Z.
In a broad sense, the concept is similar to the current implementation of PSCI interface- create a 'firmware psuedo-register' to handle the firmware revisions. The series extends this idea to all the other hypercalls such as TRNG (True Random Number Generator), PV_TIME (Paravirtualized Time), and PTP (Precision Time protocol).
For better categorization and future scaling, these firmware registers are categorized based on the service call owners. Also, unlike the existing firmware psuedo-registers, they hold the features supported in the form of a bitmap.
During the VM initialization, the registers holds an upper-limit of the features supported by each one of them. It's expected that the userspace discover the features provided by each register via GET_ONE_REG, and writeback the desired values using SET_ONE_REG. KVM allows this modification only until the VM has started.
Some of the standard function-ids, such as ARM_SMCCC_VERSION_FUNC_ID, need not be associated with a feature bit. For such ids, the series introduced an allowed-list (in kvm_hvc_call_default_allowed()), that holds all such ids. As a result, the functions that are not elected by userspace, or if they are not a part of this allowed-list, will be denied for when the guests invoke them.
Older VMMs can simply ignore this interface and the hypercall services will be exposed unconditionally to the guests, thus ensuring backward compatibility.
The patches are based off of mainline kernel 5.18-rc5, with the selftest patches from [2] applied.
Patch-1 factors out the non-PSCI related interface from psci.c to hypercalls.c, as the series would extend the list in the upcoming patches.
Patch-2 sets up the framework for the bitmap firmware psuedo-registers. It includes read/write support for the registers, and a helper to check if a particular hypercall service is supported for the guest. It also adds the register KVM_REG_ARM_STD_HYP_BMAP to support ARM's standard secure services.
Patch-3 introduces the firmware register, KVM_REG_ARM_STD_HYP_BMAP, which holds the standard hypervisor services (such as PV_TIME).
Patch-4 introduces the firmware register, KVM_REG_ARM_VENDOR_HYP_BMAP, which holds the vendor specific hypercall services.
Patch-5,6 Add the necessary documentation for the newly added firmware registers.
Patch-7 imports the SMCCC definitions from linux/arm-smccc.h into tools/ for further use in selftests.
Patch-8 adds the selftest to test the guest (using 'hvc') and userspace interfaces (SET/GET_ONE_REG).
Patch-9 adds these firmware registers into the get-reg-list selftest.
[1]: https://lore.kernel.org/kvmarm/[email protected]/T/
[2]: https://lore.kernel.org/all/[email protected]/
Regards,
Raghavendra
v6 -> v7:
Addressed the comments by Gavin and Reiji:
- kvm_arm_set_fw_reg_bmap() is optimzed to avoid unnecessary serialization of kvm->lock by checking for the KVM_ARCH_FLAG_HAS_RAN_ONCE flag or for a bitmap update before taking the lock (Reiji).
- kvm_psci_func_id_is_valid() avoids depending on *vcpu to figure out if the PSCI version is 0.1. Instead, it checks the same using KVM_PSCI_FN() for range 0 to 3 (Reiji).
- Fixed typos and comments (Gavin).
v5 -> v6:
Addressed the comments by Marc and Gavin:
- Bitmaps are represented using 'unsigned long' inctead of 'u64' (Marc).
- Replaced the array holding the allowed-list, hvc_func_default_allowed_list[], which looked up the func_id using a loop, with a switch-case statement (Marc).
- kvm_arm_set_fw_reg_bmap() now always returns -EBUSY for any 'write' of the bitmap value after the VM has started running. Documentation is adjusted accordingly (Marc).
- kvm_psci_func_id_is_valid() is moved from an inline function to kvm/psci.c (Marc).
- Merged ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID into bit-0 of the vendor hypervisor firmware register (Gavin).
- Macro optimizations and replace arg0 with arg1 (to comply with KVM convention) in hypercalls.c selftest (Gavin).
- Dropped the patch v5 10/10 (Add KVM_REG_ARM_FW_REG(3) to get-reg-list) as it was already uploaded by Andrew.
- Fixed typos
v4 -> v5:
Addressed comments by Oliver (thank you!):
- Rebased the series to accommodate ARM_SMCCC_ARCH_WORKAROUND_3 and PSCI 1.1 changes, and capturing VM's first run.
- Removed the patches related to register scoping (v4 02/13 and 03/13). I plan to re-introduce them in its own series.
- Dropped the patch that captures VM's first run.
- Moved the bitmap feature firmware registers to its own CORPOC space (0x0016).
- Move the KVM_REG_ARM_*_BIT_MAX definitions from uapi header to internal header (arm_hypercalls.h).
- Renamed the hypercall descriptor to 'struct kvm_smccc_features', and kvm_hvc_call_supported() to kvm_hvc_call_allowed().
- Introduced an allowed-list to hold the function-ids that aren't represented by feature-bits.
- Introduced kvm_psci_func_id_is_valid() to check if a given function-id is a valid PSCI id, which is used in kvm_hvc_call_allowed().
- Introduced KVM_REG_ARM_VENDOR_HYP_BIT_FUNC_FEAT as bit-0 of KVM_REG_ARM_VENDOR_HYP_BMAP register and KVM_REG_ARM_VENDOR_HYP_BIT_PTP is moved to bit-1.
- Updated the arm-smccc.h import to include the definition of ARM_SMCCC_ARCH_WORKAROUND_3.
- Introduced the KVM_REG_ARM_FW_FEAT_BMAP COPROC definition to get-reg-list selftest.
- Created a new patch to include KVM_REG_ARM_FW_REG(3) in get-reg-list.
v3 -> v4
Addressed comments and took suggestions by Reiji, Oliver, Marc, Sean and Jim:
- Renamed and moved the VM has run once check to arm64.
- Introduced the capability to dynamically modify the register encodings to include the scope information.
- Replaced mutex_lock with READ_ONCE and WRITE_ONCE when the bitmaps are accessed.
- The hypercalls selftest re-runs with KVM_CAP_ARM_REG_SCOPE enabled.
v2 -> v3
Addressed comments by Marc and Andrew:
- Dropped kvm_vcpu_has_run_once() implementation.
- Redifined kvm_vm_has_run_once() as kvm_vm_has_started() in the core KVM code that introduces a new field, 'vm_started', to track this.
- KVM_CAP_ARM_HVC_FW_REG_BMAP returns the number of psuedo-firmware bitmap registers upon a 'read'. Support for 'write' removed.
- Removed redundant spinlock, 'fw_reg_bmap_enabled' fields from the hypercall descriptor structure.
- A separate sub-struct to hold the bitmap info is removed. The bitmap info is directly stored in the hypercall descriptor structure (struct kvm_hvc_desc).
v1 -> v2
Addressed comments by Oliver (thanks!):
- Introduced kvm_vcpu_has_run_once() and kvm_vm_has_run_once() in the core kvm code, rather than relying on ARM specific vcpu->arch.has_run_once.
- Writing to KVM_REG_ARM_PSCI_VERSION is done in hypercalls.c itself, rather than separating out to psci.c.
- Introduced KVM_CAP_ARM_HVC_FW_REG_BMAP to enable the extension.
- Tracks the register accesses from VMM to decide whether to sanitize a register or not, as opposed to sanitizing upon the first 'write' in v1.
- kvm_hvc_call_supported() is implemented using a direct switch-case statement, instead of looping over all the registers to pick the register for the function-id.
- Replaced the register bit definitions with #defines, instead of enums.
- Removed the patch v1-06/08 that imports the firmware register definitions as it's not needed.
- Separated out the documentations in its own patch, and the renaming of hypercalls.rst to psci.rst into another patch.
- Add the new firmware registers to get-reg-list KVM selftest.
v1: https://lore.kernel.org/kvmarm/[email protected]/
v2: https://lore.kernel.org/kvmarm/[email protected]/
v3: https://lore.kernel.org/linux-arm-kernel/[email protected]/
v4: https://lore.kernel.org/lkml/[email protected]/
v5: https://lore.kernel.org/lkml/[email protected]/
v6: https://lore.kernel.org/kvmarm/[email protected]/
Raghavendra Rao Ananta (9):
KVM: arm64: Factor out firmware register handling from psci.c
KVM: arm64: Setup a framework for hypercall bitmap firmware registers
KVM: arm64: Add standard hypervisor firmware register
KVM: arm64: Add vendor hypervisor firmware register
Docs: KVM: Rename psci.rst to hypercalls.rst
Docs: KVM: Add doc for the bitmap firmware registers
tools: Import ARM SMCCC definitions
selftests: KVM: aarch64: Introduce hypercall ABI test
selftests: KVM: aarch64: Add the bitmap firmware registers to
get-reg-list
Documentation/virt/kvm/api.rst | 16 + Documentation/virt/kvm/arm/hypercalls.rst | 135 +++++++ Documentation/virt/kvm/arm/psci.rst | 77 ---- arch/arm64/include/asm/kvm_host.h | 16 + arch/arm64/include/uapi/asm/kvm.h | 16 + arch/arm64/kvm/arm.c | 1 + arch/arm64/kvm/guest.c | 10 +- arch/arm64/kvm/hypercalls.c | 325 ++++++++++++++++- arch/arm64/kvm/psci.c | 186 +--------- include/kvm/arm_hypercalls.h | 17 + include/kvm/arm_psci.h | 9 +- tools/include/linux/arm-smccc.h | 193 ++++++++++ tools/testing/selftests/kvm/.gitignore | 1 + tools/testing/selftests/kvm/Makefile | 1 + .../selftests/kvm/aarch64/get-reg-list.c | 8 + .../selftests/kvm/aarch64/hypercalls.c | 336 ++++++++++++++++++ 16 files changed, 1078 insertions(+), 269 deletions(-) create mode 100644 Documentation/virt/kvm/arm/hypercalls.rst delete mode 100644 Documentation/virt/kvm/arm/psci.rst create mode 100644 tools/include/linux/arm-smccc.h create mode 100644 tools/testing/selftests/kvm/aarch64/hypercalls.c
Signature · 6 lines
2.36.0.464.gb9c8b46e94-goog _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v7 1/9 KVM: arm64: Factor out firmware register handling from psci.c
Common hypercall firmware register handing is currently employed by psci.c. Since the upcoming patches add more of these registers, it's better to move the generic handling to hypercall.c for a cleaner presentation.
While we are at it, collect all the firmware registers under fw_reg_ids[] to help implement kvm_arm_get_fw_num_regs() and kvm_arm_copy_fw_reg_indices() in a generic way. Also, define KVM_REG_FEATURE_LEVEL_MASK using a GENMASK instead.
No functional change intended.
--- arch/arm64/kvm/guest.c | 2 +- arch/arm64/kvm/hypercalls.c | 185 +++++++++++++++++++++++++++++++++++ arch/arm64/kvm/psci.c | 183 ---------------------------------- include/kvm/arm_hypercalls.h | 7 ++ include/kvm/arm_psci.h | 7 -- 5 files changed, 193 insertions(+), 191 deletions(-)
arch/arm64/kvm/guest.c +1 -1
@@ -18,7 +18,7 @@#include <linux/string.h> #include <linux/vmalloc.h> #include <linux/fs.h> -#include <kvm/arm_psci.h> +#include <kvm/arm_hypercalls.h> #include <asm/cputype.h> #include <linux/uaccess.h> #include <asm/fpsimd.h>
arch/arm64/kvm/hypercalls.c +185 -0
188 lines not on this page · raw message
arch/arm64/kvm/psci.c +0 -183
186 lines not on this page · raw message
include/kvm/arm_hypercalls.h +7 -0
@@ -40,4 +40,11 @@ static inline void smccc_set_retval(struct kvm_vcpu *vcpu, vcpu_set_reg(vcpu, 3, a3); } +struct kvm_one_reg ; + +int kvm_arm_get_fw_num_regs (struct kvm_vcpu *vcpu); +int kvm_arm_copy_fw_reg_indices (struct kvm_vcpu *vcpu,u64 __user *uindices); +int kvm_arm_get_fw_reg (struct kvm_vcpu *vcpu,const struct kvm_one_reg *reg); +int kvm_arm_set_fw_reg (struct kvm_vcpu *vcpu,const struct kvm_one_reg *reg); +#endif
include/kvm/arm_psci.h +0 -7
@@ -39,11 +39,4 @@ static inline int kvm_psci_version(struct kvm_vcpu *vcpu)int kvm_psci_call (struct kvm_vcpu *vcpu); -struct kvm_one_reg ; - -int kvm_arm_get_fw_num_regs (struct kvm_vcpu *vcpu); -int kvm_arm_copy_fw_reg_indices (struct kvm_vcpu *vcpu,u64 __user *uindices); -int kvm_arm_get_fw_reg (struct kvm_vcpu *vcpu,const struct kvm_one_reg *reg); -int kvm_arm_set_fw_reg (struct kvm_vcpu *vcpu,const struct kvm_one_reg *reg); -#endif /* __KVM_ARM_PSCI_H__ */
Signature · 6 lines
2.36.0.464.gb9c8b46e94-goog _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Marc Zyngier
maintainerRe: [PATCH v7 1/9] KVM: arm64: Factor out firmware register handling from psci.c
Quoted 10 lines · Raghavendra Rao Ananta
Common hypercall firmware register handing is currently employed by
psci.c. Since the upcoming patches add more of these registers, it's better to move the generic handling tohypercall.cfor a cleaner presentation.While we are at it, collect all the firmware registers under fw_reg_ids[] to help implement
kvm_arm_get_fw_num_regs()andkvm_arm_copy_fw_reg_indices()in a generic way. Also, defineKVM_REG_FEATURE_LEVEL_MASKusing a GENMASK instead.
Yup. See below though.
Quoted 52 lines
No functional change intended.
Signed-off-by Raghavendra Rao Ananta <[email protected]>Reviewed-by Oliver Upton <[email protected]>Reviewed-by Gavin Shan <[email protected]>--- arch/arm64/kvm/guest.c | 2 +- arch/arm64/kvm/hypercalls.c | 185 +++++++++++++++++++++++++++++++++++ arch/arm64/kvm/psci.c | 183 ---------------------------------- include/kvm/arm_hypercalls.h | 7 ++ include/kvm/arm_psci.h | 7 -- 5 files changed, 193 insertions(+), 191 deletions(-)arch/arm64/kvm/guest.c +1
-1@@ -18,7 +18,7 @@#include <linux/string.h> #include <linux/vmalloc.h> #include <linux/fs.h> -#include <kvm/arm_psci.h> +#include <kvm/arm_hypercalls.h> #include <asm/cputype.h> #include <linux/uaccess.h> #include <asm/fpsimd.h> arch/arm64/kvm/hypercalls.c +17
-0@@ -158,3 +158,188 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)smccc_set_retval (vcpu, val[0 ], val[1 ], val[2 ], val[3 ]);return 1 ; } + +static const u64 kvm_arm_fw_reg_ids[] = { +KVM_REG_ARM_PSCI_VERSION , +KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1 , +KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2 , +KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3 , +}; + +int kvm_arm_get_fw_num_regs (struct kvm_vcpu *vcpu) +{ +return ARRAY_SIZE (kvm_arm_fw_reg_ids); +} + +int kvm_arm_copy_fw_reg_indices (struct kvm_vcpu *vcpu,u64 __user *uindices) +{ +int i; +
arch/arm64/kvm/hypercalls.c int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) · line 187
Quoted 10 lines
arch/arm64/kvm/hypercalls.c +10
-0+for (i =0 ; i <ARRAY_SIZE (kvm_arm_fw_reg_ids); i++) { +if (put_user (kvm_arm_fw_reg_ids[i], uindices++)) +return -EFAULT ; + } + +return 0 ; +} + +#define KVM_REG_FEATURE_LEVEL_WIDTH 4 +#define KVM_REG_FEATURE_LEVEL_MASK GENMASK(KVM_REG_FEATURE_LEVEL_WIDTH, 0)
which translates in GENMASK(4, 0), which is 5 bit wide. Not what you want.
Thanks,
M.
Signature · 5 lines
Without deviation from the norm, progress is not possible. _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v7 2/9 KVM: arm64: Setup a framework for hypercall bitmap firmware registers
In reply to Raghavendra Rao AnantaKVM regularly introduces new hypercall services to the guests without any consent from the userspace. This means, the guests can observe hypercall services in and out as they migrate across various host kernel versions. This could be a major problem if the guest discovered a hypercall, started using it, and after getting migrated to an older kernel realizes that it's no longer available. Depending on how the guest handles the change, there's a potential chance that the guest would just panic.
As a result, there's a need for the userspace to elect the services that it wishes the guest to discover. It can elect these services based on the kernels spread across its (migration) fleet. To remedy this, extend the existing firmware pseudo-registers, such as KVM_REG_ARM_PSCI_VERSION, but by creating a new COPROC register space for all the hypercall services available.
These firmware registers are categorized based on the service call owners, but unlike the existing firmware pseudo-registers, they hold the features supported in the form of a bitmap.
During the VM initialization, the registers are set to upper-limit of the features supported by the corresponding registers. It's expected that the VMMs discover the features provided by each register via GET_ONE_REG, and write back the desired values using SET_ONE_REG. KVM allows this modification only until the VM has started.
Some of the standard features are not mapped to any bits of the registers. But since they can recreate the original problem of making it available without userspace's consent, they need to be explicitly added to the case-list in kvm_hvc_call_default_allowed(). Any function-id that's not enabled via the bitmap, or not listed in kvm_hvc_call_default_allowed, will be returned as SMCCC_RET_NOT_SUPPORTED to the guest.
Older userspace code can simply ignore the feature and the hypercall services will be exposed unconditionally to the guests, thus ensuring backward compatibility.
In this patch, the framework adds the register only for ARM's standard secure services (owner value 4). Currently, this includes support only for ARM True Random Number Generator (TRNG) service, with bit-0 of the register representing mandatory features of v1.0. Other services are momentarily added in the upcoming patches.
--- arch/arm64/include/asm/kvm_host.h | 12 ++++ arch/arm64/include/uapi/asm/kvm.h | 9 +++ arch/arm64/kvm/arm.c | 1 + arch/arm64/kvm/guest.c | 8 ++- arch/arm64/kvm/hypercalls.c | 106 ++++++++++++++++++++++++++++++ arch/arm64/kvm/psci.c | 13 ++++ include/kvm/arm_hypercalls.h | 6 ++ include/kvm/arm_psci.h | 2 +- 8 files changed, 154 insertions(+), 3 deletions(-)
arch/arm64/include/asm/kvm_host.h +12 -0
@@ -101,6 +101,15 @@ struct kvm_s2_mmu {struct kvm_arch_memory_slot { }; +/** +* struct kvm_smccc_features: Descriptor of the hypercall services exposed to the guests +* +* @std_bmap: Bitmap of standard secure service calls +*/ +struct kvm_smccc_features { +unsigned long std_bmap; +}; +struct kvm_arch {struct kvm_s2_mmu mmu;
@@ -150,6 +159,9 @@ struct kvm_arch {u8 pfr0_csv2;u8 pfr0_csv3; + +/* Hypercall features firmware registers' descriptor */ +struct kvm_smccc_features smccc_feat; };struct kvm_vcpu_fault_info {
arch/arm64/include/uapi/asm/kvm.h +9 -0
@@ -332,6 +332,15 @@ struct kvm_arm_copy_mte_tags {#define KVM_ARM64_SVE_VLS_WORDS \ ((KVM_ARM64_SVE_VQ_MAX - KVM_ARM64_SVE_VQ_MIN) / 64 + 1) +/* Bitmap feature firmware registers */ +#define KVM_REG_ARM_FW_FEAT_BMAP (0x0016 << KVM_REG_ARM_COPROC_SHIFT) +#define KVM_REG_ARM_FW_FEAT_BMAP_REG (r) (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \ + KVM_REG_ARM_FW_FEAT_BMAP | \ + ((r) & 0xffff)) + +#define KVM_REG_ARM_STD_BMAP KVM_REG_ARM_FW_FEAT_BMAP_REG(0) +#define KVM_REG_ARM_STD_BIT_TRNG_V1_0 0 +/* Device Control API: ARM VGIC */ #define KVM_DEV_ARM_VGIC_GRP_ADDR 0#define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1
arch/arm64/kvm/arm.c +1 -0
@@ -156,6 +156,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) kvm->arch.max_vcpus =kvm_arm_default_max_vcpus ();set_default_spectre (kvm); +kvm_arm_init_hypercalls (kvm);return ret; out_free_stage2_pgd:
arch/arm64/kvm/guest.c +6 -2
@@ -756,7 +756,9 @@ int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)switch (reg->id &KVM_REG_ARM_COPROC_MASK ) {case KVM_REG_ARM_CORE :return get_core_reg (vcpu, reg); -case KVM_REG_ARM_FW :return kvm_arm_get_fw_reg (vcpu, reg); +case KVM_REG_ARM_FW : +case KVM_REG_ARM_FW_FEAT_BMAP : +return kvm_arm_get_fw_reg (vcpu, reg);case KVM_REG_ARM64_SVE :return get_sve_reg (vcpu, reg); }
@@ -774,7 +776,9 @@ int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)switch (reg->id &KVM_REG_ARM_COPROC_MASK ) {case KVM_REG_ARM_CORE :return set_core_reg (vcpu, reg); -case KVM_REG_ARM_FW :return kvm_arm_set_fw_reg (vcpu, reg); +case KVM_REG_ARM_FW : +case KVM_REG_ARM_FW_FEAT_BMAP : +return kvm_arm_set_fw_reg (vcpu, reg);case KVM_REG_ARM64_SVE :return set_sve_reg (vcpu, reg); }
arch/arm64/kvm/hypercalls.c +106 -0
156 lines not on this page · raw message
arch/arm64/kvm/psci.c +13 -0
@@ -437,3 +437,16 @@ int kvm_psci_call(struct kvm_vcpu *vcpu)return -EINVAL ; } } + +bool kvm_psci_func_id_is_valid (u32 func_id) +{ +if (ARM_SMCCC_OWNER_NUM (func_id) ==ARM_SMCCC_OWNER_STANDARD && +ARM_SMCCC_FUNC_NUM (func_id) >=0 &&ARM_SMCCC_FUNC_NUM (func_id) <=0x1f ) +return true; + +/* KVM's PSCI 0.1 doesn't comply with SMCCC, and has its own function-id base and range */ +if (func_id >=KVM_PSCI_FN (0 ) && func_id <=KVM_PSCI_FN (3 )) +return true; + +return false; +}
include/kvm/arm_hypercalls.h +6 -0
@@ -6,6 +6,11 @@#include <asm/kvm_emulate.h> +/* Last valid bit of the bitmapped firmware registers */ +#define KVM_REG_ARM_STD_BMAP_BIT_MAX 0 + +#define KVM_ARM_SMCCC_STD_FEATURES GENMASK(KVM_REG_ARM_STD_BMAP_BIT_MAX, 0) +int kvm_hvc_call_handler (struct kvm_vcpu *vcpu);static inline u32 smccc_get_function (struct kvm_vcpu *vcpu)
@@ -42,6 +47,7 @@ static inline void smccc_set_retval(struct kvm_vcpu *vcpu,struct kvm_one_reg ; +void kvm_arm_init_hypercalls (struct kvm *kvm);int kvm_arm_get_fw_num_regs (struct kvm_vcpu *vcpu);int kvm_arm_copy_fw_reg_indices (struct kvm_vcpu *vcpu,u64 __user *uindices);int kvm_arm_get_fw_reg (struct kvm_vcpu *vcpu,const struct kvm_one_reg *reg);
include/kvm/arm_psci.h +1 -1
@@ -36,7 +36,7 @@ static inline int kvm_psci_version(struct kvm_vcpu *vcpu) return KVM_ARM_PSCI_0_1; } -int kvm_psci_call (struct kvm_vcpu *vcpu); +bool kvm_psci_func_id_is_valid (u32 func_id);#endif /* __KVM_ARM_PSCI_H__ */
Signature · 6 lines
2.36.0.464.gb9c8b46e94-goog _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Marc Zyngier
maintainerRe: [PATCH v7 2/9] KVM: arm64: Setup a framework for hypercall bitmap firmware registers
Quoted 151 lines · Raghavendra Rao Ananta
KVM regularly introduces new hypercall services to the guests without any consent from the userspace. This means, the guests can observe hypercall services in and out as they migrate across various host kernel versions. This could be a major problem if the guest discovered a hypercall, started using it, and after getting migrated to an older kernel realizes that it's no longer available. Depending on how the guest handles the change, there's a potential chance that the guest would just panic.
As a result, there's a need for the userspace to elect the services that it wishes the guest to discover. It can elect these services based on the kernels spread across its (migration) fleet. To remedy this, extend the existing firmware pseudo-registers, such as
KVM_REG_ARM_PSCI_VERSION, but by creating a new COPROC register space for all the hypercall services available.These firmware registers are categorized based on the service call owners, but unlike the existing firmware pseudo-registers, they hold the features supported in the form of a bitmap.
During the VM initialization, the registers are set to upper-limit of the features supported by the corresponding registers. It's expected that the VMMs discover the features provided by each register via
GET_ONE_REG, and write back the desired values usingSET_ONE_REG. KVM allows this modification only until the VM has started.Some of the standard features are not mapped to any bits of the registers. But since they can recreate the original problem of making it available without userspace's consent, they need to be explicitly added to the case-list in
kvm_hvc_call_default_allowed(). Any function-id that's not enabled via the bitmap, or not listed inkvm_hvc_call_default_allowed, will be returned asSMCCC_RET_NOT_SUPPORTEDto the guest.Older userspace code can simply ignore the feature and the hypercall services will be exposed unconditionally to the guests, thus ensuring backward compatibility.
In this patch, the framework adds the register only for ARM's standard secure services (owner value 4). Currently, this includes support only for ARM True Random Number Generator (TRNG) service, with bit-0 of the register representing mandatory features of v1.0. Other services are momentarily added in the upcoming patches.
Signed-off-by Raghavendra Rao Ananta <[email protected]>Reviewed-by Gavin Shan <[email protected]>--- arch/arm64/include/asm/kvm_host.h | 12 ++++ arch/arm64/include/uapi/asm/kvm.h | 9 +++ arch/arm64/kvm/arm.c | 1 + arch/arm64/kvm/guest.c | 8 ++- arch/arm64/kvm/hypercalls.c | 106 ++++++++++++++++++++++++++++++ arch/arm64/kvm/psci.c | 13 ++++ include/kvm/arm_hypercalls.h | 6 ++ include/kvm/arm_psci.h | 2 +- 8 files changed, 154 insertions(+), 3 deletions(-)arch/arm64/include/asm/kvm_host.h +12
-0@@ -101,6 +101,15 @@ struct kvm_s2_mmu {struct kvm_arch_memory_slot { }; +/** +* struct kvm_smccc_features: Descriptor of the hypercall services exposed to the guests +* +* @std_bmap: Bitmap of standard secure service calls +*/ +struct kvm_smccc_features { +unsigned long std_bmap; +}; +struct kvm_arch {struct kvm_s2_mmu mmu;@@ -150,6 +159,9 @@ struct kvm_arch {u8 pfr0_csv2;u8 pfr0_csv3; + +/* Hypercall features firmware registers' descriptor */ +struct kvm_smccc_features smccc_feat; };struct kvm_vcpu_fault_info {arch/arm64/include/uapi/asm/kvm.h +9
-0@@ -332,6 +332,15 @@ struct kvm_arm_copy_mte_tags {#define KVM_ARM64_SVE_VLS_WORDS \ ((KVM_ARM64_SVE_VQ_MAX - KVM_ARM64_SVE_VQ_MIN) / 64 + 1) +/* Bitmap feature firmware registers */ +#define KVM_REG_ARM_FW_FEAT_BMAP (0x0016 << KVM_REG_ARM_COPROC_SHIFT) +#define KVM_REG_ARM_FW_FEAT_BMAP_REG (r) (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \ + KVM_REG_ARM_FW_FEAT_BMAP | \ + ((r) & 0xffff)) + +#define KVM_REG_ARM_STD_BMAP KVM_REG_ARM_FW_FEAT_BMAP_REG(0) +#define KVM_REG_ARM_STD_BIT_TRNG_V1_0 0 +/* Device Control API: ARM VGIC */ #define KVM_DEV_ARM_VGIC_GRP_ADDR 0#define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1arch/arm64/kvm/arm.c +1
-0@@ -156,6 +156,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) kvm->arch.max_vcpus =kvm_arm_default_max_vcpus ();set_default_spectre (kvm); +kvm_arm_init_hypercalls (kvm);return ret; out_free_stage2_pgd:arch/arm64/kvm/guest.c +6
-2@@ -756,7 +756,9 @@ int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)switch (reg->id &KVM_REG_ARM_COPROC_MASK ) {case KVM_REG_ARM_CORE :return get_core_reg (vcpu, reg); -case KVM_REG_ARM_FW :return kvm_arm_get_fw_reg (vcpu, reg); +case KVM_REG_ARM_FW : +case KVM_REG_ARM_FW_FEAT_BMAP : +return kvm_arm_get_fw_reg (vcpu, reg);case KVM_REG_ARM64_SVE :return get_sve_reg (vcpu, reg); }@@ -774,7 +776,9 @@ int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)switch (reg->id &KVM_REG_ARM_COPROC_MASK ) {case KVM_REG_ARM_CORE :return set_core_reg (vcpu, reg); -case KVM_REG_ARM_FW :return kvm_arm_set_fw_reg (vcpu, reg); +case KVM_REG_ARM_FW : +case KVM_REG_ARM_FW_FEAT_BMAP : +return kvm_arm_set_fw_reg (vcpu, reg);case KVM_REG_ARM64_SVE :return set_sve_reg (vcpu, reg); }arch/arm64/kvm/hypercalls.c +0
-0
arch/arm64/kvm/hypercalls.c static void kvm_ptp_get_time(struct kvm_vcpu *vcpu, u64 *val) · line 64
Quoted 7 lines
arch/arm64/kvm/hypercalls.c +4
-0@@ -58,6 +58,48 @@ static void kvm_ptp_get_time(struct kvm_vcpu *vcpu, u64 *val) val[3 ] =lower_32_bits (cycles); } +static bool kvm_arm_fw_reg_feat_enabled (unsigned long *reg_bmap,unsigned long feat_bit) +{ +return test_bit (feat_bit, reg_bmap); +}
Please use test_bit(std_bmap, bit) directly. It is just as readable as kvm_arm_fw_reg_feat_enabled.
Quoted 120 lines
arch/arm64/kvm/hypercalls.c +76
-0+ +static bool kvm_hvc_call_default_allowed (u32 func_id) +{ +switch (func_id) { +/* +* List of function-ids that are not gated with the bitmapped feature +* firmware registers, and are to be allowed for servicing the call by default. +*/ +case ARM_SMCCC_VERSION_FUNC_ID : +case ARM_SMCCC_ARCH_FEATURES_FUNC_ID : +case ARM_SMCCC_HV_PV_TIME_FEATURES : +case ARM_SMCCC_HV_PV_TIME_ST : +case ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID : +case ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID : +case ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID : +return true; +default : +return kvm_psci_func_id_is_valid (func_id); + } +} + +static bool kvm_hvc_call_allowed (struct kvm_vcpu *vcpu,u32 func_id) +{ +struct kvm_smccc_features *smccc_feat = &vcpu->kvm->arch.smccc_feat; + +switch (func_id) { +case ARM_SMCCC_TRNG_VERSION : +case ARM_SMCCC_TRNG_FEATURES : +case ARM_SMCCC_TRNG_GET_UUID : +case ARM_SMCCC_TRNG_RND32 : +case ARM_SMCCC_TRNG_RND64 : +return kvm_arm_fw_reg_feat_enabled (&smccc_feat->std_bmap, +KVM_REG_ARM_STD_BIT_TRNG_V1_0 ); +default : +return kvm_hvc_call_default_allowed (func_id); + } +} +int kvm_hvc_call_handler (struct kvm_vcpu *vcpu) {u32 func_id =smccc_get_function (vcpu);@@ -65,6 +107,9 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)u32 feature;gpa_t gpa; +if (!kvm_hvc_call_allowed (vcpu, func_id)) + goto out; +switch (func_id) {case ARM_SMCCC_VERSION_FUNC_ID : val[0 ] =ARM_SMCCC_VERSION_1_1 ;@@ -155,6 +200,7 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)return kvm_psci_call (vcpu); } +out:smccc_set_retval (vcpu, val[0 ], val[1 ], val[2 ], val[3 ]);return 1 ; }@@ -164,8 +210,16 @@ static const u64 kvm_arm_fw_reg_ids[] = {KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1 ,KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2 ,KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3 , + KVM_REG_ARM_STD_BMAP, }; +void kvm_arm_init_hypercalls (struct kvm *kvm) +{ +struct kvm_smccc_features *smccc_feat = &kvm->arch.smccc_feat; + + smccc_feat->std_bmap =KVM_ARM_SMCCC_STD_FEATURES ; +} +int kvm_arm_get_fw_num_regs (struct kvm_vcpu *vcpu) {return ARRAY_SIZE (kvm_arm_fw_reg_ids);@@ -237,6 +291,7 @@ static int get_kernel_wa_level(u64 regid)int kvm_arm_get_fw_reg (struct kvm_vcpu *vcpu,const struct kvm_one_reg *reg) { +struct kvm_smccc_features *smccc_feat = &vcpu->kvm->arch.smccc_feat;void __user *uaddr = (void __user *)(long )reg->addr;u64 val;@@ -249,6 +304,9 @@ int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3 : val =get_kernel_wa_level (reg->id) &KVM_REG_FEATURE_LEVEL_MASK ;break ; +case KVM_REG_ARM_STD_BMAP : + val =READ_ONCE (smccc_feat->std_bmap); +break ;default :return -ENOENT ; }@@ -259,6 +317,52 @@ int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)return 0 ; } +static int kvm_arm_set_fw_reg_bmap (struct kvm_vcpu *vcpu,u64 reg_id,u64 val) +{ +int ret =0 ; +struct kvm *kvm = vcpu->kvm; +struct kvm_smccc_features *smccc_feat = &kvm->arch.smccc_feat; +unsigned long *fw_reg_bmap, fw_reg_features; + +switch (reg_id) { +case KVM_REG_ARM_STD_BMAP : + fw_reg_bmap = &smccc_feat->std_bmap; + fw_reg_features =KVM_ARM_SMCCC_STD_FEATURES ; +break ; +default : +return -ENOENT ; + } + +/* Check for unsupported bit */ +if (val & ~fw_reg_features) +return -EINVAL ; + +/* +* Return -EBUSY if the VM (any vCPU) has already started running.
arch/arm64/kvm/hypercalls.c int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) · line 351
Quoted 10 lines
arch/arm64/kvm/hypercalls.c +10
-0+* +* To avoid unnecessary serialization of kvm->lock, check for +* KVM_ARCH_FLAG_HAS_RAN_ONCE, or if there's an update to the +* current bitmap's value, before grabbing the lock. +*/ +if (test_bit (KVM_ARCH_FLAG_HAS_RAN_ONCE , &kvm->arch.flags)) +return -EBUSY ; + +if (val == *fw_reg_bmap) +return 0 ;
Honestly, I don't think we need this fast path. It only makes the error case fast, and it is the one we really don't care about. All that can go.
Quoted 31 lines
arch/arm64/kvm/hypercalls.c +16
-0+ +mutex_lock (&kvm->lock); + +if (test_bit (KVM_ARCH_FLAG_HAS_RAN_ONCE , &kvm->arch.flags)) { + ret = -EBUSY ; + goto out; + } + +WRITE_ONCE (*fw_reg_bmap, val); +out: +mutex_unlock (&kvm->lock); +return ret; +} +int kvm_arm_set_fw_reg (struct kvm_vcpu *vcpu,const struct kvm_one_reg *reg) {void __user *uaddr = (void __user *)(long )reg->addr;@@ -337,6 +441,8 @@ int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)return -EINVAL ;return 0 ; +case KVM_REG_ARM_STD_BMAP : +return kvm_arm_set_fw_reg_bmap (vcpu, reg->id, val);default :return -ENOENT ; }arch/arm64/kvm/psci.c +0
-0
arch/arm64/kvm/psci.c int kvm_psci_call(struct kvm_vcpu *vcpu) · line 444
Quoted 8 lines
arch/arm64/kvm/psci.c +5
-0@@ -437,3 +437,16 @@ int kvm_psci_call(struct kvm_vcpu *vcpu)return -EINVAL ; } } + +bool kvm_psci_func_id_is_valid (u32 func_id) +{ +if (ARM_SMCCC_OWNER_NUM (func_id) ==ARM_SMCCC_OWNER_STANDARD && +ARM_SMCCC_FUNC_NUM (func_id) >=0 &&ARM_SMCCC_FUNC_NUM (func_id) <=0x1f )
The second term is pretty much useless: func_id is a u32, and FUNC_NUM() only extracts the bottom 16 bits. So this is always an unsigned quantity, and the test means nothing. A good compiler should tell you that (but I guess our compilers are all terrible).
arch/arm64/kvm/psci.c int kvm_psci_call(struct kvm_vcpu *vcpu) · line 452
Quoted 8 lines
arch/arm64/kvm/psci.c +8
-0+return true; + +/* KVM's PSCI 0.1 doesn't comply with SMCCC, and has its own function-id base and range */ +if (func_id >=KVM_PSCI_FN (0 ) && func_id <=KVM_PSCI_FN (3 )) +return true; + +return false; +}
Also, why is this stuck in psci.c, while the *only* user seems to be in hypercall.h?
include/kvm/arm_hypercalls.h line 10
Quoted 10 lines
include/kvm/arm_hypercalls.h +2
-0@@ -6,6 +6,11 @@#include <asm/kvm_emulate.h> +/* Last valid bit of the bitmapped firmware registers */ +#define KVM_REG_ARM_STD_BMAP_BIT_MAX 0
Does this bit represent KVM_REG_ARM_STD_BIT_TRNG_V1_0? If so, this is very error prone. You really want to keep the definitions together so that you can update the max when adding something else.
Quoted 19 lines
include/kvm/arm_hypercalls.h +4
-0+ +#define KVM_ARM_SMCCC_STD_FEATURES GENMASK(KVM_REG_ARM_STD_BMAP_BIT_MAX, 0) +int kvm_hvc_call_handler (struct kvm_vcpu *vcpu);static inline u32 smccc_get_function (struct kvm_vcpu *vcpu)@@ -42,6 +47,7 @@ static inline void smccc_set_retval(struct kvm_vcpu *vcpu,struct kvm_one_reg ; +void kvm_arm_init_hypercalls (struct kvm *kvm);int kvm_arm_get_fw_num_regs (struct kvm_vcpu *vcpu);int kvm_arm_copy_fw_reg_indices (struct kvm_vcpu *vcpu,u64 __user *uindices);int kvm_arm_get_fw_reg (struct kvm_vcpu *vcpu,const struct kvm_one_reg *reg);include/kvm/arm_psci.h +0
-0
include/kvm/arm_psci.h static inline int kvm_psci_version(struct kvm_vcpu *vcpu) · line 40
Quoted 6 lines
include/kvm/arm_psci.h +1
-1@@ -36,7 +36,7 @@ static inline int kvm_psci_version(struct kvm_vcpu *vcpu)return KVM_ARM_PSCI_0_1 ; } -int kvm_psci_call (struct kvm_vcpu *vcpu); +bool kvm_psci_func_id_is_valid (u32 func_id);
As I mentioned above, I don't think this should be globally visible.
Quoted 6 lines
include/kvm/arm_psci.h +0
-0#endif /* __KVM_ARM_PSCI_H__ */ Signature · 1 line
2.36.0.464.gb9c8b46e94-goog
Thanks,
M.
Signature · 5 lines
Without deviation from the norm, progress is not possible. _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v7 3/9 KVM: arm64: Add standard hypervisor firmware register
In reply to Raghavendra Rao AnantaIntroduce the firmware register to hold the standard hypervisor service calls (owner value 5) as a bitmap. The bitmap represents the features that'll be enabled for the guest, as configured by the user-space. Currently, this includes support only for Paravirtualized time, represented by bit-0.
--- arch/arm64/include/asm/kvm_host.h | 2 ++ arch/arm64/include/uapi/asm/kvm.h | 3 +++ arch/arm64/kvm/hypercalls.c | 21 ++++++++++++++++++--- include/kvm/arm_hypercalls.h | 2 ++ 4 files changed, 25 insertions(+), 3 deletions(-)
arch/arm64/include/asm/kvm_host.h +2 -0
@@ -105,9 +105,11 @@ struct kvm_arch_memory_slot {* struct kvm_smccc_features: Descriptor of the hypercall services exposed to the guests * * @std_bmap: Bitmap of standard secure service calls +* @std_hyp_bmap: Bitmap of standard hypervisor service calls */ struct kvm_smccc_features {unsigned long std_bmap; +unsigned long std_hyp_bmap; };struct kvm_arch {
arch/arm64/include/uapi/asm/kvm.h +3 -0
@@ -341,6 +341,9 @@ struct kvm_arm_copy_mte_tags {#define KVM_REG_ARM_STD_BMAP KVM_REG_ARM_FW_FEAT_BMAP_REG(0)#define KVM_REG_ARM_STD_BIT_TRNG_V1_0 0 +#define KVM_REG_ARM_STD_HYP_BMAP KVM_REG_ARM_FW_FEAT_BMAP_REG(1) +#define KVM_REG_ARM_STD_HYP_BIT_PV_TIME 0 +/* Device Control API: ARM VGIC */ #define KVM_DEV_ARM_VGIC_GRP_ADDR 0#define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1
arch/arm64/kvm/hypercalls.c +18 -3
@@ -72,8 +72,6 @@ static bool kvm_hvc_call_default_allowed(u32 func_id)*/ case ARM_SMCCC_VERSION_FUNC_ID :case ARM_SMCCC_ARCH_FEATURES_FUNC_ID : -case ARM_SMCCC_HV_PV_TIME_FEATURES : -case ARM_SMCCC_HV_PV_TIME_ST :case ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID :case ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID :case ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID :
@@ -95,6 +93,10 @@ static bool kvm_hvc_call_allowed(struct kvm_vcpu *vcpu, u32 func_id)case ARM_SMCCC_TRNG_RND64 :return kvm_arm_fw_reg_feat_enabled (&smccc_feat->std_bmap,KVM_REG_ARM_STD_BIT_TRNG_V1_0 ); +case ARM_SMCCC_HV_PV_TIME_FEATURES : +case ARM_SMCCC_HV_PV_TIME_ST : +return kvm_arm_fw_reg_feat_enabled (&smccc_feat->std_hyp_bmap, +KVM_REG_ARM_STD_HYP_BIT_PV_TIME );default :return kvm_hvc_call_default_allowed (func_id); }
@@ -102,6 +104,7 @@ static bool kvm_hvc_call_allowed(struct kvm_vcpu *vcpu, u32 func_id)int kvm_hvc_call_handler (struct kvm_vcpu *vcpu) { +struct kvm_smccc_features *smccc_feat = &vcpu->kvm->arch.smccc_feat;u32 func_id =smccc_get_function (vcpu);u64 val[4 ] = {SMCCC_RET_NOT_SUPPORTED };u32 feature;
@@ -165,7 +168,9 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) }break ;case ARM_SMCCC_HV_PV_TIME_FEATURES : - val[0 ] =SMCCC_RET_SUCCESS ; +if (kvm_arm_fw_reg_feat_enabled (&smccc_feat->std_hyp_bmap, +KVM_REG_ARM_STD_HYP_BIT_PV_TIME )) + val[0 ] =SMCCC_RET_SUCCESS ;break ; }break ;
@@ -211,6 +216,7 @@ static const u64 kvm_arm_fw_reg_ids[] = {KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2 ,KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3 ,KVM_REG_ARM_STD_BMAP , + KVM_REG_ARM_STD_HYP_BMAP, };void kvm_arm_init_hypercalls (struct kvm *kvm)
@@ -218,6 +224,7 @@ void kvm_arm_init_hypercalls(struct kvm *kvm)struct kvm_smccc_features *smccc_feat = &kvm->arch.smccc_feat; smccc_feat->std_bmap =KVM_ARM_SMCCC_STD_FEATURES ; + smccc_feat->std_hyp_bmap =KVM_ARM_SMCCC_STD_HYP_FEATURES ; }int kvm_arm_get_fw_num_regs (struct kvm_vcpu *vcpu)
@@ -307,6 +314,9 @@ int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)case KVM_REG_ARM_STD_BMAP : val =READ_ONCE (smccc_feat->std_bmap);break ; +case KVM_REG_ARM_STD_HYP_BMAP : + val =READ_ONCE (smccc_feat->std_hyp_bmap); +break ;default :return -ENOENT ; }
@@ -329,6 +339,10 @@ static int kvm_arm_set_fw_reg_bmap(struct kvm_vcpu *vcpu, u64 reg_id, u64 val) fw_reg_bmap = &smccc_feat->std_bmap; fw_reg_features =KVM_ARM_SMCCC_STD_FEATURES ;break ; +case KVM_REG_ARM_STD_HYP_BMAP : + fw_reg_bmap = &smccc_feat->std_hyp_bmap; + fw_reg_features =KVM_ARM_SMCCC_STD_HYP_FEATURES ; +break ;default :return -ENOENT ; }
@@ -442,6 +456,7 @@ int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)return 0 ;case KVM_REG_ARM_STD_BMAP : +case KVM_REG_ARM_STD_HYP_BMAP :return kvm_arm_set_fw_reg_bmap (vcpu, reg->id, val);default :return -ENOENT ;
include/kvm/arm_hypercalls.h +2 -0
@@ -8,8 +8,10 @@/* Last valid bit of the bitmapped firmware registers */ #define KVM_REG_ARM_STD_BMAP_BIT_MAX 0 +#define KVM_REG_ARM_STD_HYP_BMAP_BIT_MAX 0#define KVM_ARM_SMCCC_STD_FEATURES GENMASK(KVM_REG_ARM_STD_BMAP_BIT_MAX, 0) +#define KVM_ARM_SMCCC_STD_HYP_FEATURES GENMASK(KVM_REG_ARM_STD_HYP_BMAP_BIT_MAX, 0)int kvm_hvc_call_handler (struct kvm_vcpu *vcpu);
Signature · 6 lines
2.36.0.464.gb9c8b46e94-goog _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v7 4/9 KVM: arm64: Add vendor hypervisor firmware register
In reply to Raghavendra Rao AnantaIntroduce the firmware register to hold the vendor specific hypervisor service calls (owner value 6) as a bitmap. The bitmap represents the features that'll be enabled for the guest, as configured by the user-space. Currently, this includes support for KVM-vendor features along with reading the UID, represented by bit-0, and Precision Time Protocol (PTP), represented by bit-1.
--- arch/arm64/include/asm/kvm_host.h | 2 ++ arch/arm64/include/uapi/asm/kvm.h | 4 ++++ arch/arm64/kvm/hypercalls.c | 23 ++++++++++++++++++----- include/kvm/arm_hypercalls.h | 2 ++ 4 files changed, 26 insertions(+), 5 deletions(-)
arch/arm64/include/asm/kvm_host.h +2 -0
@@ -106,10 +106,12 @@ struct kvm_arch_memory_slot {* * @std_bmap: Bitmap of standard secure service calls * @std_hyp_bmap: Bitmap of standard hypervisor service calls +* @vendor_hyp_bmap: Bitmap of vendor specific hypervisor service calls */ struct kvm_smccc_features {unsigned long std_bmap;unsigned long std_hyp_bmap; +unsigned long vendor_hyp_bmap; };struct kvm_arch {
arch/arm64/include/uapi/asm/kvm.h +4 -0
@@ -344,6 +344,10 @@ struct kvm_arm_copy_mte_tags {#define KVM_REG_ARM_STD_HYP_BMAP KVM_REG_ARM_FW_FEAT_BMAP_REG(1)#define KVM_REG_ARM_STD_HYP_BIT_PV_TIME 0 +#define KVM_REG_ARM_VENDOR_HYP_BMAP KVM_REG_ARM_FW_FEAT_BMAP_REG(2) +#define KVM_REG_ARM_VENDOR_HYP_BIT_FUNC_FEAT 0 +#define KVM_REG_ARM_VENDOR_HYP_BIT_PTP 1 +/* Device Control API: ARM VGIC */ #define KVM_DEV_ARM_VGIC_GRP_ADDR 0#define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1
arch/arm64/kvm/hypercalls.c +18 -5
@@ -72,9 +72,6 @@ static bool kvm_hvc_call_default_allowed(u32 func_id)*/ case ARM_SMCCC_VERSION_FUNC_ID :case ARM_SMCCC_ARCH_FEATURES_FUNC_ID : -case ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID : -case ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID : -case ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID :return true;default :return kvm_psci_func_id_is_valid (func_id);
@@ -97,6 +94,13 @@ static bool kvm_hvc_call_allowed(struct kvm_vcpu *vcpu, u32 func_id)case ARM_SMCCC_HV_PV_TIME_ST :return kvm_arm_fw_reg_feat_enabled (&smccc_feat->std_hyp_bmap,KVM_REG_ARM_STD_HYP_BIT_PV_TIME ); +case ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID : +case ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID : +return kvm_arm_fw_reg_feat_enabled (&smccc_feat->vendor_hyp_bmap, +KVM_REG_ARM_VENDOR_HYP_BIT_FUNC_FEAT ); +case ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID : +return kvm_arm_fw_reg_feat_enabled (&smccc_feat->vendor_hyp_bmap, +KVM_REG_ARM_VENDOR_HYP_BIT_PTP );default :return kvm_hvc_call_default_allowed (func_id); }
@@ -189,8 +193,7 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) val[3 ] =ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_3 ;break ;case ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID : - val[0 ] =BIT (ARM_SMCCC_KVM_FUNC_FEATURES ); - val[0 ] |=BIT (ARM_SMCCC_KVM_FUNC_PTP ); + val[0 ] = smccc_feat->vendor_hyp_bmap;break ;case ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID :kvm_ptp_get_time (vcpu, val);
@@ -217,6 +220,7 @@ static const u64 kvm_arm_fw_reg_ids[] = {KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3 ,KVM_REG_ARM_STD_BMAP ,KVM_REG_ARM_STD_HYP_BMAP , + KVM_REG_ARM_VENDOR_HYP_BMAP, };void kvm_arm_init_hypercalls (struct kvm *kvm)
@@ -225,6 +229,7 @@ void kvm_arm_init_hypercalls(struct kvm *kvm) smccc_feat->std_bmap =KVM_ARM_SMCCC_STD_FEATURES ; smccc_feat->std_hyp_bmap =KVM_ARM_SMCCC_STD_HYP_FEATURES ; + smccc_feat->vendor_hyp_bmap =KVM_ARM_SMCCC_VENDOR_HYP_FEATURES ; }int kvm_arm_get_fw_num_regs (struct kvm_vcpu *vcpu)
@@ -317,6 +322,9 @@ int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)case KVM_REG_ARM_STD_HYP_BMAP : val =READ_ONCE (smccc_feat->std_hyp_bmap);break ; +case KVM_REG_ARM_VENDOR_HYP_BMAP : + val =READ_ONCE (smccc_feat->vendor_hyp_bmap); +break ;default :return -ENOENT ; }
@@ -343,6 +351,10 @@ static int kvm_arm_set_fw_reg_bmap(struct kvm_vcpu *vcpu, u64 reg_id, u64 val) fw_reg_bmap = &smccc_feat->std_hyp_bmap; fw_reg_features =KVM_ARM_SMCCC_STD_HYP_FEATURES ;break ; +case KVM_REG_ARM_VENDOR_HYP_BMAP : + fw_reg_bmap = &smccc_feat->vendor_hyp_bmap; + fw_reg_features =KVM_ARM_SMCCC_VENDOR_HYP_FEATURES ; +break ;default :return -ENOENT ; }
@@ -457,6 +469,7 @@ int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)return 0 ;case KVM_REG_ARM_STD_BMAP :case KVM_REG_ARM_STD_HYP_BMAP : +case KVM_REG_ARM_VENDOR_HYP_BMAP :return kvm_arm_set_fw_reg_bmap (vcpu, reg->id, val);default :return -ENOENT ;
include/kvm/arm_hypercalls.h +2 -0
@@ -9,9 +9,11 @@/* Last valid bit of the bitmapped firmware registers */ #define KVM_REG_ARM_STD_BMAP_BIT_MAX 0#define KVM_REG_ARM_STD_HYP_BMAP_BIT_MAX 0 +#define KVM_REG_ARM_VENDOR_HYP_BMAP_BIT_MAX 1#define KVM_ARM_SMCCC_STD_FEATURES GENMASK(KVM_REG_ARM_STD_BMAP_BIT_MAX, 0)#define KVM_ARM_SMCCC_STD_HYP_FEATURES GENMASK(KVM_REG_ARM_STD_HYP_BMAP_BIT_MAX, 0) +#define KVM_ARM_SMCCC_VENDOR_HYP_FEATURES GENMASK(KVM_REG_ARM_VENDOR_HYP_BMAP_BIT_MAX, 0)int kvm_hvc_call_handler (struct kvm_vcpu *vcpu);
Signature · 6 lines
2.36.0.464.gb9c8b46e94-goog _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v7 5/9 Docs: KVM: Rename psci.rst to hypercalls.rst
In reply to Raghavendra Rao AnantaSince the doc also covers general hypercalls' details, rather than just PSCI, and the fact that the bitmap firmware registers' details will be added to this doc, rename the file to a more appropriate name- hypercalls.rst.
---
Documentation/virt/kvm/arm/{psci.rst => hypercalls.rst} | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename Documentation/virt/kvm/arm/{psci.rst => hypercalls.rst} (100%)Documentation/virt/kvm/arm/hypercalls.rst renamed from Documentation/virt/kvm/arm/psci.rst +0 -0
Signature · 6 lines
2.36.0.464.gb9c8b46e94-goog _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v7 6/9 Docs: KVM: Add doc for the bitmap firmware registers
In reply to Raghavendra Rao AnantaAdd the documentation for the bitmap firmware registers in hypercalls.rst and api.rst. This includes the details for KVM_REG_ARM_STD_BMAP, KVM_REG_ARM_STD_HYP_BMAP, and KVM_REG_ARM_VENDOR_HYP_BMAP registers.
Since the document is growing to carry other hypercall related information, make necessary adjustments to present the document in a generic sense, rather than being PSCI focused.
--- Documentation/virt/kvm/api.rst | 16 ++++ Documentation/virt/kvm/arm/hypercalls.rst | 94 ++++++++++++++++++----- 2 files changed, 92 insertions(+), 18 deletions(-)
Documentation/virt/kvm/api.rst +16 -0
@@ -2542,6 +2542,22 @@ arm64 firmware pseudo-registers have the following bit pattern:: 0x6030 0000 0014 <regno:16> +arm64 bitmap feature firmware pseudo-registers have the following bit pattern:: + + 0x6030 0000 0016 <regno:16> + +The bitmap feature firmware registers exposes the hypercall services that are +available for userspace to configure. The set bits corresponds to the services +that are available for the guests to access. By default, KVM sets all the +supported bits during VM initialization. The userspace can discover the +available services via KVM_GET_ONE_REG, and write back the bitmap corresponding +to the features that it wishes guests to see via KVM_SET_ONE_REG. + +Note: These registers are immutable once any of the vCPUs of the VM has run at +least once. A KVM_SET_ONE_REG in such a scenario will return a -EBUSY to userspace. + +(See Documentation/virt/kvm/arm/hypercalls.rst for more details.) + arm64 SVE registers have the following bit patterns:: 0x6080 0000 0015 00 <n:5> <slice:5> Zn bits[2048*slice + 2047 : 2048*slice]
Documentation/virt/kvm/arm/hypercalls.rst +76 -18
113 lines not on this page · raw message
Signature · 6 lines
2.36.0.464.gb9c8b46e94-goog _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Marc Zyngier
maintainerRe: [PATCH v7 6/9] Docs: KVM: Add doc for the bitmap firmware registers
Quoted 29 lines · Raghavendra Rao Ananta
Add the documentation for the bitmap firmware registers in
hypercalls.rstandapi.rst. This includes the details forKVM_REG_ARM_STD_BMAP,KVM_REG_ARM_STD_HYP_BMAP, andKVM_REG_ARM_VENDOR_HYP_BMAPregisters.Since the document is growing to carry other hypercall related information, make necessary adjustments to present the document in a generic sense, rather than being PSCI focused.
Signed-off-by Raghavendra Rao Ananta <[email protected]>Reviewed-by Gavin Shan <[email protected]>--- Documentation/virt/kvm/api.rst | 16 ++++ Documentation/virt/kvm/arm/hypercalls.rst | 94 ++++++++++++++++++----- 2 files changed, 92 insertions(+), 18 deletions(-)Documentation/virt/kvm/api.rst +4
-0@@ -2542,6 +2542,22 @@ arm64 firmware pseudo-registers have the following bit pattern:: 0x6030 0000 0014 <regno:16> +arm64 bitmap feature firmware pseudo-registers have the following bit pattern:: + + 0x6030 0000 0016 <regno:16> +
Documentation/virt/kvm/api.rst arm64 firmware pseudo-registers have the following bit pattern:: · line 2558
Quoted 10 lines
Documentation/virt/kvm/api.rst +10
-0+The bitmap feature firmware registers exposes the hypercall services that are +available for userspace to configure. The set bits corresponds to the services +that are available for the guests to access. By default, KVM sets all the +supported bits during VM initialization. The userspace can discover the +available services via KVM_GET_ONE_REG, and write back the bitmap corresponding +to the features that it wishes guests to see via KVM_SET_ONE_REG. + +Note: These registers are immutable once any of the vCPUs of the VM has run at +least once. A KVM_SET_ONE_REG in such a scenario will return a -EBUSY to userspace. +
The placement is odd, as SVE uses ID 0x0015, and is *after* this.
Quoted 72 lines
Documentation/virt/kvm/api.rst +2
-0+(See Documentation/virt/kvm/arm/hypercalls.rst for more details.) + arm64 SVE registers have the following bit patterns:: 0x6080 0000 0015 00 <n:5> <slice:5> Zn bits[2048*slice + 2047 : 2048*slice]Documentation/virt/kvm/arm/hypercalls.rst +25
-18@@ -1,32 +1,32 @@ .. SPDX-License-Identifier: GPL-2.0 -========================================= -Power State Coordination Interface (PSCI) -========================================= +======================= +ARM Hypercall Interface +======================= -KVM implements the PSCI (Power State Coordination Interface) -specification in order to provide services such as CPU on/off, reset -and power-off to the guest. +KVM handles the hypercall services as requested by the guests. New hypercall +services are regularly made available by the ARM specification or by KVM (as +vendor services) if they make sense from a virtualization point of view. -The PSCI specification is regularly updated to provide new features, -and KVM implements these updates if they make sense from a virtualization -point of view. - -This means that a guest booted on two different versions of KVM can -observe two different "firmware" revisions. This could cause issues if -a given guest is tied to a particular PSCI revision (unlikely), or if -a migration causes a different PSCI version to be exposed out of the -blue to an unsuspecting guest. +This means that a guest booted on two different versions of KVM can observe +two different "firmware" revisions. This could cause issues if a given guest +is tied to a particular version of a hypercall service, or if a migration +causes a different version to be exposed out of the blue to an unsuspecting +guest. In order to remedy this situation, KVM exposes a set of "firmware pseudo-registers" that can be manipulated using the GET/SET_ONE_REG interface. These registers can be saved/restored by userspace, and set -to a convenient value if required. +to a convenient value as required. -The following register is defined: +The following registers are defined: * KVM_REG_ARM_PSCI_VERSION: + KVM implements the PSCI (Power State Coordination Interface) + specification in order to provide services such as CPU on/off, reset + and power-off to the guest. + - Only valid if the vcpu has the KVM_ARM_VCPU_PSCI_0_2 feature set (and thus has already been initialized) - Returns the current PSCI version on GET_ONE_REG (defaulting to the@@ -74,4 +74,62 @@ The following register is defined: KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED: The workaround is always active on this vCPU or it is not needed. -.. [1] https://developer.arm.com/-/media/developer/pdf/ARM_DEN_0070A_Firmware_interfaces_for_mitigating_CVE-2017-5715.pdf + +Bitmap Feature Firmware Registers +--------------------------------- + +Contrary to the above registers, the following registers exposes the hypercall +services in the form of a feature-bitmap to the userspace. This bitmap is +translated to the services that are available to the guest. There is a register +defined per service call owner and can be accessed via GET/SET_ONE_REG interface.
Documentation/virt/kvm/arm/hypercalls.rst The following register is defined: · line 94
Quoted 10 lines
Documentation/virt/kvm/arm/hypercalls.rst +10
-0+ +By default, these registers are set with the upper limit of the features that +are supported. This way userspace can discover all the electable hypercall services +via GET_ONE_REG. The user-space can write-back the desired bitmap back via +SET_ONE_REG. The features for the registers that are untouched, probably because +userspace isn't aware of them, will be exposed as is to the guest. + +Note that KVM would't allow the userspace to configure the registers anymore once +any of the vCPUs has run at least once. Instead, it will return a -EBUSY. +
Formatting is a bit off. We try to stay within the 80 cols format for text documents such as this.
Documentation/virt/kvm/arm/hypercalls.rst The following register is defined: · line 95
Quoted 1 line
Documentation/virt/kvm/arm/hypercalls.rst +1
-0+The psuedo-firmware bitmap register are as follows:
Typo.
Quoted 45 lines
Documentation/virt/kvm/arm/hypercalls.rst +40
-0+ +* KVM_REG_ARM_STD_BMAP: + Controls the bitmap of the ARM Standard Secure Service Calls. + + The following bits are accepted: + + Bit-0: KVM_REG_ARM_STD_BIT_TRNG_V1_0: + The bit represents the services offered under v1.0 of ARM True Random + Number Generator (TRNG) specification, ARM DEN0098. + +* KVM_REG_ARM_STD_HYP_BMAP: + Controls the bitmap of the ARM Standard Hypervisor Service Calls. + + The following bits are accepted: + + Bit-0: KVM_REG_ARM_STD_HYP_BIT_PV_TIME: + The bit represents the Paravirtualized Time service as represented by + ARM DEN0057A. + +* KVM_REG_ARM_VENDOR_HYP_BMAP: + Controls the bitmap of the Vendor specific Hypervisor Service Calls. + + The following bits are accepted: + + Bit-0: KVM_REG_ARM_VENDOR_HYP_BIT_FUNC_FEAT + The bit represents the ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID + and ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID function-ids. + + Bit-1: KVM_REG_ARM_VENDOR_HYP_BIT_PTP: + The bit represents the Precision Time Protocol KVM service. + +Errors: + + ======= ============================================================= + -ENOENT Unknown register accessed. + -EBUSY Attempt a 'write' to the register after the VM has started. + -EINVAL Invalid bitmap written to the register. + ======= ============================================================= + +.. [1] https://developer.arm.com/-/media/developer/pdf/ARM_DEN_0070A_Firmware_interfaces_for_mitigating_CVE-2017-5715.pdfSignature · 1 line
2.36.0.464.gb9c8b46e94-goog
Thanks,
M.
Signature · 5 lines
Without deviation from the norm, progress is not possible. _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v7 7/9 tools: Import ARM SMCCC definitions
In reply to Raghavendra Rao AnantaImport the standard SMCCC definitions from include/linux/arm-smccc.h.
--- tools/include/linux/arm-smccc.h | 193 ++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 tools/include/linux/arm-smccc.h
tools/include/linux/arm-smccc.h new file +193 -0
@@ -0,0 +1,193 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +* Copyright (c) 2015, Linaro Limited +*/ +#ifndef __LINUX_ARM_SMCCC_H +#define __LINUX_ARM_SMCCC_H + +#include <linux/const.h> + +/* +* This file provides common defines for ARM SMC Calling Convention as +* specified in +* https://developer.arm.com/docs/den0028/latest +* +* This code is up-to-date with version DEN 0028 C +*/ + +#define ARM_SMCCC_STD_CALL _AC(0,U) +#define ARM_SMCCC_FAST_CALL _AC(1,U) +#define ARM_SMCCC_TYPE_SHIFT 31 + +#define ARM_SMCCC_SMC_32 0 +#define ARM_SMCCC_SMC_64 1 +#define ARM_SMCCC_CALL_CONV_SHIFT 30 + +#define ARM_SMCCC_OWNER_MASK 0x3F +#define ARM_SMCCC_OWNER_SHIFT 24 + +#define ARM_SMCCC_FUNC_MASK 0xFFFF + +#define ARM_SMCCC_IS_FAST_CALL (smc_val) \ + ((smc_val) & (ARM_SMCCC_FAST_CALL << ARM_SMCCC_TYPE_SHIFT)) +#define ARM_SMCCC_IS_64 (smc_val) \ + ((smc_val) & (ARM_SMCCC_SMC_64 << ARM_SMCCC_CALL_CONV_SHIFT)) +#define ARM_SMCCC_FUNC_NUM (smc_val) ((smc_val) & ARM_SMCCC_FUNC_MASK) +#define ARM_SMCCC_OWNER_NUM (smc_val) \ + (((smc_val) >> ARM_SMCCC_OWNER_SHIFT) & ARM_SMCCC_OWNER_MASK) + +#define ARM_SMCCC_CALL_VAL (type, calling_convention, owner, func_num) \ + (((type) << ARM_SMCCC_TYPE_SHIFT) | \ + ((calling_convention) << ARM_SMCCC_CALL_CONV_SHIFT) | \ + (((owner) & ARM_SMCCC_OWNER_MASK) << ARM_SMCCC_OWNER_SHIFT) | \ + ((func_num) & ARM_SMCCC_FUNC_MASK)) + +#define ARM_SMCCC_OWNER_ARCH 0 +#define ARM_SMCCC_OWNER_CPU 1 +#define ARM_SMCCC_OWNER_SIP 2 +#define ARM_SMCCC_OWNER_OEM 3 +#define ARM_SMCCC_OWNER_STANDARD 4 +#define ARM_SMCCC_OWNER_STANDARD_HYP 5 +#define ARM_SMCCC_OWNER_VENDOR_HYP 6 +#define ARM_SMCCC_OWNER_TRUSTED_APP 48 +#define ARM_SMCCC_OWNER_TRUSTED_APP_END 49 +#define ARM_SMCCC_OWNER_TRUSTED_OS 50 +#define ARM_SMCCC_OWNER_TRUSTED_OS_END 63 + +#define ARM_SMCCC_FUNC_QUERY_CALL_UID 0xff01 + +#define ARM_SMCCC_QUIRK_NONE 0 +#define ARM_SMCCC_QUIRK_QCOM_A6 1/* Save/restore register a6 */ + +#define ARM_SMCCC_VERSION_1_0 0x10000 +#define ARM_SMCCC_VERSION_1_1 0x10001 +#define ARM_SMCCC_VERSION_1_2 0x10002 +#define ARM_SMCCC_VERSION_1_3 0x10003 + +#define ARM_SMCCC_1_3_SVE_HINT 0x10000 + +#define ARM_SMCCC_VERSION_FUNC_ID \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ + 0, 0) + +#define ARM_SMCCC_ARCH_FEATURES_FUNC_ID \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ + 0, 1) + +#define ARM_SMCCC_ARCH_SOC_ID \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ + 0, 2) + +#define ARM_SMCCC_ARCH_WORKAROUND_1 \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ + 0, 0x8000) + +#define ARM_SMCCC_ARCH_WORKAROUND_2 \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ + 0, 0x7fff) + +#define ARM_SMCCC_ARCH_WORKAROUND_3 \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ + 0, 0x3fff) + +#define ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ + ARM_SMCCC_OWNER_VENDOR_HYP, \ + ARM_SMCCC_FUNC_QUERY_CALL_UID) + +/* KVM UID value: 28b46fb6-2ec5-11e9-a9ca-4b564d003a74 */ +#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_0 0xb66fb428U +#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_1 0xe911c52eU +#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_2 0x564bcaa9U +#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_3 0x743a004dU + +/* KVM "vendor specific" services */ +#define ARM_SMCCC_KVM_FUNC_FEATURES 0 +#define ARM_SMCCC_KVM_FUNC_PTP 1 +#define ARM_SMCCC_KVM_FUNC_FEATURES_2 127 +#define ARM_SMCCC_KVM_NUM_FUNCS 128 + +#define ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ + ARM_SMCCC_OWNER_VENDOR_HYP, \ + ARM_SMCCC_KVM_FUNC_FEATURES) + +#define SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED 1 + +/* +* ptp_kvm is a feature used for time sync between vm and host. +* ptp_kvm module in guest kernel will get service from host using +* this hypercall ID. +*/ +#define ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ + ARM_SMCCC_OWNER_VENDOR_HYP, \ + ARM_SMCCC_KVM_FUNC_PTP) + +/* ptp_kvm counter type ID */ +#define KVM_PTP_VIRT_COUNTER 0 +#define KVM_PTP_PHYS_COUNTER 1 + +/* Paravirtualised time calls (defined by ARM DEN0057A) */ +#define ARM_SMCCC_HV_PV_TIME_FEATURES \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_64, \ + ARM_SMCCC_OWNER_STANDARD_HYP, \ + 0x20) + +#define ARM_SMCCC_HV_PV_TIME_ST \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_64, \ + ARM_SMCCC_OWNER_STANDARD_HYP, \ + 0x21) + +/* TRNG entropy source calls (defined by ARM DEN0098) */ +#define ARM_SMCCC_TRNG_VERSION \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ + ARM_SMCCC_OWNER_STANDARD, \ + 0x50) + +#define ARM_SMCCC_TRNG_FEATURES \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ + ARM_SMCCC_OWNER_STANDARD, \ + 0x51) + +#define ARM_SMCCC_TRNG_GET_UUID \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ + ARM_SMCCC_OWNER_STANDARD, \ + 0x52) + +#define ARM_SMCCC_TRNG_RND32 \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ + ARM_SMCCC_OWNER_STANDARD, \ + 0x53) + +#define ARM_SMCCC_TRNG_RND64 \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_64, \ + ARM_SMCCC_OWNER_STANDARD, \ + 0x53) + +/* +* Return codes defined in ARM DEN 0070A +* ARM DEN 0070A is now merged/consolidated into ARM DEN 0028 C +*/ +#define SMCCC_RET_SUCCESS 0 +#define SMCCC_RET_NOT_SUPPORTED -1 +#define SMCCC_RET_NOT_REQUIRED -2 +#define SMCCC_RET_INVALID_PARAMETER -3 + +#endif /*__LINUX_ARM_SMCCC_H*/
Signature · 6 lines
2.36.0.464.gb9c8b46e94-goog _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v7 8/9 selftests: KVM: aarch64: Introduce hypercall ABI test
In reply to Raghavendra Rao AnantaIntroduce a KVM selftest to check the hypercall interface for arm64 platforms. The test validates the user-space' [GET|SET]_ONE_REG interface to read/write the psuedo-firmware registers as well as its effects on the guest upon certain configurations.
--- tools/testing/selftests/kvm/.gitignore | 1 + tools/testing/selftests/kvm/Makefile | 1 + .../selftests/kvm/aarch64/hypercalls.c | 336 ++++++++++++++++++ 3 files changed, 338 insertions(+) create mode 100644 tools/testing/selftests/kvm/aarch64/hypercalls.c
tools/testing/selftests/kvm/.gitignore +1 -0
@@ -2,6 +2,7 @@ /aarch64/arch_timer /aarch64/debug-exceptions /aarch64/get-reg-list +/aarch64/hypercalls /aarch64/psci_test /aarch64/vcpu_width_config /aarch64/vgic_init
tools/testing/selftests/kvm/Makefile +1 -0
@@ -105,6 +105,7 @@ TEST_GEN_PROGS_x86_64 += system_counter_offset_test TEST_GEN_PROGS_aarch64 += aarch64/arch_timer TEST_GEN_PROGS_aarch64 += aarch64/debug-exceptions TEST_GEN_PROGS_aarch64 += aarch64/get-reg-list +TEST_GEN_PROGS_aarch64 += aarch64/hypercalls TEST_GEN_PROGS_aarch64 += aarch64/psci_test TEST_GEN_PROGS_aarch64 += aarch64/vcpu_width_config TEST_GEN_PROGS_aarch64 += aarch64/vgic_init
tools/testing/selftests/kvm/aarch64/hypercalls.c new file +336 -0
336 lines not on this page · raw message
Signature · 6 lines
2.36.0.464.gb9c8b46e94-goog _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v7 9/9 selftests: KVM: aarch64: Add the bitmap firmware registers to get-reg-list
In reply to Raghavendra Rao AnantaAdd the psuedo-firmware registers KVM_REG_ARM_STD_BMAP, KVM_REG_ARM_STD_HYP_BMAP, and KVM_REG_ARM_VENDOR_HYP_BMAP to the base_regs[] list.
Also, add the COPROC support for KVM_REG_ARM_FW_FEAT_BMAP.
--- tools/testing/selftests/kvm/aarch64/get-reg-list.c | 8 ++++++++ 1 file changed, 8 insertions(+)
tools/testing/selftests/kvm/aarch64/get-reg-list.c +8 -0
@@ -294,6 +294,11 @@ static void print_reg(struct vcpu_config *c, __u64 id) "%s: Unexpected bits set in FW reg id: 0x%llx", config_name(c), id);printf ("\tKVM_REG_ARM_FW_REG(%lld),\n" , id &0xffff );break ; +case KVM_REG_ARM_FW_FEAT_BMAP : +TEST_ASSERT (id ==KVM_REG_ARM_FW_FEAT_BMAP_REG (id &0xffff ), +"%s: Unexpected bits set in the bitmap feature FW reg id: 0x%llx" ,config_name (c), id); +printf ("\tKVM_REG_ARM_FW_FEAT_BMAP_REG(%lld),\n" , id &0xffff ); +break ;case KVM_REG_ARM64_SVE :if (has_cap (c,KVM_CAP_ARM_SVE ))printf ("\t%s,\n" ,sve_id_to_str (c, id));
@@ -692,6 +697,9 @@ static __u64 base_regs[] = {KVM_REG_ARM_FW_REG (1 ),/* KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1 */ KVM_REG_ARM_FW_REG (2 ),/* KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2 */ KVM_REG_ARM_FW_REG (3 ),/* KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3 */ +KVM_REG_ARM_FW_FEAT_BMAP_REG (0 ),/* KVM_REG_ARM_STD_BMAP */ +KVM_REG_ARM_FW_FEAT_BMAP_REG (1 ),/* KVM_REG_ARM_STD_HYP_BMAP */ +KVM_REG_ARM_FW_FEAT_BMAP_REG (2 ),/* KVM_REG_ARM_VENDOR_HYP_BMAP */ ARM64_SYS_REG (3 ,3 ,14 ,3 ,1 ),/* CNTV_CTL_EL0 */ ARM64_SYS_REG (3 ,3 ,14 ,3 ,2 ),/* CNTV_CVAL_EL0 */ ARM64_SYS_REG(3, 3, 14, 0, 2),
Signature · 6 lines
2.36.0.464.gb9c8b46e94-goog _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Marc Zyngier
maintainerQuoted 8 lines · Raghavendra Rao Ananta
Hello,
Continuing the discussion from [1], the series tries to add support for the userspace to elect the hypercall services that it wishes to expose to the guest, rather than the guest discovering them unconditionally. The idea employed by the series was taken from
[1] as suggested by Marc Z.
As it took some time to get there, and that there was still a bunch of things to address, I've taken the liberty to apply my own fixes to the series.
Please have a look at [1], and let me know if you're OK with the result. If you are, I'll merge the series for 5.19.
Thanks,
M.
Signature · 1 line
Without deviation from the norm, progress is not possible.
Hi Marc,
Quoted 16 lines · Marc Zyngier
Quoted 8 lines · Raghavendra Rao Ananta
Hello,
Continuing the discussion from [1], the series tries to add support for the userspace to elect the hypercall services that it wishes to expose to the guest, rather than the guest discovering them unconditionally. The idea employed by the series was taken from
[1] as suggested by Marc Z.As it took some time to get there, and that there was still a bunch of things to address, I've taken the liberty to apply my own fixes to the series.
Quoted 7 lines
Please have a look at [1], and let me know if you're OK with the result. If you are, I'll merge the series for 5.19.
Thanks,
M.
Thank you for speeding up the process; appreciate it. However, the series's selftest patches have a dependency on Oliver's PSCI_SYSTEM_SUSPEND's selftest patches [1][2]. Can we pull them in too?
aarch64/hypercalls.c: In function ‘guest_test_hvc’:aarch64/hypercalls.c:95:30: error: storage size of ‘res’ isn’t known
95 | struct arm_smccc_res res;
| ^~~aarch64/hypercalls.c:103:17: warning: implicit declaration of function ‘smccc_hvc’ [-Wimplicit-function-declaration]
103 | smccc_hvc(hc_info->func_id, hc_info->arg1, 0,
0, 0, 0, 0, 0, &res);
| ^~~~~~~~~Also, just a couple of readability nits in the fixed version:
1. Patch-2/9, hypercall.c:kvm_hvc_call_default_allowed(), in the 'default' case, do you think we should probably add a small comment that mentions we are checking for func_id in the PSCI range?
2. Patch-2/9, arm_hypercall.h, clear all the macros in this patch itself instead of doing it in increments (unless there's some reason that I'm missing)?
Regards,
Raghavendra
[1]: https://lore.kernel.org/all/[email protected]/
[2]: https://lore.kernel.org/all/[email protected]/
Quoted 4 lines
--
Without deviation from the norm, progress is not possible.
_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Marc Zyngier
maintainerQuoted 23 lines · Raghavendra Rao Ananta
Hi Marc,
Quoted 19 lines · Marc Zyngier
Quoted 8 lines · Raghavendra Rao Ananta
Hello,
Continuing the discussion from [1], the series tries to add support for the userspace to elect the hypercall services that it wishes to expose to the guest, rather than the guest discovering them unconditionally. The idea employed by the series was taken from
[1] as suggested by Marc Z.As it took some time to get there, and that there was still a bunch of things to address, I've taken the liberty to apply my own fixes to the series.
Please have a look at [1], and let me know if you're OK with the result. If you are, I'll merge the series for 5.19.
Quoted 8 lines
Quoted 4 lines
Thanks,
M.Thank you for speeding up the process; appreciate it. However, the series's selftest patches have a dependency on Oliver's PSCI_SYSTEM_SUSPEND's selftest patches [1][2]. Can we pull them in too?
Urgh... I guess this is the time to set some ground rules:
- Please don't introduce dependencies between series, that's unmanageable. I really need to see each series independently, and if there is a merge conflict, that's my job to fix (and I don't really mind).
- If there is a dependency between series, please post a version of the required patches as a prefix to your series, assuming this prefix is itself standalone. If it isn't, then something really is wrong, and the series should be resplit.
- You also should be basing your series on an *official* tag from Linus' tree (preferably -rc1, -rc2 or -rc3), and not something random like any odd commit from the KVM tree (I had conflicts while applying this on -rc3, probably due to the non-advertised dependency on Oliver's series).
Quoted 11 lines
aarch64/hypercalls.c: In function ‘guest_test_hvc’:aarch64/hypercalls.c:95:30: error: storage size of ‘res’ isn’t known
95 | structarm_smccc_resres;
| ^~~aarch64/hypercalls.c:103:17: warning: implicit declaration of function ‘smccc_hvc’ [-Wimplicit-function-declaration]
103 | smccc_hvc(hc_info->func_id,hc_info->arg1, 0,0, 0, 0, 0, 0, &res); | ^~~~~~~~~
I've picked the two patches, which means they will most likely appear twice in the history. In the future, please reach out so that we can organise this better.
Quoted 5 lines
Also, just a couple of readability nits in the fixed version:
1. Patch-2/9, hypercall.c:kvm_hvc_call_default_allowed(), in the 'default' case, do you think we should probably add a small comment that mentions we are checking for
func_idin the PSCI range?
Dumped a one-liner there.
Quoted 3 lines
2. Patch-2/9,
arm_hypercall.h, clear all the macros in this patch itself instead of doing it in increments (unless there's some reason that I'm missing)?
Ah, rebasing leftovers, now gone.
I've pushed an updated branch again, please have a look.
M.
Signature · 1 line
Without deviation from the norm, progress is not possible.
Quoted 47 lines · Marc Zyngier
Quoted 23 lines · Raghavendra Rao Ananta
Hi Marc,
Quoted 19 lines · Marc Zyngier
Quoted 8 lines · Raghavendra Rao Ananta
Hello,
Continuing the discussion from [1], the series tries to add support for the userspace to elect the hypercall services that it wishes to expose to the guest, rather than the guest discovering them unconditionally. The idea employed by the series was taken from
[1] as suggested by Marc Z.As it took some time to get there, and that there was still a bunch of things to address, I've taken the liberty to apply my own fixes to the series.
Please have a look at [1], and let me know if you're OK with the result. If you are, I'll merge the series for 5.19.
Quoted 8 lines
Quoted 4 lines
Thanks,
M.Thank you for speeding up the process; appreciate it. However, the series's selftest patches have a dependency on Oliver's PSCI_SYSTEM_SUSPEND's selftest patches [1][2]. Can we pull them in too?
Urgh... I guess this is the time to set some ground rules:
- Please don't introduce dependencies between series, that's unmanageable. I really need to see each series independently, and if there is a merge conflict, that's my job to fix (and I don't really mind).
- If there is a dependency between series, please post a version of the required patches as a prefix to your series, assuming this prefix is itself standalone. If it isn't, then something really is wrong, and the series should be resplit.
Quoted 6 lines
- You also should be basing your series on an *official* tag from Linus' tree (preferably -rc1, -rc2 or -rc3), and not something random like any odd commit from the KVM tree (I had conflicts while applying this on -rc3, probably due to the non-advertised dependency on Oliver's series).
Thanks for picking the dependency patches. I'll keep these mind the next time I push changes.
Quoted 24 lines
Quoted 11 lines
aarch64/hypercalls.c: In function ‘guest_test_hvc’:aarch64/hypercalls.c:95:30: error: storage size of ‘res’ isn’t known
95 | structarm_smccc_resres;
| ^~~aarch64/hypercalls.c:103:17: warning: implicit declaration of function ‘smccc_hvc’ [-Wimplicit-function-declaration]
103 | smccc_hvc(hc_info->func_id,hc_info->arg1, 0,0, 0, 0, 0, 0, &res); | ^~~~~~~~~I've picked the two patches, which means they will most likely appear twice in the history. In the future, please reach out so that we can organise this better.
Quoted 5 lines
Also, just a couple of readability nits in the fixed version:
1. Patch-2/9, hypercall.c:kvm_hvc_call_default_allowed(), in the 'default' case, do you think we should probably add a small comment that mentions we are checking for
func_idin the PSCI range?Dumped a one-liner there.
Quoted 8 lines
Quoted 3 lines
2. Patch-2/9,
arm_hypercall.h, clear all the macros in this patch itself instead of doing it in increments (unless there's some reason that I'm missing)?Ah, rebasing leftovers, now gone.
I've pushed an updated branch again, please have a look.
Thanks for addressing these. The series looks good now.
Regards,
Raghavendra
Quoted 4 lines
M.--
Without deviation from the norm, progress is not possible.
_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Marc Zyngier
maintainerQuoted 86 lines · Raghavendra Rao Ananta
Quoted 47 lines · Marc Zyngier
Quoted 23 lines · Raghavendra Rao Ananta
Hi Marc,
Quoted 19 lines · Marc Zyngier
Quoted 8 lines · Raghavendra Rao Ananta
Hello,
Continuing the discussion from [1], the series tries to add support for the userspace to elect the hypercall services that it wishes to expose to the guest, rather than the guest discovering them unconditionally. The idea employed by the series was taken from
[1] as suggested by Marc Z.As it took some time to get there, and that there was still a bunch of things to address, I've taken the liberty to apply my own fixes to the series.
Please have a look at [1], and let me know if you're OK with the result. If you are, I'll merge the series for 5.19.
Quoted 8 lines
Quoted 4 lines
Thanks,
M.Thank you for speeding up the process; appreciate it. However, the series's selftest patches have a dependency on Oliver's PSCI_SYSTEM_SUSPEND's selftest patches [1][2]. Can we pull them in too?
Urgh... I guess this is the time to set some ground rules:
- Please don't introduce dependencies between series, that's unmanageable. I really need to see each series independently, and if there is a merge conflict, that's my job to fix (and I don't really mind).
- If there is a dependency between series, please post a version of the required patches as a prefix to your series, assuming this prefix is itself standalone. If it isn't, then something really is wrong, and the series should be resplit.
Quoted 6 lines
- You also should be basing your series on an *official* tag from Linus' tree (preferably -rc1, -rc2 or -rc3), and not something random like any odd commit from the KVM tree (I had conflicts while applying this on -rc3, probably due to the non-advertised dependency on Oliver's series).
Thanks for picking the dependency patches. I'll keep these mind the next time I push changes.
Quoted 28 lines
Quoted 11 lines
aarch64/hypercalls.c: In function ‘guest_test_hvc’:aarch64/hypercalls.c:95:30: error: storage size of ‘res’ isn’t known
95 | structarm_smccc_resres;
| ^~~aarch64/hypercalls.c:103:17: warning: implicit declaration of function ‘smccc_hvc’ [-Wimplicit-function-declaration]
103 | smccc_hvc(hc_info->func_id,hc_info->arg1, 0,0, 0, 0, 0, 0, &res); | ^~~~~~~~~I've picked the two patches, which means they will most likely appear twice in the history. In the future, please reach out so that we can organise this better.
Quoted 5 lines
Also, just a couple of readability nits in the fixed version:
1. Patch-2/9, hypercall.c:kvm_hvc_call_default_allowed(), in the 'default' case, do you think we should probably add a small comment that mentions we are checking for
func_idin the PSCI range?Dumped a one-liner there.
Quoted 3 lines
2. Patch-2/9,
arm_hypercall.h, clear all the macros in this patch itself instead of doing it in increments (unless there's some reason that I'm missing)?
Quoted 5 lines
Quoted 4 lines
Ah, rebasing leftovers, now gone.
I've pushed an updated branch again, please have a look.
Thanks for addressing these. The series looks good now.
Except it doesn't.
I introduced a bug by overly simplifying kvm_arm_set_fw_reg_bmap(), as we have to allow userspace writing the *same* value. As it turns out, QEMU restores all the registers on each reboot. Which as the vcpus have all run. This in turns triggers another issue in QEMU, which instead of taking the hint ans stopping there, sends all the vcpus into the guest in one go with random states... Crap happens.
I'll wear a brown paper bag for the rest of the day and add the following patch to the branch.
Thanks,
M.
From 528ada2811ba0bb2b2db5bf0f829b48c50f3c13c Mon Sep 17 00:00:00 2001
From: Marc Zyngier <[email protected]>
Date: Mon, 16 May 2022 17:32:54 +0100
Subject: [PATCH] KVM: arm64: Fix hypercall bitmap writeback when vcpus have
already run
We generally want to disallow hypercall bitmaps being changed once vcpus have already run. But we must allow the write if the written value is unchanged so that userspace can rewrite the register file on reboot, for example.
Without this, a QEMU-based VM will fail to reboot correctly.
The original code was correct, and it is me that introduced the regression.
--- arch/arm64/kvm/hypercalls.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
arch/arm64/kvm/hypercalls.c +2 -1
@@ -379,7 +379,8 @@ static int kvm_arm_set_fw_reg_bmap(struct kvm_vcpu *vcpu, u64 reg_id, u64 val)mutex_lock (&kvm->lock); -if (test_bit (KVM_ARCH_FLAG_HAS_RAN_ONCE , &kvm->arch.flags)) { +if (test_bit (KVM_ARCH_FLAG_HAS_RAN_ONCE , &kvm->arch.flags) && + val != *fw_reg_bmap) { ret = -EBUSY ; goto out; }
Signature · 5 lines
2.34.1 -- Without deviation from the norm, progress is not possible.
Quoted 138 lines · Marc Zyngier
Quoted 86 lines · Raghavendra Rao Ananta
Quoted 47 lines · Marc Zyngier
Quoted 23 lines · Raghavendra Rao Ananta
Hi Marc,
Quoted 19 lines · Marc Zyngier
Quoted 8 lines · Raghavendra Rao Ananta
Hello,
Continuing the discussion from [1], the series tries to add support for the userspace to elect the hypercall services that it wishes to expose to the guest, rather than the guest discovering them unconditionally. The idea employed by the series was taken from
[1] as suggested by Marc Z.As it took some time to get there, and that there was still a bunch of things to address, I've taken the liberty to apply my own fixes to the series.
Please have a look at [1], and let me know if you're OK with the result. If you are, I'll merge the series for 5.19.
Quoted 8 lines
Quoted 4 lines
Thanks,
M.Thank you for speeding up the process; appreciate it. However, the series's selftest patches have a dependency on Oliver's PSCI_SYSTEM_SUSPEND's selftest patches [1][2]. Can we pull them in too?
Urgh... I guess this is the time to set some ground rules:
- Please don't introduce dependencies between series, that's unmanageable. I really need to see each series independently, and if there is a merge conflict, that's my job to fix (and I don't really mind).
- If there is a dependency between series, please post a version of the required patches as a prefix to your series, assuming this prefix is itself standalone. If it isn't, then something really is wrong, and the series should be resplit.
Quoted 6 lines
- You also should be basing your series on an *official* tag from Linus' tree (preferably -rc1, -rc2 or -rc3), and not something random like any odd commit from the KVM tree (I had conflicts while applying this on -rc3, probably due to the non-advertised dependency on Oliver's series).
Thanks for picking the dependency patches. I'll keep these mind the next time I push changes.
Quoted 28 lines
Quoted 11 lines
aarch64/hypercalls.c: In function ‘guest_test_hvc’:aarch64/hypercalls.c:95:30: error: storage size of ‘res’ isn’t known
95 | structarm_smccc_resres;
| ^~~aarch64/hypercalls.c:103:17: warning: implicit declaration of function ‘smccc_hvc’ [-Wimplicit-function-declaration]
103 | smccc_hvc(hc_info->func_id,hc_info->arg1, 0,0, 0, 0, 0, 0, &res); | ^~~~~~~~~I've picked the two patches, which means they will most likely appear twice in the history. In the future, please reach out so that we can organise this better.
Quoted 5 lines
Also, just a couple of readability nits in the fixed version:
1. Patch-2/9, hypercall.c:kvm_hvc_call_default_allowed(), in the 'default' case, do you think we should probably add a small comment that mentions we are checking for
func_idin the PSCI range?Dumped a one-liner there.
Quoted 3 lines
2. Patch-2/9,
arm_hypercall.h, clear all the macros in this patch itself instead of doing it in increments (unless there's some reason that I'm missing)?Quoted 5 lines
Quoted 4 lines
Ah, rebasing leftovers, now gone.
I've pushed an updated branch again, please have a look.
Thanks for addressing these. The series looks good now.
Except it doesn't.
I introduced a bug by overly simplifying
kvm_arm_set_fw_reg_bmap(), as we have to allow userspace writing the *same* value. As it turns out, QEMU restores all the registers on each reboot. Which as the vcpus have all run. This in turns triggers another issue in QEMU, which instead of taking the hint ans stopping there, sends all the vcpus into the guest in one go with random states... Crap happens.I'll wear a brown paper bag for the rest of the day and add the following patch to the branch.
Thanks,
M.From
528ada2811ba0bb2b2db5bf0f829b48c50f3c13cMon Sep 17 00:00:00 2001
From: Marc Zyngier <[email protected]>
Date: Mon, 16 May 2022 17:32:54 +0100
Subject: [PATCH] KVM: arm64: Fix hypercall bitmap writeback when vcpus have
already runWe generally want to disallow hypercall bitmaps being changed once vcpus have already run. But we must allow the write if the written value is unchanged so that userspace can rewrite the register file on reboot, for example.
Without this, a QEMU-based VM will fail to reboot correctly.
The original code was correct, and it is me that introduced the regression.
Fixes 05714cab7d63 ("KVM: arm64: Setup a framework for hypercall bitmap firmware registers")Signed-off-by Marc Zyngier <[email protected]>--- arch/arm64/kvm/hypercalls.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)arch/arm64/kvm/hypercalls.c +0
-0
arch/arm64/kvm/hypercalls.c static int kvm_arm_set_fw_reg_bmap(struct kvm_vcpu *vcpu, u64 reg_id, u64 val) · line 386
Quoted 9 lines
arch/arm64/kvm/hypercalls.c +2
-1@@ -379,7 +379,8 @@ static int kvm_arm_set_fw_reg_bmap(struct kvm_vcpu *vcpu, u64 reg_id, u64 val)mutex_lock (&kvm->lock); -if (test_bit (KVM_ARCH_FLAG_HAS_RAN_ONCE , &kvm->arch.flags)) { +if (test_bit (KVM_ARCH_FLAG_HAS_RAN_ONCE , &kvm->arch.flags) && + val != *fw_reg_bmap) { ret = -EBUSY ; goto out; }
Ha, not your fault. We have been going back and forth on this aspect of the design. Thanks for correcting this.
However, since this changes the API behavior, I think we may have to amend the documentation as well:
Documentation/virt/kvm/api.rst +2 -1
@@ -2615,7 +2615,8 @@ KVM_SET_ONE_REG. Note: These registers are immutable once any of the vCPUs of the VM has run at least once. A KVM_SET_ONE_REG in such a scenario will return -a -EBUSY to userspace. +a -EBUSY to userspace if there's an update in the bitmap. If there's no +change in the value, it'll simply return a 0. (See Documentation/virt/kvm/arm/hypercalls.rst for more details.)
(quoted diff) +0 -0
b/Documentation/virt/kvm/arm/hypercalls.rst
index 3e23084644ba..275f4dbe5792 100644
Documentation/virt/kvm/arm/hypercalls.rst +0 -0
@@ -91,9 +91,10 @@ desired bitmap back via SET_ONE_REG. The features
for the registers that
are untouched, probably because userspace isn't aware of them, will be exposed as is to the guest.
-Note that KVM will not allow the userspace to configure the registers -anymore once any of the vCPUs has run at least once. Instead, it will -return a -EBUSY.
+Note that KVM will not allow the userspace to update the registers +with a new value anymore once any of the vCPUs has run at least once, +and will return a -EBUSY. However, a 'write' of the previously configured +value is allowed and returns a 0.
The pseudo-firmware bitmap register are as follows:
@@ -129,10 +130,10 @@ The pseudo-firmware bitmap register are as follows:
Errors:
- ======= =============================================================
+ ======= ===============================================================
-ENOENT Unknown register accessed.
- -EBUSY Attempt a 'write' to the register after the VM has started.
+ -EBUSY Attempt to update the register bitmap after the VM has started.
-EINVAL Invalid bitmap written to the register.
- ======= =============================================================
+ ======= ================================================================Thank you.
Raghavendra
Quoted 6 lines
--
2.34.1--
Without deviation from the norm, progress is not possible.
_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Oliver Upton
Reviewed-byQuoted 25 lines · Marc Zyngier
Quoted 23 lines · Raghavendra Rao Ananta
Hi Marc,
Quoted 19 lines · Marc Zyngier
Quoted 8 lines · Raghavendra Rao Ananta
Hello,
Continuing the discussion from [1], the series tries to add support for the userspace to elect the hypercall services that it wishes to expose to the guest, rather than the guest discovering them unconditionally. The idea employed by the series was taken from
[1] as suggested by Marc Z.As it took some time to get there, and that there was still a bunch of things to address, I've taken the liberty to apply my own fixes to the series.
Please have a look at [1], and let me know if you're OK with the result. If you are, I'll merge the series for 5.19.
Quoted 8 lines
Quoted 8 lines
Quoted 4 lines
Thanks,
M.Thank you for speeding up the process; appreciate it. However, the series's selftest patches have a dependency on Oliver's PSCI_SYSTEM_SUSPEND's selftest patches [1][2]. Can we pull them in too?
Posted, BTW.
http://lore.kernel.org/kvmarm/[email protected]
Quoted 7 lines
Quoted 3 lines
2. Patch-2/9,
arm_hypercall.h, clear all the macros in this patch itself instead of doing it in increments (unless there's some reason that I'm missing)?Ah, rebasing leftovers, now gone.
I've pushed an updated branch again, please have a look.
Series looks good with your additions. For the pile:
_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Quoted 6 lines · Raghavendra Rao Ananta
Continuing the discussion from [1], the series tries to add support for the userspace to elect the hypercall services that it wishes to expose to the guest, rather than the guest discovering them unconditionally. The idea employed by the series was taken from
[1] as suggested by Marc Z.
Quoted 7 lines
In a broad sense, the concept is similar to the current implementation of PSCI interface- create a 'firmware psuedo-register' to handle the firmware revisions. The series extends this idea to all the other hypercalls such as TRNG (True Random Number Generator),
PV_TIME(Paravirtualized Time), and PTP (Precision Time protocol).[...]
Applied to next, thanks!
[1/9] KVM: arm64: Factor out firmware register handling from psci.c
commit: 85fbe08e4da862dc64fc10071c4a03e51b6361d0
[2/9] KVM: arm64: Setup a framework for hypercall bitmap firmware registers
commit: 05714cab7d63b189894235cf310fae7d6ffc2e9b
[3/9] KVM: arm64: Add standard hypervisor firmware register
commit: 428fd6788d4d0e0d390de9fb4486be3c1187310d
[4/9] KVM: arm64: Add vendor hypervisor firmware register
commit: b22216e1a617ca55b41337cd1e057ebc784a65d4
[5/9] Docs: KVM: Rename psci.rst to hypercalls.rst
commit: f1ced23a9be5727c6f4cac0e2262c5411038952f
[6/9] Docs: KVM: Add doc for the bitmap firmware registers
commit: fa246c68a04d46c7af6953b47dba7e16d24efbe2
[7/9] tools: Import ARM SMCCC definitions
commit: ea733263949646700977feeb662a92703f514351
[8/9] selftests: KVM: aarch64: Introduce hypercall ABI test
commit: 5ca24697d54027c1c94c94a5b920a75448108ed0
[9/9] selftests: KVM: aarch64: Add the bitmap firmware registers to get-reg-list
commit: 920f4a55fdaa6f68b31c50cca6e51fecac5857a0Cheers,
M.
Signature · 1 line
Without deviation from the norm, progress is not possible.