summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/os/chip.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/os/chip.c')
-rw-r--r--usr/src/uts/common/os/chip.c576
1 files changed, 0 insertions, 576 deletions
diff --git a/usr/src/uts/common/os/chip.c b/usr/src/uts/common/os/chip.c
deleted file mode 100644
index ad11827b0f..0000000000
--- a/usr/src/uts/common/os/chip.c
+++ /dev/null
@@ -1,576 +0,0 @@
-/*
- * 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
- * or http://www.opensolaris.org/os/licensing.
- * 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/types.h>
-#include <sys/param.h>
-#include <sys/thread.h>
-#include <sys/cpuvar.h>
-#include <sys/cpupart.h>
-#include <sys/kmem.h>
-#include <sys/cmn_err.h>
-#include <sys/kstat.h>
-#include <sys/processor.h>
-#include <sys/disp.h>
-#include <sys/chip.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_t cpu0_chip; /* chip structure for first CPU */
-cpu_physid_t cpu0_physid; /* boot CPU's physical id structure */
-
-/*
- * 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) \
- ((cp)->cpu_chip == NULL || (cp)->cpu_chip == &chip_bootstrap)
-
-static chip_t *chip_list; /* protected by CPU lock */
-static chip_set_t chip_set; /* bitmap of chips in existence */
- /* indexed by chip_seqid */
-static chipid_t chip_seqid_next = 0; /* next sequential chip id */
-static int nchips = 0; /* num chips in existence */
-
-static chip_t *chip_find(chipid_t);
-static int chip_kstat_extract(kstat_t *, int);
-
-/*
- * Declare static kstat names (defined in chip.h)
- */
-CHIP_KSTAT_NAMES;
-
-/*
- * Find the chip_t with the given chip_id.
- */
-static chip_t *
-chip_find(chipid_t chipid)
-{
- chip_t *chp, *chip_start;
-
- ASSERT(chip_list == NULL || chip_list->chip_next == chip_list ||
- MUTEX_HELD(&cpu_lock));
-
- if ((chp = chip_start = chip_list) != NULL) {
- do {
- if (chp->chip_id == chipid) {
- return (chp);
- }
- } while ((chp = chp->chip_next) != chip_start);
- }
- return (NULL);
-}
-
-chip_t *
-chip_lookup(chipid_t chipid)
-{
- chip_t *chp;
-
- mutex_enter(&cpu_lock);
- chp = chip_find(chipid);
- mutex_exit(&cpu_lock);
-
- return (chp);
-}
-
-#ifndef sun4v
-/*
- * Setup the kstats for this chip, if needed
- */
-void
-chip_kstat_create(chip_t *chp)
-{
- chip_stat_t stat;
- kstat_t *chip_kstat;
-
- ASSERT(MUTEX_HELD(&cpu_lock));
-
- if (chp->chip_kstat != NULL)
- return; /* already initialized */
-
- chip_kstat = kstat_create("chip", chp->chip_id, NULL, "misc",
- KSTAT_TYPE_NAMED, CHIP_NUM_STATS,
- KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE);
-
- if (chip_kstat != NULL) {
- chip_kstat->ks_lock = &chp->chip_kstat_mutex;
- mutex_init(chip_kstat->ks_lock, NULL, MUTEX_DEFAULT, NULL);
- chip_kstat->ks_private = chp;
- chip_kstat->ks_data = chp->chip_kstat_data;
- for (stat = 0; stat < CHIP_NUM_STATS; stat++)
- kstat_named_init(&chp->chip_kstat_data[stat],
- chip_kstat_names[stat], KSTAT_DATA_INT64);
- chip_kstat->ks_update = chip_kstat_extract;
- chp->chip_kstat = chip_kstat;
- kstat_install(chip_kstat);
- }
-}
-#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
-chip_kstat_create(chip_t *chp)
-{
-}
-#endif /* !sun4v */
-
-static int
-chip_kstat_extract(kstat_t *ksp, int rw)
-{
- struct kstat_named *ksd;
- chip_t *chp;
-
- chp = (chip_t *)ksp->ks_private;
-
- ksd = (struct kstat_named *)ksp->ks_data;
- ASSERT(ksd == chp->chip_kstat_data);
-
- /*
- * The chip kstats are read only
- */
- if (rw == KSTAT_WRITE)
- return (EACCES);
-
- ksd[CHIP_ID].value.i64 = chp->chip_id;
- ksd[CHIP_NCPUS].value.i64 = chp->chip_ncpu;
- ksd[CHIP_NRUNNING].value.i64 = chp->chip_nrunning;
- ksd[CHIP_RECHOOSE].value.i64 =
- rechoose_interval + chp->chip_rechoose_adj;
-
- 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
-chip_cpu_init(cpu_t *cp)
-{
- chipid_t cid;
- int rechoose;
- chip_t *chp;
- chip_def_t chp_def;
-
- ASSERT((chip_list == NULL) || (MUTEX_HELD(&cpu_lock)));
-
- if (chip_list == NULL)
- cp->cpu_physid = &cpu0_physid;
- else
- cp->cpu_physid = kmem_zalloc(sizeof (cpu_physid_t), KM_SLEEP);
-
- /*
- * 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
- cid = chip_plat_get_coreid(cp);
- cp->cpu_physid->cpu_coreid = cid;
- cp->cpu_physid->cpu_chipid = chip_plat_get_chipid(cp);
-#else
- cid = chip_plat_get_chipid(cp);
- cp->cpu_physid->cpu_chipid = cid;
- cp->cpu_physid->cpu_coreid = chip_plat_get_coreid(cp);
-#endif /* DO_CORELEVEL_LOADBAL */
-
- chp = chip_find(cid);
- if (chp == NULL) {
-
- /*
- * Create a new chip
- */
- if (chip_list == NULL)
- chp = &cpu0_chip;
- else
- chp = kmem_zalloc(sizeof (*chp), KM_SLEEP);
-
- chp->chip_id = cid;
- chp->chip_nrunning = 0;
-
- /*
- * If we're booting, take this moment to perform
- * some additional initialization
- */
- if (chip_list == NULL) {
- CHIP_SET_ZERO(chip_set);
- CHIP_SET_ZERO(cp->cpu_part->cp_mach->mc_chipset);
- chp->chip_nrunning++; /* for t0 */
- }
-
- /*
- * 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.
- */
- while (CHIP_SET_TEST(chip_set, chip_seqid_next))
- chip_seqid_next++;
- chp->chip_seqid = chip_seqid_next++;
- CHIP_SET_ADD(chip_set, chp->chip_seqid);
-
- ASSERT(chip_seqid_next <= CHIP_MAX_CHIPS);
-
-
- /*
- * Query the platform specific parameters
- * for this chip
- */
- chip_plat_define_chip(cp, &chp_def);
- chp->chip_rechoose_adj = chp_def.chipd_rechoose_adj;
- chp->chip_type = chp_def.chipd_type;
- chp->chip_nosteal = chp_def.chipd_nosteal;
-
- ASSERT((chp->chip_type < CHIP_NUM_TYPES) &&
- (chp->chip_type >= CHIP_DEFAULT));
-
- /*
- * Insert this chip in chip_list
- */
- if (chip_list == NULL) {
- chip_list = chp;
- chp->chip_next = chp->chip_prev = chp;
- } else {
- chip_t *chptr;
-
- chptr = chip_list;
- chp->chip_next = chptr;
- chp->chip_prev = chptr->chip_prev;
- chptr->chip_prev->chip_next = chp;
- chptr->chip_prev = chp;
- }
-
- nchips++;
- ASSERT(nchips <= CHIP_MAX_CHIPS);
-
- /*
- * The boot cpu will create the first chip's kstats
- * later in cpu_kstat_init()
- */
- if (chp != &cpu0_chip)
- chip_kstat_create(chp);
- }
-
- /*
- * Initialize the effective rechoose interval cached
- * in this cpu structure.
- */
- rechoose = rechoose_interval + chp->chip_rechoose_adj;
- cp->cpu_rechoose = (rechoose < 0) ? 0 : rechoose;
-
- cp->cpu_chip = chp;
- chp->chip_ref++;
-}
-
-/*
- * This cpu is being deleted. It has already been removed from
- * the chip's active cpu list back in chip_cpu_unassign(). Here
- * we remove the cpu's reference to the chip, and cleanup/destroy
- * the chip if needed.
- */
-void
-chip_cpu_fini(cpu_t *cp)
-{
- chip_t *chp;
- chip_t *prev, *next;
-
- ASSERT(MUTEX_HELD(&cpu_lock));
-
- /*
- * This can happen if the CPU failed to power on
- */
- if (CPU_HAS_NO_CHIP(cp))
- return;
-
- chp = cp->cpu_chip;
- cp->cpu_chip = NULL;
-
- /*
- * Clear out and free the CPU's physical id structure
- */
- cp->cpu_physid->cpu_chipid = -1;
- cp->cpu_physid->cpu_coreid = -1;
-
- if (cp->cpu_physid != &cpu0_physid) {
- ASSERT(cp->cpu_physid != NULL);
- kmem_free(cp->cpu_physid, sizeof (cpu_physid_t));
- }
- cp->cpu_physid = NULL;
-
- /*
- * Delete the chip if its last CPU is being deleted
- */
- if (--chp->chip_ref == 0) {
-
- ASSERT(chp->chip_ncpu == 0);
- ASSERT(chp->chip_cpus == NULL);
- ASSERT(chp->chip_nrunning == 0);
- ASSERT(chp->chip_lgrp == NULL);
- ASSERT((chp->chip_next_lgrp == NULL) &&
- (chp->chip_prev_lgrp == NULL));
-
- if (chip_seqid_next > chp->chip_seqid)
- chip_seqid_next = chp->chip_seqid;
- CHIP_SET_REMOVE(chip_set, chp->chip_seqid);
-
- chp->chip_id = -1;
- chp->chip_seqid = -1;
-
- /*
- * remove the chip from the system's chip list
- */
- if (chip_list == chp)
- chip_list = chp->chip_next;
-
- prev = chp->chip_prev;
- next = chp->chip_next;
-
- prev->chip_next = next;
- next->chip_prev = prev;
-
- chp->chip_next = chp->chip_prev = NULL;
-
- nchips--;
-
- /*
- * clean up any chip kstats
- */
- if (chp->chip_kstat) {
- kstat_delete(chp->chip_kstat);
- chp->chip_kstat = NULL;
- }
- /*
- * If the chip_t structure was dynamically
- * allocated, free it.
- */
- if (chp != &cpu0_chip)
- kmem_free(chp, sizeof (*chp));
- }
-}
-
-/*
- * This cpu is becoming active (online).
- * Perform all the necessary bookkeeping in it's chip_t
- */
-void
-chip_cpu_assign(cpu_t *cp)
-{
- chip_t *chp;
- cpu_t *cptr;
-
- ASSERT(chip_list == NULL || chip_list->chip_next == chip_list ||
- MUTEX_HELD(&cpu_lock));
-
- chp = cp->cpu_chip;
-
- /*
- * Add this cpu to the chip's cpu list
- */
- if (chp->chip_ncpu == 0) {
- chp->chip_cpus = cp;
- cp->cpu_next_chip = cp->cpu_prev_chip = cp;
- } else {
- cptr = chp->chip_cpus;
- cp->cpu_next_chip = cptr;
- cp->cpu_prev_chip = cptr->cpu_prev_chip;
- cp->cpu_prev_chip->cpu_next_chip = cp;
- cptr->cpu_prev_chip = cp;
- }
-
- chp->chip_ncpu++;
-
- /*
- * Notate this chip's seqid in the cpu partition's chipset
- */
- chip_cpu_move_part(cp, NULL, cp->cpu_part);
-}
-
-/*
- * This cpu is being offlined, so do the reverse
- * of cpu_chip_assign()
- */
-void
-chip_cpu_unassign(cpu_t *cp)
-{
- chip_t *chp;
- struct cpu *prev;
- struct cpu *next;
-
- ASSERT(MUTEX_HELD(&cpu_lock));
-
- chp = cp->cpu_chip;
-
- chip_cpu_move_part(cp, cp->cpu_part, NULL);
-
- /*
- * remove this cpu from the chip's cpu list
- */
- prev = cp->cpu_prev_chip;
- next = cp->cpu_next_chip;
-
- prev->cpu_next_chip = next;
- next->cpu_prev_chip = prev;
-
- cp->cpu_next_chip = cp->cpu_prev_chip = NULL;
-
- chp->chip_ncpu--;
-
- if (chp->chip_ncpu == 0) {
- chp->chip_cpus = NULL;
- } else if (chp->chip_cpus == cp) {
- chp->chip_cpus = next;
- }
-}
-
-/*
- * A cpu on the chip is moving into and/or out of a cpu partition.
- * 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
-chip_cpu_move_part(cpu_t *cp, cpupart_t *oldpp, cpupart_t *newpp)
-{
- cpu_t *cpp;
- chip_t *chp;
-
- ASSERT(chip_list->chip_next == chip_list || MUTEX_HELD(&cpu_lock));
-
- chp = cp->cpu_chip;
-
- if (newpp != NULL) {
- /*
- * Add the chip's seqid to the cpupart's chip set
- */
- CHIP_SET_ADD(newpp->cp_mach->mc_chipset, chp->chip_seqid);
- }
-
- if (oldpp != NULL) {
- cpp = cp;
- while ((cpp = cpp->cpu_next_chip) != cp) {
- if (cpp->cpu_part->cp_id == oldpp->cp_id) {
- /*
- * 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
- */
- CHIP_SET_REMOVE(oldpp->cp_mach->mc_chipset, chp->chip_seqid);
- }
-}
-
-/*
- * Called to indicate a slave CPU has started up.
- */
-void
-chip_cpu_startup(cpu_t *cp)
-{
- /*
- * Indicate that the chip has a new running thread
- * (slave startup)
- */
- CHIP_NRUNNING(cp->cpu_chip, 1);
-}
-
-/*
- * Provide the specified CPU a bootstrap chip
- */
-void
-chip_bootstrap_cpu(cpu_t *cp)
-{
- cp->cpu_chip = &chip_bootstrap;
-}
-
-/*
- * Given a chip set, return 1 if it is empty.
- */
-int
-chip_set_isnull(chip_set_t *set)
-{
- int i;
-
- for (i = 0; i < CHIP_SET_WORDS; i++) {
- if (set->csb[i] != 0)
- return (0);
- }
- return (1);
-}