diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c index 82b139255136..94d81b094182 100644 --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c @@ -37,6 +37,16 @@ DEFINE_PER_CPU(struct kvm_nvhe_init_params, kvm_init_params); void __kvm_hyp_host_forward_smc(struct kvm_cpu_context *host_ctxt); +static int pkvm_refill_memcache(struct pkvm_hyp_vcpu *hyp_vcpu) +{ + struct pkvm_hyp_vm *hyp_vm = pkvm_hyp_vcpu_to_hyp_vm(hyp_vcpu); + u64 nr_pages = VTCR_EL2_LVLS(hyp_vm->kvm.arch.vtcr) - 1; + struct kvm_vcpu *host_vcpu = hyp_vcpu->host_vcpu; + + return refill_memcache(&hyp_vcpu->vcpu.arch.pkvm_memcache, nr_pages, + &host_vcpu->arch.pkvm_memcache); +} + typedef void (*hyp_entry_exit_handler_fn)(struct pkvm_hyp_vcpu *); static void handle_pvm_entry_wfx(struct pkvm_hyp_vcpu *hyp_vcpu) @@ -89,6 +99,9 @@ static void handle_pvm_entry_hvc64(struct pkvm_hyp_vcpu *hyp_vcpu) u32 fn = smccc_get_function(&hyp_vcpu->vcpu); switch (fn) { + case ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_MAP_FUNC_ID: + pkvm_refill_memcache(hyp_vcpu); + break; case ARM_SMCCC_VENDOR_HYP_KVM_MEM_SHARE_FUNC_ID: fallthrough; case ARM_SMCCC_VENDOR_HYP_KVM_MEM_UNSHARE_FUNC_ID: @@ -267,6 +280,10 @@ static void handle_pvm_exit_hvc64(struct pkvm_hyp_vcpu *hyp_vcpu) n = 4; break; + case ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_MAP_FUNC_ID: + n = 3; + break; + case PSCI_1_1_FN_SYSTEM_RESET2: case PSCI_1_1_FN64_SYSTEM_RESET2: n = 3; @@ -825,16 +842,6 @@ out: cpu_reg(host_ctxt, 1) = ret; } -static int pkvm_refill_memcache(struct pkvm_hyp_vcpu *hyp_vcpu) -{ - struct pkvm_hyp_vm *hyp_vm = pkvm_hyp_vcpu_to_hyp_vm(hyp_vcpu); - u64 nr_pages = VTCR_EL2_LVLS(hyp_vm->kvm.arch.vtcr) - 1; - struct kvm_vcpu *host_vcpu = hyp_vcpu->host_vcpu; - - return refill_memcache(&hyp_vcpu->vcpu.arch.pkvm_memcache, nr_pages, - &host_vcpu->arch.pkvm_memcache); -} - static void handle___pkvm_host_map_guest(struct kvm_cpu_context *host_ctxt) { DECLARE_REG(u64, pfn, host_ctxt, 1); diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c index d70ff178bb8e..24c7f0486c65 100644 --- a/arch/arm64/kvm/hyp/nvhe/pkvm.c +++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c @@ -1317,6 +1317,31 @@ out_guest_err: return true; } +static bool pkvm_install_ioguard_page(struct pkvm_hyp_vcpu *hyp_vcpu, u64 *exit_code) +{ + u64 retval = SMCCC_RET_SUCCESS; + u64 ipa = smccc_get_arg1(&hyp_vcpu->vcpu); + int ret; + + ret = __pkvm_install_ioguard_page(hyp_vcpu, ipa); + if (ret == -ENOMEM) { + /* + * We ran out of memcache, let's ask for more. Cancel + * the effects of the HVC that took us here, and + * forward the hypercall to the host for page donation + * purposes. + */ + write_sysreg_el2(read_sysreg_el2(SYS_ELR) - 4, SYS_ELR); + return false; + } + + if (ret) + retval = SMCCC_RET_INVALID_PARAMETER; + + smccc_set_retval(&hyp_vcpu->vcpu, retval, 0, 0, 0); + return true; +} + bool smccc_trng_available; static bool pkvm_forward_trng(struct kvm_vcpu *vcpu) @@ -1377,7 +1402,24 @@ bool kvm_handle_pvm_hvc64(struct kvm_vcpu *vcpu, u64 *exit_code) val[0] |= BIT(ARM_SMCCC_KVM_FUNC_MEM_SHARE); val[0] |= BIT(ARM_SMCCC_KVM_FUNC_MEM_UNSHARE); val[0] |= BIT(ARM_SMCCC_KVM_FUNC_MEM_RELINQUISH); + val[0] |= BIT(ARM_SMCCC_KVM_FUNC_MMIO_GUARD_INFO); + val[0] |= BIT(ARM_SMCCC_KVM_FUNC_MMIO_GUARD_ENROLL); + val[0] |= BIT(ARM_SMCCC_KVM_FUNC_MMIO_GUARD_MAP); + val[0] |= BIT(ARM_SMCCC_KVM_FUNC_MMIO_GUARD_UNMAP); break; + case ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_ENROLL_FUNC_ID: + set_bit(KVM_ARCH_FLAG_MMIO_GUARD, &vcpu->kvm->arch.flags); + val[0] = SMCCC_RET_SUCCESS; + break; + case ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_MAP_FUNC_ID: + return pkvm_install_ioguard_page(hyp_vcpu, exit_code); + case ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_UNMAP_FUNC_ID: + if (__pkvm_remove_ioguard_page(hyp_vcpu, vcpu_get_reg(vcpu, 1))) + val[0] = SMCCC_RET_INVALID_PARAMETER; + else + val[0] = SMCCC_RET_SUCCESS; + break; + case ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_INFO_FUNC_ID: case ARM_SMCCC_VENDOR_HYP_KVM_HYP_MEMINFO_FUNC_ID: return pkvm_meminfo_call(hyp_vcpu); case ARM_SMCCC_VENDOR_HYP_KVM_MEM_SHARE_FUNC_ID: diff --git a/arch/arm64/kvm/hypercalls.c b/arch/arm64/kvm/hypercalls.c index 2a92b9bd2a46..a92428ce1912 100644 --- a/arch/arm64/kvm/hypercalls.c +++ b/arch/arm64/kvm/hypercalls.c @@ -228,6 +228,10 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) pkvm_host_reclaim_page(vcpu->kvm, smccc_get_arg1(vcpu)); val[0] = SMCCC_RET_SUCCESS; break; + case ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_MAP_FUNC_ID: + if (kvm_vm_is_protected(vcpu->kvm) && !topup_hyp_memcache(vcpu)) + val[0] = SMCCC_RET_SUCCESS; + break; case ARM_SMCCC_TRNG_VERSION: case ARM_SMCCC_TRNG_FEATURES: case ARM_SMCCC_TRNG_GET_UUID: