netbsd/sys/arch/mips/rmi/rmixl_cpucore.c
2013-04-06 16:48:33 +02:00

239 lines
6.9 KiB
C

/* $NetBSD: rmixl_cpucore.c,v 1.5 2011/04/29 22:00:03 matt Exp $ */
/*
* Copyright 2002 Wasabi Systems, Inc.
* All rights reserved.
*
* Written by Simon Burge for Wasabi Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed for the NetBSD Project by
* Wasabi Systems, Inc.
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
* or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "locators.h"
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: rmixl_cpucore.c,v 1.5 2011/04/29 22:00:03 matt Exp $");
#include "opt_multiprocessor.h"
#include <sys/param.h>
#include <sys/device.h>
#include <sys/systm.h>
#include <sys/cpu.h>
#include <uvm/uvm_extern.h>
#include <mips/rmi/rmixlvar.h>
#include <mips/rmi/rmixl_cpunodevar.h>
#include <mips/rmi/rmixl_cpucorevar.h>
#include <mips/rmi/rmixl_fmnvar.h>
static int cpucore_rmixl_match(device_t, cfdata_t, void *);
static void cpucore_rmixl_attach(device_t, device_t, void *);
static int cpucore_rmixl_print(void *, const char *);
CFATTACH_DECL_NEW(cpucore_rmixl, sizeof(struct cpucore_softc),
cpucore_rmixl_match, cpucore_rmixl_attach, NULL, NULL);
static int
cpucore_rmixl_match(device_t parent, cfdata_t cf, void *aux)
{
struct cpunode_attach_args *na = aux;
int core = cf->cf_loc[CPUNODECF_CORE];
if (!cpu_rmixl(mips_options.mips_cpu))
return 0;
if (strncmp(na->na_name, cf->cf_name, strlen(cf->cf_name)) == 0
#ifndef MULTIPROCESSOR
&& na->na_core == 0
#endif
&& (core == CPUNODECF_CORE_DEFAULT || core == na->na_core))
return 1;
return 0;
}
static void
cpucore_rmixl_attach(device_t parent, device_t self, void *aux)
{
struct cpucore_softc * const sc = device_private(self);
struct cpunode_attach_args *na = aux;
struct cpucore_attach_args ca;
u_int nthreads;
struct rmixl_config *rcp = &rmixl_configuration;
sc->sc_dev = self;
sc->sc_core = na->na_core;
KASSERT(sc->sc_hatched == false);
#if 0
#ifdef MULTIPROCESSOR
/*
* Create the TLB structure needed - one per core and core0 uses the
* default one for the system.
*/
if (sc->sc_core == 0) {
sc->sc_tlbinfo = &pmap_tlb0_info;
} else {
const vaddr_t va = (vaddr_t)&sc->sc_tlbinfo0;
paddr_t pa;
if (! pmap_extract(pmap_kernel(), va, &pa))
panic("%s: pmap_extract fail, va %#"PRIxVADDR, __func__, va);
#ifdef _LP64
sc->sc_tlbinfo = (struct pmap_tlb_info *)
MIPS_PHYS_TO_XKPHYS_CACHED(pa);
#else
sc->sc_tlbinfo = (struct pmap_tlb_info *)
MIPS_PHYS_TO_KSEG0(pa);
#endif
pmap_tlb_info_init(sc->sc_tlbinfo);
}
#endif
#endif
aprint_normal("\n");
aprint_normal_dev(self, "%lu.%02luMHz (hz cycles = %lu, "
"delay divisor = %lu)\n",
curcpu()->ci_cpu_freq / 1000000,
(curcpu()->ci_cpu_freq % 1000000) / 10000,
curcpu()->ci_cycles_per_hz, curcpu()->ci_divisor_delay);
aprint_normal("%s: ", device_xname(self));
cpu_identify(self);
nthreads = MIPS_CIDFL_RMI_NTHREADS(mips_options.mips_cpu->cpu_cidflags);
aprint_normal_dev(self, "%d %s on core\n", nthreads,
nthreads == 1 ? "thread" : "threads");
/*
* Attach CPU (RMI thread contexts) devices
* according to userapp_cpu_map bitmask.
*/
u_int thread_mask = (1 << nthreads) - 1;
u_int core_shft = sc->sc_core * nthreads;
u_int threads_enb =
(u_int)(rcp->rc_psb_info.userapp_cpu_map >> core_shft) & thread_mask;
u_int threads_dis = (~threads_enb) & thread_mask;
sc->sc_threads_dis = threads_dis;
if (threads_dis != 0) {
aprint_normal_dev(self, "threads");
u_int d = threads_dis;
while (d != 0) {
const u_int t = ffs(d) - 1;
d ^= (1 << t);
aprint_normal(" %d%s", t, (d==0) ? "" : ",");
}
aprint_normal(" offline (disabled by firmware)\n");
}
u_int threads_try_attach = threads_enb;
while (threads_try_attach != 0) {
const u_int t = ffs(threads_try_attach) - 1;
const u_int bit = 1 << t;
threads_try_attach ^= bit;
ca.ca_name = "cpu";
ca.ca_thread = t;
ca.ca_core = sc->sc_core;
if (config_found(self, &ca, cpucore_rmixl_print) == NULL) {
/*
* thread did not attach, e.g. not configured
* arrange to have it disabled in THREADEN PCR
*/
threads_enb ^= bit;
threads_dis |= bit;
}
}
sc->sc_threads_enb = threads_enb;
sc->sc_threads_dis = threads_dis;
/*
* when attaching the core of the primary cpu,
* do the post-running initialization here
*/
if (sc->sc_core == RMIXL_CPU_CORE((curcpu()->ci_cpuid)))
cpucore_rmixl_run(self);
}
static int
cpucore_rmixl_print(void *aux, const char *pnp)
{
struct cpucore_attach_args *ca = aux;
if (pnp != NULL)
aprint_normal("%s:", pnp);
aprint_normal(" thread %d", ca->ca_thread);
return (UNCONF);
}
/*
* cpucore_rmixl_run
* called from cpucore_rmixl_attach for primary core
* and called from cpu_rmixl_run for each hatched cpu
* the first call for each cpucore causes init of per-core features:
* - disable unused threads
* - set Fine-grained (Round Robin) thread scheduling mode
*/
void
cpucore_rmixl_run(device_t self)
{
struct cpucore_softc * const sc = device_private(self);
if (sc->sc_running == false) {
sc->sc_running = true;
rmixl_mtcr(RMIXL_PCR_THREADEN, sc->sc_threads_enb);
rmixl_mtcr(RMIXL_PCR_SCHEDULING, 0);
}
}
#ifdef MULTIPROCESSOR
/*
* cpucore_rmixl_hatch
* called from cpu_rmixl_hatch for each cpu
* the first call for each cpucore causes init of per-core features
*/
void
cpucore_rmixl_hatch(device_t self)
{
struct cpucore_softc * const sc = device_private(self);
if (sc->sc_hatched == false) {
/* PCRs for core#0 are set up in mach_init() */
if (sc->sc_core != 0)
rmixl_pcr_init_core();
rmixl_fmn_init_core();
sc->sc_hatched = true;
}
}
#endif /* MULTIPROCESSOR */