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