]> rtime.felk.cvut.cz Git - jailhouse.git/commitdiff
core/driver: Introduce and use Cell Start hypercall
authorJan Kiszka <jan.kiszka@siemens.com>
Wed, 26 Mar 2014 18:15:30 +0000 (19:15 +0100)
committerJan Kiszka <jan.kiszka@siemens.com>
Sat, 3 May 2014 12:56:57 +0000 (14:56 +0200)
This breaks up creation and start of execution of the a cell, a
precondition for enabling cell reload without destruction/recreation.
The new Cell Start hypercall can also be used to restart an already
running cell, thus access control needs to be applied.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Documentation/hypervisor-interfaces.txt
driver.c
hypervisor/control.c
hypervisor/include/jailhouse/hypercall.h

index 5e6f98debe32efcfead10bbbc4f51ada705a6ac4..056cd4ba445f9e674cd153bb3f6fa7eeefea25c6 100644 (file)
@@ -49,11 +49,9 @@ Return code: 0 on success, negative error code otherwise
 Hypercall "Cell Create" (code 1)
 - - - - - - - - - - - - - - - - -
 
-Creates a new cell according to the provided configuration, then set all
-cell CPUs to an architecture-specific reset state. At least one CPU will then
-execute the bootstrap code that must have been loaded into the cell's memory
-at the reset address before invoking this hypercall. See [1] for details on the
-reset state of cell CPUs.
+Creates a new cell according to the provided configuration. The cell's memory
+content will not be initialized, and the cell will be put in suspended state,
+i.e. no code is executed on its CPUs after this hypercall completed.
 
 This hypercall can only be issued on CPUs belonging to the Linux cell.
 
@@ -73,7 +71,29 @@ Return code: positive cell ID or negative error code
         -EINVAL (-22) - incorrect or inconsistent configuration data
 
 
-Hypercall "Cell Destroy" (code 2)
+Hypercall "Cell Start" (code 2)
+- - - - - - - - - - - - - - - -
+
+Sets all cell CPUs to an architecture-specific start state and resumes
+execution of the cell if it was previously suspended. At least one CPU will
+then execute the bootstrap code that must have been loaded into the cell's
+memory at the reset address before invoking this hypercall. See [1] for details
+on the start state of cell CPUs.
+
+This hypercall can only be issued on CPUs belonging to the Linux cell.
+
+Argument: ID of target cell
+
+Return code: 0 on success or negative error code
+
+    Possible errors are:
+        -EPERM  (-1)  - hypercall was issued over a non-root cell or the target
+                        cell rejected the reset request
+        -ENOENT (-2)  - cell with provided ID does not exist
+        -EINVAL (-22) - root cell specified, which cannot be started
+
+
+Hypercall "Cell Destroy" (code 4)
 - - - - - - - - - - - - - - - - -
 
 Destroys the cell of the provided name, returning its resources to the root
@@ -98,7 +118,7 @@ Return code: 0 on success, negative error code otherwise
 Note: The root cell uses ID 0. Passing this ID to "Cell Destroy" is illegal.
 
 
-Hypercall "Hypervisor Get Info" (code 3)
+Hypercall "Hypervisor Get Info" (code 5)
 - - - - - - - - - - - - - - - - - - - - -
 
 Obtain information about specific hypervisor states.
@@ -116,7 +136,7 @@ Return code: requested value (>=0) or negative error code
         -EINVAL (-22) - invalid information type
 
 
-Hypercall "Cell Get State" (code 4)
+Hypercall "Cell Get State" (code 6)
 - - - - - - - - - - - - - - - - - -
 
 Obtain information about the state of a specific cell.
@@ -137,7 +157,7 @@ Return code: cell state (>=0) or negative error code
         -EINVAL (-22) - cell state is invalid
 
 
-Hypercall "CPU Get State" (code 5)
+Hypercall "CPU Get State" (code 7)
 - - - - - - - - - - - - - - - - - -
 
 Obtain information about the state of a specific CPU.
@@ -226,15 +246,17 @@ Logical Channel "Cell State"
 
 The cell state field provides the second logical channel. On cell startup, it
 is initialized by the hypervisor to the state "Running". From then on, the
-field becomes conceptually read-only for the hypervisor and will just be
-updated by the cell itself. The following states are defined:
+field becomes conceptually read-only for the hypervisor and will only be
+updated by the cell until a terminal state is reached. The following states are
+defined:
 
  - Running (code 0)
  - Shut down (code 1), terminal state
  - Failed (code 2), terminal state
 
-Terminal states are immutable, thus cannot be left anymore once reached until
-the cell is destroyed.
+Once a cell declared to have reached a terminal state, the hypervisor is free
+to destroy or restart that cell. On restart, it will also reset the state field
+to "Running".
 
 
 References
index 1244c7e6dc681e911d76a2ea66e4834073772aad..01b9ca27ac9e036396e35660719c0eef346640a7 100644 (file)
--- a/driver.c
+++ b/driver.c
@@ -583,6 +583,10 @@ static int jailhouse_cell_create(struct jailhouse_new_cell __user *arg)
                goto error_cpu_online;
        }
 
+       err = jailhouse_call_arg(JAILHOUSE_HC_CELL_START, id);
+       if (err)
+               goto error_cell_destroy;
+
        cell->id = id;
        register_cell(cell);
 
@@ -596,6 +600,12 @@ kfree_config_out:
 
        return err;
 
+error_cell_destroy:
+       if (jailhouse_call_arg(JAILHOUSE_HC_CELL_DESTROY, id) < 0) {
+               pr_crit("Cleanup after incomplete cell creation failed");
+               goto error_cell_put;
+       }
+
 error_cpu_online:
        for_each_cpu(cpu, &cell->cpus_assigned) {
                if (!cpu_online(cpu) && cpu_up(cpu) == 0)
index 5f1fe46abd48ef16383351ef73c655adeff68c16..ce96438727d04682648fb1819780d75bb40f5564 100644 (file)
@@ -288,26 +288,23 @@ static int cell_create(struct per_cpu *cpu_data, unsigned long config_address)
        if (err)
                goto err_restore_root;
 
+       cell->comm_page.comm_region.cell_state = JAILHOUSE_CELL_SHUT_DOWN;
+
        last = &root_cell;
        while (last->next)
                last = last->next;
        last->next = cell;
        num_cells++;
 
-       /* update cell references and clean up before releasing the cpus of
-        * the new cell */
-       for_each_cpu(cpu, cell->cpu_set)
+       for_each_cpu(cpu, cell->cpu_set) {
                per_cpu(cpu)->cell = cell;
+               arch_park_cpu(cpu);
+       }
 
        printk("Created cell \"%s\"\n", cell->config->name);
 
        page_map_dump_stats("after cell creation");
 
-       for_each_cpu(cpu, cell->cpu_set) {
-               per_cpu(cpu)->failed = false;
-               arch_reset_cpu(cpu);
-       }
-
        cell_resume(cpu_data);
 
        return cell->id;
@@ -384,6 +381,32 @@ static int cell_management_prologue(struct per_cpu *cpu_data, unsigned long id,
        return 0;
 }
 
+static int cell_start(struct per_cpu *cpu_data, unsigned long id)
+{
+       struct cell *cell;
+       unsigned int cpu;
+       int err;
+
+       err = cell_management_prologue(cpu_data, id, &cell);
+       if (err)
+               return err;
+
+       /* present a consistent Communication Region state to the cell */
+       cell->comm_page.comm_region.cell_state = JAILHOUSE_CELL_RUNNING;
+       cell->comm_page.comm_region.msg_to_cell = JAILHOUSE_MSG_NONE;
+
+       for_each_cpu(cpu, cell->cpu_set) {
+               per_cpu(cpu)->failed = false;
+               arch_reset_cpu(cpu);
+       }
+
+       printk("Started cell \"%s\"\n", cell->config->name);
+
+       cell_resume(cpu_data);
+
+       return 0;
+}
+
 static int cell_destroy(struct per_cpu *cpu_data, unsigned long id)
 {
        const struct jailhouse_memory *mem;
@@ -559,6 +582,8 @@ long hypercall(struct per_cpu *cpu_data, unsigned long code, unsigned long arg)
                return shutdown(cpu_data);
        case JAILHOUSE_HC_CELL_CREATE:
                return cell_create(cpu_data, arg);
+       case JAILHOUSE_HC_CELL_START:
+               return cell_start(cpu_data, arg);
        case JAILHOUSE_HC_CELL_DESTROY:
                return cell_destroy(cpu_data, arg);
        case JAILHOUSE_HC_HYPERVISOR_GET_INFO:
index 59861127578228f342252e05f58fd9c2be3cde7a..19ff4a099629c46ec8a863e1630c34f25601397c 100644 (file)
 
 #define JAILHOUSE_HC_DISABLE                   0
 #define JAILHOUSE_HC_CELL_CREATE               1
-#define JAILHOUSE_HC_CELL_DESTROY              2
-#define JAILHOUSE_HC_HYPERVISOR_GET_INFO       3
-#define JAILHOUSE_HC_CELL_GET_STATE            4
-#define JAILHOUSE_HC_CPU_GET_STATE             5
+#define JAILHOUSE_HC_CELL_START                        2
+#define JAILHOUSE_HC_CELL_DESTROY              4
+#define JAILHOUSE_HC_HYPERVISOR_GET_INFO       5
+#define JAILHOUSE_HC_CELL_GET_STATE            6
+#define JAILHOUSE_HC_CPU_GET_STATE             7
 
 /* Hypervisor information type */
 #define JAILHOUSE_INFO_MEM_POOL_SIZE           0