]> rtime.felk.cvut.cz Git - jailhouse.git/commitdiff
core/driver: Add reconfiguration lock
authorJan Kiszka <jan.kiszka@siemens.com>
Thu, 3 Apr 2014 08:22:55 +0000 (10:22 +0200)
committerJan Kiszka <jan.kiszka@siemens.com>
Sat, 3 May 2014 12:56:57 +0000 (14:56 +0200)
Introduce the concept of a reconfiguration lock. A cell can activate
this lock by changing its state to "Running/Locked". The lock is checked
by the hypervisor before changing the system configuration via creating
or destroying a cell. This gives cells participating in the
Communication Region protocol the chance to prevent reconfigurations,
thus freezing the system setup. A cell that is supposed to be destroy
does not participate in this voting because it will already receive the
shutdown request.

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

index 2a6c9961e734d69b980bcf2192ca3b4a74c90f5d..24134964ede909a9c562a60e19e1e8099d930756 100644 (file)
@@ -61,7 +61,7 @@ Return code: positive cell ID or negative error code
 
     Possible errors are:
         -EPERM  (-1)  - hypercall was issued over a non-root cell or an active
-                        cell denied system reconfiguration
+                        cell locked the cell configurations
         -E2BIG  (-7)  - configuration data too large to process
         -ENOMEM (-12) - insufficient hypervisor-internal memory
         -EBUSY  (-16) - a resource of the new cell is already in use by another
@@ -109,7 +109,7 @@ Return code: 0 on success, negative error code otherwise
     Possible errors are:
         -EPERM  (-1)  - hypercall was issued over a non-root cell, the target
                         cell rejected the destruction request or another active
-                        cell denied system reconfiguration
+                        cell locked the cell configurations
         -ENOENT (-2)  - cell with provided ID does not exist
         -ENOMEM (-12) - insufficient hypervisor-internal memory for
                         reconfiguration
@@ -253,8 +253,9 @@ 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
+ - Running, cell configurations locked (code 1)
+ - Shut down (code 2), terminal state
+ - Failed (code 3), terminal state
 
 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
index 01b9ca27ac9e036396e35660719c0eef346640a7..b3e1e284049aa5e2f01dbfc85fb1be9247dfd45a 100644 (file)
--- a/driver.c
+++ b/driver.c
@@ -115,6 +115,8 @@ static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
        switch (jailhouse_call_arg(JAILHOUSE_HC_CELL_GET_STATE, cell->id)) {
        case JAILHOUSE_CELL_RUNNING:
                return sprintf(buffer, "running\n");
+       case JAILHOUSE_CELL_RUNNING_LOCKED:
+               return sprintf(buffer, "running/locked\n");
        case JAILHOUSE_CELL_SHUT_DOWN:
                return sprintf(buffer, "shut down\n");
        case JAILHOUSE_CELL_FAILED:
index 08ddbf79610a9794191f5615c6d4fa44936efe7e..ab10ef4d9e299d8056c042ee99324b5d29ee0cac 100644 (file)
@@ -20,6 +20,7 @@
 #include <asm/spinlock.h>
 
 enum msg_type {MSG_REQUEST, MSG_INFORMATION};
+enum management_task {CELL_START, CELL_DESTROY};
 
 struct jailhouse_system *system_config;
 
@@ -104,6 +105,18 @@ static bool cell_send_message(struct cell *cell, u32 message,
        }
 }
 
+static bool cell_reconfig_ok(struct cell *excluded_cell)
+{
+       struct cell *cell;
+
+       for_each_non_root_cell(cell)
+               if (cell != excluded_cell &&
+                   cell->comm_page.comm_region.cell_state ==
+                               JAILHOUSE_CELL_RUNNING_LOCKED)
+                       return false;
+       return true;
+}
+
 static unsigned int get_free_cell_id(void)
 {
        unsigned int id = 0;
@@ -235,6 +248,11 @@ static int cell_create(struct per_cpu *cpu_data, unsigned long config_address)
 
        cell_suspend(&root_cell, cpu_data);
 
+       if (!cell_reconfig_ok(NULL)) {
+               err = -EPERM;
+               goto err_resume;
+       }
+
        cfg_header_size = (config_address & ~PAGE_MASK) +
                sizeof(struct jailhouse_cell_desc);
 
@@ -374,7 +392,8 @@ static bool cell_shutdown_ok(struct cell *cell)
                                 MSG_REQUEST);
 }
 
-static int cell_management_prologue(struct per_cpu *cpu_data, unsigned long id,
+static int cell_management_prologue(enum management_task task,
+                                   struct per_cpu *cpu_data, unsigned long id,
                                    struct cell **cell_ptr)
 {
        /* We do not support management commands over non-root cells. */
@@ -398,7 +417,8 @@ static int cell_management_prologue(struct per_cpu *cpu_data, unsigned long id,
                return -EINVAL;
        }
 
-       if (!cell_shutdown_ok(*cell_ptr)) {
+       if ((task == CELL_DESTROY && !cell_reconfig_ok(*cell_ptr)) ||
+           !cell_shutdown_ok(*cell_ptr)) {
                cell_resume(cpu_data);
                return -EPERM;
        }
@@ -414,7 +434,7 @@ static int cell_start(struct per_cpu *cpu_data, unsigned long id)
        unsigned int cpu;
        int err;
 
-       err = cell_management_prologue(cpu_data, id, &cell);
+       err = cell_management_prologue(CELL_START, cpu_data, id, &cell);
        if (err)
                return err;
 
@@ -441,7 +461,7 @@ static int cell_destroy(struct per_cpu *cpu_data, unsigned long id)
        unsigned int cpu, n;
        int err;
 
-       err = cell_management_prologue(cpu_data, id, &cell);
+       err = cell_management_prologue(CELL_DESTROY, cpu_data, id, &cell);
        if (err)
                return err;
 
@@ -500,6 +520,7 @@ static int cell_get_state(struct per_cpu *cpu_data, unsigned long id)
 
                        switch (state) {
                        case JAILHOUSE_CELL_RUNNING:
+                       case JAILHOUSE_CELL_RUNNING_LOCKED:
                        case JAILHOUSE_CELL_SHUT_DOWN:
                        case JAILHOUSE_CELL_FAILED:
                                return state;
index 9eb05a8d2b9dd44701c7ef0ffd1b4972d7985c72..d2036c49f9d9995b1e913e14c4c2a7fcf87580c9 100644 (file)
@@ -45,8 +45,9 @@
 
 /* cell state, initialized by hypervisor, updated by cell */
 #define JAILHOUSE_CELL_RUNNING                 0
-#define JAILHOUSE_CELL_SHUT_DOWN               1 /* terminal state */
-#define JAILHOUSE_CELL_FAILED                  2 /* terminal state */
+#define JAILHOUSE_CELL_RUNNING_LOCKED          1
+#define JAILHOUSE_CELL_SHUT_DOWN               2 /* terminal state */
+#define JAILHOUSE_CELL_FAILED                  3 /* terminal state */
 
 struct jailhouse_comm_region {
        volatile __u32 msg_to_cell;