1/* $NetBSD: locore_octeon.S,v 1.14 2022/07/20 10:07:49 riastradh Exp $ */ 2 3/* 4 * Copyright (c) 2007 Internet Initiative Japan, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include <mips/asm.h> 30RCSID("$NetBSD: locore_octeon.S,v 1.14 2022/07/20 10:07:49 riastradh Exp $") 31 32#include "cpunode.h" /* for NWDOG */ 33#include "opt_cputype.h" 34#include "opt_ddb.h" 35#include "opt_multiprocessor.h" 36 37#include <mips/cpuregs.h> 38#include <arch/mips/cavium/dev/octeon_corereg.h> 39 40RCSID("$NetBSD: locore_octeon.S,v 1.14 2022/07/20 10:07:49 riastradh Exp $") 41 42#include "assym.h" 43 44#define _CP0_READ64(_cp0) \ 45 dmfc0 v0, _cp0; \ 46 j ra; \ 47 nop 48 49#define _CP0_WRITE64(_cp0) \ 50 dmtc0 a0, _cp0; \ 51 j ra; \ 52 nop 53 54 .set noreorder 55 .set noat 56 .set arch=octeon 57 58 .text 59 60LEAF(mips_cp0_cvmctl_read) 61 _CP0_READ64(MIPS_COP_0_CVMCTL) 62END(mips_cp0_cvmctl_read) 63 64#ifdef notyet /* the rest of these aren't used (yet) */ 65LEAF(mips_cp0_cvmctl_write) 66 _CP0_WRITE64(MIPS_COP_0_CVMCTL) 67END(mips_cp0_cvmctl_write) 68 69LEAF(mips_cp0_cvmmemctl_read) 70 _CP0_READ64(MIPS_COP_0_CVMMEMCTL) 71END(mips_cp0_cvmmemctl_read) 72 73LEAF(mips_cp0_cvmmemctl_write) 74 _CP0_WRITE64(MIPS_COP_0_CVMMEMCTL) 75END(mips_cp0_cvmmemctl_write) 76 77LEAF(mips_cp0_cvmcnt_read) 78 _CP0_READ64(MIPS_COP_0_CVMCNT) 79END(mips_cp0_cvmcnt_read) 80 81LEAF(mips_cp0_cvmcnt_write) 82 _CP0_WRITE64(MIPS_COP_0_CVMCNT) 83END(mips_cp0_cvmcnt_write) 84 85LEAF(mips_cp0_performance_counter_control0_read) 86 _CP0_READ64(MIPS_COP_0_PERFCNT0_CTL) 87END(mips_cp0_performance_counter_control0_read) 88 89LEAF(mips_cp0_performance_counter_control0_write) 90 _CP0_WRITE64(MIPS_COP_0_PERFCNT0_CTL) 91END(mips_cp0_performance_counter_control0_write) 92 93LEAF(mips_cp0_performance_counter_control1_read) 94 _CP0_READ64(MIPS_COP_0_PERFCNT1_CTL) 95END(mips_cp0_performance_counter_control1_read) 96 97LEAF(mips_cp0_performance_counter_control1_write) 98 _CP0_WRITE64(MIPS_COP_0_PERFCNT1_CTL) 99END(mips_cp0_performance_counter_control1_write) 100 101LEAF(mips_cp0_performance_counter_counter0_read) 102 _CP0_READ64(MIPS_COP_0_PERFCNT0_CNT) 103END(mips_cp0_performance_counter_counter0_read) 104 105LEAF(mips_cp0_performance_counter_counter0_write) 106 _CP0_WRITE64(MIPS_COP_0_PERFCNT0_CNT) 107END(mips_cp0_performance_counter_counter0_write) 108 109LEAF(mips_cp0_performance_counter_counter1_read) 110 _CP0_READ64(MIPS_COP_0_PERFCNT1_CNT) 111END(mips_cp0_performance_counter_counter1_read) 112 113LEAF(mips_cp0_performance_counter_counter1_write) 114 _CP0_WRITE64(MIPS_COP_0_PERFCNT1_CNT) 115END(mips_cp0_performance_counter_counter1_write) 116#endif /* notyet */ 117 118#ifdef MULTIPROCESSOR 119 120NESTED_NOPROFILE(octeon_cpu_spinup, 0, ra) 121 // 122 // Since the OCTEON cpus doesn't a COP0 OSCONTEXT register, each core 123 // must has its own exception vector page. The exceptions will be 124 // modified to refer to that CPU's cpu_info structure. 125 // 126 mfc0 s1, MIPS_COP_0_EBASE # get EBASE 127 andi s0, s1, MIPS_EBASE_CPUNUM # fetch cpunum 128 # insert cpunum as exception address base: 129 ins s1, s0, MIPS_EBASE_EXC_BASE_SHIFT, MIPS_EBASE_CPUNUM_WIDTH 130 ehb 131 mtc0 s1, MIPS_COP_0_EBASE # set EBASE 132 COP0_SYNC 133 134 // Indicate this CPU was started by u-boot 135 PTR_LA a0, _C_LABEL(cpus_booted) 136 li a1, 1 137 jal _C_LABEL(atomic_or_64) 138 sllv a1, a1, s0 # shift cpu number to bit position 139 140 // Wait until cpuid_infos[cpunum] is not NULL. 141 PTR_LA a1, _C_LABEL(cpuid_infos) 142 dsll v0, s0, PTR_SCALESHIFT # cpunum -> array index 143 PTR_ADD t0, a1, v0 # add to array start 1441: PTR_L a1, (t0) # get cpu_info pointer 145 SYNC_ACQ # PTR_L/SYNC_ACQ matches 146 # atomic_store_release in 147 # cpu_attach_common 148 beqz a1, 1b # loop until non-NULL 149 nop 150 151 j _C_LABEL(cpu_trampoline) 152 nop 153END(octeon_cpu_spinup) 154#endif /* MULTIPROCESSOR */ 155 156#if NWDOG > 0 || defined(DDB) 157 158#define UINT64_C(x) (x) 159 160#include <mips/cavium/dev/octeon_ciureg.h> 161 162NESTED_NOPROFILE(octeon_reset_vector, 0, ra) 163 mfc0 k0, MIPS_COP_0_STATUS # get cp0 status 164 bbit1 k0, V_MIPS3_SR_SR, 1f # MIPS3_SR_SR 165 ins k0, zero, V_MIPS_SR_BEV, 1 # clear boot exception vectors 166 mtc0 k0, MIPS_COP_0_STATUS # write cp0 status 167 ehb # hazard barrier 168#ifdef MULTIPROCESSOR 169 mfc0 k0, MIPS_COP_0_EBASE # get EBASE 170 andi k0, k0, MIPS_EBASE_CPUNUM # fetch cpunum 171 dsll k0, k0, PTR_SCALESHIFT # cpunum -> array index 172 PTR_LA k1, _C_LABEL(cpuid_infos) 173 PTR_ADDU k1, k1, k0 # add to array start 174 PTR_L k0, (k1) # get cpu_info 175#else 176 PTR_LA k0, _C_LABEL(cpu_info_store) # get cpu_info 177#endif 178 j _C_LABEL(mips64r2_kern_nonmaskable_intr) 179 sd zero, CIU_NMI_OFFSET(k1)# clear NMI 1801: 181 li k1, ((MIPS_XKPHYS_START|CIU_BASE) >> 32) # CIU base (MSW) 182 dsll k1, 32 # shift it place 183 ld k0, CIU_FUSE_OFFSET(k1) # get mask of CPUs 184 sd k0, CIU_SOFT_RST_OFFSET(k1) # reset them 185 ld v0, CIU_SOFT_RST_OFFSET(k1) # force a load 186 sd k0, CIU_SOFT_RST_OFFSET(k1) # do it again. 1872: 188 wait # wait forever 189 b 2b # and loop until reset 190 nop 191END(octeon_reset_vector) 192#endif 193