1 /* $NetBSD: mmu_sh3.c,v 1.5 2002/05/09 12:27:04 uch Exp $ */ 2 3 /*- 4 * Copyright (c) 2002 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by UCHIYAMA Yasushi. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 42 #include <sh3/pte.h> /* NetBSD/sh3 specific PTE */ 43 #include <sh3/mmu.h> 44 #include <sh3/mmu_sh3.h> 45 46 void 47 sh3_mmu_start() 48 { 49 50 /* Zero clear all TLB entry */ 51 sh3_tlb_invalidate_all(); 52 53 /* Set current ASID to 0 */ 54 sh_tlb_set_asid(0); 55 56 _reg_write_4(SH3_MMUCR, SH3_MMUCR_AT | SH3_MMUCR_TF); 57 } 58 59 void 60 sh3_tlb_invalidate_addr(int asid, vaddr_t va) 61 { 62 u_int32_t a, d; 63 int w; 64 65 d = (va & SH3_MMUAA_D_VPN_MASK_4K) | asid; /* 4K page */ 66 va = va & SH3_MMU_VPN_MASK; /* [16:12] entry index */ 67 68 /* Probe entry and invalidate it. */ 69 for (w = 0; w < SH3_MMU_WAY; w++) { 70 a = va | (w << SH3_MMU_WAY_SHIFT); /* way [9:8] */ 71 if ((_reg_read_4(SH3_MMUAA | a) & 72 (SH3_MMUAA_D_VPN_MASK_4K | SH3_MMUAA_D_ASID_MASK)) == d) { 73 _reg_write_4(SH3_MMUAA | a, 0); 74 break; 75 } 76 } 77 } 78 79 void 80 sh3_tlb_invalidate_asid(int asid) 81 { 82 u_int32_t aw, a; 83 int e, w; 84 85 /* Invalidate entry attribute to ASID */ 86 for (w = 0; w < SH3_MMU_WAY; w++) { 87 aw = (w << SH3_MMU_WAY_SHIFT); 88 for (e = 0; e < SH3_MMU_ENTRY; e++) { 89 a = aw | (e << SH3_MMU_VPN_SHIFT); 90 if ((_reg_read_4(SH3_MMUAA | a) & 91 SH3_MMUAA_D_ASID_MASK) == asid) { 92 _reg_write_4(SH3_MMUAA | a, 0); 93 } 94 } 95 } 96 } 97 98 void 99 sh3_tlb_invalidate_all() 100 { 101 u_int32_t aw, a; 102 int e, w; 103 104 /* Zero clear all TLB entry to avoid unexpected VPN match. */ 105 for (w = 0; w < SH3_MMU_WAY; w++) { 106 aw = (w << SH3_MMU_WAY_SHIFT); 107 for (e = 0; e < SH3_MMU_ENTRY; e++) { 108 a = aw | (e << SH3_MMU_VPN_SHIFT); 109 _reg_write_4(SH3_MMUAA | a, 0); 110 _reg_write_4(SH3_MMUDA | a, 0); 111 } 112 } 113 } 114 115 void 116 sh3_tlb_update(int asid, vaddr_t va, u_int32_t pte) 117 { 118 u_int32_t oasid; 119 120 KDASSERT(asid < 0x100 && (pte & ~PGOFSET) != 0 && va != 0); 121 122 /* Save old ASID */ 123 oasid = _reg_read_4(SH3_PTEH) & SH3_PTEH_ASID_MASK; 124 125 /* Invalidate old entry (if any) */ 126 sh3_tlb_invalidate_addr(asid, va); 127 128 /* Load new entry */ 129 _reg_write_4(SH3_PTEH, (va & ~PGOFSET) | asid); 130 _reg_write_4(SH3_PTEL, pte & PG_HW_BITS); 131 __asm__ __volatile__("ldtlb"); 132 133 /* Restore old ASID */ 134 if (asid != oasid) 135 _reg_write_4(SH3_PTEH, oasid); 136 } 137