subr_pcpu.c revision 116182
176440Sjhb/*
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 116182 2003-06-11 00:56:59Z obrien $");
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>
5687702Sjhb#include <ddb/ddb.h>
5776440Sjhb
5887702Sjhbstatic struct pcpu *cpuid_to_pcpu[MAXCPU];
5976440Sjhbstruct cpuhead cpuhead = SLIST_HEAD_INITIALIZER(cpuhead);
6076440Sjhb
6176440Sjhb/*
6287702Sjhb * Initialize the MI portions of a struct pcpu.
6376440Sjhb */
6476440Sjhbvoid
6587702Sjhbpcpu_init(struct pcpu *pcpu, int cpuid, size_t size)
6676440Sjhb{
6776440Sjhb
6887702Sjhb	bzero(pcpu, size);
6987702Sjhb	KASSERT(cpuid >= 0 && cpuid < MAXCPU,
7087702Sjhb	    ("pcpu_init: invalid cpuid %d", cpuid));
7187702Sjhb	pcpu->pc_cpuid = cpuid;
7288901Speter	pcpu->pc_cpumask = 1 << cpuid;
7387702Sjhb	cpuid_to_pcpu[cpuid] = pcpu;
7487702Sjhb	SLIST_INSERT_HEAD(&cpuhead, pcpu, pc_allcpu);
7587702Sjhb	cpu_pcpu_init(pcpu, cpuid, size);
7676440Sjhb}
7776440Sjhb
7876440Sjhb/*
7987702Sjhb * Destroy a struct pcpu.
8076440Sjhb */
8187702Sjhbvoid
8287702Sjhbpcpu_destroy(struct pcpu *pcpu)
8376440Sjhb{
8476440Sjhb
8587702Sjhb	SLIST_REMOVE(&cpuhead, pcpu, pcpu, pc_allcpu);
8687702Sjhb	cpuid_to_pcpu[pcpu->pc_cpuid] = NULL;
8776440Sjhb}
8887702Sjhb
8987702Sjhb/*
9087702Sjhb * Locate a struct pcpu by cpu id.
9187702Sjhb */
9287702Sjhbstruct pcpu *
9387702Sjhbpcpu_find(u_int cpuid)
9487702Sjhb{
9587702Sjhb
9687702Sjhb	return (cpuid_to_pcpu[cpuid]);
9787702Sjhb}
9887702Sjhb
9987702Sjhb#ifdef DDB
10087702SjhbDB_SHOW_COMMAND(pcpu, db_show_pcpu)
10187702Sjhb{
10287702Sjhb	struct pcpu *pc;
10387702Sjhb	struct thread *td;
10487702Sjhb	int id;
10587702Sjhb
10687702Sjhb	if (have_addr)
10787702Sjhb		id = ((addr >> 4) % 16) * 10 + (addr % 16);
10887702Sjhb	else
10987702Sjhb		id = PCPU_GET(cpuid);
11087702Sjhb	pc = pcpu_find(id);
11187702Sjhb	if (pc == NULL) {
11287702Sjhb		db_printf("CPU %d not found\n", id);
11387702Sjhb		return;
11487702Sjhb	}
11587702Sjhb	db_printf("cpuid        = %d\n", pc->pc_cpuid);
11687702Sjhb	db_printf("curthread    = ");
11787702Sjhb	td = pc->pc_curthread;
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("curpcb       = %p\n", pc->pc_curpcb);
12487702Sjhb	db_printf("fpcurthread  = ");
12587702Sjhb	td = pc->pc_fpcurthread;
12687702Sjhb	if (td != NULL)
12787702Sjhb		db_printf("%p: pid %d \"%s\"\n", td, td->td_proc->p_pid,
12887702Sjhb		    td->td_proc->p_comm);
12987702Sjhb	else
13087702Sjhb		db_printf("none\n");
13187702Sjhb	db_printf("idlethread   = ");
13287702Sjhb	td = pc->pc_idlethread;
13387702Sjhb	if (td != NULL)
13487702Sjhb		db_printf("%p: pid %d \"%s\"\n", td, td->td_proc->p_pid,
13587702Sjhb		    td->td_proc->p_comm);
13687702Sjhb	else
13787702Sjhb		db_printf("none\n");
13887702Sjhb	db_show_mdpcpu(pc);
13987702Sjhb
14087702Sjhb#ifdef WITNESS
14187702Sjhb	db_printf("spin locks held:\n");
14287702Sjhb	witness_list_locks(&pc->pc_spinlocks);
14387702Sjhb#endif
14487702Sjhb}
14587702Sjhb#endif
146