From: Luca Miccio <[email protected]> Implement all the functions needed by the coloring interface for the arm64 architecture. Coloring selection is retrieved by the jailhouse_cache structure(s) in cell's configuration. Each structure defines a color range that will be mapped to the corresponding color bitmask. The configuration is cell-wide and will be used with all the memory regions flagged with JAILHOUSE_MEM_COLORED. If no color selection is provided by the user and coloring is enabled, use all the available colors on the platform.
Signed-off-by: Luca Miccio <[email protected]> Signed-off-by: Marco Solieri <[email protected]> Acked-by: Angelo Ruocco <[email protected]> --- hypervisor/arch/arm64/Kbuild | 1 + hypervisor/arch/arm64/coloring.c | 232 +++++++++++++++++++++++++++++++ 2 files changed, 233 insertions(+) create mode 100644 hypervisor/arch/arm64/coloring.c diff --git a/hypervisor/arch/arm64/Kbuild b/hypervisor/arch/arm64/Kbuild index c34b0f32..6c566e4d 100644 --- a/hypervisor/arch/arm64/Kbuild +++ b/hypervisor/arch/arm64/Kbuild @@ -22,3 +22,4 @@ always := lib.a 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-$(CONFIG_COLORING) += coloring.o diff --git a/hypervisor/arch/arm64/coloring.c b/hypervisor/arch/arm64/coloring.c new file mode 100644 index 00000000..cb2d80e9 --- /dev/null +++ b/hypervisor/arch/arm64/coloring.c @@ -0,0 +1,232 @@ +/* + * Jailhouse, a Linux-based partitioning hypervisor + * + * Copyright (c) Universita' di Modena e Reggio Emilia, 2020 + * + * Authors: + * Luca Miccio <[email protected]> + * Marco Solieri <[email protected]> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + */ +#include <jailhouse/coloring.h> +#include <jailhouse/printk.h> +#include <jailhouse/entry.h> +#include <jailhouse/cell.h> +#include <jailhouse/control.h> + +#define for_each_cache_region(cache, config, counter) \ + for ((cache) = jailhouse_cell_cache_regions(config), (counter) = 0;\ + (counter) < (config)->num_cache_regions; \ + (cache)++, (counter)++) + +/** Default color bitmask uses all available colors */ +unsigned long color_bitmask_default[COLOR_BITMASK_SIZE]; + +/** Do care bits for coloring */ +unsigned long addr_col_mask; + +/** Max number of colors available on the platform */ +#define COLORING_MAX_NUM ((addr_col_mask >> PAGE_SHIFT) + 1) + +#define MSB_LONG_IDX(word) (word ? (BITS_PER_LONG - clz(word) - 1) : 0) +static inline unsigned long msb_color_bitmask(unsigned long *color_bitmask) +{ + unsigned long ret = 0; + unsigned int layer = COLOR_BITMASK_SIZE - 1; + + if (!color_bitmask) + return 0; + + while (!ret) { + ret = MSB_LONG_IDX(color_bitmask[layer]); + layer--; + } + + return ret; +} + +#define CTR_LINESIZE_MASK 0x7 +#define CTR_SIZE_SHIFT 13 +#define CTR_SIZE_MASK 0x3FFF +#define CTR_SELECT_L2 (1 << 1) +#define CTR_SELECT_L3 (1 << 2) +#define CTR_CTYPEn_MASK 0x7 +#define CTR_CTYPE2_SHIFT 3 +#define CTR_LLC_ON (1 << 2) +#define CTR_LOC_SHIFT 24 +#define CTR_LOC_MASK 0x7 +#define CTR_LOC_NOT_IMPLEMENTED (1 << 0) + +unsigned long get_llc_way_size(void) +{ + unsigned int cache_sel; + unsigned int cache_global_info; + unsigned int cache_info; + unsigned int cache_line_size; + unsigned int cache_set_num; + unsigned int cache_sel_tmp; + + arm_read_sysreg(CLIDR_EL1, cache_global_info); + + /* Check if at least L2 is implemented */ + if (((cache_global_info >> CTR_LOC_SHIFT) & CTR_LOC_MASK) + == CTR_LOC_NOT_IMPLEMENTED) { + printk("ERROR: L2 Cache not implemented\n"); + return trace_error(-ENODEV); + } + + /* Save old value of CSSELR_EL1 */ + arm_read_sysreg(CSSELR_EL1, cache_sel_tmp); + + /* Get LLC index */ + if (((cache_global_info >> CTR_CTYPE2_SHIFT) & CTR_CTYPEn_MASK) + == CTR_LLC_ON) + cache_sel = CTR_SELECT_L2; + else + cache_sel = CTR_SELECT_L3; + + /* Select the correct LLC in CSSELR_EL1 */ + arm_write_sysreg(CSSELR_EL1, cache_sel); + + /* Ensure write */ + isb(); + + /* Get info about the LLC */ + arm_read_sysreg(CCSIDR_EL1, cache_info); + + /* ARM TRM: (Log2(Number of bytes in cache line)) - 4. */ + cache_line_size = 1 << ((cache_info & CTR_LINESIZE_MASK) + 4); + /* ARM TRM: (Number of sets in cache) - 1 */ + cache_set_num = ((cache_info >> CTR_SIZE_SHIFT) & CTR_SIZE_MASK) + 1; + + /* Restore value in CSSELR_EL1 */ + arm_write_sysreg(CSSELR_EL1, cache_sel_tmp); + + /* Ensure write */ + isb(); + + return (cache_line_size * cache_set_num); +} + +int coloring_paging_init(unsigned int llc_way_size) +{ + unsigned int i; + + if (!llc_way_size) { + llc_way_size = get_llc_way_size(); + if (!llc_way_size) + return -ENODEV; + } + + /** + * Setup addr_col_mask + * This mask represents the bits in the address that can be used + * for defining available colors + */ + for (i = PAGE_SHIFT; i < MSB_LONG_IDX(llc_way_size); i++) + set_bit(i, &addr_col_mask); + + if (COLORING_MAX_NUM > MAX_COLOR_SUPPORTED) + return -ENOMEM; + + /* Setup default color bitmask */ + for (i = 0; i < COLORING_MAX_NUM; i++) + set_bit(i, color_bitmask_default); + + printk("Coloring information:\n"); + printk("LLC way size: %uKiB\n", llc_way_size >> 10); + printk("Address color mask: 0x%lx\n", addr_col_mask); + printk("Max number of avail. colors: %ld\n", COLORING_MAX_NUM); + return 0; +} + +int coloring_cell_init(struct cell *cell) +{ + const struct jailhouse_cache *cache; + int counter = 0; + int i; + + memset(cell->arch.color_bitmask, 0, + sizeof(unsigned long) * COLOR_BITMASK_SIZE); + + /* Root cell is currently not supported */ + if (cell == &root_cell) + return 0; + + for_each_cache_region(cache, cell->config, counter) { + if ((cache->start + cache->size) > COLORING_MAX_NUM || + !cache->size) { + printk("Wrong color config. Max value is %ld\n", + COLORING_MAX_NUM); + return -ERANGE; + } + + for (i = cache->start; i < (cache->start + cache->size); i++) + set_bit(i, cell->arch.color_bitmask); + } + + /* If no coloring configuration is provided, use all colors available */ + if (!counter) + memcpy(cell->arch.color_bitmask, color_bitmask_default, + sizeof(unsigned long) * COLOR_BITMASK_SIZE); + + printk("Cell [%s] color config: 0x%lx%lx%lx%lx\n", + cell->config->name, + cell->arch.color_bitmask[3], cell->arch.color_bitmask[2], + cell->arch.color_bitmask[1], cell->arch.color_bitmask[0]); + + return 0; +} + +unsigned long next_colored(unsigned long phys, unsigned long *color_bitmask) +{ + unsigned int high_idx; + unsigned int phys_col_id; + unsigned long retval = phys; + + if (!color_bitmask) + return phys; + + high_idx = MSB_LONG_IDX(addr_col_mask); + + phys_col_id = (phys & addr_col_mask) >> PAGE_SHIFT; + /** + * Loop over all possible colors starting from `phys_col_id` and find + * the next color id that belongs to `color_bitmask`. + */ + while (!test_bit(phys_col_id, color_bitmask)) { + /** + * If we go out of bounds, restart from 0 and carry 1 + * outside addr_col_mask MSB. + */ + if (phys_col_id > msb_color_bitmask(color_bitmask)) { + phys_col_id = 0; + retval += 1UL << (high_idx + 1); + } else + phys_col_id++; + } + + /* Reset old color configuration */ + retval &= ~(addr_col_mask); + retval |= (phys_col_id << PAGE_SHIFT); + + return retval; +} + +unsigned long get_end_addr(unsigned long start, unsigned long size, + unsigned long *color_bitmask) +{ + unsigned color_num = 0; + + /* Get number of colors from mask */ + for (int i = 0; i < MAX_COLOR_SUPPORTED; i++) + if (test_bit(i, color_bitmask)) + color_num++; + + /* Check if start address is compliant to color selection */ + start = next_colored(start, color_bitmask); + + return start + PAGE_ALIGN((size*COLORING_MAX_NUM)/color_num); +} -- 2.25.1 -- 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/20200421100351.292395-8-ms%40xt3.it.
