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; 79f53d15feSStephan Uphoff 80ba228f6dSJohn Baldwin } 81ba228f6dSJohn Baldwin 82ba228f6dSJohn Baldwin /* 830bbc8826SJohn Baldwin * Destroy a struct pcpu. 84ba228f6dSJohn Baldwin */ 850bbc8826SJohn Baldwin void 860bbc8826SJohn Baldwin pcpu_destroy(struct pcpu *pcpu) 87ba228f6dSJohn Baldwin { 88ba228f6dSJohn Baldwin 890bbc8826SJohn Baldwin SLIST_REMOVE(&cpuhead, pcpu, pcpu, pc_allcpu); 900bbc8826SJohn Baldwin cpuid_to_pcpu[pcpu->pc_cpuid] = NULL; 91ba228f6dSJohn Baldwin } 920bbc8826SJohn Baldwin 930bbc8826SJohn Baldwin /* 940bbc8826SJohn Baldwin * Locate a struct pcpu by cpu id. 950bbc8826SJohn Baldwin */ 960bbc8826SJohn Baldwin struct pcpu * 970bbc8826SJohn Baldwin pcpu_find(u_int cpuid) 980bbc8826SJohn Baldwin { 990bbc8826SJohn Baldwin 1000bbc8826SJohn Baldwin return (cpuid_to_pcpu[cpuid]); 1010bbc8826SJohn Baldwin } 1020bbc8826SJohn Baldwin 1030bbc8826SJohn Baldwin #ifdef DDB 1040bbc8826SJohn Baldwin 1059b791585SRobert Watson static void 1069b791585SRobert Watson show_pcpu(struct pcpu *pc) 1079b791585SRobert Watson { 1089b791585SRobert Watson struct thread *td; 1099b791585SRobert Watson 1100bbc8826SJohn Baldwin db_printf("cpuid = %d\n", pc->pc_cpuid); 1110bbc8826SJohn Baldwin db_printf("curthread = "); 1120bbc8826SJohn Baldwin td = pc->pc_curthread; 1130bbc8826SJohn Baldwin if (td != NULL) 1140bbc8826SJohn Baldwin db_printf("%p: pid %d \"%s\"\n", td, td->td_proc->p_pid, 1150bbc8826SJohn Baldwin td->td_proc->p_comm); 1160bbc8826SJohn Baldwin else 1170bbc8826SJohn Baldwin db_printf("none\n"); 1180bbc8826SJohn Baldwin db_printf("curpcb = %p\n", pc->pc_curpcb); 1190bbc8826SJohn Baldwin db_printf("fpcurthread = "); 1200bbc8826SJohn Baldwin td = pc->pc_fpcurthread; 1210bbc8826SJohn Baldwin if (td != NULL) 1220bbc8826SJohn Baldwin db_printf("%p: pid %d \"%s\"\n", td, td->td_proc->p_pid, 1230bbc8826SJohn Baldwin td->td_proc->p_comm); 1240bbc8826SJohn Baldwin else 1250bbc8826SJohn Baldwin db_printf("none\n"); 1260bbc8826SJohn Baldwin db_printf("idlethread = "); 1270bbc8826SJohn Baldwin td = pc->pc_idlethread; 1280bbc8826SJohn Baldwin if (td != NULL) 1290bbc8826SJohn Baldwin db_printf("%p: pid %d \"%s\"\n", td, td->td_proc->p_pid, 1300bbc8826SJohn Baldwin td->td_proc->p_comm); 1310bbc8826SJohn Baldwin else 1320bbc8826SJohn Baldwin db_printf("none\n"); 1330bbc8826SJohn Baldwin db_show_mdpcpu(pc); 1340bbc8826SJohn Baldwin 1350bbc8826SJohn Baldwin #ifdef WITNESS 1360bbc8826SJohn Baldwin db_printf("spin locks held:\n"); 1370bbc8826SJohn Baldwin witness_list_locks(&pc->pc_spinlocks); 1380bbc8826SJohn Baldwin #endif 1390bbc8826SJohn Baldwin } 1409b791585SRobert Watson 1419b791585SRobert Watson DB_SHOW_COMMAND(pcpu, db_show_pcpu) 1429b791585SRobert Watson { 1439b791585SRobert Watson struct pcpu *pc; 1449b791585SRobert Watson int id; 1459b791585SRobert Watson 1469b791585SRobert Watson if (have_addr) 1479b791585SRobert Watson id = ((addr >> 4) % 16) * 10 + (addr % 16); 1489b791585SRobert Watson else 1499b791585SRobert Watson id = PCPU_GET(cpuid); 1509b791585SRobert Watson pc = pcpu_find(id); 1519b791585SRobert Watson if (pc == NULL) { 1529b791585SRobert Watson db_printf("CPU %d not found\n", id); 1539b791585SRobert Watson return; 1549b791585SRobert Watson } 1559b791585SRobert Watson show_pcpu(pc); 1569b791585SRobert Watson } 1579b791585SRobert Watson 1589b791585SRobert Watson DB_SHOW_COMMAND(allpcpu, db_show_cpu_all) 1599b791585SRobert Watson { 1609b791585SRobert Watson struct pcpu *pc; 1619b791585SRobert Watson int id; 1629b791585SRobert Watson 1639b791585SRobert Watson db_printf("Current CPU: %d\n\n", PCPU_GET(cpuid)); 16455de4dcaSJohn Baldwin for (id = 0; id <= mp_maxid; id++) { 1659b791585SRobert Watson pc = pcpu_find(id); 1669b791585SRobert Watson if (pc != NULL) { 1679b791585SRobert Watson show_pcpu(pc); 1689b791585SRobert Watson db_printf("\n"); 1699b791585SRobert Watson } 1709b791585SRobert Watson } 1719b791585SRobert Watson } 1720bbc8826SJohn Baldwin #endif 173