예제 #1
0
int vtd_cell_init(struct cell *cell)
{
	struct jailhouse_cell_desc *config = cell->config;
	const struct jailhouse_memory *mem =
		jailhouse_cell_mem_regions(config);
	const struct jailhouse_pci_device *dev =
		jailhouse_cell_pci_devices(cell->config);
	void *reg_base = dmar_reg_base;
	int n, err;

	// HACK for QEMU
	if (dmar_units == 0)
		return 0;

	if (cell->id >= dmar_num_did)
		return -ERANGE;

	cell->vtd.pg_structs.root_paging = vtd_paging;
	cell->vtd.pg_structs.root_table = page_alloc(&mem_pool, 1);
	if (!cell->vtd.pg_structs.root_table)
		return -ENOMEM;

	for (n = 0; n < config->num_memory_regions; n++, mem++) {
		err = vtd_map_memory_region(cell, mem);
		if (err)
			/* FIXME: release vtd.pg_structs.root_table */
			return err;
	}

	for (n = 0; n < config->num_pci_devices; n++)
		if (!vtd_add_device_to_cell(cell, &dev[n]))
			/* FIXME: release vtd.pg_structs.root_table,
			 * revert device additions*/
			return -ENOMEM;

	if (!(mmio_read32(reg_base + VTD_GSTS_REG) & VTD_GSTS_TES))
		for (n = 0; n < dmar_units; n++, reg_base += PAGE_SIZE) {
			mmio_write64(reg_base + VTD_RTADDR_REG,
				     page_map_hvirt2phys(root_entry_table));
			mmio_write32(reg_base + VTD_GCMD_REG, VTD_GCMD_SRTP);
			while (!(mmio_read32(reg_base + VTD_GSTS_REG) &
				 VTD_GSTS_SRTP))
				cpu_relax();

			vtd_flush_dmar_caches(reg_base, VTD_CCMD_CIRG_GLOBAL,
					      VTD_IOTLB_IIRG_GLOBAL);

			mmio_write32(reg_base + VTD_GCMD_REG, VTD_GCMD_TE);
			while (!(mmio_read32(reg_base + VTD_GSTS_REG) &
				 VTD_GSTS_TES))
				cpu_relax();
		}

	return 0;
}
예제 #2
0
int arch_map_memory_region(struct cell *cell,
			   const struct jailhouse_memory *mem)
{
	int err;

	err = vmx_map_memory_region(cell, mem);
	if (err)
		return err;

	err = vtd_map_memory_region(cell, mem);
	if (err)
		vmx_unmap_memory_region(cell, mem);
	return err;
}