1*36fd90dcSjsg /* $OpenBSD: iommuvar.h,v 1.19 2021/03/11 11:17:00 jsg Exp $ */ 2296d8018Sjason /* $NetBSD: iommuvar.h,v 1.9 2001/10/07 20:30:41 eeh Exp $ */ 32a7ff519Sjason 42a7ff519Sjason /* 5745b6152Shenric * Copyright (c) 2003 Henric Jungheim 62a7ff519Sjason * Copyright (c) 1999 Matthew R. Green 72a7ff519Sjason * All rights reserved. 82a7ff519Sjason * 92a7ff519Sjason * Redistribution and use in source and binary forms, with or without 102a7ff519Sjason * modification, are permitted provided that the following conditions 112a7ff519Sjason * are met: 122a7ff519Sjason * 1. Redistributions of source code must retain the above copyright 132a7ff519Sjason * notice, this list of conditions and the following disclaimer. 142a7ff519Sjason * 2. Redistributions in binary form must reproduce the above copyright 152a7ff519Sjason * notice, this list of conditions and the following disclaimer in the 162a7ff519Sjason * documentation and/or other materials provided with the distribution. 172a7ff519Sjason * 3. The name of the author may not be used to endorse or promote products 182a7ff519Sjason * derived from this software without specific prior written permission. 192a7ff519Sjason * 202a7ff519Sjason * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 212a7ff519Sjason * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 222a7ff519Sjason * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 232a7ff519Sjason * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 242a7ff519Sjason * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 252a7ff519Sjason * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 262a7ff519Sjason * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 272a7ff519Sjason * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 282a7ff519Sjason * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 292a7ff519Sjason * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 302a7ff519Sjason * SUCH DAMAGE. 312a7ff519Sjason */ 322a7ff519Sjason 332a7ff519Sjason #ifndef _SPARC64_DEV_IOMMUVAR_H_ 342a7ff519Sjason #define _SPARC64_DEV_IOMMUVAR_H_ 352a7ff519Sjason 36745b6152Shenric #ifndef _SYS_TREE_H_ 37745b6152Shenric #include <sys/tree.h> 38745b6152Shenric #endif 39745b6152Shenric 402f23c37cSkettenis #include <sys/extent.h> 41e2a0f4edSderaadt #include <sys/mutex.h> 42e2a0f4edSderaadt 432a7ff519Sjason /* 44eb79e960Shenric * per-Streaming Buffer state 45eb79e960Shenric */ 46eb79e960Shenric struct strbuf_ctl { 47eb79e960Shenric bus_space_tag_t sb_bustag; /* streaming buffer registers */ 48eb79e960Shenric bus_space_handle_t sb_sb; /* Handle for our regs */ 49745b6152Shenric struct iommu_state *sb_iommu; /* Associated IOMMU */ 50745b6152Shenric /* 51745b6152Shenric * Since implementing the per-map IOMMU state, these per-STC 52745b6152Shenric * flush areas are not used other than as a boolean flag to indicate 53745b6152Shenric * the presence of a working and enabled STC. For inconsistency's 54745b6152Shenric * sake, the "sb" pointers of iommu_state are sometimes used for the 55*36fd90dcSjsg * same purpose. This should be consolidated. DEFINITELY, since 56e2a0f4edSderaadt * mutex operations must happen at this level. 57745b6152Shenric */ 58e2a0f4edSderaadt struct mutex sb_mtx; /* one flush at a time */ 59e2a0f4edSderaadt 60eb79e960Shenric paddr_t sb_flushpa; /* to flush streaming buffers */ 61eb79e960Shenric volatile int64_t *sb_flush; 62eb79e960Shenric }; 63eb79e960Shenric 64eb79e960Shenric /* 65745b6152Shenric * per-map STC flush area 66745b6152Shenric */ 67745b6152Shenric struct strbuf_flush { 68745b6152Shenric char sbf_area[0x80]; /* Holds 64-byte long/aligned buffer */ 69745b6152Shenric void *sbf_flush; /* Kernel virtual address of buffer */ 70745b6152Shenric paddr_t sbf_flushpa; /* Physical address of buffer area */ 71745b6152Shenric }; 72745b6152Shenric 73745b6152Shenric /* 74745b6152Shenric * per-map DVMA page table 75745b6152Shenric */ 76745b6152Shenric struct iommu_page_entry { 77745b6152Shenric SPLAY_ENTRY(iommu_page_entry) ipe_node; 78745b6152Shenric paddr_t ipe_pa; 7941dd5daeSoga bus_addr_t ipe_va; 80745b6152Shenric }; 81745b6152Shenric struct iommu_page_map { 82745b6152Shenric SPLAY_HEAD(iommu_page_tree, iommu_page_entry) ipm_tree; 83745b6152Shenric int ipm_maxpage; /* Size of allocated page map */ 84745b6152Shenric int ipm_pagecnt; /* Number of entries in use */ 85745b6152Shenric struct iommu_page_entry ipm_map[1]; 86745b6152Shenric }; 87745b6152Shenric 88745b6152Shenric /* 89745b6152Shenric * per-map IOMMU state 90745b6152Shenric * 91745b6152Shenric * This is what bus_dvmamap_t'c _dm_cookie should be pointing to. 92745b6152Shenric */ 93745b6152Shenric struct iommu_map_state { 94745b6152Shenric struct strbuf_flush ims_flush; /* flush should be first (alignment) */ 95745b6152Shenric struct strbuf_ctl *ims_sb; /* Link to parent */ 9652a32323Skettenis struct iommu_state *ims_iommu; 97745b6152Shenric int ims_flags; 982f23c37cSkettenis struct extent_region ims_er; 99745b6152Shenric struct iommu_page_map ims_map; /* map must be last (array at end) */ 100745b6152Shenric }; 101745b6152Shenric #define IOMMU_MAP_STREAM 1 102745b6152Shenric 103630edadfSdlg struct iommu_hw { 104630edadfSdlg void (*ihw_enable)(struct iommu_state *); 105630edadfSdlg 106630edadfSdlg unsigned long ihw_dvma_pa; 107630edadfSdlg 108630edadfSdlg unsigned long ihw_bypass; 109630edadfSdlg unsigned long ihw_bypass_nc; /* non-cached */ 110630edadfSdlg unsigned long ihw_bypass_ro; /* relaxed ordering */ 111630edadfSdlg 112630edadfSdlg unsigned int ihw_flags; 113630edadfSdlg #define IOMMU_HW_FLUSH_CACHE (1 << 0) 114630edadfSdlg }; 115630edadfSdlg 116630edadfSdlg extern const struct iommu_hw iommu_hw_default; 117630edadfSdlg 118745b6152Shenric /* 1192a7ff519Sjason * per-IOMMU state 1202a7ff519Sjason */ 1212a7ff519Sjason struct iommu_state { 1222a7ff519Sjason paddr_t is_ptsb; /* TSB physical address */ 1232a7ff519Sjason int64_t *is_tsb; /* TSB virtual address */ 1242a7ff519Sjason int is_tsbsize; /* 0 = 8K, ... */ 1252a7ff519Sjason u_int is_dvmabase; 126e580baadSjason u_int is_dvmaend; 127745b6152Shenric int64_t is_cr; /* Control register value */ 128e2a0f4edSderaadt struct mutex is_mtx; 1292a7ff519Sjason struct extent *is_dvmamap; /* DVMA map for this instance */ 130630edadfSdlg const struct iommu_hw *is_hw; 1312a7ff519Sjason 132eb79e960Shenric struct strbuf_ctl *is_sb[2]; /* Streaming buffers if any */ 1332a7ff519Sjason 134bdd819b7Skettenis paddr_t is_scratch; /* Scratch page */ 135bdd819b7Skettenis 1362a7ff519Sjason /* copies of our parents state, to allow us to be self contained */ 1372a7ff519Sjason bus_space_tag_t is_bustag; /* our bus tag */ 138eb79e960Shenric bus_space_handle_t is_iommu; /* IOMMU registers */ 13952a32323Skettenis uint64_t is_devhandle; 1402a7ff519Sjason }; 1412a7ff519Sjason 142d277156aSsobrado /* interfaces for PCI/SBus code */ 143630edadfSdlg void iommu_init(char *, const struct iommu_hw *, struct iommu_state *, 144630edadfSdlg int, u_int32_t); 145c4071fd1Smillert void iommu_reset(struct iommu_state *); 14641dd5daeSoga paddr_t iommu_extract(struct iommu_state *, bus_addr_t); 14741dd5daeSoga int64_t iommu_lookup_tte(struct iommu_state *, bus_addr_t); 148745b6152Shenric int64_t iommu_fetch_tte(struct iommu_state *, paddr_t); 14958fd28b8Shenric /* bus_dma_tag_t implementation functions */ 15058fd28b8Shenric int iommu_dvmamap_create(bus_dma_tag_t, bus_dma_tag_t, struct strbuf_ctl *, 15158fd28b8Shenric bus_size_t, int, bus_size_t, bus_size_t, int, bus_dmamap_t *); 15258fd28b8Shenric void iommu_dvmamap_destroy(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t); 15358fd28b8Shenric int iommu_dvmamap_load(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t, void *, 15458fd28b8Shenric bus_size_t, struct proc *, int); 15558fd28b8Shenric void iommu_dvmamap_unload(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t); 15658fd28b8Shenric int iommu_dvmamap_load_raw(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t, 15758fd28b8Shenric bus_dma_segment_t *, int, bus_size_t, int); 15858fd28b8Shenric void iommu_dvmamap_sync(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t, 159745b6152Shenric bus_addr_t, bus_size_t, int); 16058fd28b8Shenric int iommu_dvmamem_alloc(bus_dma_tag_t, bus_dma_tag_t, bus_size_t, 16158fd28b8Shenric bus_size_t, bus_size_t, bus_dma_segment_t *, int, int *, int); 16258fd28b8Shenric void iommu_dvmamem_free(bus_dma_tag_t, bus_dma_tag_t, bus_dma_segment_t *, 16358fd28b8Shenric int); 1642a7ff519Sjason 165eb79e960Shenric #define IOMMUREG_READ(is, reg) \ 166eb79e960Shenric bus_space_read_8((is)->is_bustag, \ 167eb79e960Shenric (is)->is_iommu, \ 168eb79e960Shenric IOMMUREG(reg)) 169eb79e960Shenric 170eb79e960Shenric #define IOMMUREG_WRITE(is, reg, v) \ 171eb79e960Shenric bus_space_write_8((is)->is_bustag, \ 172eb79e960Shenric (is)->is_iommu, \ 173eb79e960Shenric IOMMUREG(reg), \ 174eb79e960Shenric (v)) 175eb79e960Shenric 1762a7ff519Sjason #endif /* _SPARC64_DEV_IOMMUVAR_H_ */ 177eb79e960Shenric 178