Add generic architecture API layer needed to implement coloring: arch_color_map_memory_region() // cell_create arch_color_unmap_memory_region() // cell_destroy arch_color_remap_to_root() // cell_load arch_color_unmap_from_root() // cell_start
Currently only arm64 will implement the API. arm32 could be also a possible target for coloring. x86 already features CAT support. ARM architectures also implement: arm_color_dcache_flush_memory_region() // range flushing arm_color_init() // hook for the initialization of coloring The architecture operations implement functionalities that consider the color assigned to a memory region when performing the VA <-> PA translation. This patch uses a reserved memory region as mapping-scratchpad to perform coloring during the load operations. The mapping is removed during the start operation. A later patch makes the start of the memory region configurable. Refer to the Documentation/cache-coloring.md for an introduction of the coloring isolation software techniques. Signed-off-by: Andrea Bastoni <[email protected]> --- driver/cell.c | 10 +++- .../arch/arm-common/include/asm/dcaches.h | 8 +++ hypervisor/arch/arm-common/mmu_cell.c | 52 ++++++++++------ hypervisor/arch/arm/include/asm/coloring.h | 59 +++++++++++++++++++ hypervisor/arch/arm64/include/asm/coloring.h | 59 +++++++++++++++++++ hypervisor/arch/arm64/setup.c | 3 + hypervisor/arch/x86/include/asm/coloring.h | 45 ++++++++++++++ hypervisor/control.c | 56 ++++++++++++------ hypervisor/include/jailhouse/control.h | 7 +++ include/jailhouse/cell-config.h | 6 ++ 10 files changed, 267 insertions(+), 38 deletions(-) create mode 100644 hypervisor/arch/arm/include/asm/coloring.h create mode 100644 hypervisor/arch/arm64/include/asm/coloring.h create mode 100644 hypervisor/arch/x86/include/asm/coloring.h diff --git a/driver/cell.c b/driver/cell.c index ade61edb..30a4c501 100644 --- a/driver/cell.c +++ b/driver/cell.c @@ -333,7 +333,15 @@ static int load_image(struct cell *cell, if (regions == 0) return -EINVAL; - phys_start = (mem->phys_start + image_offset) & PAGE_MASK; + if (mem->flags & JAILHOUSE_MEM_COLORED) { + /* Tweak the base address to request remapping of + * a reserved, high memory region. + */ + phys_start = (mem->virt_start + ROOT_MAP_OFFSET + image_offset) + & PAGE_MASK; + } else { + phys_start = (mem->phys_start + image_offset) & PAGE_MASK; + } page_offs = offset_in_page(image_offset); image_mem = jailhouse_ioremap(phys_start, 0, PAGE_ALIGN(image.size + page_offs)); diff --git a/hypervisor/arch/arm-common/include/asm/dcaches.h b/hypervisor/arch/arm-common/include/asm/dcaches.h index 87c316dc..26c5201a 100644 --- a/hypervisor/arch/arm-common/include/asm/dcaches.h +++ b/hypervisor/arch/arm-common/include/asm/dcaches.h @@ -11,6 +11,8 @@ * This work is licensed under the terms of the GNU GPL, version 2. See * the COPYING file in the top-level directory. */ +#ifndef _JAILHOUSE_DCACHES_H +#define _JAILHOUSE_DCACHES_H #ifndef __ASSEMBLY__ @@ -22,7 +24,13 @@ enum dcache_flush { DCACHE_CLEAN_AND_INVALIDATE, }; +void arm_dcache_flush_memory_region( + unsigned long region_addr, + unsigned long region_size, + enum dcache_flush flush); void arm_dcaches_flush(void *addr, unsigned long size, enum dcache_flush flush); void arm_cell_dcaches_flush(struct cell *cell, enum dcache_flush flush); #endif /* !__ASSEMBLY__ */ + +#endif diff --git a/hypervisor/arch/arm-common/mmu_cell.c b/hypervisor/arch/arm-common/mmu_cell.c index 7f9bb10a..202cc621 100644 --- a/hypervisor/arch/arm-common/mmu_cell.c +++ b/hypervisor/arch/arm-common/mmu_cell.c @@ -16,6 +16,7 @@ #include <asm/sysregs.h> #include <asm/control.h> #include <asm/iommu.h> +#include <asm/coloring.h> int arch_map_memory_region(struct cell *cell, const struct jailhouse_memory *mem) @@ -73,9 +74,33 @@ unsigned long arch_paging_gphys2phys(unsigned long gphys, unsigned long flags) return paging_virt2phys(&this_cell()->arch.mm, gphys, flags); } +void arm_dcache_flush_memory_region( + unsigned long region_addr, + unsigned long region_size, + enum dcache_flush flush) +{ + unsigned long size; + + while (region_size > 0) { + size = MIN(region_size, + NUM_TEMPORARY_PAGES * PAGE_SIZE); + + /* cannot fail, mapping area is preallocated */ + paging_create(&this_cpu_data()->pg_structs, region_addr, + size, TEMPORARY_MAPPING_BASE, + PAGE_DEFAULT_FLAGS, + PAGING_NON_COHERENT | PAGING_NO_HUGE); + + arm_dcaches_flush((void *)TEMPORARY_MAPPING_BASE, size, + flush); + + region_addr += size; + region_size -= size; + } +} + void arm_cell_dcaches_flush(struct cell *cell, enum dcache_flush flush) { - unsigned long region_addr, region_size, size; struct jailhouse_memory const *mem; unsigned int n; @@ -83,24 +108,13 @@ void arm_cell_dcaches_flush(struct cell *cell, enum dcache_flush flush) if (mem->flags & (JAILHOUSE_MEM_IO | JAILHOUSE_MEM_COMM_REGION)) continue; - region_addr = mem->phys_start; - region_size = mem->size; - - while (region_size > 0) { - size = MIN(region_size, - NUM_TEMPORARY_PAGES * PAGE_SIZE); - - /* cannot fail, mapping area is preallocated */ - paging_create(&this_cpu_data()->pg_structs, region_addr, - size, TEMPORARY_MAPPING_BASE, - PAGE_DEFAULT_FLAGS, - PAGING_NON_COHERENT | PAGING_NO_HUGE); - - arm_dcaches_flush((void *)TEMPORARY_MAPPING_BASE, size, - flush); - - region_addr += size; - region_size -= size; + if (mem->flags & JAILHOUSE_MEM_COLORED) { + arm_color_dcache_flush_memory_region(cell, mem, + flush); + } else { + arm_dcache_flush_memory_region(mem->phys_start, + mem->size, + flush); } } diff --git a/hypervisor/arch/arm/include/asm/coloring.h b/hypervisor/arch/arm/include/asm/coloring.h new file mode 100644 index 00000000..12d973ca --- /dev/null +++ b/hypervisor/arch/arm/include/asm/coloring.h @@ -0,0 +1,59 @@ +/* + * Jailhouse Cache Coloring Support + * + * Copyright (C) Technical University of Munich, 2020 + * + * Authors: + * Andrea Bastoni <[email protected]> + * + * This work is licensed under the terms of the GNU GPL, version 2. See the + * COPYING file in the top-level directory. + */ +#ifndef _JAILHOUSE_COLORING_H +#define _JAILHOUSE_COLORING_H + +#include <asm/dcaches.h> + +/* Coloring is only implemented on arm64, nothing to initialize on arm */ +static inline void arm_color_init(void) +{ + return; +} + +/* Make sure we catch incorrect calls to these functions for arm */ +static inline void arm_color_dcache_flush_memory_region( + struct cell *cell, + const struct jailhouse_memory *mr, + enum dcache_flush flush_type) +{ + BUG(); +} + +static inline void arch_color_unmap_memory_region( + struct cell *cell, + const struct jailhouse_memory *mr) +{ + BUG(); +} + +static inline int arch_color_map_memory_region( + struct cell *cell, + const struct jailhouse_memory *mr) +{ + BUG(); + return 0; +} + +static inline int arch_color_remap_to_root(const struct jailhouse_memory *mr) +{ + BUG(); + return 0; +} + +static inline int arch_color_unmap_from_root(const struct jailhouse_memory *mr) +{ + BUG(); + return 0; +} + +#endif diff --git a/hypervisor/arch/arm64/include/asm/coloring.h b/hypervisor/arch/arm64/include/asm/coloring.h new file mode 100644 index 00000000..54bfa9dd --- /dev/null +++ b/hypervisor/arch/arm64/include/asm/coloring.h @@ -0,0 +1,59 @@ +/* + * Jailhouse Cache Coloring Support + * + * Copyright (C) Technical University of Munich, 2020 + * + * Authors: + * Andrea Bastoni <[email protected]> + * + * This work is licensed under the terms of the GNU GPL, version 2. See the + * COPYING file in the top-level directory. + */ +#ifndef _JAILHOUSE_COLORING_H +#define _JAILHOUSE_COLORING_H + +#include <asm/dcaches.h> + +/* Initial empty stub for coloring functions. */ +static inline void arm_color_init(void) +{ + return; +} + +/* Make sure we catch incorrect calls to these functions for arm */ +static inline void arm_color_dcache_flush_memory_region( + struct cell *cell, + const struct jailhouse_memory *mr, + enum dcache_flush flush_type) +{ + BUG(); +} + +static inline void arch_color_unmap_memory_region( + struct cell *cell, + const struct jailhouse_memory *mr) +{ + BUG(); +} + +static inline int arch_color_map_memory_region( + struct cell *cell, + const struct jailhouse_memory *mr) +{ + BUG(); + return 0; +} + +static inline int arch_color_remap_to_root(const struct jailhouse_memory *mr) +{ + BUG(); + return 0; +} + +static inline int arch_color_unmap_from_root(const struct jailhouse_memory *mr) +{ + BUG(); + return 0; +} + +#endif diff --git a/hypervisor/arch/arm64/setup.c b/hypervisor/arch/arm64/setup.c index a24bf1d7..548e49b7 100644 --- a/hypervisor/arch/arm64/setup.c +++ b/hypervisor/arch/arm64/setup.c @@ -20,6 +20,7 @@ #include <asm/irqchip.h> #include <asm/setup.h> #include <asm/smccc.h> +#include <asm/coloring.h> extern u8 __trampoline_start[]; @@ -40,6 +41,8 @@ int arch_init_early(void) if (err) return err; + arm_color_init(); + return arm_init_early(); } diff --git a/hypervisor/arch/x86/include/asm/coloring.h b/hypervisor/arch/x86/include/asm/coloring.h new file mode 100644 index 00000000..e1f37413 --- /dev/null +++ b/hypervisor/arch/x86/include/asm/coloring.h @@ -0,0 +1,45 @@ +/* + * Jailhouse Cache Coloring Support + * + * Copyright (C) Technical University of Munich, 2020 + * + * Authors: + * Andrea Bastoni <[email protected]> + * + * This work is licensed under the terms of the GNU GPL, version 2. See the + * COPYING file in the top-level directory. + */ +#ifndef _JAILHOUSE_COLORING_H +#define _JAILHOUSE_COLORING_H + +/* Coloring is only implemented on arm64. + * Make sure we catch incorrect calls to these functions for x86 + */ +static inline void arch_color_unmap_memory_region( + struct cell *cell, + const struct jailhouse_memory *mr) +{ + BUG(); +} + +static inline int arch_color_map_memory_region( + struct cell *cell, + const struct jailhouse_memory *mr) +{ + BUG(); + return 0; +} + +static inline int arch_color_remap_to_root(const struct jailhouse_memory *mr) +{ + BUG(); + return 0; +} + +static inline int arch_color_unmap_from_root(const struct jailhouse_memory *mr) +{ + BUG(); + return 0; +} + +#endif diff --git a/hypervisor/control.c b/hypervisor/control.c index 2214406f..b99d4380 100644 --- a/hypervisor/control.c +++ b/hypervisor/control.c @@ -21,9 +21,9 @@ #include <jailhouse/utils.h> #include <asm/control.h> #include <asm/spinlock.h> +#include <asm/coloring.h> enum msg_type {MSG_REQUEST, MSG_INFORMATION}; -enum failure_mode {ABORT_ON_ERROR, WARN_ON_ERROR}; enum management_task {CELL_START, CELL_SET_LOADABLE, CELL_DESTROY}; /** System configuration as used while activating the hypervisor. */ @@ -319,8 +319,8 @@ static int unmap_from_root_cell(const struct jailhouse_memory *mem) return arch_unmap_memory_region(&root_cell, &tmp); } -static int remap_to_root_cell(const struct jailhouse_memory *mem, - enum failure_mode mode) +int remap_to_root_cell(const struct jailhouse_memory *mem, + enum failure_mode mode) { const struct jailhouse_memory *root_mem; struct jailhouse_memory overlap; @@ -380,17 +380,23 @@ static void cell_destroy_internal(struct cell *cell) } for_each_mem_region(mem, cell->config, n) { - if (!JAILHOUSE_MEMORY_IS_SUBPAGE(mem)) - /* - * This cannot fail. The region was mapped as a whole - * before, thus no hugepages need to be broken up to - * unmap it. - */ - arch_unmap_memory_region(cell, mem); + if (mem->flags & JAILHOUSE_MEM_COLORED) { + /* Coloring requires fine-granular unmap + remap */ + arch_color_unmap_memory_region(cell, mem); + } else { + if (!JAILHOUSE_MEMORY_IS_SUBPAGE(mem)) { + /* + * This cannot fail. The region was mapped as + * a whole before, thus no hugepages need to + * be broken up to unmap it. + */ + arch_unmap_memory_region(cell, mem); + } - if (!(mem->flags & (JAILHOUSE_MEM_COMM_REGION | - JAILHOUSE_MEM_ROOTSHARED))) - remap_to_root_cell(mem, WARN_ON_ERROR); + if (!(mem->flags & (JAILHOUSE_MEM_COMM_REGION | + JAILHOUSE_MEM_ROOTSHARED))) + remap_to_root_cell(mem, WARN_ON_ERROR); + } } for_each_unit_reverse(unit) @@ -531,10 +537,16 @@ static int cell_create(struct per_cpu *cpu_data, unsigned long config_address) goto err_destroy_cell; } - if (JAILHOUSE_MEMORY_IS_SUBPAGE(mem)) + if (JAILHOUSE_MEMORY_IS_SUBPAGE(mem)) { err = mmio_subpage_register(cell, mem); - else - err = arch_map_memory_region(cell, mem); + } else { + if (mem->flags & JAILHOUSE_MEM_COLORED) { + /* Coloring always at page boundaries */ + err = arch_color_map_memory_region(cell, mem); + } else { + err = arch_map_memory_region(cell, mem); + } + } if (err) goto err_destroy_cell; } @@ -633,7 +645,11 @@ static int cell_start(struct per_cpu *cpu_data, unsigned long id) /* unmap all loadable memory regions from the root cell */ for_each_mem_region(mem, cell->config, n) if (mem->flags & JAILHOUSE_MEM_LOADABLE) { - err = unmap_from_root_cell(mem); + if (mem->flags & JAILHOUSE_MEM_COLORED) { + err = arch_color_unmap_from_root(mem); + } else { + err = unmap_from_root_cell(mem); + } if (err) goto out_resume; } @@ -711,7 +727,11 @@ static int cell_set_loadable(struct per_cpu *cpu_data, unsigned long id) /* map all loadable memory regions into the root cell */ for_each_mem_region(mem, cell->config, n) if (mem->flags & JAILHOUSE_MEM_LOADABLE) { - err = remap_to_root_cell(mem, ABORT_ON_ERROR); + if (mem->flags & JAILHOUSE_MEM_COLORED) { + err = arch_color_remap_to_root(mem); + } else { + err = remap_to_root_cell(mem, ABORT_ON_ERROR); + } if (err) goto out_resume; } diff --git a/hypervisor/include/jailhouse/control.h b/hypervisor/include/jailhouse/control.h index f2b07c0d..76eb0428 100644 --- a/hypervisor/include/jailhouse/control.h +++ b/hypervisor/include/jailhouse/control.h @@ -132,6 +132,13 @@ void shutdown(void); void __attribute__((noreturn)) panic_stop(void); void panic_park(void); +enum failure_mode {ABORT_ON_ERROR, WARN_ON_ERROR}; +/** + * (Re)Mapping of a cell memory into root cell upon loading and destroy. + */ +int remap_to_root_cell(const struct jailhouse_memory *mem, + enum failure_mode mode); + /** * Resume a suspended remote CPU. * @param cpu_id ID of the target CPU. diff --git a/include/jailhouse/cell-config.h b/include/jailhouse/cell-config.h index 6b54e34b..8a3a201f 100644 --- a/include/jailhouse/cell-config.h +++ b/include/jailhouse/cell-config.h @@ -115,6 +115,7 @@ struct jailhouse_cell_desc { #define JAILHOUSE_MEM_LOADABLE 0x0040 #define JAILHOUSE_MEM_ROOTSHARED 0x0080 #define JAILHOUSE_MEM_NO_HUGEPAGES 0x0100 +#define JAILHOUSE_MEM_COLORED 0x0200 #define JAILHOUSE_MEM_IO_UNALIGNED 0x8000 #define JAILHOUSE_MEM_IO_WIDTH_SHIFT 16 /* uses bits 16..19 */ #define JAILHOUSE_MEM_IO_8 (1 << JAILHOUSE_MEM_IO_WIDTH_SHIFT) @@ -127,8 +128,13 @@ struct jailhouse_memory { __u64 virt_start; __u64 size; __u64 flags; + /* only meaningful with JAILHOUSE_MEM_COLORED */ + size_t colors; } __attribute__((packed)); +// FIXME: COLORING depending on design discussions, keep / remove / adapt +#define ROOT_MAP_OFFSET 0x0C000000000UL + #define JAILHOUSE_SHMEM_NET_REGIONS(start, dev_id) \ { \ .phys_start = start, \ -- 2.29.2 -- You received this message because you are subscribed to the Google Groups "Jailhouse" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/jailhouse-dev/20210125120044.56794-3-andrea.bastoni%40tum.de.
