Extend mapping/unmapping operations to consider cache partitions specified via "coloring" and perform virt2phys mapping accordingly.
Also provide colored flushing of a memory region as well as an initialization helper to read the configuration parameters (way_size, root_map_offset). The root_map_offset is used as offset scratchpad to simplify the remapping_to/unmap_from root operations when loading and starting inmates. Refer to the Documentation/cache-coloring.md for an introduction of the coloring isolation software techniques. Signed-off-by: Andrea Bastoni <andrea.bast...@tum.de> --- .../arch/arm-common/include/asm/coloring.h | 45 +++++ .../arch/arm-common/include/asm/dcaches.h | 8 + hypervisor/arch/arm-common/mmu_cell.c | 68 +++++--- hypervisor/arch/arm64/Kbuild | 1 + hypervisor/arch/arm64/coloring.c | 108 ++++++++++++ hypervisor/arch/arm64/include/asm/coloring.h | 155 ++++++++++++++++++ hypervisor/arch/arm64/setup.c | 3 + hypervisor/control.c | 23 ++- hypervisor/include/jailhouse/control.h | 4 + include/jailhouse/coloring.h | 39 +++++ 10 files changed, 431 insertions(+), 23 deletions(-) create mode 100644 hypervisor/arch/arm-common/include/asm/coloring.h create mode 100644 hypervisor/arch/arm64/coloring.c create mode 100644 hypervisor/arch/arm64/include/asm/coloring.h create mode 100644 include/jailhouse/coloring.h diff --git a/hypervisor/arch/arm-common/include/asm/coloring.h b/hypervisor/arch/arm-common/include/asm/coloring.h new file mode 100644 index 00000000..91aa6285 --- /dev/null +++ b/hypervisor/arch/arm-common/include/asm/coloring.h @@ -0,0 +1,45 @@ +/* + * Jailhouse Cache Coloring Support - Stubs for ARMv7 + * + * Copyright (C) Technical University of Munich, 2020 + * + * Authors: + * Andrea Bastoni <andrea.bast...@tum.de> at https://rtsl.cps.mw.tum.de + * + * This work is licensed under the terms of the GNU GPL, version 2. See the + * COPYING file in the top-level directory. + */ +#ifndef _JAILHOUSE_ASM_COLORING_H +#define _JAILHOUSE_ASM_COLORING_H + +#include <jailhouse/utils.h> +#include <jailhouse/control.h> + +static inline void arm_color_dcache_flush_memory_region( + unsigned long phys, + unsigned long size, + unsigned long virt, + u64 color_mask, + enum dcache_flush flush_type) +{ + BUG(); +} + +static inline int +color_paging_create(const struct paging_structures *pg_structs, + unsigned long phys, unsigned long size, unsigned long virt, + unsigned long access_flags, unsigned long paging_flags, + u64 color_mask, u64 mem_flags) +{ + return -EINVAL; +} + +static inline int +color_paging_destroy(const struct paging_structures *pg_structs, + unsigned long phys, unsigned long size, unsigned long virt, + unsigned long paging_flags, u64 color_mask, u64 mem_flags) +{ + return -EINVAL; +} + +#endif 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..4c7827ce 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) @@ -46,7 +47,12 @@ int arch_map_memory_region(struct cell *cell, if (err) return err; - err = paging_create(&cell->arch.mm, phys_start, mem->size, + if (mem->flags & JAILHOUSE_MEM_COLORED) + err = color_paging_create(&cell->arch.mm, phys_start, + mem->size, mem->virt_start, access_flags, + paging_flags, mem->colors, mem->flags); + else + err = paging_create(&cell->arch.mm, phys_start, mem->size, mem->virt_start, access_flags, paging_flags); if (err) iommu_unmap_memory_region(cell, mem); @@ -63,6 +69,11 @@ int arch_unmap_memory_region(struct cell *cell, if (err) return err; + if (mem->flags & JAILHOUSE_MEM_COLORED) + return color_paging_destroy(&cell->arch.mm, + mem->phys_start, mem->size, mem->virt_start, + PAGING_COHERENT, mem->colors, mem->flags); + return paging_destroy(&cell->arch.mm, mem->virt_start, mem->size, PAGING_COHERENT); } @@ -73,9 +84,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 +118,17 @@ 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( + mem->phys_start, + mem->size, + mem->virt_start, + mem->colors, + flush); + } else { + arm_dcache_flush_memory_region(mem->phys_start, + mem->size, + flush); } } diff --git a/hypervisor/arch/arm64/Kbuild b/hypervisor/arch/arm64/Kbuild index 4d328021..a5525811 100644 --- a/hypervisor/arch/arm64/Kbuild +++ b/hypervisor/arch/arm64/Kbuild @@ -23,3 +23,4 @@ lib-y := $(common-objs-y) lib-y += entry.o setup.o control.o mmio.o paging.o caches.o traps.o lib-y += iommu.o smmu-v3.o ti-pvu.o lib-y += smmu.o +lib-y += coloring.o diff --git a/hypervisor/arch/arm64/coloring.c b/hypervisor/arch/arm64/coloring.c new file mode 100644 index 00000000..5ec437f1 --- /dev/null +++ b/hypervisor/arch/arm64/coloring.c @@ -0,0 +1,108 @@ +/* + * Jailhouse Cache Coloring Support + * + * Copyright (C) Università di Modena e Reggio Emilia, 2018 + * Copyright (C) Boston University, 2020 + * Copyright (C) Technical University of Munich, 2020 + * + * Authors: + * Luca Miccio <lucmic...@gmail.com> + * Renato Mancuso (BU) <rmanc...@bu.edu> + * Andrea Bastoni <andrea.bast...@tum.de> at https://rtsl.cps.mw.tum.de + * + * This work is licensed under the terms of the GNU GPL, version 2. See the + * COPYING file in the top-level directory. + */ +#include <jailhouse/control.h> +#include <jailhouse/paging.h> +#include <jailhouse/printk.h> +#include <jailhouse/unit.h> +#include <jailhouse/cell.h> +#include <jailhouse/coloring.h> +#include <asm/coloring.h> + +/** + * Only parameter needed to determine the coloring. + */ +u64 coloring_way_size = 0; + +/** Temporary load-mapping parameter */ +u64 coloring_root_map_offset = 0; + +static int dispatch_op( + struct color_op *op, + unsigned long bphys, + unsigned long bvirt, + unsigned long bsize) +{ + if (op->op & (COL_OP_CREATE | COL_OP_LOAD)) { + if (op->op & COL_OP_LOAD) { + /* Fix addr to match the driver's IPA ioremap */ + bvirt += coloring_root_map_offset; + } + return paging_create(op->pg_structs, bphys, bsize, bvirt, + op->access_flags, op->paging_flags); + } + + if (op->op & (COL_OP_DESTROY | COL_OP_START)) { + if (op->op & COL_OP_START) { + /* Match the address specified during load */ + bvirt += coloring_root_map_offset; + } + return paging_destroy(op->pg_structs, bvirt, bsize, + op->paging_flags); + } + + if (op->op & COL_OP_FLUSH) { + arm_dcache_flush_memory_region(bphys, bsize, op->flush_type); + return 0; + } + + return -EINVAL; +} + +int color_do_op(struct color_op *op) +{ + unsigned long bvirt, bphys, bsize; + /* bit: start, low, contiguous bit range width */ + unsigned int bs, bl, bw; + unsigned int n; + u64 colors; + int err; + + col_print("[%c] OP 0x%x: P: 0x%08lx V: 0x%08lx " + "(S: 0x%lx C: 0x%08llx A: 0x%lx P: 0x%lx F: 0x%d)\n", + (op->pg_structs == &root_cell.arch.mm) ? 'r' : 'c', + op->op, op->phys, op->virt, op->size, op->color_mask, + op->access_flags, op->paging_flags, op->flush_type); + + n = 0; + bvirt = op->virt; + bphys = bsize = 0; + while (bvirt < op->virt + op->size) { + bs = bl = bw = 0; + colors = op->color_mask; + + while (colors != 0) { + /* update colors with next color-range */ + get_bit_range(&colors, &bl, &bw); + bs += bl; + bsize = bw * PAGE_SIZE; + bphys = op->phys + (bs * PAGE_SIZE) + + (n * coloring_way_size); + + err = dispatch_op(op, bphys, bvirt, bsize); + if (err) + return err; + + /* update next round */ + bvirt += bsize; + } + n++; + } + + col_print("end P: 0x%08lx V: 0x%08lx (bsize = 0x%08lx)\n", + bphys, bvirt - bsize, bsize); + + return err; +} diff --git a/hypervisor/arch/arm64/include/asm/coloring.h b/hypervisor/arch/arm64/include/asm/coloring.h new file mode 100644 index 00000000..233237fc --- /dev/null +++ b/hypervisor/arch/arm64/include/asm/coloring.h @@ -0,0 +1,155 @@ +/* + * Jailhouse Cache Coloring Support + * + * Copyright (C) Università di Modena e Reggio Emilia, 2018 + * Copyright (C) Boston University, 2020 + * Copyright (C) Technical University of Munich, 2020 + * + * Authors: + * Luca Miccio <lucmic...@gmail.com> + * Renato Mancuso (BU) <rmanc...@bu.edu> + * Andrea Bastoni <andrea.bast...@tum.de> at https://rtsl.cps.mw.tum.de + * + * This work is licensed under the terms of the GNU GPL, version 2. See the + * COPYING file in the top-level directory. + */ +#ifndef _JAILHOUSE_ASM_COLORING_H +#define _JAILHOUSE_ASM_COLORING_H + +#include <jailhouse/cell-config.h> +#include <jailhouse/utils.h> +#include <jailhouse/control.h> + +#ifdef CONFIG_DEBUG +#define col_print(fmt, ...) \ + printk("[COL] " fmt, ##__VA_ARGS__) +#else +#define col_print(fmt, ...) do { } while (0) +#endif + +/** Color operations */ +#define COL_OP_CREATE 0x1 +#define COL_OP_DESTROY 0x2 +#define COL_OP_START 0x4 +#define COL_OP_LOAD 0x8 +#define COL_OP_FLUSH 0x10 + +/** + * Only parameter needed to determine the coloring. + */ +extern u64 coloring_way_size; + +/** Temporary load-mapping parameter */ +extern u64 coloring_root_map_offset; + +/** + * Colored Operation + */ +struct color_op { + const struct paging_structures *pg_structs; + unsigned long phys; + unsigned long size; + unsigned long virt; + unsigned long access_flags; + unsigned long paging_flags; + u64 color_mask; + enum dcache_flush flush_type; + unsigned int op; +}; + +/** + * Colored operations on a cell / memory region. + * + * Encapsulate the loops needed to iterate through a region and identify + * the color-compatible phys2virt mappings. + */ +extern int color_do_op(struct color_op *op); + +static inline void arm_color_dcache_flush_memory_region( + unsigned long phys, + unsigned long size, + unsigned long virt, + u64 color_mask, + enum dcache_flush flush_type) +{ + struct color_op op; + + if (coloring_way_size == 0) + BUG(); + + op.phys = phys; + op.size = size; + op.virt = virt; + op.color_mask = color_mask; + op.flush_type = flush_type; + op.op = COL_OP_FLUSH; + + color_do_op(&op); +} + +/** + * Detection of coloring way size. + */ +static inline void arm_color_init(void) +{ + coloring_way_size = system_config->platform_info.color.way_size; + coloring_root_map_offset = + system_config->platform_info.color.root_map_offset; + + printk("Init Coloring: Way size: 0x%llx, TMP load addr: 0x%llx\n", + coloring_way_size, coloring_root_map_offset); +} + +static inline int +color_paging_create(const struct paging_structures *pg_structs, + unsigned long phys, unsigned long size, unsigned long virt, + unsigned long access_flags, unsigned long paging_flags, + u64 color_mask, u64 mem_flags) +{ + struct color_op op; + + if (coloring_way_size == 0) + return -EINVAL; + + op.pg_structs = pg_structs; + op.phys = phys; + op.size = size; + op.virt = virt; + op.access_flags = access_flags; + op.paging_flags = paging_flags; + op.color_mask = color_mask; + if (mem_flags & JAILHOUSE_MEM_TMP_ROOT_REMAP) { + op.op = COL_OP_LOAD; + } else { + op.op = COL_OP_CREATE; + } + + return color_do_op(&op); +} + +static inline int +color_paging_destroy(const struct paging_structures *pg_structs, + unsigned long phys, unsigned long size, unsigned long virt, + unsigned long paging_flags, u64 color_mask, u64 mem_flags) +{ + struct color_op op; + + if (coloring_way_size == 0) + return -EINVAL; + + op.pg_structs = pg_structs; + op.phys = phys; + op.size = size; + op.virt = virt; + op.paging_flags = paging_flags; + op.color_mask = color_mask; + if (mem_flags & JAILHOUSE_MEM_TMP_ROOT_REMAP) { + op.op = COL_OP_START; + } else { + op.op = COL_OP_DESTROY; + } + + return color_do_op(&op); +} + +#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/control.c b/hypervisor/control.c index 2214406f..d3b40c6a 100644 --- a/hypervisor/control.c +++ b/hypervisor/control.c @@ -300,7 +300,7 @@ static bool address_in_region(unsigned long addr, addr < (region->phys_start + region->size); } -static int unmap_from_root_cell(const struct jailhouse_memory *mem) +static int unmap_from_root_cell(const struct jailhouse_memory *mem, bool create) { /* * arch_unmap_memory_region and mmio_subpage_unregister use the @@ -316,6 +316,12 @@ static int unmap_from_root_cell(const struct jailhouse_memory *mem) return 0; } + if (!create && (mem->flags & JAILHOUSE_MEM_COLORED)) { + /* start cell: remove temporary mapping */ + tmp.flags |= JAILHOUSE_MEM_TMP_ROOT_REMAP; + tmp.virt_start = mem->virt_start; + } + return arch_unmap_memory_region(&root_cell, &tmp); } @@ -347,6 +353,17 @@ static int remap_to_root_cell(const struct jailhouse_memory *mem, overlap.phys_start - root_mem->phys_start; overlap.flags = root_mem->flags; + if (mem->flags & JAILHOUSE_MEM_COLORED) { + /* Use the colors from the to-be-remapped region */ + overlap.flags |= JAILHOUSE_MEM_COLORED; + overlap.colors = mem->colors; + if (mode == ABORT_ON_ERROR) { + /* load cell: setup temporary mapping */ + overlap.flags |= JAILHOUSE_MEM_TMP_ROOT_REMAP; + overlap.virt_start = mem->virt_start; + } + } + if (JAILHOUSE_MEMORY_IS_SUBPAGE(&overlap)) err = mmio_subpage_register(&root_cell, &overlap); else @@ -526,7 +543,7 @@ static int cell_create(struct per_cpu *cpu_data, unsigned long config_address) */ if (!(mem->flags & (JAILHOUSE_MEM_COMM_REGION | JAILHOUSE_MEM_ROOTSHARED))) { - err = unmap_from_root_cell(mem); + err = unmap_from_root_cell(mem, true); if (err) goto err_destroy_cell; } @@ -633,7 +650,7 @@ 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); + err = unmap_from_root_cell(mem, false); if (err) goto out_resume; } diff --git a/hypervisor/include/jailhouse/control.h b/hypervisor/include/jailhouse/control.h index f2b07c0d..03b0f3fd 100644 --- a/hypervisor/include/jailhouse/control.h +++ b/hypervisor/include/jailhouse/control.h @@ -9,6 +9,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_CONTROL_H +#define _JAILHOUSE_CONTROL_H #include <jailhouse/bitops.h> #include <jailhouse/percpu.h> @@ -291,3 +293,5 @@ void __attribute__((noreturn)) arch_panic_stop(void); void arch_panic_park(void); /** @} */ + +#endif diff --git a/include/jailhouse/coloring.h b/include/jailhouse/coloring.h new file mode 100644 index 00000000..86158196 --- /dev/null +++ b/include/jailhouse/coloring.h @@ -0,0 +1,39 @@ +/* + * Jailhouse Cache Coloring Support + * + * Copyright (C) Technical University of Munich, 2020 + * + * Authors: + * Andrea Bastoni <andrea.bast...@tum.de> + * + * This work is licensed under the terms of the GNU GPL, version 2. See the + * COPYING file in the top-level directory. + */ +/** MSB/LSB function names differs between Jailhouse and Linux */ +#define _lsb(x) ffsl(x) +#define _msb(x) msbl(x) + +/** + * Get range of contiguous bits in a bitmask. + * + * The function returns: + * - bitmask without the extracted bit range. + * - low: original bit position of range start. + * - size: size of the range + * + * The function assumes bitmask is not 0. + */ +static inline void get_bit_range( + u64 *bitmask, + unsigned int *low, + unsigned int *size) +{ + unsigned int _range; + + *low = _lsb(*bitmask); + _range = *bitmask >> *low; + *bitmask = _range & (_range + 1UL); + + _range = _range ^ *bitmask; + *size = _msb(_range) + 1; +} -- 2.30.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 jailhouse-dev+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/jailhouse-dev/20210322194507.82643-5-andrea.bastoni%40tum.de.