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 <[email protected]> --- 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
