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. */
struct jailhouse_system *system_config;
static DEFINE_SPINLOCK(shutdown_lock);
#define for_each_non_root_cell(c) \
for ((c) = root_cell.next; (c); (c) = (c)->next)
+/**
+ * CPU set iterator.
+ * @param cpu Previous CPU ID.
+ * @param cpu_set CPU set to iterate over.
+ * @param exception CPU ID to skip if it is contained.
+ *
+ * @return Next CPU ID in the set.
+ *
+ * @note For internal use only. Use for_each_cpu() or for_each_cpu_except()
+ * instead.
+ */
unsigned int next_cpu(unsigned int cpu, struct cpu_set *cpu_set, int exception)
{
do
return cpu;
}
+/**
+ * Check if a CPU ID is contained in the system's CPU set, i.e. the initial CPU
+ * set of the root cell.
+ * @param cpu_id CPU ID to check.
+ *
+ * @return True if CPU ID is valid.
+ */
bool cpu_id_valid(unsigned long cpu_id)
{
const unsigned long *system_cpu_set =
}
/**
- * cell_send_message - Deliver a message to cell and wait for the reply
- * @cell: target cell
- * @message: message code to be sent (JAILHOUSE_MSG_*)
- * @type: message type, defines the valid replies
+ * Deliver a message to cell and wait for the reply.
+ * @param cell Target cell.
+ * @param message Message code to be sent (JAILHOUSE_MSG_*).
+ * @param type Message type, defines the valid replies.
*
- * Returns true if a request message was approved or reception of an
- * information message was acknowledged by the target cell. It also return true
- * of the target cell does not support a communication region, is shut down or
- * in failed state. Return false on request denial or invalid replies.
+ * @return True if a request message was approved or reception of an
+ * informational message was acknowledged by the target cell. It also
+ * returns true if the target cell does not support an active
+ * communication region, is shut down or in failed state. Returns
+ * false on request denial or invalid replies.
*/
static bool cell_send_message(struct cell *cell, u32 message,
enum msg_type type)
return id;
}
-/* cell must be zero-initialized */
+/**
+ * Initialize a new cell.
+ * @param cell Cell to be initializes.
+ *
+ * @return 0 on success, negative error code otherwise.
+ *
+ * @note The cell data structure must be zero-initialized.
+ */
int cell_init(struct cell *cell)
{
const unsigned long *config_cpu_set =
page_free(&mem_pool, cell->cpu_set, 1);
}
+/**
+ * Perform basic validation of cell memory regions.
+ * @param config Cell configuration description.
+ *
+ * @return 0 if the regions are valid, @c -EINVAL if the validation failed.
+ *
+ * Checks performed on the memory regions are:
+ * \li Page alignment of physical and virtual address and the size.
+ * \li Use of supported flags only.
+ */
int check_mem_regions(const struct jailhouse_cell_desc *config)
{
const struct jailhouse_memory *mem =
return -EINVAL;
}
+/**
+ * Handle hypercall invoked by a cell.
+ * @param code Hypercall code.
+ * @param arg1 First hypercall argument.
+ * @param arg2 Seconds hypercall argument.
+ *
+ * @return Value that shall be passed to the caller of the hypercall on return.
+ *
+ * @note If @c arg1 and @c arg2 are valid depends on the hypercall code.
+ */
long hypercall(unsigned long code, unsigned long arg1, unsigned long arg2)
{
struct per_cpu *cpu_data = this_cpu_data();
}
}
+/**
+ * Stops the current CPU on panic and prevents any execution on it until the
+ * system is rebooted.
+ *
+ * @note This service should be used when facing an unrecoverable error of the
+ * hypervisor.
+ *
+ * @see panic_park
+ */
void panic_stop(void)
{
panic_printk("Stopping CPU %d (Cell: \"%s\")\n", this_cpu_id(),
arch_panic_stop();
}
+/**
+ * Parks the current CPU on panic, allowing to restart it by resetting the
+ * cell's CPU state.
+ *
+ * @note This service should be used when facing an error of a cell CPU, e.g. a
+ * cell boundary violation.
+ *
+ * @see panic_stop
+ */
void panic_park(void)
{
struct cell *cell = this_cell();
#define SHUTDOWN_NONE 0
#define SHUTDOWN_STARTED 1
+/**
+ * @defgroup Control Control Subsystem
+ *
+ * The control subsystem provides services for managing cells and the
+ * hypervisor during runtime. It implements the hypercall interface and
+ * performs the required access control and parameter validation for it.
+ *
+ * @{
+ */
+
extern struct jailhouse_system *system_config;
unsigned int next_cpu(unsigned int cpu, struct cpu_set *cpu_set,
int exception);
+/**
+ * Loop-generating macro for iterating over all CPUs in a set.
+ * @param cpu Iteration variable holding the current CPU ID
+ * (unsigned int).
+ * @param set CPU set to iterate over (struct cpu_set).
+ *
+ * @see for_each_cpu_except
+ */
#define for_each_cpu(cpu, set) \
for ((cpu) = -1; \
(cpu) = next_cpu((cpu), (set), -1), \
(cpu) <= (set)->max_cpu_id; \
)
+/**
+ * Loop-generating macro for iterating over all CPUs in a set, except the
+ * specified one.
+ * @param cpu Iteration variable holding the current CPU ID
+ * (unsigned int).
+ * @param set CPU set to iterate over (struct cpu_set).
+ * @param exception CPU to skip if it is part of the set.
+ *
+* @see for_each_cpu
+ */
#define for_each_cpu_except(cpu, set, exception) \
for ((cpu) = -1; \
(cpu) = next_cpu((cpu), (set), (exception)), \
(cpu) <= (set)->max_cpu_id; \
)
+/**
+ * Check if the CPU is assigned to the specified cell.
+ * @param cell Cell the CPU may belong to.
+ * @param cpu_id ID of the CPU.
+ *
+ * @return True if the CPU is assigned to the cell.
+ */
static inline bool cell_owns_cpu(struct cell *cell, unsigned int cpu_id)
{
return (cpu_id <= cell->cpu_set->max_cpu_id &&
void __attribute__((noreturn)) panic_stop(void);
void panic_park(void);
+/**
+ * Suspend a remote CPU.
+ * @param cpu_id ID of the target CPU.
+ *
+ * Suspension means that the target CPU is no longer executing cell code or
+ * arbitrary hypervisor code. It may actively wait in the hypervisor context,
+ * so the suspension time should be kept short.
+ *
+ * The function waits for the target CPU to enter suspended state.
+ *
+ * This service can be used to synchronize with other CPUs before performing
+ * management tasks.
+ *
+ * @note This function must not be invoked for the caller's CPU.
+ *
+ * @see arch_resume_cpu
+ * @see arch_reset_cpu
+ * @see arch_park_cpu
+ */
void arch_suspend_cpu(unsigned int cpu_id);
+
+/**
+ * Resume a suspended remote CPU.
+ * @param cpu_id ID of the target CPU.
+ *
+ * @note This function must not be invoked for the caller's CPU.
+ *
+ * @see arch_suspend_cpu
+ */
void arch_resume_cpu(unsigned int cpu_id);
+
+/**
+ * Reset a suspended remote CPU and resumes its execution.
+ * @param cpu_id ID of the target CPU.
+ *
+ * Sets the target CPU into the architecture-specific reset set and resumes its
+ * execution.
+ *
+ * @note This function must not be invoked for the caller's CPU or if the
+ * target CPU is not in suspend state.
+ *
+ * @see arch_suspend_cpu
+ */
void arch_reset_cpu(unsigned int cpu_id);
+
+/**
+ * Park a suspended remote CPU.
+ * @param cpu_id ID of the target CPU.
+ *
+ * Parking means that the target CPU does not execute cell code but can handle
+ * asynchronous events again. Parking is not implemented as busy-waiting and
+ * may set the CPU into an appropriate power-saving mode. The CPU can therefore
+ * be left in this state for an undefined time.
+ *
+ * Parking may destroy the cell-visible CPU state and cannot be used to resume
+ * cell execution in the previous state without additional measures.
+ *
+ * @note This function must not be invoked for the caller's CPU or if the
+ * target CPU is not in suspend state.
+ *
+ * @see arch_suspend_cpu
+ */
void arch_park_cpu(unsigned int cpu_id);
+
+/**
+ * Releases hypervisor control over the target CPU.
+ * @param cpu_id ID of the target CPU.
+ *
+ * @note This function must not be invoked for the caller's CPU.
+ *
+ * @note The target CPU need not be suspended before calling the function.
+ *
+ * @note The caller has to ensure that the target CPU has enough time to reach
+ * the shutdown position before destroying the code path it has to take to get
+ * there. This can be ensured by bringing the CPU online again under Linux
+ * before cleaning up the hypervisor.
+ */
void arch_shutdown_cpu(unsigned int cpu_id);
+/**
+ * Performs the architecture-specific steps for mapping a memory region into a
+ * cell's address space.
+ * @param cell Cell for which the mapping shall be done.
+ * @param mem Memory region to map.
+ *
+ * @return 0 on success, negative error code otherwise.
+ *
+ * @see arch_unmap_memory_region
+ */
int arch_map_memory_region(struct cell *cell,
const struct jailhouse_memory *mem);
+
+/**
+ * Performs the architecture-specific steps for unmapping a memory region from
+ * a cell's address space.
+ * @param cell Cell for which the unmapping shall be done.
+ * @param mem Memory region to unmap.
+ *
+ * @return 0 on success, negative error code otherwise.
+ *
+ * @see arch_map_memory_region
+ */
int arch_unmap_memory_region(struct cell *cell,
const struct jailhouse_memory *mem);
+/**
+ * Performs the architecture-specific steps for creating a new cell.
+ * @param cell Data structure of the new cell.
+ *
+ * @return 0 on success, negative error code otherwise.
+ *
+ * @see arch_cell_destroy
+ */
int arch_cell_create(struct cell *cell);
+
+/**
+ * Performs the architecture-specific steps for destroying a cell.
+ * @param cell Cell to be destroyed.
+ *
+ * @see arch_cell_create
+ */
void arch_cell_destroy(struct cell *cell);
+/**
+ * Performs the architecture-specific steps for applying configuration changes.
+ * @param cell_added_removed Cell that was added or removed to/from the
+ * system or NULL.
+ *
+ * @see pci_config_commit
+ */
void arch_config_commit(struct cell *cell_added_removed);
+/**
+ * Shutdown architecture-specific subsystems while disabling the hypervisor.
+ */
void arch_shutdown(void);
+/**
+ * Performs the architecture-specifc steps to stop the current CPU on panic.
+ *
+ * @note This function never returns.
+ *
+ * @see panic_stop
+ */
void __attribute__((noreturn)) arch_panic_stop(void);
+
+/**
+ * Performs the architecture-specific steps to park the current CPU on panic.
+ *
+ * @note This function only marks the CPU as parked and then returns to the
+ * caller.
+ *
+ * @see panic_park
+ */
void arch_panic_park(void);
+
+/** @} */