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
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
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
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:
#include <asm/spinlock.h>
enum msg_type {MSG_REQUEST, MSG_INFORMATION};
+enum management_task {CELL_START, CELL_DESTROY};
struct jailhouse_system *system_config;
}
}
+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;
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);
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. */
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;
}
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;
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;
switch (state) {
case JAILHOUSE_CELL_RUNNING:
+ case JAILHOUSE_CELL_RUNNING_LOCKED:
case JAILHOUSE_CELL_SHUT_DOWN:
case JAILHOUSE_CELL_FAILED:
return state;
/* 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;