subr_pcpu.c revision 150576
1139804Simp/*- 276440Sjhb * Copyright (c) 2001 Wind River Systems, Inc. 376440Sjhb * All rights reserved. 476440Sjhb * Written by: John Baldwin <jhb@FreeBSD.org> 576440Sjhb * 676440Sjhb * Redistribution and use in source and binary forms, with or without 776440Sjhb * modification, are permitted provided that the following conditions 876440Sjhb * are met: 976440Sjhb * 1. Redistributions of source code must retain the above copyright 1076440Sjhb * notice, this list of conditions and the following disclaimer. 1176440Sjhb * 2. Redistributions in binary form must reproduce the above copyright 1276440Sjhb * notice, this list of conditions and the following disclaimer in the 1376440Sjhb * documentation and/or other materials provided with the distribution. 1476440Sjhb * 4. Neither the name of the author nor the names of any co-contributors 1576440Sjhb * may be used to endorse or promote products derived from this software 1676440Sjhb * without specific prior written permission. 1776440Sjhb * 1876440Sjhb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1976440Sjhb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2076440Sjhb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2176440Sjhb * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2276440Sjhb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2376440Sjhb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2476440Sjhb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2576440Sjhb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2676440Sjhb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2776440Sjhb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2876440Sjhb * SUCH DAMAGE. 2976440Sjhb */ 3076440Sjhb 3176440Sjhb/* 3276440Sjhb * This module provides MI support for per-cpu data. 3385444Sjhb * 3485444Sjhb * Each architecture determines the mapping of logical CPU IDs to physical 3585444Sjhb * CPUs. The requirements of this mapping are as follows: 3685444Sjhb * - Logical CPU IDs must reside in the range 0 ... MAXCPU - 1. 3785444Sjhb * - The mapping is not required to be dense. That is, there may be 3885444Sjhb * gaps in the mappings. 3985444Sjhb * - The platform sets the value of MAXCPU in <machine/param.h>. 4085444Sjhb * - It is suggested, but not required, that in the non-SMP case, the 4185444Sjhb * platform define MAXCPU to be 1 and define the logical ID of the 4285444Sjhb * sole CPU as 0. 4376440Sjhb */ 4476440Sjhb 45116182Sobrien#include <sys/cdefs.h> 46116182Sobrien__FBSDID("$FreeBSD: head/sys/kern/subr_pcpu.c 150576 2005-09-26 16:55:11Z rwatson $"); 47116182Sobrien 4887702Sjhb#include "opt_ddb.h" 4987702Sjhb 5076440Sjhb#include <sys/param.h> 5176440Sjhb#include <sys/systm.h> 5287702Sjhb#include <sys/linker_set.h> 5387702Sjhb#include <sys/lock.h> 5476440Sjhb#include <sys/pcpu.h> 5587702Sjhb#include <sys/proc.h> 56150576Srwatson#include <sys/smp.h> 5787702Sjhb#include <ddb/ddb.h> 5876440Sjhb 5987702Sjhbstatic struct pcpu *cpuid_to_pcpu[MAXCPU]; 6076440Sjhbstruct cpuhead cpuhead = SLIST_HEAD_INITIALIZER(cpuhead); 6176440Sjhb 6276440Sjhb/* 6387702Sjhb * Initialize the MI portions of a struct pcpu. 6476440Sjhb */ 6576440Sjhbvoid 6687702Sjhbpcpu_init(struct pcpu *pcpu, int cpuid, size_t size) 6776440Sjhb{ 6876440Sjhb 6987702Sjhb bzero(pcpu, size); 7087702Sjhb KASSERT(cpuid >= 0 && cpuid < MAXCPU, 7187702Sjhb ("pcpu_init: invalid cpuid %d", cpuid)); 7287702Sjhb pcpu->pc_cpuid = cpuid; 7388901Speter pcpu->pc_cpumask = 1 << cpuid; 7487702Sjhb cpuid_to_pcpu[cpuid] = pcpu; 7587702Sjhb SLIST_INSERT_HEAD(&cpuhead, pcpu, pc_allcpu); 7687702Sjhb cpu_pcpu_init(pcpu, cpuid, size); 7776440Sjhb} 7876440Sjhb 7976440Sjhb/* 8087702Sjhb * Destroy a struct pcpu. 8176440Sjhb */ 8287702Sjhbvoid 8387702Sjhbpcpu_destroy(struct pcpu *pcpu) 8476440Sjhb{ 8576440Sjhb 8687702Sjhb SLIST_REMOVE(&cpuhead, pcpu, pcpu, pc_allcpu); 8787702Sjhb cpuid_to_pcpu[pcpu->pc_cpuid] = NULL; 8876440Sjhb} 8987702Sjhb 9087702Sjhb/* 9187702Sjhb * Locate a struct pcpu by cpu id. 9287702Sjhb */ 9387702Sjhbstruct pcpu * 9487702Sjhbpcpu_find(u_int cpuid) 9587702Sjhb{ 9687702Sjhb 9787702Sjhb return (cpuid_to_pcpu[cpuid]); 9887702Sjhb} 9987702Sjhb 10087702Sjhb#ifdef DDB 101150576Srwatson 102150576Srwatsonstatic void 103150576Srwatsonshow_pcpu(struct pcpu *pc) 10487702Sjhb{ 10587702Sjhb struct thread *td; 10687702Sjhb 10787702Sjhb db_printf("cpuid = %d\n", pc->pc_cpuid); 10887702Sjhb db_printf("curthread = "); 10987702Sjhb td = pc->pc_curthread; 11087702Sjhb if (td != NULL) 11187702Sjhb db_printf("%p: pid %d \"%s\"\n", td, td->td_proc->p_pid, 11287702Sjhb td->td_proc->p_comm); 11387702Sjhb else 11487702Sjhb db_printf("none\n"); 11587702Sjhb db_printf("curpcb = %p\n", pc->pc_curpcb); 11687702Sjhb db_printf("fpcurthread = "); 11787702Sjhb td = pc->pc_fpcurthread; 11887702Sjhb if (td != NULL) 11987702Sjhb db_printf("%p: pid %d \"%s\"\n", td, td->td_proc->p_pid, 12087702Sjhb td->td_proc->p_comm); 12187702Sjhb else 12287702Sjhb db_printf("none\n"); 12387702Sjhb db_printf("idlethread = "); 12487702Sjhb td = pc->pc_idlethread; 12587702Sjhb if (td != NULL) 12687702Sjhb db_printf("%p: pid %d \"%s\"\n", td, td->td_proc->p_pid, 12787702Sjhb td->td_proc->p_comm); 12887702Sjhb else 12987702Sjhb db_printf("none\n"); 13087702Sjhb db_show_mdpcpu(pc); 13187702Sjhb 13287702Sjhb#ifdef WITNESS 13387702Sjhb db_printf("spin locks held:\n"); 13487702Sjhb witness_list_locks(&pc->pc_spinlocks); 13587702Sjhb#endif 13687702Sjhb} 137150576Srwatson 138150576SrwatsonDB_SHOW_COMMAND(pcpu, db_show_pcpu) 139150576Srwatson{ 140150576Srwatson struct pcpu *pc; 141150576Srwatson int id; 142150576Srwatson 143150576Srwatson if (have_addr) 144150576Srwatson id = ((addr >> 4) % 16) * 10 + (addr % 16); 145150576Srwatson else 146150576Srwatson id = PCPU_GET(cpuid); 147150576Srwatson pc = pcpu_find(id); 148150576Srwatson if (pc == NULL) { 149150576Srwatson db_printf("CPU %d not found\n", id); 150150576Srwatson return; 151150576Srwatson } 152150576Srwatson show_pcpu(pc); 153150576Srwatson} 154150576Srwatson 155150576SrwatsonDB_SHOW_COMMAND(allpcpu, db_show_cpu_all) 156150576Srwatson{ 157150576Srwatson struct pcpu *pc; 158150576Srwatson int id; 159150576Srwatson 160150576Srwatson db_printf("Current CPU: %d\n\n", PCPU_GET(cpuid)); 161150576Srwatson for (id = 0; id < mp_maxid; id++) { 162150576Srwatson pc = pcpu_find(id); 163150576Srwatson if (pc != NULL) { 164150576Srwatson show_pcpu(pc); 165150576Srwatson db_printf("\n"); 166150576Srwatson } 167150576Srwatson } 168150576Srwatson} 16987702Sjhb#endif 170