19454b2d8SWarner Losh /*- 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 31ba228f6dSJohn Baldwin /* 32ba228f6dSJohn Baldwin * This module provides MI support for per-cpu data. 33882bcf58SJohn Baldwin * 34882bcf58SJohn Baldwin * Each architecture determines the mapping of logical CPU IDs to physical 35882bcf58SJohn Baldwin * CPUs. The requirements of this mapping are as follows: 36882bcf58SJohn Baldwin * - Logical CPU IDs must reside in the range 0 ... MAXCPU - 1. 37882bcf58SJohn Baldwin * - The mapping is not required to be dense. That is, there may be 38882bcf58SJohn Baldwin * gaps in the mappings. 39882bcf58SJohn Baldwin * - The platform sets the value of MAXCPU in <machine/param.h>. 40882bcf58SJohn Baldwin * - It is suggested, but not required, that in the non-SMP case, the 41882bcf58SJohn Baldwin * platform define MAXCPU to be 1 and define the logical ID of the 42882bcf58SJohn Baldwin * sole CPU as 0. 43ba228f6dSJohn Baldwin */ 44ba228f6dSJohn Baldwin 45677b542eSDavid E. O'Brien #include <sys/cdefs.h> 46677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 47677b542eSDavid E. O'Brien 480bbc8826SJohn Baldwin #include "opt_ddb.h" 490bbc8826SJohn Baldwin 50ba228f6dSJohn Baldwin #include <sys/param.h> 51ba228f6dSJohn Baldwin #include <sys/systm.h> 520bbc8826SJohn Baldwin #include <sys/linker_set.h> 530bbc8826SJohn Baldwin #include <sys/lock.h> 54ba228f6dSJohn Baldwin #include <sys/pcpu.h> 550bbc8826SJohn Baldwin #include <sys/proc.h> 569b791585SRobert Watson #include <sys/smp.h> 570bbc8826SJohn Baldwin #include <ddb/ddb.h> 58ba228f6dSJohn Baldwin 59f53d15feSStephan Uphoff struct pcpu *cpuid_to_pcpu[MAXCPU]; 60ba228f6dSJohn Baldwin struct cpuhead cpuhead = SLIST_HEAD_INITIALIZER(cpuhead); 61ba228f6dSJohn Baldwin 62ba228f6dSJohn Baldwin /* 630bbc8826SJohn Baldwin * Initialize the MI portions of a struct pcpu. 64ba228f6dSJohn Baldwin */ 65ba228f6dSJohn Baldwin void 660bbc8826SJohn Baldwin pcpu_init(struct pcpu *pcpu, int cpuid, size_t size) 67ba228f6dSJohn Baldwin { 68ba228f6dSJohn Baldwin 690bbc8826SJohn Baldwin bzero(pcpu, size); 700bbc8826SJohn Baldwin KASSERT(cpuid >= 0 && cpuid < MAXCPU, 710bbc8826SJohn Baldwin ("pcpu_init: invalid cpuid %d", cpuid)); 720bbc8826SJohn Baldwin pcpu->pc_cpuid = cpuid; 73ab8061d8SPeter Wemm pcpu->pc_cpumask = 1 << cpuid; 740bbc8826SJohn Baldwin cpuid_to_pcpu[cpuid] = pcpu; 750bbc8826SJohn Baldwin SLIST_INSERT_HEAD(&cpuhead, pcpu, pc_allcpu); 760bbc8826SJohn Baldwin cpu_pcpu_init(pcpu, cpuid, size); 77f53d15feSStephan Uphoff pcpu->pc_rm_queue.rmq_next = &pcpu->pc_rm_queue; 78f53d15feSStephan Uphoff pcpu->pc_rm_queue.rmq_prev = &pcpu->pc_rm_queue; 798f51ad55SJeff Roberson #ifdef KTR 808f51ad55SJeff Roberson snprintf(pcpu->pc_name, sizeof(pcpu->pc_name), "CPU %d", cpuid); 818f51ad55SJeff Roberson #endif 82f53d15feSStephan Uphoff 83ba228f6dSJohn Baldwin } 84ba228f6dSJohn Baldwin 85ba228f6dSJohn Baldwin /* 860bbc8826SJohn Baldwin * Destroy a struct pcpu. 87ba228f6dSJohn Baldwin */ 880bbc8826SJohn Baldwin void 890bbc8826SJohn Baldwin pcpu_destroy(struct pcpu *pcpu) 90ba228f6dSJohn Baldwin { 91ba228f6dSJohn Baldwin 920bbc8826SJohn Baldwin SLIST_REMOVE(&cpuhead, pcpu, pcpu, pc_allcpu); 930bbc8826SJohn Baldwin cpuid_to_pcpu[pcpu->pc_cpuid] = NULL; 94ba228f6dSJohn Baldwin } 950bbc8826SJohn Baldwin 960bbc8826SJohn Baldwin /* 970bbc8826SJohn Baldwin * Locate a struct pcpu by cpu id. 980bbc8826SJohn Baldwin */ 990bbc8826SJohn Baldwin struct pcpu * 1000bbc8826SJohn Baldwin pcpu_find(u_int cpuid) 1010bbc8826SJohn Baldwin { 1020bbc8826SJohn Baldwin 1030bbc8826SJohn Baldwin return (cpuid_to_pcpu[cpuid]); 1040bbc8826SJohn Baldwin } 1050bbc8826SJohn Baldwin 1060bbc8826SJohn Baldwin #ifdef DDB 1070bbc8826SJohn Baldwin 1089b791585SRobert Watson static void 1099b791585SRobert Watson show_pcpu(struct pcpu *pc) 1109b791585SRobert Watson { 1119b791585SRobert Watson struct thread *td; 1129b791585SRobert Watson 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, 118431f8906SJulian Elischer td->td_name); 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, 126431f8906SJulian Elischer td->td_name); 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, 133431f8906SJulian Elischer td->td_name); 1340bbc8826SJohn Baldwin else 1350bbc8826SJohn Baldwin db_printf("none\n"); 1360bbc8826SJohn Baldwin db_show_mdpcpu(pc); 1370bbc8826SJohn Baldwin 13821ca7b57SMarko Zec #ifdef VIMAGE 13921ca7b57SMarko Zec db_printf("curvnet = %p\n", pc->pc_curthread->td_vnet); 14021ca7b57SMarko Zec #endif 14121ca7b57SMarko Zec 1420bbc8826SJohn Baldwin #ifdef WITNESS 1430bbc8826SJohn Baldwin db_printf("spin locks held:\n"); 1440bbc8826SJohn Baldwin witness_list_locks(&pc->pc_spinlocks); 1450bbc8826SJohn Baldwin #endif 1460bbc8826SJohn Baldwin } 1479b791585SRobert Watson 1489b791585SRobert Watson DB_SHOW_COMMAND(pcpu, db_show_pcpu) 1499b791585SRobert Watson { 1509b791585SRobert Watson struct pcpu *pc; 1519b791585SRobert Watson int id; 1529b791585SRobert Watson 1539b791585SRobert Watson if (have_addr) 1549b791585SRobert Watson id = ((addr >> 4) % 16) * 10 + (addr % 16); 1559b791585SRobert Watson else 1569b791585SRobert Watson id = PCPU_GET(cpuid); 1579b791585SRobert Watson pc = pcpu_find(id); 1589b791585SRobert Watson if (pc == NULL) { 1599b791585SRobert Watson db_printf("CPU %d not found\n", id); 1609b791585SRobert Watson return; 1619b791585SRobert Watson } 1629b791585SRobert Watson show_pcpu(pc); 1639b791585SRobert Watson } 1649b791585SRobert Watson 16539297ba4SSam Leffler DB_SHOW_ALL_COMMAND(pcpu, db_show_cpu_all) 1669b791585SRobert Watson { 1679b791585SRobert Watson struct pcpu *pc; 1689b791585SRobert Watson int id; 1699b791585SRobert Watson 1709b791585SRobert Watson db_printf("Current CPU: %d\n\n", PCPU_GET(cpuid)); 17155de4dcaSJohn Baldwin for (id = 0; id <= mp_maxid; id++) { 1729b791585SRobert Watson pc = pcpu_find(id); 1739b791585SRobert Watson if (pc != NULL) { 1749b791585SRobert Watson show_pcpu(pc); 1759b791585SRobert Watson db_printf("\n"); 1769b791585SRobert Watson } 1779b791585SRobert Watson } 1789b791585SRobert Watson } 17939297ba4SSam Leffler DB_SHOW_ALIAS(allpcpu, db_show_cpu_all); 1800bbc8826SJohn Baldwin #endif 181