[PATCH RFC v15 15/30] gunyah: Add hypercalls for demand paging

From: Elliot Berman
Date: Fri Dec 15 2023 - 19:25:39 EST


Three hypercalls are needed to support demand paging.

Signed-off-by: Elliot Berman <quic_eberman@xxxxxxxxxxx>
---
arch/arm64/gunyah/gunyah_hypercall.c | 60 +++++++++++++++++++++++++++
arch/arm64/include/asm/gunyah.h | 21 ++++++++++
include/linux/gunyah.h | 79 ++++++++++++++++++++++++++++++++++++
3 files changed, 160 insertions(+)

diff --git a/arch/arm64/gunyah/gunyah_hypercall.c b/arch/arm64/gunyah/gunyah_hypercall.c
index cadc512934c4..468a5bcb98b1 100644
--- a/arch/arm64/gunyah/gunyah_hypercall.c
+++ b/arch/arm64/gunyah/gunyah_hypercall.c
@@ -39,6 +39,9 @@ EXPORT_SYMBOL_GPL(arch_is_gunyah_guest);
#define GUNYAH_HYPERCALL_HYP_IDENTIFY GUNYAH_HYPERCALL(0x8000)
#define GUNYAH_HYPERCALL_MSGQ_SEND GUNYAH_HYPERCALL(0x801B)
#define GUNYAH_HYPERCALL_MSGQ_RECV GUNYAH_HYPERCALL(0x801C)
+#define GUNYAH_HYPERCALL_ADDRSPACE_MAP GUNYAH_HYPERCALL(0x802B)
+#define GUNYAH_HYPERCALL_ADDRSPACE_UNMAP GUNYAH_HYPERCALL(0x802C)
+#define GUNYAH_HYPERCALL_MEMEXTENT_DONATE GUNYAH_HYPERCALL(0x8061)
/* clang-format on */

/**
@@ -92,5 +95,62 @@ enum gunyah_error gunyah_hypercall_msgq_recv(u64 capid, void *buff, size_t size,
}
EXPORT_SYMBOL_GPL(gunyah_hypercall_msgq_recv);

+enum gunyah_error gunyah_hypercall_addrspace_map(u64 capid, u64 extent_capid, u64 vbase,
+ u32 extent_attrs, u32 flags, u64 offset, u64 size)
+{
+ struct arm_smccc_1_2_regs args = {
+ .a0 = GUNYAH_HYPERCALL_ADDRSPACE_MAP,
+ .a1 = capid,
+ .a2 = extent_capid,
+ .a3 = vbase,
+ .a4 = extent_attrs,
+ .a5 = flags,
+ .a6 = offset,
+ .a7 = size,
+ /* C language says this will be implictly zero. Gunyah requires 0, so be explicit */
+ .a8 = 0,
+ };
+ struct arm_smccc_1_2_regs res;
+
+ arm_smccc_1_2_hvc(&args, &res);
+
+ return res.a0;
+}
+EXPORT_SYMBOL_GPL(gunyah_hypercall_addrspace_map);
+
+enum gunyah_error gunyah_hypercall_addrspace_unmap(u64 capid, u64 extent_capid, u64 vbase,
+ u32 flags, u64 offset, u64 size)
+{
+ struct arm_smccc_1_2_regs args = {
+ .a0 = GUNYAH_HYPERCALL_ADDRSPACE_UNMAP,
+ .a1 = capid,
+ .a2 = extent_capid,
+ .a3 = vbase,
+ .a4 = flags,
+ .a5 = offset,
+ .a6 = size,
+ /* C language says this will be implictly zero. Gunyah requires 0, so be explicit */
+ .a7 = 0,
+ };
+ struct arm_smccc_1_2_regs res;
+
+ arm_smccc_1_2_hvc(&args, &res);
+
+ return res.a0;
+}
+EXPORT_SYMBOL_GPL(gunyah_hypercall_addrspace_unmap);
+
+enum gunyah_error gunyah_hypercall_memextent_donate(u32 options, u64 from_capid, u64 to_capid,
+ u64 offset, u64 size)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_1_1_hvc(GUNYAH_HYPERCALL_MEMEXTENT_DONATE, options, from_capid, to_capid,
+ offset, size, 0, &res);
+
+ return res.a0;
+}
+EXPORT_SYMBOL_GPL(gunyah_hypercall_memextent_donate);
+
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Gunyah Hypervisor Hypercalls");
diff --git a/arch/arm64/include/asm/gunyah.h b/arch/arm64/include/asm/gunyah.h
index 0cd3debe22b6..4adf24977fd1 100644
--- a/arch/arm64/include/asm/gunyah.h
+++ b/arch/arm64/include/asm/gunyah.h
@@ -33,4 +33,25 @@ static inline int arch_gunyah_fill_irq_fwspec_params(u32 virq,
return 0;
}

+enum arch_gunyah_memtype {
+ /* clang-format off */
+ GUNYAH_MEMTYPE_DEVICE_nGnRnE = 0,
+ GUNYAH_DEVICE_nGnRE = 1,
+ GUNYAH_DEVICE_nGRE = 2,
+ GUNYAH_DEVICE_GRE = 3,
+
+ GUNYAH_NORMAL_NC = 0b0101,
+ GUNYAH_NORMAL_ONC_IWT = 0b0110,
+ GUNYAH_NORMAL_ONC_IWB = 0b0111,
+ GUNYAH_NORMAL_OWT_INC = 0b1001,
+ GUNYAH_NORMAL_WT = 0b1010,
+ GUNYAH_NORMAL_OWT_IWB = 0b1011,
+ GUNYAH_NORMAL_OWB_INC = 0b1101,
+ GUNYAH_NORMAL_OWB_IWT = 0b1110,
+ GUNYAH_NORMAL_WB = 0b1111,
+ /* clang-format on */
+};
+
+#define ARCH_GUNYAH_DEFAULT_MEMTYPE GUNYAH_NORMAL_WB
+
#endif
diff --git a/include/linux/gunyah.h b/include/linux/gunyah.h
index ecd62d0e36ad..86f48dc1d56d 100644
--- a/include/linux/gunyah.h
+++ b/include/linux/gunyah.h
@@ -151,4 +151,83 @@ enum gunyah_error gunyah_hypercall_msgq_send(u64 capid, size_t size, void *buff,
enum gunyah_error gunyah_hypercall_msgq_recv(u64 capid, void *buff, size_t size,
size_t *recv_size, bool *ready);

+#define GUNYAH_ADDRSPACE_SELF_CAP 0
+
+enum gunyah_pagetable_access {
+ /* clang-format off */
+ GUNYAH_PAGETABLE_ACCESS_NONE = 0,
+ GUNYAH_PAGETABLE_ACCESS_X = 1,
+ GUNYAH_PAGETABLE_ACCESS_W = 2,
+ GUNYAH_PAGETABLE_ACCESS_R = 4,
+ GUNYAH_PAGETABLE_ACCESS_RX = 5,
+ GUNYAH_PAGETABLE_ACCESS_RW = 6,
+ GUNYAH_PAGETABLE_ACCESS_RWX = 7,
+ /* clang-format on */
+};
+
+/* clang-format off */
+#define GUNYAH_MEMEXTENT_MAPPING_USER_ACCESS GENMASK_ULL(2, 0)
+#define GUNYAH_MEMEXTENT_MAPPING_KERNEL_ACCESS GENMASK_ULL(6, 4)
+#define GUNYAH_MEMEXTENT_MAPPING_TYPE GENMASK_ULL(23, 16)
+/* clang-format on */
+
+enum gunyah_memextent_donate_type {
+ /* clang-format off */
+ GUNYAH_MEMEXTENT_DONATE_TO_CHILD = 0,
+ GUNYAH_MEMEXTENT_DONATE_TO_PARENT = 1,
+ GUNYAH_MEMEXTENT_DONATE_TO_SIBLING = 2,
+ GUNYAH_MEMEXTENT_DONATE_TO_PROTECTED = 3,
+ GUNYAH_MEMEXTENT_DONATE_FROM_PROTECTED = 4,
+ /* clang-format on */
+};
+
+enum gunyah_addrspace_map_flag_bits {
+ /* clang-format off */
+ GUNYAH_ADDRSPACE_MAP_FLAG_PARTIAL = 0,
+ GUNYAH_ADDRSPACE_MAP_FLAG_PRIVATE = 1,
+ GUNYAH_ADDRSPACE_MAP_FLAG_VMMIO = 2,
+ GUNYAH_ADDRSPACE_MAP_FLAG_NOSYNC = 31,
+ /* clang-format on */
+};
+
+enum gunyah_error gunyah_hypercall_addrspace_map(u64 capid, u64 extent_capid,
+ u64 vbase, u32 extent_attrs,
+ u32 flags, u64 offset,
+ u64 size);
+enum gunyah_error gunyah_hypercall_addrspace_unmap(u64 capid, u64 extent_capid,
+ u64 vbase, u32 flags,
+ u64 offset, u64 size);
+
+/* clang-format off */
+#define GUNYAH_MEMEXTENT_OPTION_TYPE_MASK GENMASK_ULL(7, 0)
+#define GUNYAH_MEMEXTENT_OPTION_NOSYNC BIT(31)
+/* clang-format on */
+
+enum gunyah_error gunyah_hypercall_memextent_donate(u32 options, u64 from_capid,
+ u64 to_capid, u64 offset,
+ u64 size);
+
+struct gunyah_hypercall_vcpu_run_resp {
+ union {
+ enum {
+ /* clang-format off */
+ /* VCPU is ready to run */
+ GUNYAH_VCPU_STATE_READY = 0,
+ /* VCPU is sleeping until an interrupt arrives */
+ GUNYAH_VCPU_STATE_EXPECTS_WAKEUP = 1,
+ /* VCPU is powered off */
+ GUNYAH_VCPU_STATE_POWERED_OFF = 2,
+ /* VCPU is blocked in EL2 for unspecified reason */
+ GUNYAH_VCPU_STATE_BLOCKED = 3,
+ /* VCPU has returned for MMIO READ */
+ GUNYAH_VCPU_ADDRSPACE_VMMIO_READ = 4,
+ /* VCPU has returned for MMIO WRITE */
+ GUNYAH_VCPU_ADDRSPACE_VMMIO_WRITE = 5,
+ /* clang-format on */
+ } state;
+ u64 sized_state;
+ };
+ u64 state_data[3];
+};
+
#endif

--
2.43.0