cpufunc.h revision 241374
1178172Simp/* $OpenBSD: pio.h,v 1.2 1998/09/15 10:50:12 pefo Exp $ */ 2178172Simp 3206713Sjmallett/*- 4206713Sjmallett * Copyright (c) 2002-2004 Juli Mallett. All rights reserved. 5206713Sjmallett * 6206713Sjmallett * Redistribution and use in source and binary forms, with or without 7206713Sjmallett * modification, are permitted provided that the following conditions 8206713Sjmallett * are met: 9206713Sjmallett * 1. Redistributions of source code must retain the above copyright 10206713Sjmallett * notice, this list of conditions and the following disclaimer. 11206713Sjmallett * 2. Redistributions in binary form must reproduce the above copyright 12206713Sjmallett * notice, this list of conditions and the following disclaimer in the 13206713Sjmallett * documentation and/or other materials provided with the distribution. 14206713Sjmallett * 15206713Sjmallett * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16206713Sjmallett * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17206713Sjmallett * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18206713Sjmallett * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19206713Sjmallett * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20206713Sjmallett * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21206713Sjmallett * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22206713Sjmallett * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23206713Sjmallett * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24206713Sjmallett * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25206713Sjmallett * SUCH DAMAGE. 26206713Sjmallett */ 27178172Simp/* 28178172Simp * Copyright (c) 1995-1999 Per Fogelstrom. All rights reserved. 29178172Simp * 30178172Simp * Redistribution and use in source and binary forms, with or without 31178172Simp * modification, are permitted provided that the following conditions 32178172Simp * are met: 33178172Simp * 1. Redistributions of source code must retain the above copyright 34178172Simp * notice, this list of conditions and the following disclaimer. 35178172Simp * 2. Redistributions in binary form must reproduce the above copyright 36178172Simp * notice, this list of conditions and the following disclaimer in the 37178172Simp * documentation and/or other materials provided with the distribution. 38178172Simp * 3. All advertising materials mentioning features or use of this software 39178172Simp * must display the following acknowledgement: 40178172Simp * This product includes software developed by Per Fogelstrom. 41178172Simp * 4. The name of the author may not be used to endorse or promote products 42178172Simp * derived from this software without specific prior written permission 43178172Simp * 44178172Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 45178172Simp * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 46178172Simp * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 47178172Simp * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 48178172Simp * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 49178172Simp * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 50178172Simp * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 51178172Simp * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 52178172Simp * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 53178172Simp * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 54178172Simp * 55178172Simp * JNPR: cpufunc.h,v 1.5 2007/08/09 11:23:32 katta 56178172Simp * $FreeBSD: head/sys/mips/include/cpufunc.h 241374 2012-10-09 14:32:30Z attilio $ 57178172Simp */ 58178172Simp 59178172Simp#ifndef _MACHINE_CPUFUNC_H_ 60178172Simp#define _MACHINE_CPUFUNC_H_ 61178172Simp 62178172Simp#include <sys/types.h> 63178172Simp#include <machine/cpuregs.h> 64178172Simp 65178172Simp/* 66178172Simp * These functions are required by user-land atomi ops 67178172Simp */ 68178172Simp 69178172Simpstatic __inline void 70178172Simpmips_barrier(void) 71178172Simp{ 72227658Sjchandra#if defined(CPU_CNMIPS) || defined(CPU_RMI) || defined(CPU_NLM) 73241374Sattilio __compiler_membar(); 74218383Sjmallett#else 75178172Simp __asm __volatile (".set noreorder\n\t" 76178172Simp "nop\n\t" 77178172Simp "nop\n\t" 78178172Simp "nop\n\t" 79178172Simp "nop\n\t" 80178172Simp "nop\n\t" 81178172Simp "nop\n\t" 82178172Simp "nop\n\t" 83178172Simp "nop\n\t" 84178172Simp ".set reorder\n\t" 85178172Simp : : : "memory"); 86218383Sjmallett#endif 87178172Simp} 88178172Simp 89178172Simpstatic __inline void 90206713Sjmallettmips_cp0_sync(void) 91206713Sjmallett{ 92206713Sjmallett __asm __volatile (__XSTRING(COP0_SYNC)); 93206713Sjmallett} 94206713Sjmallett 95206713Sjmallettstatic __inline void 96178172Simpmips_wbflush(void) 97178172Simp{ 98218383Sjmallett#if defined(CPU_CNMIPS) 99218383Sjmallett __asm __volatile (".set noreorder\n\t" 100218383Sjmallett "syncw\n\t" 101218383Sjmallett ".set reorder\n" 102218383Sjmallett : : : "memory"); 103218383Sjmallett#else 104178172Simp __asm __volatile ("sync" : : : "memory"); 105178172Simp mips_barrier(); 106218383Sjmallett#endif 107178172Simp} 108178172Simp 109178172Simp#ifdef _KERNEL 110216947Sjmallett/* 111216947Sjmallett * XXX 112216947Sjmallett * It would be nice to add variants that read/write register_t, to avoid some 113216947Sjmallett * ABI checks. 114216947Sjmallett */ 115206713Sjmallett#if defined(__mips_n32) || defined(__mips_n64) 116216972Sjmallett#define MIPS_RW64_COP0(n,r) \ 117178172Simpstatic __inline uint64_t \ 118178172Simpmips_rd_ ## n (void) \ 119178172Simp{ \ 120178172Simp int v0; \ 121178172Simp __asm __volatile ("dmfc0 %[v0], $"__XSTRING(r)";" \ 122178172Simp : [v0] "=&r"(v0)); \ 123178172Simp mips_barrier(); \ 124178172Simp return (v0); \ 125178172Simp} \ 126178172Simpstatic __inline void \ 127178172Simpmips_wr_ ## n (uint64_t a0) \ 128178172Simp{ \ 129178172Simp __asm __volatile ("dmtc0 %[a0], $"__XSTRING(r)";" \ 130178172Simp __XSTRING(COP0_SYNC)";" \ 131178172Simp "nop;" \ 132178172Simp "nop;" \ 133178172Simp : \ 134178172Simp : [a0] "r"(a0)); \ 135178172Simp mips_barrier(); \ 136178172Simp} struct __hack 137178172Simp 138218383Sjmallett#define MIPS_RW64_COP0_SEL(n,r,s) \ 139218383Sjmallettstatic __inline uint64_t \ 140218383Sjmallettmips_rd_ ## n(void) \ 141218383Sjmallett{ \ 142218383Sjmallett int v0; \ 143218383Sjmallett __asm __volatile ("dmfc0 %[v0], $"__XSTRING(r)", "__XSTRING(s)";" \ 144218383Sjmallett : [v0] "=&r"(v0)); \ 145218383Sjmallett mips_barrier(); \ 146218383Sjmallett return (v0); \ 147218383Sjmallett} \ 148218383Sjmallettstatic __inline void \ 149218383Sjmallettmips_wr_ ## n(uint64_t a0) \ 150218383Sjmallett{ \ 151218383Sjmallett __asm __volatile ("dmtc0 %[a0], $"__XSTRING(r)", "__XSTRING(s)";" \ 152218383Sjmallett __XSTRING(COP0_SYNC)";" \ 153218383Sjmallett : \ 154218383Sjmallett : [a0] "r"(a0)); \ 155218383Sjmallett mips_barrier(); \ 156218383Sjmallett} struct __hack 157218383Sjmallett 158206713Sjmallett#if defined(__mips_n64) 159216972SjmallettMIPS_RW64_COP0(excpc, MIPS_COP_0_EXC_PC); 160216972SjmallettMIPS_RW64_COP0(entryhi, MIPS_COP_0_TLB_HI); 161216972SjmallettMIPS_RW64_COP0(pagemask, MIPS_COP_0_TLB_PG_MASK); 162218383Sjmallett#ifdef CPU_CNMIPS 163218383SjmallettMIPS_RW64_COP0_SEL(cvmcount, MIPS_COP_0_COUNT, 6); 164218383SjmallettMIPS_RW64_COP0_SEL(cvmctl, MIPS_COP_0_COUNT, 7); 165218383SjmallettMIPS_RW64_COP0_SEL(cvmmemctl, MIPS_COP_0_COMPARE, 7); 166218383SjmallettMIPS_RW64_COP0_SEL(icache_err, MIPS_COP_0_CACHE_ERR, 0); 167218383SjmallettMIPS_RW64_COP0_SEL(dcache_err, MIPS_COP_0_CACHE_ERR, 1); 168206713Sjmallett#endif 169218383Sjmallett#endif 170217354Sjchandra#if defined(__mips_n64) || defined(__mips_n32) /* PHYSADDR_64_BIT */ 171217354SjchandraMIPS_RW64_COP0(entrylo0, MIPS_COP_0_TLB_LO0); 172217354SjchandraMIPS_RW64_COP0(entrylo1, MIPS_COP_0_TLB_LO1); 173217354Sjchandra#endif 174216972SjmallettMIPS_RW64_COP0(xcontext, MIPS_COP_0_TLB_XCONTEXT); 175178172Simp 176216972Sjmallett#undef MIPS_RW64_COP0 177218383Sjmallett#undef MIPS_RW64_COP0_SEL 178178172Simp#endif 179178172Simp 180216972Sjmallett#define MIPS_RW32_COP0(n,r) \ 181178172Simpstatic __inline uint32_t \ 182178172Simpmips_rd_ ## n (void) \ 183178172Simp{ \ 184178172Simp int v0; \ 185178172Simp __asm __volatile ("mfc0 %[v0], $"__XSTRING(r)";" \ 186178172Simp : [v0] "=&r"(v0)); \ 187178172Simp mips_barrier(); \ 188178172Simp return (v0); \ 189178172Simp} \ 190178172Simpstatic __inline void \ 191178172Simpmips_wr_ ## n (uint32_t a0) \ 192178172Simp{ \ 193178172Simp __asm __volatile ("mtc0 %[a0], $"__XSTRING(r)";" \ 194178172Simp __XSTRING(COP0_SYNC)";" \ 195178172Simp "nop;" \ 196178172Simp "nop;" \ 197178172Simp : \ 198178172Simp : [a0] "r"(a0)); \ 199178172Simp mips_barrier(); \ 200178172Simp} struct __hack 201178172Simp 202216972Sjmallett#define MIPS_RW32_COP0_SEL(n,r,s) \ 203202031Simpstatic __inline uint32_t \ 204206829Sjmallettmips_rd_ ## n(void) \ 205202031Simp{ \ 206202031Simp int v0; \ 207202031Simp __asm __volatile ("mfc0 %[v0], $"__XSTRING(r)", "__XSTRING(s)";" \ 208202031Simp : [v0] "=&r"(v0)); \ 209202031Simp mips_barrier(); \ 210202031Simp return (v0); \ 211202031Simp} \ 212202031Simpstatic __inline void \ 213206829Sjmallettmips_wr_ ## n(uint32_t a0) \ 214202031Simp{ \ 215202031Simp __asm __volatile ("mtc0 %[a0], $"__XSTRING(r)", "__XSTRING(s)";" \ 216202031Simp __XSTRING(COP0_SYNC)";" \ 217202031Simp "nop;" \ 218202031Simp "nop;" \ 219202031Simp : \ 220202031Simp : [a0] "r"(a0)); \ 221202031Simp mips_barrier(); \ 222202031Simp} struct __hack 223202031Simp 224210311Sjmallett#ifdef CPU_CNMIPS 225178172Simpstatic __inline void mips_sync_icache (void) 226178172Simp{ 227202031Simp __asm __volatile ( 228202031Simp ".set push\n" 229202031Simp ".set mips64\n" 230202031Simp ".word 0x041f0000\n" /* xxx ICACHE */ 231202031Simp "nop\n" 232202031Simp ".set pop\n" 233202031Simp : : ); 234178172Simp} 235178172Simp#endif 236178172Simp 237216972SjmallettMIPS_RW32_COP0(compare, MIPS_COP_0_COMPARE); 238216972SjmallettMIPS_RW32_COP0(config, MIPS_COP_0_CONFIG); 239216972SjmallettMIPS_RW32_COP0_SEL(config1, MIPS_COP_0_CONFIG, 1); 240216972SjmallettMIPS_RW32_COP0_SEL(config2, MIPS_COP_0_CONFIG, 2); 241216972SjmallettMIPS_RW32_COP0_SEL(config3, MIPS_COP_0_CONFIG, 3); 242218383Sjmallett#ifdef CPU_CNMIPS 243218383SjmallettMIPS_RW32_COP0_SEL(config4, MIPS_COP_0_CONFIG, 4); 244218383Sjmallett#endif 245224115Sjchandra#ifdef CPU_NLM 246224115SjchandraMIPS_RW32_COP0_SEL(config6, MIPS_COP_0_CONFIG, 6); 247224115SjchandraMIPS_RW32_COP0_SEL(config7, MIPS_COP_0_CONFIG, 7); 248224115Sjchandra#endif 249216972SjmallettMIPS_RW32_COP0(count, MIPS_COP_0_COUNT); 250216972SjmallettMIPS_RW32_COP0(index, MIPS_COP_0_TLB_INDEX); 251216972SjmallettMIPS_RW32_COP0(wired, MIPS_COP_0_TLB_WIRED); 252216972SjmallettMIPS_RW32_COP0(cause, MIPS_COP_0_CAUSE); 253216947Sjmallett#if !defined(__mips_n64) 254216972SjmallettMIPS_RW32_COP0(excpc, MIPS_COP_0_EXC_PC); 255216947Sjmallett#endif 256216972SjmallettMIPS_RW32_COP0(status, MIPS_COP_0_STATUS); 257178172Simp 258178172Simp/* XXX: Some of these registers are specific to MIPS32. */ 259206713Sjmallett#if !defined(__mips_n64) 260216972SjmallettMIPS_RW32_COP0(entryhi, MIPS_COP_0_TLB_HI); 261216972SjmallettMIPS_RW32_COP0(pagemask, MIPS_COP_0_TLB_PG_MASK); 262206713Sjmallett#endif 263227782Sjchandra#ifdef CPU_NLM 264227782SjchandraMIPS_RW32_COP0_SEL(pagegrain, MIPS_COP_0_TLB_PG_MASK, 1); 265227782Sjchandra#endif 266217354Sjchandra#if !defined(__mips_n64) && !defined(__mips_n32) /* !PHYSADDR_64_BIT */ 267217354SjchandraMIPS_RW32_COP0(entrylo0, MIPS_COP_0_TLB_LO0); 268217354SjchandraMIPS_RW32_COP0(entrylo1, MIPS_COP_0_TLB_LO1); 269217354Sjchandra#endif 270216972SjmallettMIPS_RW32_COP0(prid, MIPS_COP_0_PRID); 271206713Sjmallett/* XXX 64-bit? */ 272216972SjmallettMIPS_RW32_COP0_SEL(ebase, MIPS_COP_0_PRID, 1); 273216972SjmallettMIPS_RW32_COP0(watchlo, MIPS_COP_0_WATCH_LO); 274216972SjmallettMIPS_RW32_COP0_SEL(watchlo1, MIPS_COP_0_WATCH_LO, 1); 275216972SjmallettMIPS_RW32_COP0_SEL(watchlo2, MIPS_COP_0_WATCH_LO, 2); 276216972SjmallettMIPS_RW32_COP0_SEL(watchlo3, MIPS_COP_0_WATCH_LO, 3); 277216972SjmallettMIPS_RW32_COP0(watchhi, MIPS_COP_0_WATCH_HI); 278216972SjmallettMIPS_RW32_COP0_SEL(watchhi1, MIPS_COP_0_WATCH_HI, 1); 279216972SjmallettMIPS_RW32_COP0_SEL(watchhi2, MIPS_COP_0_WATCH_HI, 2); 280216972SjmallettMIPS_RW32_COP0_SEL(watchhi3, MIPS_COP_0_WATCH_HI, 3); 281204635Sgnn 282216972SjmallettMIPS_RW32_COP0_SEL(perfcnt0, MIPS_COP_0_PERFCNT, 0); 283216972SjmallettMIPS_RW32_COP0_SEL(perfcnt1, MIPS_COP_0_PERFCNT, 1); 284216972SjmallettMIPS_RW32_COP0_SEL(perfcnt2, MIPS_COP_0_PERFCNT, 2); 285216972SjmallettMIPS_RW32_COP0_SEL(perfcnt3, MIPS_COP_0_PERFCNT, 3); 286204635Sgnn 287216972Sjmallett#undef MIPS_RW32_COP0 288216972Sjmallett#undef MIPS_RW32_COP0_SEL 289178172Simp 290178172Simpstatic __inline register_t 291178172Simpintr_disable(void) 292178172Simp{ 293178172Simp register_t s; 294178172Simp 295178172Simp s = mips_rd_status(); 296178172Simp mips_wr_status(s & ~MIPS_SR_INT_IE); 297178172Simp 298206713Sjmallett return (s & MIPS_SR_INT_IE); 299178172Simp} 300178172Simp 301178172Simpstatic __inline register_t 302178172Simpintr_enable(void) 303178172Simp{ 304178172Simp register_t s; 305178172Simp 306178172Simp s = mips_rd_status(); 307178172Simp mips_wr_status(s | MIPS_SR_INT_IE); 308178172Simp 309178172Simp return (s); 310178172Simp} 311178172Simp 312206713Sjmallettstatic __inline void 313206713Sjmallettintr_restore(register_t ie) 314206713Sjmallett{ 315206713Sjmallett if (ie == MIPS_SR_INT_IE) { 316206713Sjmallett intr_enable(); 317206713Sjmallett } 318206713Sjmallett} 319178172Simp 320212532Sjchandrastatic __inline uint32_t 321212532Sjchandraset_intr_mask(uint32_t mask) 322212532Sjchandra{ 323212532Sjchandra uint32_t ostatus; 324212532Sjchandra 325212532Sjchandra ostatus = mips_rd_status(); 326212632Sneel mask = (ostatus & ~MIPS_SR_INT_MASK) | (mask & MIPS_SR_INT_MASK); 327212532Sjchandra mips_wr_status(mask); 328212532Sjchandra return (ostatus); 329212532Sjchandra} 330212532Sjchandra 331212532Sjchandrastatic __inline uint32_t 332212532Sjchandraget_intr_mask(void) 333212532Sjchandra{ 334212532Sjchandra 335212532Sjchandra return (mips_rd_status() & MIPS_SR_INT_MASK); 336212532Sjchandra} 337212532Sjchandra 338178172Simpstatic __inline void 339178172Simpbreakpoint(void) 340178172Simp{ 341178172Simp __asm __volatile ("break"); 342178172Simp} 343178172Simp 344205675Sneel#if defined(__GNUC__) && !defined(__mips_o32) 345232872Sjmallett#define mips3_ld(a) (*(const volatile uint64_t *)(a)) 346232872Sjmallett#define mips3_sd(a, v) (*(volatile uint64_t *)(a) = (v)) 347205675Sneel#else 348205675Sneeluint64_t mips3_ld(volatile uint64_t *va); 349205675Sneelvoid mips3_sd(volatile uint64_t *, uint64_t); 350205675Sneel#endif /* __GNUC__ */ 351205675Sneel 352178172Simp#endif /* _KERNEL */ 353178172Simp 354178172Simp#define readb(va) (*(volatile uint8_t *) (va)) 355178172Simp#define readw(va) (*(volatile uint16_t *) (va)) 356178172Simp#define readl(va) (*(volatile uint32_t *) (va)) 357178172Simp 358178172Simp#define writeb(va, d) (*(volatile uint8_t *) (va) = (d)) 359178172Simp#define writew(va, d) (*(volatile uint16_t *) (va) = (d)) 360178172Simp#define writel(va, d) (*(volatile uint32_t *) (va) = (d)) 361178172Simp 362178172Simp#endif /* !_MACHINE_CPUFUNC_H_ */ 363