chip.c revision 685679f7e4cc349aa1260fad8dbfaf07089c7b19
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/processor.h>
/*
* CMT aware scheduler/dispatcher support
*
* With the introduction of Chip Multi-Threaded (CMT) processor architectures,
* it is no longer necessarily true that a given physical processor
* module (chip) will present itself as a single schedulable entity (cpu_t).
* Rather, each chip may present itself as one or more "logical" CPUs.
*
* The logical CPUs presented may share physical components on the chip
* such as caches, data pipes, FPUs, etc. It is advantageous to have the
* kernel know which logical CPUs are presented by a given chip,
* and what facilities on the chip are shared, since the kernel can then use
* this information to employ scheduling policies that help improve the
* availability of per chip resources, and increase utilization of a thread's
* cache investment.
*
* The "chip_t" structure represents a physical processor.
* It is used to keep track of which logical CPUs are presented by a given
* chip, and to provide a parameterized representation of a chip's
* properties. A count of the number of running threads is also
* maintained, and is used by the dispatcher to balance load across the
* system's chips to improve performance through increased chip resource
* availability.
*
* Locking:
*
* Safely traversing the per lgroup lists requires the same protections
* as traversing the cpu lists. One must either:
* - hold cpu_lock
* - have disabled kernel preemption
* - be at high SPL
* - have cpu's paused
*
* Safely traversing the global "chip_list" requires holding cpu_lock.
*
* A chip's nrunning count should only be modified using the
* CHIP_NRUNNING() macro, through which updates of the count are done
* atomically.
*/
/*
* chip_bootstrap is used on platforms where it is possible to enter the
* dispatcher before a new CPU's chip initialization has happened.
*/
static chip_t chip_bootstrap;
#define CPU_HAS_NO_CHIP(cp) \
/* indexed by chip_seqid */
static int nchips = 0; /* num chips in existence */
static int chip_kstat_extract(kstat_t *, int);
/*
* Declare static kstat names (defined in chip.h)
*/
/*
* Find the chip_t with the given chip_id.
*/
static chip_t *
{
MUTEX_HELD(&cpu_lock));
do {
return (chp);
}
}
return (NULL);
}
chip_t *
{
return (chp);
}
#ifndef sun4v
/*
* Setup the kstats for this chip, if needed
*/
void
{
return; /* already initialized */
if (chip_kstat != NULL) {
}
}
#else
/*
* Note: On sun4v systems, chip kstats don't currently
* exist, since "chip" structures and policies are being
* leveraged to implement core level balancing, and exporting
* chip kstats in light of this would be both misleading
* and confusing.
*/
/* ARGSUSED */
void
{
}
#endif /* !sun4v */
static int
{
struct kstat_named *ksd;
/*
* The chip kstats are read only
*/
if (rw == KSTAT_WRITE)
return (EACCES);
return (0);
}
/*
* If necessary, instantiate a chip_t for this CPU.
* Called when a CPU is being added to the system either in startup,
* or because of DR. The cpu will be assigned to the chip's active
* CPU list later in chip_cpu_assign()
*/
void
{
int rechoose;
else
/*
* Call into the platform to fetch this cpu's chip and core ids.
* The ids are cached in the CPU's physical id structure.
*
* On sun4v platforms, the chip infrastructure is currently being
* leveraged to implement core level load balancing.
*/
#ifdef DO_CORELEVEL_LOADBAL
#else
#endif /* DO_CORELEVEL_LOADBAL */
/*
* Create a new chip
*/
else
chp->chip_nrunning = 0;
/*
* If we're booting, take this moment to perform
* some additional initialization
*/
}
/*
* Find the next free sequential chip id.
* A chip's sequential id exists in the range
* 0 .. CHIP_MAX_CHIPS, and is suitable for use with
* chip sets.
*/
/*
* Query the platform specific parameters
* for this chip
*/
/*
* Insert this chip in chip_list
*/
} else {
}
nchips++;
/*
* The boot cpu will create the first chip's kstats
* later in cpu_kstat_init()
*/
}
/*
* Initialize the effective rechoose interval cached
* in this cpu structure.
*/
}
/*
* This cpu is being deleted. It has already been removed from
* the chip's active cpu list back in chip_cpu_unassign(). Here
* the chip if needed.
*/
void
{
/*
* This can happen if the CPU failed to power on
*/
if (CPU_HAS_NO_CHIP(cp))
return;
/*
* Clear out and free the CPU's physical id structure
*/
}
/*
* Delete the chip if its last CPU is being deleted
*/
/*
* remove the chip from the system's chip list
*/
nchips--;
/*
* clean up any chip kstats
*/
if (chp->chip_kstat) {
}
/*
* If the chip_t structure was dynamically
* allocated, free it.
*/
}
}
/*
* This cpu is becoming active (online).
* Perform all the necessary bookkeeping in it's chip_t
*/
void
{
MUTEX_HELD(&cpu_lock));
/*
* Add this cpu to the chip's cpu list
*/
} else {
}
/*
* Notate this chip's seqid in the cpu partition's chipset
*/
}
/*
* This cpu is being offlined, so do the reverse
* of cpu_chip_assign()
*/
void
{
/*
* remove this cpu from the chip's cpu list
*/
}
}
/*
* Maintain the cpuparts' chip membership set.
* oldpp is NULL when a cpu is being offlined.
* newpp is NULL when a cpu is being onlined.
*/
void
{
/*
* Add the chip's seqid to the cpupart's chip set
*/
}
/*
* Another cpu on the chip is in the old
* cpu partition, so we're done
*/
return;
}
}
/*
* No other cpu on the chip is in the old partition
* so remove the chip's seqid from it's set
*/
}
}
/*
* Called to indicate a slave CPU has started up.
*/
void
{
/*
* Indicate that the chip has a new running thread
* (slave startup)
*/
}
/*
* Provide the specified CPU a bootstrap chip
*/
void
{
}
/*
* Given a chip set, return 1 if it is empty.
*/
int
{
int i;
for (i = 0; i < CHIP_SET_WORDS; i++) {
return (0);
}
return (1);
}