@@ -163,6 +163,32 @@ static int kvm_vcpu_exit_hcall(struct kvm_vcpu *vcpu, u32 nr, u32 nr_args)
return 0;
}
+static int kvm_vcpu_handle_xshare(struct kvm_vcpu *vcpu, u32 nr)
+{
+ if (IS_ENABLED(CONFIG_KVM_GENERIC_PRIVATE_MEM_MAPPABLE)) {
+ u64 mask = vcpu->kvm->arch.hypercall_exit_enabled;
+ gfn_t gfn = vcpu_get_reg(vcpu, 1) >> PAGE_SHIFT;
+ unsigned long attributes = 0;
+ int ret;
+
+ if (!(mask & BIT(nr)))
+ goto err;
+
+ if (nr == ARM_SMCCC_KVM_FUNC_MEM_UNSHARE)
+ attributes = KVM_MEMORY_ATTRIBUTE_NOT_MAPPABLE;
+
+ ret = kvm_vm_set_mem_attributes_kernel(vcpu->kvm, gfn, gfn + 1, attributes);
+ if (ret)
+ goto err;
+ }
+
+ return kvm_vcpu_exit_hcall(vcpu, nr, 3);
+
+err:
+ smccc_set_retval(vcpu, SMCCC_RET_INVALID_PARAMETER, 0, 0, 0);
+ return 1;
+}
+
#define SMC32_ARCH_RANGE_BEGIN ARM_SMCCC_VERSION_FUNC_ID
#define SMC32_ARCH_RANGE_END ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
ARM_SMCCC_SMC_32, \
@@ -411,9 +437,9 @@ int kvm_smccc_call_handler(struct kvm_vcpu *vcpu)
val[0] = SMCCC_RET_SUCCESS;
break;
case ARM_SMCCC_VENDOR_HYP_KVM_MEM_SHARE_FUNC_ID:
- return kvm_vcpu_exit_hcall(vcpu, ARM_SMCCC_KVM_FUNC_MEM_SHARE, 3);
+ return kvm_vcpu_handle_xshare(vcpu, ARM_SMCCC_KVM_FUNC_MEM_SHARE);
case ARM_SMCCC_VENDOR_HYP_KVM_MEM_UNSHARE_FUNC_ID:
- return kvm_vcpu_exit_hcall(vcpu, ARM_SMCCC_KVM_FUNC_MEM_UNSHARE, 3);
+ return kvm_vcpu_handle_xshare(vcpu, ARM_SMCCC_KVM_FUNC_MEM_UNSHARE);
case ARM_SMCCC_TRNG_VERSION:
case ARM_SMCCC_TRNG_FEATURES:
case ARM_SMCCC_TRNG_GET_UUID:
Track memory being explicitly shared by the guest to the host, and update the NOT_MAPPABLE attribute accordingly. This would allow shared memory to be mapped by the host, and enable us to ensure that unshared memory is not mappable by the host. Signed-off-by: Fuad Tabba <tabba@google.com> --- arch/arm64/kvm/hypercalls.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-)