Skip to content

Commit 3175e05

Browse files
committed
Merge branch 'for-next/pkvm-guest' into for-next/core
* for-next/pkvm-guest: arm64: smccc: Reserve block of KVM "vendor" services for pKVM hypercalls drivers/virt: pkvm: Intercept ioremap using pKVM MMIO_GUARD hypercall arm64: mm: Add confidential computing hook to ioremap_prot() drivers/virt: pkvm: Hook up mem_encrypt API using pKVM hypercalls arm64: mm: Add top-level dispatcher for internal mem_encrypt API drivers/virt: pkvm: Add initial support for running as a protected guest firmware/smccc: Call arch-specific hook on discovering KVM services
2 parents 119e3ee + 21be9f7 commit 3175e05

File tree

17 files changed

+437
-2
lines changed

17 files changed

+437
-2
lines changed

Documentation/virt/kvm/arm/hypercalls.rst

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,101 @@ Provides a discovery mechanism for other KVM/arm64 hypercalls.
4444
----------------------------------------
4545

4646
See ptp_kvm.rst
47+
48+
``ARM_SMCCC_KVM_FUNC_HYP_MEMINFO``
49+
----------------------------------
50+
51+
Query the memory protection parameters for a pKVM protected virtual machine.
52+
53+
+---------------------+-------------------------------------------------------------+
54+
| Presence: | Optional; pKVM protected guests only. |
55+
+---------------------+-------------------------------------------------------------+
56+
| Calling convention: | HVC64 |
57+
+---------------------+----------+--------------------------------------------------+
58+
| Function ID: | (uint32) | 0xC6000002 |
59+
+---------------------+----------+----+---------------------------------------------+
60+
| Arguments: | (uint64) | R1 | Reserved / Must be zero |
61+
| +----------+----+---------------------------------------------+
62+
| | (uint64) | R2 | Reserved / Must be zero |
63+
| +----------+----+---------------------------------------------+
64+
| | (uint64) | R3 | Reserved / Must be zero |
65+
+---------------------+----------+----+---------------------------------------------+
66+
| Return Values: | (int64) | R0 | ``INVALID_PARAMETER (-3)`` on error, else |
67+
| | | | memory protection granule in bytes |
68+
+---------------------+----------+----+---------------------------------------------+
69+
70+
``ARM_SMCCC_KVM_FUNC_MEM_SHARE``
71+
--------------------------------
72+
73+
Share a region of memory with the KVM host, granting it read, write and execute
74+
permissions. The size of the region is equal to the memory protection granule
75+
advertised by ``ARM_SMCCC_KVM_FUNC_HYP_MEMINFO``.
76+
77+
+---------------------+-------------------------------------------------------------+
78+
| Presence: | Optional; pKVM protected guests only. |
79+
+---------------------+-------------------------------------------------------------+
80+
| Calling convention: | HVC64 |
81+
+---------------------+----------+--------------------------------------------------+
82+
| Function ID: | (uint32) | 0xC6000003 |
83+
+---------------------+----------+----+---------------------------------------------+
84+
| Arguments: | (uint64) | R1 | Base IPA of memory region to share |
85+
| +----------+----+---------------------------------------------+
86+
| | (uint64) | R2 | Reserved / Must be zero |
87+
| +----------+----+---------------------------------------------+
88+
| | (uint64) | R3 | Reserved / Must be zero |
89+
+---------------------+----------+----+---------------------------------------------+
90+
| Return Values: | (int64) | R0 | ``SUCCESS (0)`` |
91+
| | | +---------------------------------------------+
92+
| | | | ``INVALID_PARAMETER (-3)`` |
93+
+---------------------+----------+----+---------------------------------------------+
94+
95+
``ARM_SMCCC_KVM_FUNC_MEM_UNSHARE``
96+
----------------------------------
97+
98+
Revoke access permission from the KVM host to a memory region previously shared
99+
with ``ARM_SMCCC_KVM_FUNC_MEM_SHARE``. The size of the region is equal to the
100+
memory protection granule advertised by ``ARM_SMCCC_KVM_FUNC_HYP_MEMINFO``.
101+
102+
+---------------------+-------------------------------------------------------------+
103+
| Presence: | Optional; pKVM protected guests only. |
104+
+---------------------+-------------------------------------------------------------+
105+
| Calling convention: | HVC64 |
106+
+---------------------+----------+--------------------------------------------------+
107+
| Function ID: | (uint32) | 0xC6000004 |
108+
+---------------------+----------+----+---------------------------------------------+
109+
| Arguments: | (uint64) | R1 | Base IPA of memory region to unshare |
110+
| +----------+----+---------------------------------------------+
111+
| | (uint64) | R2 | Reserved / Must be zero |
112+
| +----------+----+---------------------------------------------+
113+
| | (uint64) | R3 | Reserved / Must be zero |
114+
+---------------------+----------+----+---------------------------------------------+
115+
| Return Values: | (int64) | R0 | ``SUCCESS (0)`` |
116+
| | | +---------------------------------------------+
117+
| | | | ``INVALID_PARAMETER (-3)`` |
118+
+---------------------+----------+----+---------------------------------------------+
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+
+---------------------+----------+----+---------------------------------------------+

arch/arm/include/asm/hypervisor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@
77
void kvm_init_hyp_services(void);
88
bool kvm_arm_hyp_service_available(u32 func_id);
99

10+
static inline void kvm_arch_init_hyp_services(void) { };
11+
1012
#endif

arch/arm64/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ config ARM64
3434
select ARCH_HAS_KERNEL_FPU_SUPPORT if KERNEL_MODE_NEON
3535
select ARCH_HAS_KEEPINITRD
3636
select ARCH_HAS_MEMBARRIER_SYNC_CORE
37+
select ARCH_HAS_MEM_ENCRYPT
3738
select ARCH_HAS_NMI_SAFE_THIS_CPU_OPS
3839
select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
3940
select ARCH_HAS_PTE_DEVMAP

arch/arm64/include/asm/hypervisor.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,15 @@
77
void kvm_init_hyp_services(void);
88
bool kvm_arm_hyp_service_available(u32 func_id);
99

10+
#ifdef CONFIG_ARM_PKVM_GUEST
11+
void pkvm_init_hyp_services(void);
12+
#else
13+
static inline void pkvm_init_hyp_services(void) { };
14+
#endif
15+
16+
static inline void kvm_arch_init_hyp_services(void)
17+
{
18+
pkvm_init_hyp_services();
19+
};
20+
1021
#endif

arch/arm64/include/asm/io.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,10 @@ __iowrite64_copy(void __iomem *to, const void *from, size_t count)
271271
* I/O memory mapping functions.
272272
*/
273273

274+
typedef int (*ioremap_prot_hook_t)(phys_addr_t phys_addr, size_t size,
275+
pgprot_t *prot);
276+
int arm64_ioremap_prot_hook_register(const ioremap_prot_hook_t hook);
277+
274278
#define ioremap_prot ioremap_prot
275279

276280
#define _PAGE_IOREMAP PROT_DEVICE_nGnRE

arch/arm64/include/asm/mem_encrypt.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
#ifndef __ASM_MEM_ENCRYPT_H
3+
#define __ASM_MEM_ENCRYPT_H
4+
5+
struct arm64_mem_crypt_ops {
6+
int (*encrypt)(unsigned long addr, int numpages);
7+
int (*decrypt)(unsigned long addr, int numpages);
8+
};
9+
10+
int arm64_mem_crypt_ops_register(const struct arm64_mem_crypt_ops *ops);
11+
12+
int set_memory_encrypted(unsigned long addr, int numpages);
13+
int set_memory_decrypted(unsigned long addr, int numpages);
14+
15+
#endif /* __ASM_MEM_ENCRYPT_H */

arch/arm64/include/asm/set_memory.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#ifndef _ASM_ARM64_SET_MEMORY_H
44
#define _ASM_ARM64_SET_MEMORY_H
55

6+
#include <asm/mem_encrypt.h>
67
#include <asm-generic/set_memory.h>
78

89
bool can_set_direct_map(void);

arch/arm64/mm/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# SPDX-License-Identifier: GPL-2.0
22
obj-y := dma-mapping.o extable.o fault.o init.o \
33
cache.o copypage.o flush.o \
4-
ioremap.o mmap.o pgd.o mmu.o \
4+
ioremap.o mmap.o pgd.o mem_encrypt.o mmu.o \
55
context.o proc.o pageattr.o fixmap.o
66
obj-$(CONFIG_ARM64_CONTPTE) += contpte.o
77
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o

arch/arm64/mm/ioremap.c

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,22 @@
33
#include <linux/mm.h>
44
#include <linux/io.h>
55

6+
static ioremap_prot_hook_t ioremap_prot_hook;
7+
8+
int arm64_ioremap_prot_hook_register(ioremap_prot_hook_t hook)
9+
{
10+
if (WARN_ON(ioremap_prot_hook))
11+
return -EBUSY;
12+
13+
ioremap_prot_hook = hook;
14+
return 0;
15+
}
16+
617
void __iomem *ioremap_prot(phys_addr_t phys_addr, size_t size,
718
unsigned long prot)
819
{
920
unsigned long last_addr = phys_addr + size - 1;
21+
pgprot_t pgprot = __pgprot(prot);
1022

1123
/* Don't allow outside PHYS_MASK */
1224
if (last_addr & ~PHYS_MASK)
@@ -16,7 +28,16 @@ void __iomem *ioremap_prot(phys_addr_t phys_addr, size_t size,
1628
if (WARN_ON(pfn_is_map_memory(__phys_to_pfn(phys_addr))))
1729
return NULL;
1830

19-
return generic_ioremap_prot(phys_addr, size, __pgprot(prot));
31+
/*
32+
* If a hook is registered (e.g. for confidential computing
33+
* purposes), call that now and barf if it fails.
34+
*/
35+
if (unlikely(ioremap_prot_hook) &&
36+
WARN_ON(ioremap_prot_hook(phys_addr, size, &pgprot))) {
37+
return NULL;
38+
}
39+
40+
return generic_ioremap_prot(phys_addr, size, pgprot);
2041
}
2142
EXPORT_SYMBOL(ioremap_prot);
2243

arch/arm64/mm/mem_encrypt.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/*
3+
* Implementation of the memory encryption/decryption API.
4+
*
5+
* Since the low-level details of the operation depend on the
6+
* Confidential Computing environment (e.g. pKVM, CCA, ...), this just
7+
* acts as a top-level dispatcher to whatever hooks may have been
8+
* registered.
9+
*
10+
* Author: Will Deacon <[email protected]>
11+
* Copyright (C) 2024 Google LLC
12+
*
13+
* "Hello, boils and ghouls!"
14+
*/
15+
16+
#include <linux/bug.h>
17+
#include <linux/compiler.h>
18+
#include <linux/err.h>
19+
#include <linux/mm.h>
20+
21+
#include <asm/mem_encrypt.h>
22+
23+
static const struct arm64_mem_crypt_ops *crypt_ops;
24+
25+
int arm64_mem_crypt_ops_register(const struct arm64_mem_crypt_ops *ops)
26+
{
27+
if (WARN_ON(crypt_ops))
28+
return -EBUSY;
29+
30+
crypt_ops = ops;
31+
return 0;
32+
}
33+
34+
int set_memory_encrypted(unsigned long addr, int numpages)
35+
{
36+
if (likely(!crypt_ops) || WARN_ON(!PAGE_ALIGNED(addr)))
37+
return 0;
38+
39+
return crypt_ops->encrypt(addr, numpages);
40+
}
41+
EXPORT_SYMBOL_GPL(set_memory_encrypted);
42+
43+
int set_memory_decrypted(unsigned long addr, int numpages)
44+
{
45+
if (likely(!crypt_ops) || WARN_ON(!PAGE_ALIGNED(addr)))
46+
return 0;
47+
48+
return crypt_ops->decrypt(addr, numpages);
49+
}
50+
EXPORT_SYMBOL_GPL(set_memory_decrypted);

0 commit comments

Comments
 (0)