From: Luca Miccio <[email protected]>

The usual life cycle of an inmate is divided in 4 phases: creation,
loading, starting and destruction. The most crucial phase for coloring
is the loading one because Jailhouse relies on Linux and its driver
module for loading binaries. In order to avoid exposing the coloring
logic outside the hypervisor, use a separate memory for loading binaries
to colored regions.
During creation and destruction phases there is no functional change:
the memory is mapped and unmapped using coloring functions as they
should since we are handling colored regions.
During loading phase a special colored mapping is created. The latter
has the same physical start and coloring logic as the cell's memory but
virtually starts at col_load_address.
This will expose a virtually contiguous memory region that will be used
by the driver to load binaries. During starting phase this special
memory is destroyed.

Add the missing CELL_CREATE state and introduce a management function
that handles the colored scenario for all the above phases.

Signed-off-by: Luca Miccio <[email protected]>
Signed-off-by: Marco Solieri <[email protected]>
---
 hypervisor/control.c | 128 ++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 119 insertions(+), 9 deletions(-)

diff --git a/hypervisor/control.c b/hypervisor/control.c
index b38ac2e9..af9dca73 100644
--- a/hypervisor/control.c
+++ b/hypervisor/control.c
@@ -19,12 +19,13 @@
 #include <jailhouse/string.h>
 #include <jailhouse/unit.h>
 #include <jailhouse/utils.h>
+#include <jailhouse/coloring.h>
 #include <asm/control.h>
 #include <asm/spinlock.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};
+enum management_task {CELL_CREATE, CELL_START, CELL_SET_LOADABLE, 
CELL_DESTROY};
 
 /** System configuration as used while activating the hypervisor. */
 struct jailhouse_system *system_config;
@@ -318,6 +319,97 @@ static int unmap_from_root_cell(const struct 
jailhouse_memory *mem)
        return arch_unmap_memory_region(&root_cell, &tmp);
 }
 
+#ifdef CONFIG_COLORING
+static bool color_mem_exceed_mem(const struct jailhouse_memory *col_mem,
+       const struct jailhouse_memory *mem, unsigned long *color_bitmask)
+{
+       unsigned long col_mem_phys_end = get_end_addr(col_mem->phys_start,
+               col_mem->size, color_bitmask);
+
+       return address_in_region(col_mem->phys_start, mem) &&
+               (col_mem_phys_end > (mem->phys_start + mem->size));
+}
+
+static int color_root_cell_management(const struct jailhouse_memory *mem,
+                             struct cell *cell, enum management_task op)
+{
+       struct jailhouse_memory mem_to_map;
+       const struct jailhouse_memory *rootm;
+       int err = 0;
+       int counter;
+
+       /** Check if memory exceeds the one available from the root cell */
+       if (op == CELL_CREATE || op == CELL_DESTROY) {
+               for_each_mem_region(rootm, root_cell.config, counter)
+                       if (color_mem_exceed_mem(mem, rootm,
+                               cell->arch.color_bitmask))
+                               printk("WARNING: colored memory exceed root 
cell size\n");
+       }
+
+       /** Setup common parameter of the memory to map */
+       mem_to_map.phys_start = mem->phys_start;
+       mem_to_map.size = mem->size;
+       mem_to_map.flags = mem->flags;
+
+       /** Color configuration must be equal between cell and root cell */
+       memcpy(root_cell.arch.color_bitmask, cell->arch.color_bitmask,
+               sizeof(u64)*COLOR_BITMASK_SIZE);
+
+       /**
+        * Colored memory region must be handled carefully when managing
+        * root-cell memory regions w.r.t cell management operations:
+        * - CELL_CREATE: the memory has to be unmapped from the root cell using
+        * the coloring logic so only the correct memory is removed from it.
+        * - CELL_SET_LOADABLE: in order to load binaries into the colored
+        * region we do not remap to the root cell the same region but we create
+        * a convenient memory space that virtually starts from col_load_address
+        * The latter is mapped using the same coloring configuration and size
+        * of the cell's one. This allows us to expose a virtually contiguous
+        * memory to the root cell that can be used without implementing
+        * coloring logic in the Linux driver.
+        * - CELL_START: since the loading operation is performed on a specific
+        * memory region, when the cell has to be started we have to
+        * remove from the root cell only the mapping starting at
+        * col_load_address.
+        * - CELL_DESTROY: when the cell is destroyed we need to remap to the
+        * root-cell the memory region using the same coloring configuration of
+        * the cell.
+        */
+       switch (op) {
+       case CELL_CREATE:
+               mem_to_map.virt_start = mem_to_map.phys_start;
+               err = arch_unmap_memory_region(&root_cell, &mem_to_map);
+               break;
+       case CELL_SET_LOADABLE:
+               mem_to_map.virt_start =
+                       system_config->platform_info.col_load_address;
+               err = arch_map_memory_region(&root_cell, &mem_to_map);
+               break;
+       case CELL_START:
+               mem_to_map.virt_start =
+                       system_config->platform_info.col_load_address;
+               mem_to_map.flags &= ~JAILHOUSE_MEM_COLORED;
+               err = arch_unmap_memory_region(&root_cell, &mem_to_map);
+               break;
+       case CELL_DESTROY:
+               mem_to_map.virt_start = mem_to_map.phys_start;
+               err = arch_map_memory_region(&root_cell, &mem_to_map);
+               break;
+       default:
+               err = -ENOMEM;
+               break;
+       }
+
+       return err;
+}
+#else
+static int color_root_cell_management(const struct jailhouse_memory *mem,
+               struct cell *cell, enum management_task op)
+{
+       panic_printk("Coloring is not enabled but colored memory used.\n");
+       return -ENOMEM;
+}
+#endif
 static int remap_to_root_cell(const struct jailhouse_memory *mem,
                              enum failure_mode mode)
 {
@@ -388,8 +480,13 @@ static void cell_destroy_internal(struct cell *cell)
                        arch_unmap_memory_region(cell, mem);
 
                if (!(mem->flags & (JAILHOUSE_MEM_COMM_REGION |
-                                   JAILHOUSE_MEM_ROOTSHARED)))
-                       remap_to_root_cell(mem, WARN_ON_ERROR);
+                                   JAILHOUSE_MEM_ROOTSHARED))) {
+                       if (mem->flags & JAILHOUSE_MEM_COLORED)
+                               color_root_cell_management(mem, cell,
+                                       CELL_DESTROY);
+                       else
+                               remap_to_root_cell(mem, WARN_ON_ERROR);
+               }
        }
 
        for_each_unit_reverse(unit)
@@ -525,7 +622,11 @@ 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);
+                       if (mem->flags & JAILHOUSE_MEM_COLORED)
+                               err = color_root_cell_management(mem, cell,
+                                       CELL_CREATE);
+                       else
+                               err = unmap_from_root_cell(mem);
                        if (err)
                                goto err_destroy_cell;
                }
@@ -632,7 +733,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 = color_root_cell_management(mem,
+                                               cell, CELL_START);
+                               else
+                                       err = unmap_from_root_cell(mem);
                                if (err)
                                        goto out_resume;
                        }
@@ -708,12 +813,17 @@ static int cell_set_loadable(struct per_cpu *cpu_data, 
unsigned long id)
        pci_cell_reset(cell);
 
        /* map all loadable memory regions into the root cell */
-       for_each_mem_region(mem, cell->config, n)
+       for_each_mem_region(mem, cell->config, n) {
                if (mem->flags & JAILHOUSE_MEM_LOADABLE) {
-                       err = remap_to_root_cell(mem, ABORT_ON_ERROR);
-                       if (err)
-                               goto out_resume;
+                       if (mem->flags & JAILHOUSE_MEM_COLORED)
+                               err = color_root_cell_management(mem, cell,
+                                       CELL_SET_LOADABLE);
+                       else
+                               err = remap_to_root_cell(mem, ABORT_ON_ERROR);
                }
+               if (err)
+                       goto out_resume;
+       }
 
        config_commit(NULL);
 
-- 
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-6-ms%40xt3.it.

Reply via email to