int arch_cell_create(struct cell *cell) { int err; err = vcpu_cell_init(cell); if (err) return err; err = iommu_cell_init(cell); if (err) goto error_vm_exit; err = pci_cell_init(cell); if (err) goto error_iommu_exit; err = ioapic_cell_init(cell); if (err) goto error_pci_exit; cell->comm_page.comm_region.pm_timer_address = system_config->platform_info.x86.pm_timer_address; return 0; error_pci_exit: pci_cell_exit(cell); error_iommu_exit: iommu_cell_exit(cell); error_vm_exit: vcpu_cell_exit(cell); return err; }
void arch_cell_destroy(struct cell *cell) { ioapic_cell_exit(cell); pci_cell_exit(cell); iommu_cell_exit(cell); vcpu_cell_exit(cell); }
int vcpu_cell_init(struct cell *cell) { const u8 *pio_bitmap = jailhouse_cell_pio_bitmap(cell->config); u32 pio_bitmap_size = cell->config->pio_bitmap_size; struct vcpu_io_bitmap cell_iobm, root_cell_iobm; unsigned int n, pm_timer_addr; u32 size; int err; u8 *b; /* PM timer has to be provided */ if (system_config->platform_info.x86.pm_timer_address == 0) return -EINVAL; err = vcpu_vendor_cell_init(cell); if (err) { vcpu_cell_exit(cell); return err; } vcpu_vendor_get_cell_io_bitmap(cell, &cell_iobm); memset(cell_iobm.data, -1, cell_iobm.size); for (n = 0; n < 2; n++) { size = pio_bitmap_size <= PAGE_SIZE ? pio_bitmap_size : PAGE_SIZE; memcpy(cell_iobm.data + n * PAGE_SIZE, pio_bitmap, size); pio_bitmap += size; pio_bitmap_size -= size; } /* moderation access to i8042 command register */ cell_iobm.data[I8042_CMD_REG / 8] |= 1 << (I8042_CMD_REG % 8); if (cell != &root_cell) { /* * Shrink PIO access of root cell corresponding to new cell's * access rights. */ vcpu_vendor_get_cell_io_bitmap(&root_cell, &root_cell_iobm); pio_bitmap = jailhouse_cell_pio_bitmap(cell->config); pio_bitmap_size = cell->config->pio_bitmap_size; for (b = root_cell_iobm.data; pio_bitmap_size > 0; b++, pio_bitmap++, pio_bitmap_size--) *b |= ~*pio_bitmap; } /* permit access to the PM timer */ pm_timer_addr = system_config->platform_info.x86.pm_timer_address; for (n = 0; n < 4; n++, pm_timer_addr++) { b = cell_iobm.data; b[pm_timer_addr / 8] &= ~(1 << (pm_timer_addr % 8)); } return 0; }
int arch_cell_create(struct cell *cell) { unsigned int cpu; int err; err = vcpu_cell_init(cell); if (err) return err; err = iommu_cell_init(cell); if (err) goto error_vm_exit; err = pci_cell_init(cell); if (err) goto error_iommu_exit; err = ioapic_cell_init(cell); if (err) goto error_pci_exit; err = cat_cell_init(cell); if (err) goto error_ioapic_exit; cell->comm_page.comm_region.pm_timer_address = system_config->platform_info.x86.pm_timer_address; cell->comm_page.comm_region.num_cpus = 0; for_each_cpu(cpu, cell->cpu_set) cell->comm_page.comm_region.num_cpus++; return 0; error_ioapic_exit: ioapic_cell_exit(cell); error_pci_exit: pci_cell_exit(cell); error_iommu_exit: iommu_cell_exit(cell); error_vm_exit: vcpu_cell_exit(cell); return err; }