Home | History | Annotate | Line # | Download | only in cavium
octeon_cpunode.c revision 1.1.2.2
      1  1.1.2.2  skrll /*-
      2  1.1.2.2  skrll  * Copyright (c) 2014 The NetBSD Foundation, Inc.
      3  1.1.2.2  skrll  * All rights reserved.
      4  1.1.2.2  skrll  *
      5  1.1.2.2  skrll  * This code is derived from software contributed to The NetBSD Foundation
      6  1.1.2.2  skrll  * by Matt Thomas of 3am Software Foundry.
      7  1.1.2.2  skrll  *
      8  1.1.2.2  skrll  * Redistribution and use in source and binary forms, with or without
      9  1.1.2.2  skrll  * modification, are permitted provided that the following conditions
     10  1.1.2.2  skrll  * are met:
     11  1.1.2.2  skrll  * 1. Redistributions of source code must retain the above copyright
     12  1.1.2.2  skrll  *    notice, this list of conditions and the following disclaimer.
     13  1.1.2.2  skrll  * 2. Redistributions in binary form must reproduce the above copyright
     14  1.1.2.2  skrll  *    notice, this list of conditions and the following disclaimer in the
     15  1.1.2.2  skrll  *    documentation and/or other materials provided with the distribution.
     16  1.1.2.2  skrll  *
     17  1.1.2.2  skrll  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     18  1.1.2.2  skrll  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     19  1.1.2.2  skrll  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     20  1.1.2.2  skrll  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     21  1.1.2.2  skrll  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22  1.1.2.2  skrll  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23  1.1.2.2  skrll  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     24  1.1.2.2  skrll  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     25  1.1.2.2  skrll  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     26  1.1.2.2  skrll  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     27  1.1.2.2  skrll  * POSSIBILITY OF SUCH DAMAGE.
     28  1.1.2.2  skrll  */
     29  1.1.2.2  skrll #define __INTR_PRIVATE
     30  1.1.2.2  skrll #include <sys/cdefs.h>
     31  1.1.2.2  skrll 
     32  1.1.2.2  skrll __KERNEL_RCSID(0, "$NetBSD");
     33  1.1.2.2  skrll 
     34  1.1.2.2  skrll #include "locators.h"
     35  1.1.2.2  skrll 
     36  1.1.2.2  skrll #include <sys/param.h>
     37  1.1.2.2  skrll #include <sys/device.h>
     38  1.1.2.2  skrll #include <sys/lwp.h>
     39  1.1.2.2  skrll #include <sys/cpu.h>
     40  1.1.2.2  skrll 
     41  1.1.2.2  skrll #include <mips/cache.h>
     42  1.1.2.2  skrll #include <mips/cpuset.h>
     43  1.1.2.2  skrll #include <mips/mips_opcode.h>
     44  1.1.2.2  skrll 
     45  1.1.2.2  skrll #include <mips/cavium/octeonvar.h>
     46  1.1.2.2  skrll #include <mips/cavium/dev/octeon_ciureg.h>
     47  1.1.2.2  skrll #include <mips/cavium/dev/octeon_corereg.h>
     48  1.1.2.2  skrll 
     49  1.1.2.2  skrll struct cpunode_attach_args {
     50  1.1.2.2  skrll 	const char *cnaa_name;
     51  1.1.2.2  skrll 	int cnaa_cpunum;
     52  1.1.2.2  skrll };
     53  1.1.2.2  skrll 
     54  1.1.2.2  skrll static int cpunode_mainbus_match(device_t, cfdata_t, void *);
     55  1.1.2.2  skrll static void cpunode_mainbus_attach(device_t, device_t, void *);
     56  1.1.2.2  skrll 
     57  1.1.2.2  skrll static int cpu_cpunode_match(device_t, cfdata_t, void *);
     58  1.1.2.2  skrll static void cpu_cpunode_attach(device_t, device_t, void *);
     59  1.1.2.2  skrll 
     60  1.1.2.2  skrll CFATTACH_DECL_NEW(cpunode, 0,
     61  1.1.2.2  skrll     cpunode_mainbus_match, cpunode_mainbus_attach, NULL, NULL);
     62  1.1.2.2  skrll 
     63  1.1.2.2  skrll CFATTACH_DECL_NEW(cpunode_cpu, 0,
     64  1.1.2.2  skrll     cpu_cpunode_match, cpu_cpunode_attach, NULL, NULL);
     65  1.1.2.2  skrll 
     66  1.1.2.2  skrll volatile __cpuset_t cpus_booted = 1;
     67  1.1.2.2  skrll 
     68  1.1.2.2  skrll static int
     69  1.1.2.2  skrll cpunode_mainbus_print(void *aux, const char *pnp)
     70  1.1.2.2  skrll {
     71  1.1.2.2  skrll 	struct cpunode_attach_args * const cnaa = aux;
     72  1.1.2.2  skrll 
     73  1.1.2.2  skrll 	aprint_normal(" core %d", cnaa->cnaa_cpunum);
     74  1.1.2.2  skrll 
     75  1.1.2.2  skrll 	return UNCONF;
     76  1.1.2.2  skrll }
     77  1.1.2.2  skrll 
     78  1.1.2.2  skrll int
     79  1.1.2.2  skrll cpunode_mainbus_match(device_t parent, cfdata_t cf, void *aux)
     80  1.1.2.2  skrll {
     81  1.1.2.2  skrll 
     82  1.1.2.2  skrll 	return 1;
     83  1.1.2.2  skrll }
     84  1.1.2.2  skrll 
     85  1.1.2.2  skrll void
     86  1.1.2.2  skrll cpunode_mainbus_attach(device_t parent, device_t self, void *aux)
     87  1.1.2.2  skrll {
     88  1.1.2.2  skrll 	uint64_t fuse = octeon_xkphys_read_8(CIU_FUSE);
     89  1.1.2.2  skrll 	int cpunum = 0;
     90  1.1.2.2  skrll 
     91  1.1.2.2  skrll 	aprint_naive(": %u core%s\n",
     92  1.1.2.2  skrll 	    popcount32((uint32_t)fuse),
     93  1.1.2.2  skrll 	    fuse == 1 ? "" : "s");
     94  1.1.2.2  skrll 
     95  1.1.2.2  skrll 	aprint_normal(": %u core%s",
     96  1.1.2.2  skrll 	    popcount32((uint32_t)fuse),
     97  1.1.2.2  skrll 	    fuse == 1 ? "" : "s");
     98  1.1.2.2  skrll 	const uint64_t cvmctl = mips_cp0_cvmctl_read();
     99  1.1.2.2  skrll 	aprint_normal(", %scrypto", (cvmctl & CP0_CVMCTL_NOCRYPTO) ? "no " : "");
    100  1.1.2.2  skrll 	aprint_normal((cvmctl & CP0_CVMCTL_KASUMI) ? "+kasumi" : "");
    101  1.1.2.2  skrll 	aprint_normal(", %s64bit-mul", (cvmctl & CP0_CVMCTL_NOMUL) ? "no " : "");
    102  1.1.2.2  skrll 	if (cvmctl & CP0_CVMCTL_REPUN)
    103  1.1.2.2  skrll 		aprint_normal(", unaligned-access ok");
    104  1.1.2.2  skrll 	aprint_normal("\n");
    105  1.1.2.2  skrll 
    106  1.1.2.2  skrll 	for (; fuse != 0; fuse >>= 1, cpunum++) {
    107  1.1.2.2  skrll 		struct cpunode_attach_args cnaa = {
    108  1.1.2.2  skrll 			.cnaa_name = "cpu",
    109  1.1.2.2  skrll 			.cnaa_cpunum = cpunum,
    110  1.1.2.2  skrll 		};
    111  1.1.2.2  skrll 		config_found(self, &cnaa, cpunode_mainbus_print);
    112  1.1.2.2  skrll 	}
    113  1.1.2.2  skrll }
    114  1.1.2.2  skrll 
    115  1.1.2.2  skrll int
    116  1.1.2.2  skrll cpu_cpunode_match(device_t parent, cfdata_t cf, void *aux)
    117  1.1.2.2  skrll {
    118  1.1.2.2  skrll 	struct cpunode_attach_args * const cnaa = aux;
    119  1.1.2.2  skrll 	const int cpunum = cf->cf_loc[CPUNODECF_CORE];
    120  1.1.2.2  skrll 
    121  1.1.2.2  skrll 	return cpunum == CPUNODECF_CORE_DEFAULT
    122  1.1.2.2  skrll 	    || cpunum == cnaa->cnaa_cpunum;
    123  1.1.2.2  skrll }
    124  1.1.2.2  skrll 
    125  1.1.2.2  skrll #if defined(MULTIPROCESSOR)
    126  1.1.2.2  skrll static bool
    127  1.1.2.2  skrll octeon_fixup_cpu_info_references(int32_t load_addr, uint32_t new_insns[2],
    128  1.1.2.2  skrll     void *arg)
    129  1.1.2.2  skrll {
    130  1.1.2.2  skrll 	struct cpu_info * const ci = arg;
    131  1.1.2.2  skrll 
    132  1.1.2.2  skrll 	KASSERT(MIPS_KSEG0_P(load_addr));
    133  1.1.2.2  skrll 	KASSERT(!MIPS_CACHE_VIRTUAL_ALIAS);
    134  1.1.2.2  skrll #ifdef MULTIPROCESSOR
    135  1.1.2.2  skrll 	KASSERT(!CPU_IS_PRIMARY(curcpu()));
    136  1.1.2.2  skrll #endif
    137  1.1.2.2  skrll 	load_addr += (intptr_t)ci - (intptr_t)&cpu_info_store;
    138  1.1.2.2  skrll 
    139  1.1.2.2  skrll 	KASSERT((intptr_t)ci <= load_addr);
    140  1.1.2.2  skrll 	KASSERT(load_addr < (intptr_t)(ci + 1));
    141  1.1.2.2  skrll 
    142  1.1.2.2  skrll 	KASSERT(INSN_LUI_P(new_insns[0]));
    143  1.1.2.2  skrll 	KASSERT(INSN_LOAD_P(new_insns[1]) || INSN_STORE_P(new_insns[1]));
    144  1.1.2.2  skrll 
    145  1.1.2.2  skrll 	/*
    146  1.1.2.2  skrll 	 * Use the lui and load/store instruction as a prototype and
    147  1.1.2.2  skrll 	 * make it refer to cpu1_info_store instead of cpu_info_store.
    148  1.1.2.2  skrll 	 */
    149  1.1.2.2  skrll 	new_insns[0] &= __BITS(31,16);
    150  1.1.2.2  skrll 	new_insns[1] &= __BITS(31,16);
    151  1.1.2.2  skrll 	new_insns[0] |= (uint16_t)((load_addr + 0x8000) >> 16);
    152  1.1.2.2  skrll 	new_insns[1] |= (uint16_t)load_addr;
    153  1.1.2.2  skrll #ifdef DEBUG_VERBOSE
    154  1.1.2.2  skrll 	printf("%s: %08x: insn#1 %08x: lui r%u, %d\n",
    155  1.1.2.2  skrll 	    __func__, (int32_t)load_addr, new_insns[0],
    156  1.1.2.2  skrll 	    (new_insns[0] >> 16) & 31,
    157  1.1.2.2  skrll 	    (int16_t)new_insns[0]);
    158  1.1.2.2  skrll 	printf("%s: %08x: insn#2 %08x: %c%c r%u, %d(r%u)\n",
    159  1.1.2.2  skrll 	    __func__, (int32_t)load_addr, new_insns[0],
    160  1.1.2.2  skrll 	    INSN_LOAD_P(new_insns[1]) ? 'l' : 's',
    161  1.1.2.2  skrll 	    INSN_LW_P(new_insns[1]) ? 'w' : 'd',
    162  1.1.2.2  skrll 	    (new_insns[0] >> 16) & 31,
    163  1.1.2.2  skrll 	    (int16_t)new_insns[1],
    164  1.1.2.2  skrll 	    (new_insns[0] >> 21) & 31);
    165  1.1.2.2  skrll #endif
    166  1.1.2.2  skrll 	return true;
    167  1.1.2.2  skrll }
    168  1.1.2.2  skrll 
    169  1.1.2.2  skrll static void
    170  1.1.2.2  skrll octeon_cpu_init(struct cpu_info *ci)
    171  1.1.2.2  skrll {
    172  1.1.2.2  skrll 	bool ok __diagused;
    173  1.1.2.2  skrll 
    174  1.1.2.2  skrll 	// First thing is setup the execption vectors for this cpu.
    175  1.1.2.2  skrll 	mips64r2_vector_init(&mips_splsw);
    176  1.1.2.2  skrll 
    177  1.1.2.2  skrll 	// Next rewrite those exceptions to use this cpu's cpu_info.
    178  1.1.2.2  skrll 	ok = mips_fixup_exceptions(octeon_fixup_cpu_info_references, ci);
    179  1.1.2.2  skrll 	KASSERT(ok);
    180  1.1.2.2  skrll 
    181  1.1.2.2  skrll 	(void) splhigh();
    182  1.1.2.2  skrll 
    183  1.1.2.2  skrll #ifdef DEBUG
    184  1.1.2.2  skrll 	KASSERT((mipsNN_cp0_ebase_read() & MIPS_EBASE_CPUNUM) == ci->ci_cpuid);
    185  1.1.2.2  skrll 	KASSERT(curcpu() == ci);
    186  1.1.2.2  skrll #endif
    187  1.1.2.2  skrll }
    188  1.1.2.2  skrll 
    189  1.1.2.2  skrll static void
    190  1.1.2.2  skrll octeon_cpu_run(struct cpu_info *ci)
    191  1.1.2.2  skrll {
    192  1.1.2.2  skrll }
    193  1.1.2.2  skrll #endif /* MULTIPROCESSOR */
    194  1.1.2.2  skrll 
    195  1.1.2.2  skrll static void
    196  1.1.2.2  skrll cpu_cpunode_attach_common(device_t self, struct cpu_info *ci)
    197  1.1.2.2  skrll {
    198  1.1.2.2  skrll 	ci->ci_dev = self;
    199  1.1.2.2  skrll 	self->dv_private = ci;
    200  1.1.2.2  skrll 
    201  1.1.2.2  skrll 	aprint_normal(": %lu.%02luMHz (hz cycles = %lu, delay divisor = %lu)\n",
    202  1.1.2.2  skrll 	    ci->ci_cpu_freq / 1000000,
    203  1.1.2.2  skrll 	    (ci->ci_cpu_freq % 1000000) / 10000,
    204  1.1.2.2  skrll 	    ci->ci_cycles_per_hz, ci->ci_divisor_delay);
    205  1.1.2.2  skrll 
    206  1.1.2.2  skrll 	aprint_normal("%s: ", device_xname(self));
    207  1.1.2.2  skrll 	cpu_identify(self);
    208  1.1.2.2  skrll 	cpu_attach_common(self, ci);
    209  1.1.2.2  skrll }
    210  1.1.2.2  skrll 
    211  1.1.2.2  skrll void
    212  1.1.2.2  skrll cpu_cpunode_attach(device_t parent, device_t self, void *aux)
    213  1.1.2.2  skrll {
    214  1.1.2.2  skrll 	struct cpunode_attach_args * const cnaa = aux;
    215  1.1.2.2  skrll 	const int cpunum = cnaa->cnaa_cpunum;
    216  1.1.2.2  skrll 
    217  1.1.2.2  skrll 	if (cpunum == 0) {
    218  1.1.2.2  skrll 		cpu_cpunode_attach_common(self, curcpu());
    219  1.1.2.2  skrll #ifdef MULTIPROCESSOR
    220  1.1.2.2  skrll 		mips_locoresw.lsw_cpu_init = octeon_cpu_init;
    221  1.1.2.2  skrll 		mips_locoresw.lsw_cpu_run = octeon_cpu_run;
    222  1.1.2.2  skrll #endif
    223  1.1.2.2  skrll 		return;
    224  1.1.2.2  skrll 	}
    225  1.1.2.2  skrll #ifdef MULTIPROCESSOR
    226  1.1.2.2  skrll 	KASSERTMSG(cpunum == 1, "cpunum %d", cpunum);
    227  1.1.2.2  skrll 	if (!CPUSET_HAS_P(cpus_booted, cpunum)) {
    228  1.1.2.2  skrll 		aprint_naive(" disabled\n");
    229  1.1.2.2  skrll 		aprint_normal(" disabled (unresponsive)\n");
    230  1.1.2.2  skrll 		return;
    231  1.1.2.2  skrll 	}
    232  1.1.2.2  skrll 	struct cpu_info * const ci = cpu_info_alloc(NULL, cpunum, 0, cpunum, 0);
    233  1.1.2.2  skrll 
    234  1.1.2.2  skrll 	ci->ci_softc = &octeon_cpu1_softc;
    235  1.1.2.2  skrll 	ci->ci_softc->cpu_ci = ci;
    236  1.1.2.2  skrll 
    237  1.1.2.2  skrll 	cpu_cpunode_attach_common(self, ci);
    238  1.1.2.2  skrll #else
    239  1.1.2.2  skrll 	aprint_naive(": disabled\n");
    240  1.1.2.2  skrll 	aprint_normal(": disabled (uniprocessor kernel)\n");
    241  1.1.2.2  skrll #endif
    242  1.1.2.2  skrll }
    243