Skip to content

Commit 0f12694

Browse files
committed
drivers/virt: pkvm: Intercept ioremap using pKVM MMIO_GUARD hypercall
Hook up pKVM's MMIO_GUARD hypercall so that ioremap() and friends will register the target physical address as MMIO with the hypervisor, allowing guest exits to that page to be emulated by the host with full syndrome information. Acked-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent c86fa34 commit 0f12694

File tree

3 files changed

+68
-0
lines changed

3 files changed

+68
-0
lines changed

Documentation/virt/kvm/arm/hypercalls.rst

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,29 @@ memory protection granule advertised by ``ARM_SMCCC_KVM_FUNC_HYP_MEMINFO``.
116116
| | | +---------------------------------------------+
117117
| | | | ``INVALID_PARAMETER (-3)`` |
118118
+---------------------+----------+----+---------------------------------------------+
119+
120+
``ARM_SMCCC_KVM_FUNC_MMIO_GUARD``
121+
----------------------------------
122+
123+
Request that a given memory region is handled as MMIO by the hypervisor,
124+
allowing accesses to this region to be emulated by the KVM host. The size of the
125+
region is equal to the memory protection granule advertised by
126+
``ARM_SMCCC_KVM_FUNC_HYP_MEMINFO``.
127+
128+
+---------------------+-------------------------------------------------------------+
129+
| Presence: | Optional; pKVM protected guests only. |
130+
+---------------------+-------------------------------------------------------------+
131+
| Calling convention: | HVC64 |
132+
+---------------------+----------+--------------------------------------------------+
133+
| Function ID: | (uint32) | 0xC6000007 |
134+
+---------------------+----------+----+---------------------------------------------+
135+
| Arguments: | (uint64) | R1 | Base IPA of MMIO memory region |
136+
| +----------+----+---------------------------------------------+
137+
| | (uint64) | R2 | Reserved / Must be zero |
138+
| +----------+----+---------------------------------------------+
139+
| | (uint64) | R3 | Reserved / Must be zero |
140+
+---------------------+----------+----+---------------------------------------------+
141+
| Return Values: | (int64) | R0 | ``SUCCESS (0)`` |
142+
| | | +---------------------------------------------+
143+
| | | | ``INVALID_PARAMETER (-3)`` |
144+
+---------------------+----------+----+---------------------------------------------+

drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99

1010
#include <linux/arm-smccc.h>
1111
#include <linux/array_size.h>
12+
#include <linux/io.h>
1213
#include <linux/mem_encrypt.h>
1314
#include <linux/mm.h>
15+
#include <linux/pgtable.h>
1416

1517
#include <asm/hypervisor.h>
1618

@@ -67,6 +69,36 @@ static const struct arm64_mem_crypt_ops pkvm_crypt_ops = {
6769
.decrypt = pkvm_set_memory_decrypted,
6870
};
6971

72+
static int mmio_guard_ioremap_hook(phys_addr_t phys, size_t size,
73+
pgprot_t *prot)
74+
{
75+
phys_addr_t end;
76+
pteval_t protval = pgprot_val(*prot);
77+
78+
/*
79+
* We only expect MMIO emulation for regions mapped with device
80+
* attributes.
81+
*/
82+
if (protval != PROT_DEVICE_nGnRE && protval != PROT_DEVICE_nGnRnE)
83+
return 0;
84+
85+
phys = PAGE_ALIGN_DOWN(phys);
86+
end = phys + PAGE_ALIGN(size);
87+
88+
while (phys < end) {
89+
const int func_id = ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_FUNC_ID;
90+
int err;
91+
92+
err = arm_smccc_do_one_page(func_id, phys);
93+
if (err)
94+
return err;
95+
96+
phys += PAGE_SIZE;
97+
}
98+
99+
return 0;
100+
}
101+
70102
void pkvm_init_hyp_services(void)
71103
{
72104
int i;
@@ -89,4 +121,7 @@ void pkvm_init_hyp_services(void)
89121

90122
pkvm_granule = res.a0;
91123
arm64_mem_crypt_ops_register(&pkvm_crypt_ops);
124+
125+
if (kvm_arm_hyp_service_available(ARM_SMCCC_KVM_FUNC_MMIO_GUARD))
126+
arm64_ioremap_prot_hook_register(&mmio_guard_ioremap_hook);
92127
}

include/linux/arm-smccc.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@
118118
#define ARM_SMCCC_KVM_FUNC_HYP_MEMINFO 2
119119
#define ARM_SMCCC_KVM_FUNC_MEM_SHARE 3
120120
#define ARM_SMCCC_KVM_FUNC_MEM_UNSHARE 4
121+
#define ARM_SMCCC_KVM_FUNC_MMIO_GUARD 7
121122
#define ARM_SMCCC_KVM_FUNC_FEATURES_2 127
122123
#define ARM_SMCCC_KVM_NUM_FUNCS 128
123124

@@ -158,6 +159,12 @@
158159
ARM_SMCCC_OWNER_VENDOR_HYP, \
159160
ARM_SMCCC_KVM_FUNC_MEM_UNSHARE)
160161

162+
#define ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_FUNC_ID \
163+
ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
164+
ARM_SMCCC_SMC_64, \
165+
ARM_SMCCC_OWNER_VENDOR_HYP, \
166+
ARM_SMCCC_KVM_FUNC_MMIO_GUARD)
167+
161168
/* ptp_kvm counter type ID */
162169
#define KVM_PTP_VIRT_COUNTER 0
163170
#define KVM_PTP_PHYS_COUNTER 1

0 commit comments

Comments
 (0)