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