Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
DISCONTINUED:openSUSE:11.1:Update
xen
19734-vtd-gcmd-submit.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 19734-vtd-gcmd-submit.patch of Package xen
# HG changeset patch # User Keir Fraser <keir.fraser@citrix.com> # Date 1244190582 -3600 # Node ID 4fb8a6c993e21e18b5eefddd6d5df20e7f8c7848 # Parent a69daf23602a8b7f41a7dc304c7050def59597c7 VT-d: correct way to submit command to GCMD register Per VT-d spec, software should submit only one "incremental" command at a time to Global Command reigster. Current implementation uses a variable (gcmd) to record the state of Global Status register. It's error prone. Signed-off-by: Weidong Han <weidong.han@intel.com> --- a/xen/drivers/passthrough/vtd/intremap.c +++ b/xen/drivers/passthrough/vtd/intremap.c @@ -538,6 +538,7 @@ void msi_msg_write_remap_rte( int enable_intremap(struct iommu *iommu) { struct ir_ctrl *ir_ctrl; + u32 gcmd; s_time_t start_time; ASSERT(ecap_intr_remap(iommu->ecap) && iommu_intremap); @@ -565,8 +566,9 @@ int enable_intremap(struct iommu *iommu) dmar_writeq(iommu->reg, DMAR_IRTA_REG, ir_ctrl->iremap_maddr); /* set SIRTP */ - iommu->gcmd |= DMA_GCMD_SIRTP; - dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd); + gcmd = dmar_readl(iommu->reg, DMAR_GSTS_REG); + gcmd |= DMA_GCMD_SIRTP; + dmar_writel(iommu->reg, DMAR_GCMD_REG, gcmd); /* Make sure hardware complete it */ start_time = NOW(); @@ -578,8 +580,8 @@ int enable_intremap(struct iommu *iommu) } /* enable comaptiblity format interrupt pass through */ - iommu->gcmd |= DMA_GCMD_CFI; - dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd); + gcmd |= DMA_GCMD_CFI; + dmar_writel(iommu->reg, DMAR_GCMD_REG, gcmd); start_time = NOW(); while ( !(dmar_readl(iommu->reg, DMAR_GSTS_REG) & DMA_GSTS_CFIS) ) @@ -590,8 +592,8 @@ int enable_intremap(struct iommu *iommu) } /* enable interrupt remapping hardware */ - iommu->gcmd |= DMA_GCMD_IRE; - dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd); + gcmd |= DMA_GCMD_IRE; + dmar_writel(iommu->reg, DMAR_GCMD_REG, gcmd); start_time = NOW(); while ( !(dmar_readl(iommu->reg, DMAR_GSTS_REG) & DMA_GSTS_IRES) ) @@ -611,12 +613,13 @@ int enable_intremap(struct iommu *iommu) void disable_intremap(struct iommu *iommu) { + u32 sts; s_time_t start_time; ASSERT(ecap_intr_remap(iommu->ecap) && iommu_intremap); - iommu->gcmd &= ~(DMA_GCMD_SIRTP | DMA_GCMD_CFI | DMA_GCMD_IRE); - dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd); + sts = dmar_readl(iommu->reg, DMAR_GSTS_REG); + dmar_writel(iommu->reg, DMAR_GCMD_REG, sts & (~DMA_GCMD_IRE)); start_time = NOW(); while ( dmar_readl(iommu->reg, DMAR_GSTS_REG) & DMA_GSTS_IRES ) --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -266,10 +266,10 @@ static void iommu_flush_write_buffer(str if ( !rwbf_quirk && !cap_rwbf(iommu->cap) ) return; - val = iommu->gcmd | DMA_GCMD_WBF; spin_lock_irqsave(&iommu->register_lock, flag); - dmar_writel(iommu->reg, DMAR_GCMD_REG, val); + val = dmar_readl(iommu->reg, DMAR_GSTS_REG); + dmar_writel(iommu->reg, DMAR_GCMD_REG, val | DMA_GCMD_WBF); /* Make sure hardware complete it */ start_time = NOW(); @@ -616,7 +616,7 @@ static void iommu_free_pagetable(u64 pt_ static int iommu_set_root_entry(struct iommu *iommu) { - u32 cmd, sts; + u32 sts; unsigned long flags; s_time_t start_time; @@ -631,8 +631,9 @@ static int iommu_set_root_entry(struct i } dmar_writeq(iommu->reg, DMAR_RTADDR_REG, iommu->root_maddr); - cmd = iommu->gcmd | DMA_GCMD_SRTP; - dmar_writel(iommu->reg, DMAR_GCMD_REG, cmd); + + sts = dmar_readl(iommu->reg, DMAR_GSTS_REG); + dmar_writel(iommu->reg, DMAR_GCMD_REG, sts | DMA_GCMD_SRTP); /* Make sure hardware complete it */ start_time = NOW(); @@ -661,8 +662,9 @@ static int iommu_enable_translation(stru dprintk(XENLOG_INFO VTDPREFIX, "iommu_enable_translation: iommu->reg = %p\n", iommu->reg); spin_lock_irqsave(&iommu->register_lock, flags); - iommu->gcmd |= DMA_GCMD_TE; - dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd); + sts = dmar_readl(iommu->reg, DMAR_GSTS_REG); + dmar_writel(iommu->reg, DMAR_GCMD_REG, sts | DMA_GCMD_TE); + /* Make sure hardware complete it */ start_time = NOW(); for ( ; ; ) @@ -689,8 +691,8 @@ static void iommu_disable_translation(st s_time_t start_time; spin_lock_irqsave(&iommu->register_lock, flags); - iommu->gcmd &= ~ DMA_GCMD_TE; - dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd); + sts = dmar_readl(iommu->reg, DMAR_GSTS_REG); + dmar_writel(iommu->reg, DMAR_GCMD_REG, sts & (~DMA_GCMD_TE)); /* Make sure hardware complete it */ start_time = NOW(); --- a/xen/drivers/passthrough/vtd/qinval.c +++ b/xen/drivers/passthrough/vtd/qinval.c @@ -415,6 +415,7 @@ static int flush_iotlb_qi( int enable_qinval(struct iommu *iommu) { + u32 sts; s_time_t start_time; struct qi_ctrl *qi_ctrl; struct iommu_flush *flush; @@ -449,8 +450,8 @@ int enable_qinval(struct iommu *iommu) dmar_writeq(iommu->reg, DMAR_IQT_REG, 0); /* enable queued invalidation hardware */ - iommu->gcmd |= DMA_GCMD_QIE; - dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd); + sts = dmar_readl(iommu->reg, DMAR_GSTS_REG); + dmar_writel(iommu->reg, DMAR_GCMD_REG, sts | DMA_GCMD_QIE); /* Make sure hardware complete it */ start_time = NOW(); @@ -466,12 +467,13 @@ int enable_qinval(struct iommu *iommu) void disable_qinval(struct iommu *iommu) { + u32 sts; s_time_t start_time; ASSERT(ecap_queued_inval(iommu->ecap) && iommu_qinval); - iommu->gcmd &= ~DMA_GCMD_QIE; - dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd); + sts = dmar_readl(iommu->reg, DMAR_GSTS_REG); + dmar_writel(iommu->reg, DMAR_GCMD_REG, sts & (~DMA_GCMD_QIE)); /* Make sure hardware complete it */ start_time = NOW(); --- a/xen/include/xen/iommu.h +++ b/xen/include/xen/iommu.h @@ -49,7 +49,6 @@ struct iommu { struct list_head list; void __iomem *reg; /* Pointer to hardware regs, virtual addr */ u32 index; /* Sequence number of iommu */ - u32 gcmd; /* Holds TE, EAFL. Don't need SRTP, SFL, WBF */ u32 nr_pt_levels; u64 cap; u64 ecap;
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor