mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
iommu: Map dom0 initial allocation in 'dom0-strict' iommu mode.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
This commit is contained in:
1 parent
6518d6c62b
commit
338666b9df
6 files changed
+76
-38
No files matched your search
@@ -2298,6 +2298,8 @@ int __init construct_dom0(struct domain *d,
|
||||
|
||||
physdev_init_dom0(d);
|
||||
|
||||
iommu_dom0_init(d);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1142,6 +1142,8 @@ int __init construct_dom0(
|
||||
|
||||
BUG_ON(rc != 0);
|
||||
|
||||
iommu_dom0_init(dom0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -212,9 +212,9 @@ static int get_paging_mode(unsigned long entries)
|
||||
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 )
|
||||
@@ -224,29 +224,28 @@ static int amd_iommu_domain_init(struct domain *domain)
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
amd_iommu_setup_dom0_devices(domain);
|
||||
}
|
||||
|
||||
hd->domain_id = domain->domain_id;
|
||||
hd->domain_id = d->domain_id;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void amd_iommu_dom0_init(struct domain *d)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
amd_iommu_setup_dom0_devices(d);
|
||||
}
|
||||
|
||||
static void amd_iommu_disable_domain_device(
|
||||
struct domain *domain, struct amd_iommu *iommu, int bdf)
|
||||
{
|
||||
@@ -433,6 +432,7 @@ static int amd_iommu_group_id(u8 bus, u8 devfn)
|
||||
|
||||
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,
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#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);
|
||||
@@ -97,12 +98,39 @@ int iommu_domain_init(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;
|
||||
|
||||
@@ -1171,30 +1171,33 @@ void __init iommu_free(struct acpi_drhd_unit *drhd)
|
||||
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);
|
||||
|
||||
setup_dom0_devices(d);
|
||||
setup_dom0_rmrr(d);
|
||||
|
||||
iommu_flush_all();
|
||||
|
||||
for_each_drhd_unit ( drhd )
|
||||
{
|
||||
iommu = drhd->iommu;
|
||||
iommu_enable_translation(iommu);
|
||||
}
|
||||
iommu_set_dom0_mapping(d);
|
||||
}
|
||||
|
||||
return 0;
|
||||
setup_dom0_devices(d);
|
||||
setup_dom0_rmrr(d);
|
||||
|
||||
iommu_flush_all();
|
||||
|
||||
for_each_drhd_unit ( drhd )
|
||||
{
|
||||
iommu = drhd->iommu;
|
||||
iommu_enable_translation(iommu);
|
||||
}
|
||||
}
|
||||
|
||||
static int domain_context_mapping_one(
|
||||
@@ -2161,6 +2164,7 @@ static void vtd_resume(void)
|
||||
|
||||
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,
|
||||
|
||||
@@ -64,6 +64,7 @@ int intremap_enabled(void);
|
||||
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);
|
||||
@@ -109,6 +110,7 @@ bool_t pt_irq_need_timer(uint32_t flags);
|
||||
|
||||
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);
|
||||
|
||||