physdev_init_dom0(d);
+ iommu_dom0_init(d);
+
return 0;
}
BUG_ON(rc != 0);
+ iommu_dom0_init(dom0);
+
return 0;
}
return level;
}
-static int amd_iommu_domain_init(struct domain *domain)
+static int amd_iommu_domain_init(struct domain *d)
{
- struct hvm_iommu *hd = domain_hvm_iommu(domain);
+ struct hvm_iommu *hd = domain_hvm_iommu(d);
/* allocate page directroy */
if ( allocate_domain_resources(hd) != 0 )
return -ENOMEM;
}
- hd->paging_mode = is_hvm_domain(domain)?
+ hd->paging_mode = is_hvm_domain(d) ?
IOMMU_PAGE_TABLE_LEVEL_4 : get_paging_mode(max_page);
- if ( domain->domain_id == 0 )
- {
- unsigned long i;
+ hd->domain_id = d->domain_id;
- if ( !iommu_passthrough && !need_iommu(domain) )
- {
- /* setup 1:1 page table for dom0 */
- for ( i = 0; i < max_page; i++ )
- amd_iommu_map_page(domain, i, i,
- IOMMUF_readable|IOMMUF_writable);
- }
+ return 0;
+}
- amd_iommu_setup_dom0_devices(domain);
- }
+static void amd_iommu_dom0_init(struct domain *d)
+{
+ unsigned long i;
- hd->domain_id = domain->domain_id;
+ if ( !iommu_passthrough && !need_iommu(d) )
+ {
+ /* Set up 1:1 page table for dom0 */
+ for ( i = 0; i < max_page; i++ )
+ amd_iommu_map_page(d, i, i, IOMMUF_readable|IOMMUF_writable);
+ }
- return 0;
+ amd_iommu_setup_dom0_devices(d);
}
static void amd_iommu_disable_domain_device(
const struct iommu_ops amd_iommu_ops = {
.init = amd_iommu_domain_init,
+ .dom0_init = amd_iommu_dom0_init,
.add_device = amd_iommu_add_device,
.remove_device = amd_iommu_remove_device,
.assign_device = amd_iommu_assign_device,
#include <asm/hvm/iommu.h>
#include <xen/paging.h>
#include <xen/guest_access.h>
+#include <xen/softirq.h>
static void parse_iommu_param(char *s);
static int iommu_populate_page_table(struct domain *d);
if ( !iommu_enabled )
return 0;
- d->need_iommu = ((d->domain_id == 0) && iommu_dom0_strict);
-
hd->platform_ops = iommu_get_ops();
return hd->platform_ops->init(d);
}
+void iommu_dom0_init(struct domain *d)
+{
+ struct hvm_iommu *hd = domain_hvm_iommu(d);
+
+ if ( !iommu_enabled )
+ return;
+
+ d->need_iommu = !!iommu_dom0_strict;
+ if ( need_iommu(d) )
+ {
+ struct page_info *page;
+ unsigned int i = 0;
+ page_list_for_each ( page, &d->page_list )
+ {
+ unsigned long mfn = page_to_mfn(page);
+ unsigned int mapping = IOMMUF_readable;
+ if ( ((page->u.inuse.type_info & PGT_count_mask) == 0) ||
+ ((page->u.inuse.type_info & PGT_type_mask)
+ == PGT_writable_page) )
+ mapping |= IOMMUF_writable;
+ hd->platform_ops->map_page(d, mfn, mfn, mapping);
+ if ( !(i++ & 0xfffff) )
+ process_pending_softirqs();
+ }
+ }
+
+ return hd->platform_ops->dom0_init(d);
+}
+
int iommu_add_device(struct pci_dev *pdev)
{
struct hvm_iommu *hd;
static int intel_iommu_domain_init(struct domain *d)
{
struct hvm_iommu *hd = domain_hvm_iommu(d);
- struct iommu *iommu;
- struct acpi_drhd_unit *drhd;
hd->agaw = width_to_agaw(DEFAULT_DOMAIN_ADDRESS_WIDTH);
- if ( d->domain_id == 0 )
+ return 0;
+}
+
+static void intel_iommu_dom0_init(struct domain *d)
+{
+ struct iommu *iommu;
+ struct acpi_drhd_unit *drhd;
+
+ if ( !iommu_passthrough && !need_iommu(d) )
{
/* Set up 1:1 page table for dom0 */
- if ( !need_iommu(d) )
- iommu_set_dom0_mapping(d);
+ iommu_set_dom0_mapping(d);
+ }
- setup_dom0_devices(d);
- setup_dom0_rmrr(d);
+ setup_dom0_devices(d);
+ setup_dom0_rmrr(d);
- iommu_flush_all();
+ iommu_flush_all();
- for_each_drhd_unit ( drhd )
- {
- iommu = drhd->iommu;
- iommu_enable_translation(iommu);
- }
+ for_each_drhd_unit ( drhd )
+ {
+ iommu = drhd->iommu;
+ iommu_enable_translation(iommu);
}
-
- return 0;
}
static int domain_context_mapping_one(
const struct iommu_ops intel_iommu_ops = {
.init = intel_iommu_domain_init,
+ .dom0_init = intel_iommu_dom0_init,
.add_device = intel_iommu_add_device,
.remove_device = intel_iommu_remove_device,
.assign_device = intel_iommu_assign_device,
int iommu_add_device(struct pci_dev *pdev);
int iommu_remove_device(struct pci_dev *pdev);
int iommu_domain_init(struct domain *d);
+void iommu_dom0_init(struct domain *d);
void iommu_domain_destroy(struct domain *d);
int device_assigned(u8 bus, u8 devfn);
int assign_device(struct domain *d, u8 bus, u8 devfn);
struct iommu_ops {
int (*init)(struct domain *d);
+ void (*dom0_init)(struct domain *d);
int (*add_device)(struct pci_dev *pdev);
int (*remove_device)(struct pci_dev *pdev);
int (*assign_device)(struct domain *d, u8 bus, u8 devfn);