/*
* Jailhouse, a Linux-based partitioning hypervisor
*
- * Copyright (c) Siemens AG, 2013-2015
+ * Copyright (c) Siemens AG, 2013-2016
* Copyright (c) Valentine Sinitsyn, 2014
*
* Authors:
#include <asm/spinlock.h>
#include <asm/vtd.h>
+/* A unit can occupy up to 3 pages for registers, we reserve 4. */
+#define DMAR_MMIO_SIZE (PAGE_SIZE * 4)
+
struct vtd_irte_usage {
u16 device_id;
u16 vector:10,
for (n = 0; n < dmar_units; n++) {
vtd_submit_iq_request(reg_base, inv_queue, &inv_context);
vtd_submit_iq_request(reg_base, inv_queue, &inv_iotlb);
- reg_base += PAGE_SIZE;
+ reg_base += DMAR_MMIO_SIZE;
inv_queue += PAGE_SIZE;
}
}
* case from different CPUs */
fault_reporting_cpu_id = cpu_data->cpu_id;
- for (n = 0; n < dmar_units; n++, reg_base += PAGE_SIZE) {
+ for (n = 0; n < dmar_units; n++, reg_base += DMAR_MMIO_SIZE) {
/* Mask events */
mmio_write32_field(reg_base + VTD_FECTL_REG, VTD_FECTL_IM, 1);
if (this_cpu_id() != fault_reporting_cpu_id)
return;
- for (n = 0; n < dmar_units; n++, reg_base += PAGE_SIZE)
+ for (n = 0; n < dmar_units; n++, reg_base += DMAR_MMIO_SIZE)
if (mmio_read32_field(reg_base + VTD_FSTS_REG, VTD_FSTS_PPF)) {
fr_index = mmio_read32_field(reg_base + VTD_FSTS_REG,
VTD_FSTS_FRI_MASK);
if (units == 0)
return trace_error(-EINVAL);
- dmar_reg_base = page_alloc(&remap_pool, units);
+ dmar_reg_base = page_alloc(&remap_pool, units * PAGES(DMAR_MMIO_SIZE));
if (!dmar_reg_base)
return trace_error(-ENOMEM);
for (n = 0; n < units; n++) {
unit = &system_config->platform_info.x86.iommu_units[n];
- reg_base = dmar_reg_base + n * PAGE_SIZE;
+ reg_base = dmar_reg_base + n * DMAR_MMIO_SIZE;
- err = paging_create(&hv_paging_structs, unit->base, PAGE_SIZE,
+ err = paging_create(&hv_paging_structs, unit->base, unit->size,
(unsigned long)reg_base,
PAGE_DEFAULT_FLAGS | PAGE_FLAG_DEVICE,
PAGING_NON_COHERENT);
return 0;
}
- printk("Found DMAR @%p\n", unit->base);
+ printk("DMAR unit @0x%lx/0x%x\n", unit->base, unit->size);
caps = mmio_read64(reg_base + VTD_CAP_REG);
if (caps & VTD_CAP_SAGAW39)
for (n = 0; n < dmar_units; n++) {
vtd_submit_iq_request(reg_base, inv_queue, &inv_int);
- reg_base += PAGE_SIZE;
+ reg_base += DMAR_MMIO_SIZE;
inv_queue += PAGE_SIZE;
}
}
if (cell_added_removed == &root_cell) {
for (n = 0; n < dmar_units; n++) {
vtd_init_unit(reg_base, inv_queue);
- reg_base += PAGE_SIZE;
+ reg_base += DMAR_MMIO_SIZE;
inv_queue += PAGE_SIZE;
}
dmar_units_initialized = true;
unsigned int n;
if (dmar_units_initialized)
- for (n = 0; n < dmar_units; n++, reg_base += PAGE_SIZE) {
+ for (n = 0; n < dmar_units; n++, reg_base += DMAR_MMIO_SIZE) {
vtd_update_gcmd_reg(reg_base, VTD_GCMD_TE, 0);
vtd_update_gcmd_reg(reg_base, VTD_GCMD_IRE, 0);
if (root_cell.arch.vtd.ir_emulation)