Message ID | 20201015183457.1719068-1-dwmw2@infradead.org |
---|---|
State | New |
Headers | show |
Series | [1/2] intel_iommu: Support IR-only mode without DMA translation | expand |
On Thu, 2020-10-15 at 19:34 +0100, David Woodhouse wrote: > From: David Woodhouse <dwmw@amazon.co.uk> > > By setting none of the SAGAW bits we can indicate to a guest that DMA > translation isn't supported. Tested by booting Windows 10, as well as > Linux guests with the fix at https://git.kernel.org/torvalds/c/c40aaaac10 > > Signed-off-by: David Woodhouse <dwmw@amazon.co.uk> Shall I resend these? They still seem to apply cleanly. > --- > hw/i386/intel_iommu.c | 14 ++++++++++---- > include/hw/i386/intel_iommu.h | 1 + > 2 files changed, 11 insertions(+), 4 deletions(-) > > diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c > index 749eb6ad63..f49b4af931 100644 > --- a/hw/i386/intel_iommu.c > +++ b/hw/i386/intel_iommu.c > @@ -2189,7 +2189,7 @@ static void vtd_handle_gcmd_write(IntelIOMMUState *s) > uint32_t changed = status ^ val; > > trace_vtd_reg_write_gcmd(status, val); > - if (changed & VTD_GCMD_TE) { > + if ((changed & VTD_GCMD_TE) && s->dma_translation) { > /* Translation enable/disable */ > vtd_handle_gcmd_te(s, val & VTD_GCMD_TE); > } > @@ -3086,6 +3086,7 @@ static Property vtd_properties[] = { > DEFINE_PROP_BOOL("caching-mode", IntelIOMMUState, caching_mode, FALSE), > DEFINE_PROP_BOOL("x-scalable-mode", IntelIOMMUState, scalable_mode, FALSE), > DEFINE_PROP_BOOL("dma-drain", IntelIOMMUState, dma_drain, true), > + DEFINE_PROP_BOOL("dma-translation", IntelIOMMUState, dma_translation, true), > DEFINE_PROP_END_OF_LIST(), > }; > > @@ -3607,12 +3608,17 @@ static void vtd_init(IntelIOMMUState *s) > s->next_frcd_reg = 0; > s->cap = VTD_CAP_FRO | VTD_CAP_NFR | VTD_CAP_ND | > VTD_CAP_MAMV | VTD_CAP_PSI | VTD_CAP_SLLPS | > - VTD_CAP_SAGAW_39bit | VTD_CAP_MGAW(s->aw_bits); > + VTD_CAP_MGAW(s->aw_bits); > if (s->dma_drain) { > s->cap |= VTD_CAP_DRAIN; > } > - if (s->aw_bits == VTD_HOST_AW_48BIT) { > - s->cap |= VTD_CAP_SAGAW_48bit; > + if (s->dma_translation) { > + if (s->aw_bits >= VTD_HOST_AW_39BIT) { > + s->cap |= VTD_CAP_SAGAW_39bit; > + } > + if (s->aw_bits >= VTD_HOST_AW_48BIT) { > + s->cap |= VTD_CAP_SAGAW_48bit; > + } > } > s->ecap = VTD_ECAP_QI | VTD_ECAP_IRO; > > diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h > index 41783ee46d..42d6a6a636 100644 > --- a/include/hw/i386/intel_iommu.h > +++ b/include/hw/i386/intel_iommu.h > @@ -266,6 +266,7 @@ struct IntelIOMMUState { > bool buggy_eim; /* Force buggy EIM unless eim=off */ > uint8_t aw_bits; /* Host/IOVA address width (in bits) */ > bool dma_drain; /* Whether DMA r/w draining enabled */ > + bool dma_translation; /* Whether DMA translation supported */ > > /* > * Protects IOMMU states in general. Currently it protects the
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index 749eb6ad63..f49b4af931 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -2189,7 +2189,7 @@ static void vtd_handle_gcmd_write(IntelIOMMUState *s) uint32_t changed = status ^ val; trace_vtd_reg_write_gcmd(status, val); - if (changed & VTD_GCMD_TE) { + if ((changed & VTD_GCMD_TE) && s->dma_translation) { /* Translation enable/disable */ vtd_handle_gcmd_te(s, val & VTD_GCMD_TE); } @@ -3086,6 +3086,7 @@ static Property vtd_properties[] = { DEFINE_PROP_BOOL("caching-mode", IntelIOMMUState, caching_mode, FALSE), DEFINE_PROP_BOOL("x-scalable-mode", IntelIOMMUState, scalable_mode, FALSE), DEFINE_PROP_BOOL("dma-drain", IntelIOMMUState, dma_drain, true), + DEFINE_PROP_BOOL("dma-translation", IntelIOMMUState, dma_translation, true), DEFINE_PROP_END_OF_LIST(), }; @@ -3607,12 +3608,17 @@ static void vtd_init(IntelIOMMUState *s) s->next_frcd_reg = 0; s->cap = VTD_CAP_FRO | VTD_CAP_NFR | VTD_CAP_ND | VTD_CAP_MAMV | VTD_CAP_PSI | VTD_CAP_SLLPS | - VTD_CAP_SAGAW_39bit | VTD_CAP_MGAW(s->aw_bits); + VTD_CAP_MGAW(s->aw_bits); if (s->dma_drain) { s->cap |= VTD_CAP_DRAIN; } - if (s->aw_bits == VTD_HOST_AW_48BIT) { - s->cap |= VTD_CAP_SAGAW_48bit; + if (s->dma_translation) { + if (s->aw_bits >= VTD_HOST_AW_39BIT) { + s->cap |= VTD_CAP_SAGAW_39bit; + } + if (s->aw_bits >= VTD_HOST_AW_48BIT) { + s->cap |= VTD_CAP_SAGAW_48bit; + } } s->ecap = VTD_ECAP_QI | VTD_ECAP_IRO; diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h index 41783ee46d..42d6a6a636 100644 --- a/include/hw/i386/intel_iommu.h +++ b/include/hw/i386/intel_iommu.h @@ -266,6 +266,7 @@ struct IntelIOMMUState { bool buggy_eim; /* Force buggy EIM unless eim=off */ uint8_t aw_bits; /* Host/IOVA address width (in bits) */ bool dma_drain; /* Whether DMA r/w draining enabled */ + bool dma_translation; /* Whether DMA translation supported */ /* * Protects IOMMU states in general. Currently it protects the