subr_pcpu.c revision 152021
167754Smsmith/*- 267754Smsmith * Copyright (c) 2001 Wind River Systems, Inc. 367754Smsmith * All rights reserved. 491116Smsmith * Written by: John Baldwin <jhb@FreeBSD.org> 567754Smsmith * 667754Smsmith * Redistribution and use in source and binary forms, with or without 767754Smsmith * modification, are permitted provided that the following conditions 867754Smsmith * are met: 967754Smsmith * 1. Redistributions of source code must retain the above copyright 1067754Smsmith * notice, this list of conditions and the following disclaimer. 1167754Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1291116Smsmith * notice, this list of conditions and the following disclaimer in the 1370243Smsmith * documentation and/or other materials provided with the distribution. 1467754Smsmith * 4. Neither the name of the author nor the names of any co-contributors 1567754Smsmith * may be used to endorse or promote products derived from this software 1667754Smsmith * without specific prior written permission. 1767754Smsmith * 1867754Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1967754Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2067754Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2167754Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2267754Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2367754Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2467754Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2567754Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2667754Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2767754Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2867754Smsmith * SUCH DAMAGE. 2967754Smsmith */ 3067754Smsmith 3167754Smsmith/* 3267754Smsmith * This module provides MI support for per-cpu data. 3367754Smsmith * 3467754Smsmith * Each architecture determines the mapping of logical CPU IDs to physical 3567754Smsmith * CPUs. The requirements of this mapping are as follows: 3667754Smsmith * - Logical CPU IDs must reside in the range 0 ... MAXCPU - 1. 3767754Smsmith * - The mapping is not required to be dense. That is, there may be 3867754Smsmith * gaps in the mappings. 3967754Smsmith * - The platform sets the value of MAXCPU in <machine/param.h>. 4067754Smsmith * - It is suggested, but not required, that in the non-SMP case, the 4167754Smsmith * platform define MAXCPU to be 1 and define the logical ID of the 4267754Smsmith * sole CPU as 0. 4367754Smsmith */ 4467754Smsmith 4567754Smsmith#include <sys/cdefs.h> 4667754Smsmith__FBSDID("$FreeBSD: head/sys/kern/subr_pcpu.c 152021 2005-11-03 21:06:29Z jhb $"); 4767754Smsmith 4867754Smsmith#include "opt_ddb.h" 4967754Smsmith 5067754Smsmith#include <sys/param.h> 5167754Smsmith#include <sys/systm.h> 5267754Smsmith#include <sys/linker_set.h> 5367754Smsmith#include <sys/lock.h> 5467754Smsmith#include <sys/pcpu.h> 5567754Smsmith#include <sys/proc.h> 5667754Smsmith#include <sys/smp.h> 5767754Smsmith#include <ddb/ddb.h> 5867754Smsmith 5967754Smsmithstatic struct pcpu *cpuid_to_pcpu[MAXCPU]; 6067754Smsmithstruct cpuhead cpuhead = SLIST_HEAD_INITIALIZER(cpuhead); 6167754Smsmith 6267754Smsmith/* 6367754Smsmith * Initialize the MI portions of a struct pcpu. 6467754Smsmith */ 6567754Smsmithvoid 6667754Smsmithpcpu_init(struct pcpu *pcpu, int cpuid, size_t size) 6767754Smsmith{ 6867754Smsmith 6967754Smsmith bzero(pcpu, size); 7067754Smsmith KASSERT(cpuid >= 0 && cpuid < MAXCPU, 7167754Smsmith ("pcpu_init: invalid cpuid %d", cpuid)); 7267754Smsmith pcpu->pc_cpuid = cpuid; 7367754Smsmith pcpu->pc_cpumask = 1 << cpuid; 7467754Smsmith cpuid_to_pcpu[cpuid] = pcpu; 7567754Smsmith SLIST_INSERT_HEAD(&cpuhead, pcpu, pc_allcpu); 7667754Smsmith cpu_pcpu_init(pcpu, cpuid, size); 7767754Smsmith} 7867754Smsmith 7967754Smsmith/* 8067754Smsmith * Destroy a struct pcpu. 8167754Smsmith */ 8267754Smsmithvoid 8367754Smsmithpcpu_destroy(struct pcpu *pcpu) 8467754Smsmith{ 8567754Smsmith 8667754Smsmith SLIST_REMOVE(&cpuhead, pcpu, pcpu, pc_allcpu); 8767754Smsmith cpuid_to_pcpu[pcpu->pc_cpuid] = NULL; 8867754Smsmith} 8967754Smsmith 9067754Smsmith/* 9167754Smsmith * Locate a struct pcpu by cpu id. 9267754Smsmith */ 9367754Smsmithstruct pcpu * 9467754Smsmithpcpu_find(u_int cpuid) 9567754Smsmith{ 9667754Smsmith 9767754Smsmith return (cpuid_to_pcpu[cpuid]); 9867754Smsmith} 9967754Smsmith 10067754Smsmith#ifdef DDB 10167754Smsmith 10267754Smsmithstatic void 10367754Smsmithshow_pcpu(struct pcpu *pc) 10467754Smsmith{ 10567754Smsmith struct thread *td; 10667754Smsmith 10767754Smsmith db_printf("cpuid = %d\n", pc->pc_cpuid); 10867754Smsmith db_printf("curthread = "); 10967754Smsmith td = pc->pc_curthread; 11067754Smsmith if (td != NULL) 11167754Smsmith db_printf("%p: pid %d \"%s\"\n", td, td->td_proc->p_pid, 11267754Smsmith td->td_proc->p_comm); 11367754Smsmith else 11467754Smsmith db_printf("none\n"); 11567754Smsmith db_printf("curpcb = %p\n", pc->pc_curpcb); 11667754Smsmith db_printf("fpcurthread = "); 11767754Smsmith td = pc->pc_fpcurthread; 11867754Smsmith if (td != NULL) 11967754Smsmith db_printf("%p: pid %d \"%s\"\n", td, td->td_proc->p_pid, 12067754Smsmith td->td_proc->p_comm); 12167754Smsmith else 12267754Smsmith db_printf("none\n"); 12377424Smsmith db_printf("idlethread = "); 12491116Smsmith td = pc->pc_idlethread; 12567754Smsmith if (td != NULL) 12667754Smsmith db_printf("%p: pid %d \"%s\"\n", td, td->td_proc->p_pid, 12767754Smsmith td->td_proc->p_comm); 12867754Smsmith else 12991116Smsmith db_printf("none\n"); 13067754Smsmith db_show_mdpcpu(pc); 13191116Smsmith 13291116Smsmith#ifdef WITNESS 13391116Smsmith db_printf("spin locks held:\n"); 13467754Smsmith witness_list_locks(&pc->pc_spinlocks); 13591116Smsmith#endif 13667754Smsmith} 13791116Smsmith 13891116SmsmithDB_SHOW_COMMAND(pcpu, db_show_pcpu) 13967754Smsmith{ 14067754Smsmith struct pcpu *pc; 14167754Smsmith int id; 14267754Smsmith 14391116Smsmith if (have_addr) 14491116Smsmith id = ((addr >> 4) % 16) * 10 + (addr % 16); 14591116Smsmith else 14691116Smsmith id = PCPU_GET(cpuid); 14791116Smsmith pc = pcpu_find(id); 14867754Smsmith if (pc == NULL) { 14967754Smsmith db_printf("CPU %d not found\n", id); 15091116Smsmith return; 15167754Smsmith } 15267754Smsmith show_pcpu(pc); 15391116Smsmith} 15467754Smsmith 15567754SmsmithDB_SHOW_COMMAND(allpcpu, db_show_cpu_all) 15691116Smsmith{ 15767754Smsmith struct pcpu *pc; 15891116Smsmith int id; 15991116Smsmith 16091116Smsmith db_printf("Current CPU: %d\n\n", PCPU_GET(cpuid)); 16167754Smsmith for (id = 0; id <= mp_maxid; id++) { 16291116Smsmith pc = pcpu_find(id); 16367754Smsmith if (pc != NULL) { 16467754Smsmith show_pcpu(pc); 16591116Smsmith db_printf("\n"); 16667754Smsmith } 16791116Smsmith } 16891116Smsmith} 16991116Smsmith#endif 17067754Smsmith