|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [RFC PATCH v1 06/26] xen/arm/cca: add Realm granule helpers
Add the memory-tracking preflight and the single-granule delegate
helpers. Realm-owned pages have to come from fine, conventional
tracking regions.
Signed-off-by: Koichiro Den <den@xxxxxxxxxxxxx>
---
xen/arch/arm/cca/Makefile | 1 +
xen/arch/arm/cca/granule.c | 150 +++++++++++++++++++++++++++++++++
xen/arch/arm/include/asm/cca.h | 5 ++
3 files changed, 156 insertions(+)
create mode 100644 xen/arch/arm/cca/granule.c
diff --git a/xen/arch/arm/cca/Makefile b/xen/arch/arm/cca/Makefile
index aaa04e3b914b..7f20d43323c3 100644
--- a/xen/arch/arm/cca/Makefile
+++ b/xen/arch/arm/cca/Makefile
@@ -1,2 +1,3 @@
+obj-y += granule.o
obj-y += rmi.o
obj-y += state.o
diff --git a/xen/arch/arm/cca/granule.c b/xen/arch/arm/cca/granule.c
new file mode 100644
index 000000000000..d2be4d240f19
--- /dev/null
+++ b/xen/arch/arm/cca/granule.c
@@ -0,0 +1,150 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <xen/bootinfo.h>
+#include <xen/errno.h>
+#include <xen/init.h>
+#include <xen/lib.h>
+
+#include <asm/cca.h>
+
+#include "rmi.h"
+
+static paddr_t __init arm_cca_l0gpt_size(unsigned long features1)
+{
+ unsigned long l0gptsz = arm_cca_rmi_field_get(
+ features1, ARM_CCA_RMI_FEATURE_REGISTER_1_L0GPTSZ_SHIFT,
+ ARM_CCA_RMI_FEATURE_REGISTER_1_L0GPTSZ_WIDTH);
+
+ return 1ULL << (30 + l0gptsz);
+}
+
+static int __init arm_cca_verify_memory_tracking(paddr_t start, paddr_t end)
+{
+ while ( start < end )
+ {
+ unsigned long category, state;
+ paddr_t next;
+ int rc;
+
+ rc = arm_cca_rmi_granule_tracking_get(start, end, &category, &state,
+ &next);
+ if ( rc != 0 )
+ return rc;
+
+ if ( category != ARM_CCA_RMI_MEM_CATEGORY_CONVENTIONAL ||
+ state != ARM_CCA_RMI_TRACKING_FINE ||
+ next <= start || next > end )
+ {
+ printk(XENLOG_ERR
+ "ARM CCA: memory [%#" PRIpaddr ", %#" PRIpaddr
+ ") is not fine-tracked conventional memory\n",
+ start, end);
+ return -EOPNOTSUPP;
+ }
+
+ start = next;
+ }
+
+ return 0;
+}
+
+static int __init arm_cca_create_gpts(paddr_t start, paddr_t end,
+ paddr_t l0gpt_size)
+{
+ paddr_t base = ROUNDDOWN(start, l0gpt_size);
+ paddr_t stop = ROUNDUP(end, l0gpt_size);
+
+ while ( base < stop )
+ {
+ int rc = arm_cca_rmi_gpt_l1_create(base);
+
+ if ( rc != 0 )
+ {
+ printk(XENLOG_ERR
+ "ARM CCA: failed to create GPT L1 for %#" PRIpaddr "\n",
+ base);
+ return rc;
+ }
+
+ base += l0gpt_size;
+ }
+
+ return 0;
+}
+
+int __init arm_cca_prepare_host_memory(unsigned long features1)
+{
+ const struct membanks *mem = bootinfo_get_mem();
+ paddr_t l0gpt_size = arm_cca_l0gpt_size(features1);
+ unsigned int i;
+ int rc;
+
+ for ( i = 0; i < mem->nr_banks; i++ )
+ {
+ paddr_t start = mem->bank[i].start;
+ paddr_t end = start + mem->bank[i].size;
+
+ rc = arm_cca_verify_memory_tracking(start, end);
+ if ( rc != 0 )
+ return rc;
+
+ rc = arm_cca_create_gpts(start, end, l0gpt_size);
+ if ( rc != 0 )
+ return rc;
+ }
+
+ return 0;
+}
+
+static int arm_cca_process_granule_range(paddr_t start, paddr_t end,
+ bool delegate)
+{
+ paddr_t cur = start;
+ int rc;
+
+ /*
+ * arm_cca_prepare_host_memory() checks that host DRAM is fine-tracked and
+ * has GPT L1 metadata before any Realm-owned granule can be delegated.
+ */
+ if ( start >= end || !IS_ALIGNED(start, PAGE_SIZE) ||
+ !IS_ALIGNED(end, PAGE_SIZE) )
+ return -EINVAL;
+
+ while ( cur < end )
+ {
+ paddr_t out_top = INVALID_PADDR;
+
+ if ( delegate )
+ rc = arm_cca_rmi_granule_range_delegate(cur, end, &out_top);
+ else
+ rc = arm_cca_rmi_granule_range_undelegate(cur, end, &out_top);
+
+ if ( rc != 0 )
+ return rc;
+
+ if ( out_top <= cur || out_top > end )
+ return -EIO;
+
+ cur = out_top;
+ }
+
+ return 0;
+}
+
+/* DEN0137 2.0-bet1 - D1.1.1 Granule delegation flow. */
+int arm_cca_delegate_granule(paddr_t granule)
+{
+ if ( !IS_ALIGNED(granule, PAGE_SIZE) )
+ return -EINVAL;
+
+ return arm_cca_process_granule_range(granule, granule + PAGE_SIZE, true);
+}
+
+/* DEN0137 2.0-bet1 - D1.1.2 Granule undelegation flow. */
+int arm_cca_undelegate_granule(paddr_t granule)
+{
+ if ( !IS_ALIGNED(granule, PAGE_SIZE) )
+ return -EINVAL;
+
+ return arm_cca_process_granule_range(granule, granule + PAGE_SIZE, false);
+}
diff --git a/xen/arch/arm/include/asm/cca.h b/xen/arch/arm/include/asm/cca.h
index 6bf644fbcee5..c35d51f750a3 100644
--- a/xen/arch/arm/include/asm/cca.h
+++ b/xen/arch/arm/include/asm/cca.h
@@ -2,6 +2,7 @@
#ifndef ARM_CCA_H
#define ARM_CCA_H
+#include <xen/init.h>
#include <xen/types.h>
/*
@@ -79,4 +80,8 @@ void arm_cca_vcpu_destroy(struct vcpu *v);
void *arm_cca_alloc_rec_run(void);
void arm_cca_free_rec_run(void *run);
+int arm_cca_delegate_granule(paddr_t granule);
+int arm_cca_undelegate_granule(paddr_t granule);
+int arm_cca_prepare_host_memory(unsigned long features1) __init;
+
#endif /* ARM_CCA_H */
--
2.51.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |