svn commit: r277315 - stable/10/sys/x86/iommu
Konstantin Belousov
kib at FreeBSD.org
Sun Jan 18 09:49:34 UTC 2015
Author: kib
Date: Sun Jan 18 09:49:32 2015
New Revision: 277315
URL: https://svnweb.freebsd.org/changeset/base/277315
Log:
MFC r277023:
Avoid excessive flushing and do missed neccessary flushing in the IOMMU
page table update code.
Modified:
stable/10/sys/x86/iommu/intel_ctx.c
stable/10/sys/x86/iommu/intel_dmar.h
stable/10/sys/x86/iommu/intel_idpgtbl.c
stable/10/sys/x86/iommu/intel_utils.c
Directory Properties:
stable/10/ (props changed)
Modified: stable/10/sys/x86/iommu/intel_ctx.c
==============================================================================
--- stable/10/sys/x86/iommu/intel_ctx.c Sun Jan 18 07:08:06 2015 (r277314)
+++ stable/10/sys/x86/iommu/intel_ctx.c Sun Jan 18 09:49:32 2015 (r277315)
@@ -96,7 +96,8 @@ dmar_ensure_ctx_page(struct dmar_unit *d
re += bus;
dmar_pte_store(&re->r1, DMAR_ROOT_R1_P | (DMAR_ROOT_R1_CTP_MASK &
VM_PAGE_TO_PHYS(ctxm)));
- dmar_unmap_pgtbl(sf, DMAR_IS_COHERENT(dmar));
+ dmar_flush_root_to_ram(dmar, re);
+ dmar_unmap_pgtbl(sf);
TD_PINNED_ASSERT;
}
@@ -153,6 +154,7 @@ ctx_id_entry_init(struct dmar_ctx *ctx,
(DMAR_CTX1_ASR_MASK & VM_PAGE_TO_PHYS(ctx_root)) |
DMAR_CTX1_P);
}
+ dmar_flush_ctx_to_ram(unit, ctxp);
}
static int
@@ -358,7 +360,7 @@ dmar_get_ctx(struct dmar_unit *dmar, dev
ctx->domain = alloc_unrl(dmar->domids);
if (ctx->domain == -1) {
DMAR_UNLOCK(dmar);
- dmar_unmap_pgtbl(sf, true);
+ dmar_unmap_pgtbl(sf);
dmar_ctx_dtr(ctx, true, true);
TD_PINNED_ASSERT;
return (NULL);
@@ -383,7 +385,7 @@ dmar_get_ctx(struct dmar_unit *dmar, dev
} else {
dmar_ctx_dtr(ctx1, true, true);
}
- dmar_unmap_pgtbl(sf, DMAR_IS_COHERENT(dmar));
+ dmar_unmap_pgtbl(sf);
}
ctx->refs++;
if ((ctx->flags & DMAR_CTX_RMRR) != 0)
@@ -474,7 +476,7 @@ dmar_free_ctx_locked(struct dmar_unit *d
if (ctx->refs > 1) {
ctx->refs--;
DMAR_UNLOCK(dmar);
- dmar_unmap_pgtbl(sf, DMAR_IS_COHERENT(dmar));
+ dmar_unmap_pgtbl(sf);
TD_PINNED_ASSERT;
return;
}
@@ -490,6 +492,7 @@ dmar_free_ctx_locked(struct dmar_unit *d
*/
dmar_pte_clear(&ctxp->ctx1);
ctxp->ctx2 = 0;
+ dmar_flush_ctx_to_ram(dmar, ctxp);
dmar_inv_ctx_glob(dmar);
if ((dmar->hw_ecap & DMAR_ECAP_DI) != 0) {
if (dmar->qi_enabled)
@@ -507,7 +510,7 @@ dmar_free_ctx_locked(struct dmar_unit *d
taskqueue_drain(dmar->delayed_taskqueue, &ctx->unload_task);
KASSERT(TAILQ_EMPTY(&ctx->unload_entries),
("unfinished unloads %p", ctx));
- dmar_unmap_pgtbl(sf, DMAR_IS_COHERENT(dmar));
+ dmar_unmap_pgtbl(sf);
free_unr(dmar->domids, ctx->domain);
dmar_ctx_dtr(ctx, true, true);
TD_PINNED_ASSERT;
Modified: stable/10/sys/x86/iommu/intel_dmar.h
==============================================================================
--- stable/10/sys/x86/iommu/intel_dmar.h Sun Jan 18 07:08:06 2015 (r277314)
+++ stable/10/sys/x86/iommu/intel_dmar.h Sun Jan 18 09:49:32 2015 (r277315)
@@ -230,11 +230,14 @@ struct vm_page *dmar_pgalloc(vm_object_t
void dmar_pgfree(vm_object_t obj, vm_pindex_t idx, int flags);
void *dmar_map_pgtbl(vm_object_t obj, vm_pindex_t idx, int flags,
struct sf_buf **sf);
-void dmar_unmap_pgtbl(struct sf_buf *sf, bool coherent);
+void dmar_unmap_pgtbl(struct sf_buf *sf);
int dmar_load_root_entry_ptr(struct dmar_unit *unit);
int dmar_inv_ctx_glob(struct dmar_unit *unit);
int dmar_inv_iotlb_glob(struct dmar_unit *unit);
int dmar_flush_write_bufs(struct dmar_unit *unit);
+void dmar_flush_pte_to_ram(struct dmar_unit *unit, dmar_pte_t *dst);
+void dmar_flush_ctx_to_ram(struct dmar_unit *unit, dmar_ctx_entry_t *dst);
+void dmar_flush_root_to_ram(struct dmar_unit *unit, dmar_root_entry_t *dst);
int dmar_enable_translation(struct dmar_unit *unit);
int dmar_disable_translation(struct dmar_unit *unit);
bool dmar_barrier_enter(struct dmar_unit *dmar, u_int barrier_id);
Modified: stable/10/sys/x86/iommu/intel_idpgtbl.c
==============================================================================
--- stable/10/sys/x86/iommu/intel_idpgtbl.c Sun Jan 18 07:08:06 2015 (r277314)
+++ stable/10/sys/x86/iommu/intel_idpgtbl.c Sun Jan 18 09:49:32 2015 (r277315)
@@ -146,7 +146,7 @@ ctx_idmap_nextlvl(struct idpgtbl *tbl, i
}
}
/* ctx_get_idmap_pgtbl flushes CPU cache if needed. */
- dmar_unmap_pgtbl(sf, true);
+ dmar_unmap_pgtbl(sf);
VM_OBJECT_WLOCK(tbl->pgtbl_obj);
}
@@ -361,7 +361,7 @@ ctx_pgtbl_map_pte(struct dmar_ctx *ctx,
pte = (dmar_pte_t *)sf_buf_kva(*sf);
} else {
if (*sf != NULL)
- dmar_unmap_pgtbl(*sf, DMAR_IS_COHERENT(ctx->dmar));
+ dmar_unmap_pgtbl(*sf);
*idxp = idx;
retry:
pte = dmar_map_pgtbl(ctx->pgtbl_obj, idx, flags, sf);
@@ -397,9 +397,10 @@ retry:
}
dmar_pte_store(&ptep->pte, DMAR_PTE_R | DMAR_PTE_W |
VM_PAGE_TO_PHYS(m));
+ dmar_flush_pte_to_ram(ctx->dmar, ptep);
sf_buf_page(sfp)->wire_count += 1;
m->wire_count--;
- dmar_unmap_pgtbl(sfp, DMAR_IS_COHERENT(ctx->dmar));
+ dmar_unmap_pgtbl(sfp);
/* Only executed once. */
goto retry;
}
@@ -467,20 +468,19 @@ ctx_map_buf_locked(struct dmar_ctx *ctx,
if (pte == NULL) {
KASSERT((flags & DMAR_PGF_WAITOK) == 0,
("failed waitable pte alloc %p", ctx));
- if (sf != NULL) {
- dmar_unmap_pgtbl(sf,
- DMAR_IS_COHERENT(ctx->dmar));
- }
+ if (sf != NULL)
+ dmar_unmap_pgtbl(sf);
ctx_unmap_buf_locked(ctx, base1, base - base1, flags);
TD_PINNED_ASSERT;
return (ENOMEM);
}
dmar_pte_store(&pte->pte, VM_PAGE_TO_PHYS(ma[pi]) | pflags |
(superpage ? DMAR_PTE_SP : 0));
+ dmar_flush_pte_to_ram(ctx->dmar, pte);
sf_buf_page(sf)->wire_count += 1;
}
if (sf != NULL)
- dmar_unmap_pgtbl(sf, DMAR_IS_COHERENT(ctx->dmar));
+ dmar_unmap_pgtbl(sf);
TD_PINNED_ASSERT;
return (0);
}
@@ -567,9 +567,10 @@ ctx_unmap_clear_pte(struct dmar_ctx *ctx
vm_page_t m;
dmar_pte_clear(&pte->pte);
+ dmar_flush_pte_to_ram(ctx->dmar, pte);
m = sf_buf_page(*sf);
if (free_sf) {
- dmar_unmap_pgtbl(*sf, DMAR_IS_COHERENT(ctx->dmar));
+ dmar_unmap_pgtbl(*sf);
*sf = NULL;
}
m->wire_count--;
@@ -651,7 +652,7 @@ ctx_unmap_buf_locked(struct dmar_ctx *ct
(uintmax_t)base, (uintmax_t)size, (uintmax_t)pg_sz));
}
if (sf != NULL)
- dmar_unmap_pgtbl(sf, DMAR_IS_COHERENT(ctx->dmar));
+ dmar_unmap_pgtbl(sf);
/*
* See 11.1 Write Buffer Flushing for an explanation why RWBF
* can be ignored there.
Modified: stable/10/sys/x86/iommu/intel_utils.c
==============================================================================
--- stable/10/sys/x86/iommu/intel_utils.c Sun Jan 18 07:08:06 2015 (r277314)
+++ stable/10/sys/x86/iommu/intel_utils.c Sun Jan 18 09:49:32 2015 (r277315)
@@ -351,20 +351,46 @@ dmar_map_pgtbl(vm_object_t obj, vm_pinde
}
void
-dmar_unmap_pgtbl(struct sf_buf *sf, bool coherent)
+dmar_unmap_pgtbl(struct sf_buf *sf)
{
- vm_page_t m;
- m = sf_buf_page(sf);
sf_buf_free(sf);
sched_unpin();
+}
+
+static void
+dmar_flush_transl_to_ram(struct dmar_unit *unit, void *dst, size_t sz)
+{
+ if (DMAR_IS_COHERENT(unit))
+ return;
/*
* If DMAR does not snoop paging structures accesses, flush
* CPU cache to memory.
*/
- if (!coherent)
- pmap_invalidate_cache_pages(&m, 1);
+ pmap_invalidate_cache_range((uintptr_t)dst, (uintptr_t)dst + sz,
+ TRUE);
+}
+
+void
+dmar_flush_pte_to_ram(struct dmar_unit *unit, dmar_pte_t *dst)
+{
+
+ dmar_flush_transl_to_ram(unit, dst, sizeof(*dst));
+}
+
+void
+dmar_flush_ctx_to_ram(struct dmar_unit *unit, dmar_ctx_entry_t *dst)
+{
+
+ dmar_flush_transl_to_ram(unit, dst, sizeof(*dst));
+}
+
+void
+dmar_flush_root_to_ram(struct dmar_unit *unit, dmar_root_entry_t *dst)
+{
+
+ dmar_flush_transl_to_ram(unit, dst, sizeof(*dst));
}
/*
More information about the svn-src-stable
mailing list