If the cell id is chosen by the driver instead of the hypervisor, the
cell id gets part of the cell configuration.
As part of the configuration, move the cell id from hypervisor's struct
cell to struct jailhouse_cell_desc, as this structure is passed from the
driver to the hypervisor.
Let the hypervisor as well as the driver check collisions of cells.
Both, cell name and cell id are still both unique values.
Signed-off-by: Ralf Ramsauer <
ra...@ramses-pyramidenbau.de>
diff --git a/driver/cell.c b/driver/cell.c
index 06e2b7f..b8c4403 100644
--- a/driver/cell.c
+++ b/driver/cell.c
@@ -40,18 +40,30 @@ void jailhouse_cell_kobj_release(struct kobject *kobj)
static struct cell *cell_create(const struct jailhouse_cell_desc *cell_desc)
{
struct cell *cell;
+ unsigned int id;
int err;
if (cell_desc->num_memory_regions >=
ULONG_MAX / sizeof(struct jailhouse_memory))
return ERR_PTR(-EINVAL);
+ /* determine cell id */
+ id = 0;
+retry:
+ list_for_each_entry(cell, &cells, entry)
+ if (cell->id == id) {
+ id++;
+ goto retry;
+ }
+
cell = kzalloc(sizeof(*cell), GFP_KERNEL);
if (!cell)
return ERR_PTR(-ENOMEM);
INIT_LIST_HEAD(&cell->entry);
+ cell->id = id;
+
bitmap_copy(cpumask_bits(&cell->cpus_assigned),
jailhouse_cell_cpu_set(cell_desc),
min(nr_cpumask_bits, (int)cell_desc->cpu_set_size * 8));
@@ -146,7 +158,7 @@ int jailhouse_cmd_cell_create(struct jailhouse_cell_create __user *arg)
void __user *user_config;
struct cell *cell;
unsigned int cpu;
- int id, err = 0;
+ int err = 0;
if (copy_from_user(&cell_params, arg, sizeof(cell_params)))
return -EFAULT;
@@ -193,6 +205,8 @@ int jailhouse_cmd_cell_create(struct jailhouse_cell_create __user *arg)
goto unlock_out;
}
+ config->id = cell->id;
+
if (!cpumask_subset(&cell->cpus_assigned, &root_cell->cpus_assigned)) {
err = -EBUSY;
goto error_cell_delete;
@@ -211,13 +225,10 @@ int jailhouse_cmd_cell_create(struct jailhouse_cell_create __user *arg)
jailhouse_pci_do_all_devices(cell, JAILHOUSE_PCI_TYPE_DEVICE,
JAILHOUSE_PCI_ACTION_CLAIM);
- id = jailhouse_call_arg1(JAILHOUSE_HC_CELL_CREATE, __pa(config));
- if (id < 0) {
- err = id;
+ err = jailhouse_call_arg1(JAILHOUSE_HC_CELL_CREATE, __pa(config));
+ if (err < 0)
goto error_cpu_online;
- }
- cell->id = id;
cell_register(cell);
pr_info("Created Jailhouse cell \"%s\"\n", config->name);
diff --git a/hypervisor/arch/arm/mmu_cell.c b/hypervisor/arch/arm/mmu_cell.c
index d26c9d3..45f0f0e 100644
--- a/hypervisor/arch/arm/mmu_cell.c
+++ b/hypervisor/arch/arm/mmu_cell.c
@@ -92,7 +92,7 @@ void arm_cell_dcaches_flush(struct cell *cell, enum dcache_flush flush)
int arm_paging_cell_init(struct cell *cell)
{
- if (cell->id > 0xff)
+ if (cell->config->id > 0xff)
return trace_error(-E2BIG);
cell->arch.mm.root_paging = cell_paging;
@@ -115,7 +115,7 @@ void arm_paging_vcpu_init(struct paging_structures *pg_structs)
unsigned long cell_table = paging_hvirt2phys(pg_structs->root_table);
u64 vttbr = 0;
- vttbr |= (u64)this_cell()->id << VTTBR_VMID_SHIFT;
+ vttbr |= (u64)this_cell()->config->id << VTTBR_VMID_SHIFT;
vttbr |= (u64)(cell_table & TTBR_MASK);
arm_write_sysreg(VTTBR_EL2, vttbr);
diff --git a/hypervisor/arch/x86/amd_iommu.c b/hypervisor/arch/x86/amd_iommu.c
index b3b8087..d91b7b3 100644
--- a/hypervisor/arch/x86/amd_iommu.c
+++ b/hypervisor/arch/x86/amd_iommu.c
@@ -360,7 +360,7 @@ int iommu_cell_init(struct cell *cell)
if (iommu_units_count == 0)
return 0;
- if (cell->id > 0xffff)
+ if (cell->config->id > 0xffff)
return trace_error(-ERANGE);
return 0;
@@ -529,7 +529,7 @@ int iommu_add_pci_device(struct cell *cell, struct pci_device *device)
memset(dte, 0, sizeof(*dte));
/* DomainID */
- dte->raw64[1] = cell->id & 0xffff;
+ dte->raw64[1] = cell->config->id & 0xffff;
/* Translation information */
dte->raw64[0] = DTE_IR | DTE_IW |
@@ -689,9 +689,9 @@ void iommu_config_commit(struct cell *cell_added_removed)
/* Flush caches */
if (cell_added_removed) {
amd_iommu_invalidate_pages(iommu,
- cell_added_removed->id & 0xffff);
+ cell_added_removed->config->id & 0xffff);
amd_iommu_invalidate_pages(iommu,
-
root_cell.id & 0xffff);
+ root_cell.config->id & 0xffff);
}
/* Execute all commands in the buffer */
amd_iommu_completion_wait(iommu);
diff --git a/hypervisor/arch/x86/vtd.c b/hypervisor/arch/x86/vtd.c
index 546f160..0a75fb3 100644
--- a/hypervisor/arch/x86/vtd.c
+++ b/hypervisor/arch/x86/vtd.c
@@ -809,7 +809,7 @@ int iommu_add_pci_device(struct cell *cell, struct pci_device *device)
paging_hvirt2phys(cell->arch.vtd.pg_structs.root_table);
context_entry->hi_word =
(dmar_pt_levels == 3 ? VTD_CTX_AGAW_39 : VTD_CTX_AGAW_48) |
- (cell->id << VTD_CTX_DID_SHIFT);
+ (cell->config->id << VTD_CTX_DID_SHIFT);
arch_paging_flush_cpu_caches(context_entry, sizeof(*context_entry));
return 0;
@@ -853,7 +853,7 @@ int iommu_cell_init(struct cell *cell)
unsigned int n;
int result;
- if (cell->id >= dmar_num_did)
+ if (cell->config->id >= dmar_num_did)
return trace_error(-ERANGE);
cell->arch.vtd.pg_structs.root_paging = vtd_paging;
@@ -1033,8 +1033,8 @@ void iommu_config_commit(struct cell *cell_added_removed)
dmar_units_initialized = true;
} else {
if (cell_added_removed)
- vtd_flush_domain_caches(cell_added_removed->id);
- vtd_flush_domain_caches(
root_cell.id);
+ vtd_flush_domain_caches(cell_added_removed->config->id);
+ vtd_flush_domain_caches(root_cell.config->id);
}
}
diff --git a/hypervisor/control.c b/hypervisor/control.c
index 8fd9b88..1d48623 100644
--- a/hypervisor/control.c
+++ b/hypervisor/control.c
@@ -147,21 +147,6 @@ static void cell_reconfig_completed(void)
MSG_INFORMATION);
}
-static unsigned int get_free_cell_id(void)
-{
- unsigned int id = 0;
- struct cell *cell;
-
-retry:
- for_each_cell(cell)
- if (cell->id == id) {
- id++;
- goto retry;
- }
-
- return id;
-}
-
/**
* Initialize a new cell.
* @param cell Cell to be initialized.
@@ -178,8 +163,6 @@ int cell_init(struct cell *cell)
struct cpu_set *cpu_set;
int err;
- cell->id = get_free_cell_id();
-
if (cpu_set_size > PAGE_SIZE)
return trace_error(-EINVAL);
if (cpu_set_size > sizeof(cell->small_cpu_set.bitmap)) {
@@ -367,7 +350,8 @@ static int cell_create(struct per_cpu *cpu_data, unsigned long config_address)
* sizeof(cell->config->name) == sizeof(cfg->name) and
* cell->config->name is guaranteed to be null-terminated.
*/
- if (strcmp(cell->config->name, cfg->name) == 0) {
+ if (strcmp(cell->config->name, cfg->name) == 0 ||
+ cell->config->id == cfg->id) {
err = -EEXIST;
goto err_resume;
}
@@ -468,7 +452,7 @@ static int cell_create(struct per_cpu *cpu_data, unsigned long config_address)
cell_resume(cpu_data);
- return cell->id;
+ return 0;
err_destroy_cell:
cell_destroy_internal(cpu_data, cell);
@@ -501,7 +485,7 @@ static int cell_management_prologue(enum management_task task,
cell_suspend(&root_cell, cpu_data);
for_each_cell(*cell_ptr)
- if ((*cell_ptr)->id == id)
+ if ((*cell_ptr)->config->id == id)
break;
if (!*cell_ptr) {
@@ -652,7 +636,7 @@ static int cell_get_state(struct per_cpu *cpu_data, unsigned long id)
* this hypercall.
*/
for_each_cell(cell)
- if (cell->id == id) {
+ if (cell->config->id == id) {
u32 state = cell->comm_page.comm_region.cell_state;
switch (state) {
diff --git a/hypervisor/include/jailhouse/cell-config.h b/hypervisor/include/jailhouse/cell-config.h
index 8e8495d..4e2b5cb 100644
--- a/hypervisor/include/jailhouse/cell-config.h
+++ b/hypervisor/include/jailhouse/cell-config.h
@@ -48,6 +48,7 @@
struct jailhouse_cell_desc {
char signature[8];
char name[JAILHOUSE_CELL_NAME_MAXLEN+1];
+ unsigned int id; /* set by the driver */
__u32 flags;
__u32 cpu_set_size;
diff --git a/hypervisor/include/jailhouse/cell.h b/hypervisor/include/jailhouse/cell.h
index 024af9e..75e4fd1 100644
--- a/hypervisor/include/jailhouse/cell.h
+++ b/hypervisor/include/jailhouse/cell.h
@@ -35,8 +35,6 @@ struct cell {
/** Architecture-specific fields. */
struct arch_cell arch;
- /** ID of the cell. */
- unsigned int id;
/** Number of pages used for storing cell-specific states and
* configuration data. */
unsigned int data_pages;
diff --git a/hypervisor/setup.c b/hypervisor/setup.c
index 4b79189..b76f845 100644
--- a/hypervisor/setup.c
+++ b/hypervisor/setup.c
@@ -53,7 +53,6 @@ static void init_early(unsigned int cpu_id)
root_cell.config = &system_config->root_cell;
-
root_cell.id = -1;
error = cell_init(&root_cell);
if (error)
return;
--
2.9.3