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