1ba228f6dSJohn Baldwin /* 2ba228f6dSJohn Baldwin * Copyright (c) 2001 Wind River Systems, Inc. 3ba228f6dSJohn Baldwin * All rights reserved. 4ba228f6dSJohn Baldwin * Written by: John Baldwin <jhb@FreeBSD.org> 5ba228f6dSJohn Baldwin * 6ba228f6dSJohn Baldwin * Redistribution and use in source and binary forms, with or without 7ba228f6dSJohn Baldwin * modification, are permitted provided that the following conditions 8ba228f6dSJohn Baldwin * are met: 9ba228f6dSJohn Baldwin * 1. Redistributions of source code must retain the above copyright 10ba228f6dSJohn Baldwin * notice, this list of conditions and the following disclaimer. 11ba228f6dSJohn Baldwin * 2. Redistributions in binary form must reproduce the above copyright 12ba228f6dSJohn Baldwin * notice, this list of conditions and the following disclaimer in the 13ba228f6dSJohn Baldwin * documentation and/or other materials provided with the distribution. 14ba228f6dSJohn Baldwin * 4. Neither the name of the author nor the names of any co-contributors 15ba228f6dSJohn Baldwin * may be used to endorse or promote products derived from this software 16ba228f6dSJohn Baldwin * without specific prior written permission. 17ba228f6dSJohn Baldwin * 18ba228f6dSJohn Baldwin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19ba228f6dSJohn Baldwin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20ba228f6dSJohn Baldwin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21ba228f6dSJohn Baldwin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22ba228f6dSJohn Baldwin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23ba228f6dSJohn Baldwin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24ba228f6dSJohn Baldwin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25ba228f6dSJohn Baldwin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26ba228f6dSJohn Baldwin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27ba228f6dSJohn Baldwin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28ba228f6dSJohn Baldwin * SUCH DAMAGE. 29ba228f6dSJohn Baldwin * 30ba228f6dSJohn Baldwin * $FreeBSD$ 31ba228f6dSJohn Baldwin */ 32ba228f6dSJohn Baldwin 33ba228f6dSJohn Baldwin /* 34ba228f6dSJohn Baldwin * This module provides MI support for per-cpu data. 35882bcf58SJohn Baldwin * 36882bcf58SJohn Baldwin * Each architecture determines the mapping of logical CPU IDs to physical 37882bcf58SJohn Baldwin * CPUs. The requirements of this mapping are as follows: 38882bcf58SJohn Baldwin * - Logical CPU IDs must reside in the range 0 ... MAXCPU - 1. 39882bcf58SJohn Baldwin * - The mapping is not required to be dense. That is, there may be 40882bcf58SJohn Baldwin * gaps in the mappings. 41882bcf58SJohn Baldwin * - The platform sets the value of MAXCPU in <machine/param.h>. 42882bcf58SJohn Baldwin * - It is suggested, but not required, that in the non-SMP case, the 43882bcf58SJohn Baldwin * platform define MAXCPU to be 1 and define the logical ID of the 44882bcf58SJohn Baldwin * sole CPU as 0. 45ba228f6dSJohn Baldwin */ 46ba228f6dSJohn Baldwin 470bbc8826SJohn Baldwin #include "opt_ddb.h" 480bbc8826SJohn Baldwin 49ba228f6dSJohn Baldwin #include <sys/param.h> 50ba228f6dSJohn Baldwin #include <sys/systm.h> 510bbc8826SJohn Baldwin #include <sys/linker_set.h> 520bbc8826SJohn Baldwin #include <sys/lock.h> 53ba228f6dSJohn Baldwin #include <sys/pcpu.h> 540bbc8826SJohn Baldwin #include <sys/proc.h> 550bbc8826SJohn Baldwin #include <ddb/ddb.h> 56ba228f6dSJohn Baldwin 570bbc8826SJohn Baldwin static struct pcpu *cpuid_to_pcpu[MAXCPU]; 58ba228f6dSJohn Baldwin struct cpuhead cpuhead = SLIST_HEAD_INITIALIZER(cpuhead); 59ba228f6dSJohn Baldwin 60ba228f6dSJohn Baldwin /* 610bbc8826SJohn Baldwin * Initialize the MI portions of a struct pcpu. 62ba228f6dSJohn Baldwin */ 63ba228f6dSJohn Baldwin void 640bbc8826SJohn Baldwin pcpu_init(struct pcpu *pcpu, int cpuid, size_t size) 65ba228f6dSJohn Baldwin { 66ba228f6dSJohn Baldwin 670bbc8826SJohn Baldwin bzero(pcpu, size); 680bbc8826SJohn Baldwin KASSERT(cpuid >= 0 && cpuid < MAXCPU, 690bbc8826SJohn Baldwin ("pcpu_init: invalid cpuid %d", cpuid)); 700bbc8826SJohn Baldwin pcpu->pc_cpuid = cpuid; 710bbc8826SJohn Baldwin cpuid_to_pcpu[cpuid] = pcpu; 720bbc8826SJohn Baldwin SLIST_INSERT_HEAD(&cpuhead, pcpu, pc_allcpu); 730bbc8826SJohn Baldwin cpu_pcpu_init(pcpu, cpuid, size); 74ba228f6dSJohn Baldwin } 75ba228f6dSJohn Baldwin 76ba228f6dSJohn Baldwin /* 770bbc8826SJohn Baldwin * Destroy a struct pcpu. 78ba228f6dSJohn Baldwin */ 790bbc8826SJohn Baldwin void 800bbc8826SJohn Baldwin pcpu_destroy(struct pcpu *pcpu) 81ba228f6dSJohn Baldwin { 82ba228f6dSJohn Baldwin 830bbc8826SJohn Baldwin SLIST_REMOVE(&cpuhead, pcpu, pcpu, pc_allcpu); 840bbc8826SJohn Baldwin cpuid_to_pcpu[pcpu->pc_cpuid] = NULL; 85ba228f6dSJohn Baldwin } 860bbc8826SJohn Baldwin 870bbc8826SJohn Baldwin /* 880bbc8826SJohn Baldwin * Locate a struct pcpu by cpu id. 890bbc8826SJohn Baldwin */ 900bbc8826SJohn Baldwin struct pcpu * 910bbc8826SJohn Baldwin pcpu_find(u_int cpuid) 920bbc8826SJohn Baldwin { 930bbc8826SJohn Baldwin 940bbc8826SJohn Baldwin return (cpuid_to_pcpu[cpuid]); 950bbc8826SJohn Baldwin } 960bbc8826SJohn Baldwin 970bbc8826SJohn Baldwin #ifdef DDB 980bbc8826SJohn Baldwin DB_SHOW_COMMAND(pcpu, db_show_pcpu) 990bbc8826SJohn Baldwin { 1000bbc8826SJohn Baldwin struct pcpu *pc; 1010bbc8826SJohn Baldwin struct thread *td; 1020bbc8826SJohn Baldwin int id; 1030bbc8826SJohn Baldwin 1040bbc8826SJohn Baldwin if (have_addr) 1050bbc8826SJohn Baldwin id = ((addr >> 4) % 16) * 10 + (addr % 16); 1060bbc8826SJohn Baldwin else 1070bbc8826SJohn Baldwin id = PCPU_GET(cpuid); 1080bbc8826SJohn Baldwin pc = pcpu_find(id); 1090bbc8826SJohn Baldwin if (pc == NULL) { 1100bbc8826SJohn Baldwin db_printf("CPU %d not found\n", id); 1110bbc8826SJohn Baldwin return; 1120bbc8826SJohn Baldwin } 1130bbc8826SJohn Baldwin db_printf("cpuid = %d\n", pc->pc_cpuid); 1140bbc8826SJohn Baldwin db_printf("curthread = "); 1150bbc8826SJohn Baldwin td = pc->pc_curthread; 1160bbc8826SJohn Baldwin if (td != NULL) 1170bbc8826SJohn Baldwin db_printf("%p: pid %d \"%s\"\n", td, td->td_proc->p_pid, 1180bbc8826SJohn Baldwin td->td_proc->p_comm); 1190bbc8826SJohn Baldwin else 1200bbc8826SJohn Baldwin db_printf("none\n"); 1210bbc8826SJohn Baldwin db_printf("curpcb = %p\n", pc->pc_curpcb); 1220bbc8826SJohn Baldwin db_printf("fpcurthread = "); 1230bbc8826SJohn Baldwin td = pc->pc_fpcurthread; 1240bbc8826SJohn Baldwin if (td != NULL) 1250bbc8826SJohn Baldwin db_printf("%p: pid %d \"%s\"\n", td, td->td_proc->p_pid, 1260bbc8826SJohn Baldwin td->td_proc->p_comm); 1270bbc8826SJohn Baldwin else 1280bbc8826SJohn Baldwin db_printf("none\n"); 1290bbc8826SJohn Baldwin db_printf("idlethread = "); 1300bbc8826SJohn Baldwin td = pc->pc_idlethread; 1310bbc8826SJohn Baldwin if (td != NULL) 1320bbc8826SJohn Baldwin db_printf("%p: pid %d \"%s\"\n", td, td->td_proc->p_pid, 1330bbc8826SJohn Baldwin td->td_proc->p_comm); 1340bbc8826SJohn Baldwin else 1350bbc8826SJohn Baldwin db_printf("none\n"); 1360bbc8826SJohn Baldwin db_show_mdpcpu(pc); 1370bbc8826SJohn Baldwin 1380bbc8826SJohn Baldwin #ifdef WITNESS 1390bbc8826SJohn Baldwin db_printf("spin locks held:\n"); 1400bbc8826SJohn Baldwin witness_list_locks(&pc->pc_spinlocks); 1410bbc8826SJohn Baldwin #endif 1420bbc8826SJohn Baldwin } 1430bbc8826SJohn Baldwin #endif 144