From 51fdb79fd4ed39cf89e666e26493b649b3515def Mon Sep 17 00:00:00 2001 From: kettenis Date: Sat, 12 Jul 2008 13:08:04 +0000 Subject: [PATCH] Perform IOMMU cache flushes on Oberon. --- sys/arch/sparc64/dev/iommu.c | 27 +++++++++++++++++++++++---- sys/arch/sparc64/dev/iommureg.h | 9 +++++++-- sys/arch/sparc64/dev/iommuvar.h | 4 +++- sys/arch/sparc64/dev/psychoreg.h | 4 ++-- sys/arch/sparc64/dev/pyro.c | 6 +++++- sys/arch/sparc64/dev/schizoreg.h | 7 +++---- 6 files changed, 43 insertions(+), 14 deletions(-) diff --git a/sys/arch/sparc64/dev/iommu.c b/sys/arch/sparc64/dev/iommu.c index c9ef4eb2210..50da7b37b2a 100644 --- a/sys/arch/sparc64/dev/iommu.c +++ b/sys/arch/sparc64/dev/iommu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: iommu.c,v 1.49 2007/12/15 18:08:07 deraadt Exp $ */ +/* $OpenBSD: iommu.c,v 1.50 2008/07/12 13:08:04 kettenis Exp $ */ /* $NetBSD: iommu.c,v 1.47 2002/02/08 20:03:45 eeh Exp $ */ /* @@ -263,6 +263,9 @@ iommu_reset(struct iommu_state *is) if (sb->sb_flush) printf(", STC%d enabled", i); } + + if (is->is_flags & IOMMU_FLUSH_CACHE) + IOMMUREG_WRITE(is, iommu_cache_invalidate, -1ULL); } /* @@ -1807,7 +1810,7 @@ iommu_iomap_load_map(struct iommu_state *is, struct iommu_map_state *ims, struct iommu_page_map *ipm = &ims->ims_map; struct iommu_page_entry *e; struct strbuf_ctl *sb = ims->ims_sb; - int i; + int i, slot; if (sb->sb_flush == NULL) flags &= ~BUS_DMA_STREAMING; @@ -1820,6 +1823,14 @@ iommu_iomap_load_map(struct iommu_state *is, struct iommu_map_state *ims, for (i = 0, e = ipm->ipm_map; i < ipm->ipm_pagecnt; ++i, ++e) { e->ipe_va = vmaddr; iommu_enter(is, sb, e->ipe_va, e->ipe_pa, flags); + + /* Flush cache if necessary. */ + slot = IOTSBSLOT(e->ipe_va, is->is_tsbsize); + if (is->is_flags & IOMMU_FLUSH_CACHE && + (i == (ipm->ipm_pagecnt - 1) || (slot % 8) == 7)) + IOMMUREG_WRITE(is, iommu_cache_flush, + is->is_ptsb + slot * 8); + vmaddr += PAGE_SIZE; } @@ -1835,11 +1846,19 @@ iommu_iomap_unload_map(struct iommu_state *is, struct iommu_map_state *ims) struct iommu_page_map *ipm = &ims->ims_map; struct iommu_page_entry *e; struct strbuf_ctl *sb = ims->ims_sb; - int i; + int i, slot; - for (i = 0, e = ipm->ipm_map; i < ipm->ipm_pagecnt; ++i, ++e) + for (i = 0, e = ipm->ipm_map; i < ipm->ipm_pagecnt; ++i, ++e) { iommu_remove(is, sb, e->ipe_va); + /* Flush cache if necessary. */ + slot = IOTSBSLOT(e->ipe_va, is->is_tsbsize); + if (is->is_flags & IOMMU_FLUSH_CACHE && + (i == (ipm->ipm_pagecnt - 1) || (slot % 8) == 7)) + IOMMUREG_WRITE(is, iommu_cache_flush, + is->is_ptsb + slot * 8); + } + return (0); } diff --git a/sys/arch/sparc64/dev/iommureg.h b/sys/arch/sparc64/dev/iommureg.h index 53cc1de104a..153c058cf36 100644 --- a/sys/arch/sparc64/dev/iommureg.h +++ b/sys/arch/sparc64/dev/iommureg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: iommureg.h,v 1.15 2007/05/29 09:53:59 sobrado Exp $ */ +/* $OpenBSD: iommureg.h,v 1.16 2008/07/12 13:08:04 kettenis Exp $ */ /* $NetBSD: iommureg.h,v 1.6 2001/07/20 00:07:13 eeh Exp $ */ /* @@ -54,6 +54,11 @@ struct iommureg { volatile u_int64_t iommu_cr; /* IOMMU control register */ volatile u_int64_t iommu_tsb; /* IOMMU TSB base register */ volatile u_int64_t iommu_flush; /* IOMMU flush register */ + volatile u_int64_t iommu_ctxflush; + volatile u_int64_t iommu_reserved[28]; + volatile u_int64_t iommu_cache_flush; + volatile u_int64_t iommu_cache_invalidate; + volatile u_int64_t iommu_reserved2[30]; }; /* streaming buffer registers */ @@ -94,7 +99,7 @@ struct iommu_strbuf { #define IOTTE_STREAM 0x1000000000000000LL /* Is page streamable? */ #define IOTTE_LOCAL 0x0800000000000000LL /* Accesses to same bus segment? */ #define IOTTE_CONTEXT 0x07ff800000000000LL /* context number */ -#define IOTTE_PAMASK 0x000007ffffffe000LL /* Let's assume this is correct (bits 42..13) */ +#define IOTTE_PAMASK 0x00007fffffffe000LL /* Let's assume this is correct (bits 42..13) */ #define IOTTE_C 0x0000000000000010LL /* Accesses to cacheable space */ #define IOTTE_W 0x0000000000000002LL /* Writeable */ #define IOTTE_SOFTWARE 0x0000000000001f80LL /* For software use (bits 12..7) */ diff --git a/sys/arch/sparc64/dev/iommuvar.h b/sys/arch/sparc64/dev/iommuvar.h index 390f2d697bb..99d233b82de 100644 --- a/sys/arch/sparc64/dev/iommuvar.h +++ b/sys/arch/sparc64/dev/iommuvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: iommuvar.h,v 1.12 2008/03/09 19:27:56 kettenis Exp $ */ +/* $OpenBSD: iommuvar.h,v 1.13 2008/07/12 13:08:04 kettenis Exp $ */ /* $NetBSD: iommuvar.h,v 1.9 2001/10/07 20:30:41 eeh Exp $ */ /* @@ -110,6 +110,8 @@ struct iommu_state { int64_t is_cr; /* Control register value */ struct mutex is_mtx; struct extent *is_dvmamap; /* DVMA map for this instance */ + int is_flags; +#define IOMMU_FLUSH_CACHE 0x00000001 struct strbuf_ctl *is_sb[2]; /* Streaming buffers if any */ diff --git a/sys/arch/sparc64/dev/psychoreg.h b/sys/arch/sparc64/dev/psychoreg.h index 94e297588da..93a01382129 100644 --- a/sys/arch/sparc64/dev/psychoreg.h +++ b/sys/arch/sparc64/dev/psychoreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: psychoreg.h,v 1.11 2006/02/06 17:19:31 jmc Exp $ */ +/* $OpenBSD: psychoreg.h,v 1.12 2008/07/12 13:08:04 kettenis Exp $ */ /* $NetBSD: psychoreg.h,v 1.6.4.2 2001/09/13 01:14:40 thorpej Exp $ */ /* @@ -85,7 +85,7 @@ struct psychoreg { struct iommureg psy_iommu; /* 1fe.0000.0200,0210 */ - u_int64_t pad3[317]; + u_int64_t pad3[256]; u_int64_t pcia_slot0_int; /* PCI bus a slot 0 irq map reg */ /* 1fe.0000.0c00 */ u_int64_t pcia_slot1_int; /* PCI bus a slot 1 irq map reg */ /* 1fe.0000.0c08 */ diff --git a/sys/arch/sparc64/dev/pyro.c b/sys/arch/sparc64/dev/pyro.c index dad704e0491..5570e623027 100644 --- a/sys/arch/sparc64/dev/pyro.c +++ b/sys/arch/sparc64/dev/pyro.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pyro.c,v 1.13 2008/07/12 12:21:04 kettenis Exp $ */ +/* $OpenBSD: pyro.c,v 1.14 2008/07/12 13:08:04 kettenis Exp $ */ /* * Copyright (c) 2002 Jason L. Wright (jason@thought.net) @@ -240,6 +240,10 @@ pyro_init_iommu(struct pyro_softc *sc, struct pyro_pbm *pbm) panic("couldn't malloc iommu name"); snprintf(name, 32, "%s dvma", sc->sc_dv.dv_xname); + /* On Oberon, we need to flush the cache. */ + if (sc->sc_oberon) + is->is_flags |= IOMMU_FLUSH_CACHE; + iommu_init(name, is, tsbsize, iobase); } diff --git a/sys/arch/sparc64/dev/schizoreg.h b/sys/arch/sparc64/dev/schizoreg.h index ef4d5dabcf1..af4344e8026 100644 --- a/sys/arch/sparc64/dev/schizoreg.h +++ b/sys/arch/sparc64/dev/schizoreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: schizoreg.h,v 1.19 2008/02/10 12:53:01 kettenis Exp $ */ +/* $OpenBSD: schizoreg.h,v 1.20 2008/07/12 13:08:04 kettenis Exp $ */ /* * Copyright (c) 2002 Jason L. Wright (jason@thought.net) @@ -27,9 +27,8 @@ */ struct schizo_pbm_regs { volatile u_int64_t _unused1[64]; /* 0x0000 - 0x01ff */ - struct iommureg iommu; /* 0x0200 - 0x0217 */ - volatile u_int64_t iommu_ctxflush; /* 0x0218 - 0x021f */ - volatile u_int64_t _unused2[444]; + struct iommureg iommu; /* 0x0200 - 0x03ff */ + volatile u_int64_t _unused2[384]; volatile u_int64_t imap[64]; volatile u_int64_t _unused3[64]; volatile u_int64_t iclr[64]; -- 2.20.1