subr_pcpu.c revision 191816
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 191816 2009-05-05 10:56:12Z zec $"); 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 59173444Supsstruct 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); 77173444Sups pcpu->pc_rm_queue.rmq_next = &pcpu->pc_rm_queue; 78173444Sups pcpu->pc_rm_queue.rmq_prev = &pcpu->pc_rm_queue; 79187357Sjeff#ifdef KTR 80187357Sjeff snprintf(pcpu->pc_name, sizeof(pcpu->pc_name), "CPU %d", cpuid); 81187357Sjeff#endif 82173444Sups 8376440Sjhb} 8476440Sjhb 8576440Sjhb/* 8687702Sjhb * Destroy a struct pcpu. 8776440Sjhb */ 8887702Sjhbvoid 8987702Sjhbpcpu_destroy(struct pcpu *pcpu) 9076440Sjhb{ 9176440Sjhb 9287702Sjhb SLIST_REMOVE(&cpuhead, pcpu, pcpu, pc_allcpu); 9387702Sjhb cpuid_to_pcpu[pcpu->pc_cpuid] = NULL; 9476440Sjhb} 9587702Sjhb 9687702Sjhb/* 9787702Sjhb * Locate a struct pcpu by cpu id. 9887702Sjhb */ 9987702Sjhbstruct pcpu * 10087702Sjhbpcpu_find(u_int cpuid) 10187702Sjhb{ 10287702Sjhb 10387702Sjhb return (cpuid_to_pcpu[cpuid]); 10487702Sjhb} 10587702Sjhb 10687702Sjhb#ifdef DDB 107150576Srwatson 108150576Srwatsonstatic void 109150576Srwatsonshow_pcpu(struct pcpu *pc) 11087702Sjhb{ 11187702Sjhb struct thread *td; 11287702Sjhb 11387702Sjhb db_printf("cpuid = %d\n", pc->pc_cpuid); 11487702Sjhb db_printf("curthread = "); 11587702Sjhb td = pc->pc_curthread; 11687702Sjhb if (td != NULL) 11787702Sjhb db_printf("%p: pid %d \"%s\"\n", td, td->td_proc->p_pid, 118173600Sjulian td->td_name); 11987702Sjhb else 12087702Sjhb db_printf("none\n"); 12187702Sjhb db_printf("curpcb = %p\n", pc->pc_curpcb); 12287702Sjhb db_printf("fpcurthread = "); 12387702Sjhb td = pc->pc_fpcurthread; 12487702Sjhb if (td != NULL) 12587702Sjhb db_printf("%p: pid %d \"%s\"\n", td, td->td_proc->p_pid, 126173600Sjulian td->td_name); 12787702Sjhb else 12887702Sjhb db_printf("none\n"); 12987702Sjhb db_printf("idlethread = "); 13087702Sjhb td = pc->pc_idlethread; 13187702Sjhb if (td != NULL) 13287702Sjhb db_printf("%p: pid %d \"%s\"\n", td, td->td_proc->p_pid, 133173600Sjulian td->td_name); 13487702Sjhb else 13587702Sjhb db_printf("none\n"); 13687702Sjhb db_show_mdpcpu(pc); 13787702Sjhb 138191816Szec#ifdef VIMAGE 139191816Szec db_printf("curvnet = %p\n", pc->pc_curthread->td_vnet); 140191816Szec#endif 141191816Szec 14287702Sjhb#ifdef WITNESS 14387702Sjhb db_printf("spin locks held:\n"); 14487702Sjhb witness_list_locks(&pc->pc_spinlocks); 14587702Sjhb#endif 14687702Sjhb} 147150576Srwatson 148150576SrwatsonDB_SHOW_COMMAND(pcpu, db_show_pcpu) 149150576Srwatson{ 150150576Srwatson struct pcpu *pc; 151150576Srwatson int id; 152150576Srwatson 153150576Srwatson if (have_addr) 154150576Srwatson id = ((addr >> 4) % 16) * 10 + (addr % 16); 155150576Srwatson else 156150576Srwatson id = PCPU_GET(cpuid); 157150576Srwatson pc = pcpu_find(id); 158150576Srwatson if (pc == NULL) { 159150576Srwatson db_printf("CPU %d not found\n", id); 160150576Srwatson return; 161150576Srwatson } 162150576Srwatson show_pcpu(pc); 163150576Srwatson} 164150576Srwatson 165183054SsamDB_SHOW_ALL_COMMAND(pcpu, db_show_cpu_all) 166150576Srwatson{ 167150576Srwatson struct pcpu *pc; 168150576Srwatson int id; 169150576Srwatson 170150576Srwatson db_printf("Current CPU: %d\n\n", PCPU_GET(cpuid)); 171152021Sjhb for (id = 0; id <= mp_maxid; id++) { 172150576Srwatson pc = pcpu_find(id); 173150576Srwatson if (pc != NULL) { 174150576Srwatson show_pcpu(pc); 175150576Srwatson db_printf("\n"); 176150576Srwatson } 177150576Srwatson } 178150576Srwatson} 179183054SsamDB_SHOW_ALIAS(allpcpu, db_show_cpu_all); 18087702Sjhb#endif 181