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.

Reply via email to