summaryrefslogtreecommitdiff
path: root/deleted_files
diff options
context:
space:
mode:
authoresaxe <none@none>2007-01-17 18:01:29 -0800
committeresaxe <none@none>2007-01-17 18:01:29 -0800
commitfb2f18f820d90b001aea4fb27dd654bc1263c440 (patch)
tree4b88b69e1244f360a85d70294a4498ecf57ca283 /deleted_files
parent9a7670889e9c36ec355371e6b02f2d9084f040dc (diff)
downloadillumos-gate-fb2f18f820d90b001aea4fb27dd654bc1263c440.tar.gz
6461311 multi-level CMT scheduling optimizations
6509639 cpu0 is not in the right chip_t if its chipid is not zero --HG-- rename : usr/src/uts/common/os/chip.c => deleted_files/usr/src/uts/common/os/chip.c rename : usr/src/uts/common/sys/chip.h => deleted_files/usr/src/uts/common/sys/chip.h
Diffstat (limited to 'deleted_files')
-rw-r--r--deleted_files/usr/src/uts/common/os/chip.c576
-rw-r--r--deleted_files/usr/src/uts/common/sys/chip.h207
2 files changed, 783 insertions, 0 deletions
diff --git a/deleted_files/usr/src/uts/common/os/chip.c b/deleted_files/usr/src/uts/common/os/chip.c
new file mode 100644
index 0000000000..ad11827b0f
--- /dev/null
+++ b/deleted_files/usr/src/uts/common/os/chip.c
@@ -0,0 +1,576 @@
+/*
+ * 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);
+}
diff --git a/deleted_files/usr/src/uts/common/sys/chip.h b/deleted_files/usr/src/uts/common/sys/chip.h
new file mode 100644
index 0000000000..8889756884
--- /dev/null
+++ b/deleted_files/usr/src/uts/common/sys/chip.h
@@ -0,0 +1,207 @@
+/*
+ * 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.
+ */
+
+#ifndef _CHIP_H
+#define _CHIP_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * generic kernel CMT processor support
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if (defined(_KERNEL) || defined(_KMEMUSER))
+#include <sys/cpuvar.h>
+#include <sys/processor.h>
+#include <sys/bitmap.h>
+#include <sys/atomic.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+/*
+ * Chip types
+ */
+typedef enum chip_type {
+ CHIP_DEFAULT, /* Default, non CMT processor */
+ CHIP_SMT, /* SMT, single core */
+ CHIP_CMP_SPLIT_CACHE, /* CMP with split caches */
+ CHIP_CMP_SHARED_CACHE, /* CMP with shared caches */
+ CHIP_CMT, /* CMT w/ multiple cores and threads */
+ CHIP_NUM_TYPES
+} chip_type_t;
+
+
+/*
+ * Balancing is possible if multiple chips exist in the lgroup
+ * but only necessary if the chip has multiple online logical CPUs
+ */
+#define CHIP_SHOULD_BALANCE(chp) \
+ (((chp)->chip_ncpu > 1) && ((chp)->chip_next_lgrp != (chp)))
+
+/*
+ * Platform's definition of a chip's properties
+ */
+typedef struct chip_def {
+ chip_type_t chipd_type;
+ int chipd_rechoose_adj;
+ hrtime_t chipd_nosteal;
+} chip_def_t;
+
+/*
+ * Per chip kstats
+ */
+typedef enum chip_stat_types {
+ CHIP_ID, /* chip "id" */
+ CHIP_NCPUS, /* number of active cpus */
+ CHIP_NRUNNING, /* number of running threads on chip */
+ CHIP_RECHOOSE, /* chip's rechoose_interval */
+ CHIP_NUM_STATS /* always last */
+} chip_stat_t;
+
+#define CHIP_KSTAT_NAMES \
+static char *chip_kstat_names[] = { \
+ \
+ "chip_id", \
+ "logical_cpus", \
+ "chip_nrunning", \
+ "chip_rechoose_interval", \
+}
+
+/*
+ * Physical processor (chip) structure.
+ */
+typedef struct chip {
+ chipid_t chip_id; /* chip's "id" */
+ chipid_t chip_seqid; /* sequential id */
+ struct chip *chip_prev; /* previous chip on list */
+ struct chip *chip_next; /* next chip on list */
+ struct chip *chip_prev_lgrp; /* prev chip in lgroup */
+ struct chip *chip_next_lgrp; /* next chip in lgroup */
+ chip_type_t chip_type; /* type of chip */
+ uint16_t chip_ncpu; /* number of active cpus */
+ uint16_t chip_ref; /* chip's reference count */
+ struct cpu *chip_cpus; /* per chip cpu list */
+ struct lgrp *chip_lgrp; /* chip lives in this lgroup */
+ int chip_rechoose_adj; /* chip specific adjustment */
+
+ /*
+ * chip kstats
+ */
+ kstat_t *chip_kstat;
+ kmutex_t chip_kstat_mutex;
+ struct kstat_named chip_kstat_data[CHIP_NUM_STATS];
+
+ struct chip *chip_balance; /* chip to balance against */
+ uint32_t chip_nrunning; /* # of running threads */
+ hrtime_t chip_nosteal; /* nosteal interval (nsecs) */
+} chip_t;
+
+/*
+ * IDs associating a CPU with various physical hardware
+ */
+typedef struct cpu_physid {
+ chipid_t cpu_chipid; /* CPU's physical processor */
+ id_t cpu_coreid; /* CPU's physical core */
+} cpu_physid_t;
+
+/*
+ * Change the number of running threads on the chip
+ */
+#define CHIP_NRUNNING(chp, n) { \
+ atomic_add_32(&((chp)->chip_nrunning), (n)); \
+}
+
+/*
+ * True if this CPU is active on the chip
+ */
+#define CHIP_CPU_ACTIVE(cp) ((cp)->cpu_next_chip != NULL)
+
+/*
+ * Sets of chips
+ * The "id" used here should be a chip's sequential id.
+ * (chip_seqid)
+ */
+#if defined(_MACHDEP)
+
+#define CHIP_MAX_CHIPS NCPU
+#define CHIP_SET_WORDS BT_BITOUL(CHIP_MAX_CHIPS)
+
+typedef struct chip_set {
+ ulong_t csb[CHIP_SET_WORDS];
+} chip_set_t;
+
+extern int chip_set_isnull(chip_set_t *);
+
+#define CHIP_SET_ISNULL(set) chip_set_isnull(&(set))
+#define CHIP_SET_TEST(set, id) BT_TEST((set).csb, id)
+#define CHIP_SET_REMOVE(set, id) BT_CLEAR((set).csb, id)
+#define CHIP_SET_ADD(set, id) BT_SET((set).csb, id)
+
+#define CHIP_SET_ZERO(set) { \
+ int _i; \
+ for (_i = 0; _i < CHIP_SET_WORDS; _i++) \
+ (set).csb[_i] = 0; \
+}
+
+#define CHIP_IN_CPUPART(chp, cp) \
+ (CHIP_SET_TEST((cp)->cp_mach->mc_chipset, (chp)->chip_seqid))
+
+#endif /* _MACHDEP */
+
+/*
+ * Common kernel chip operations
+ */
+void chip_cpu_init(cpu_t *);
+void chip_cpu_fini(cpu_t *);
+void chip_cpu_assign(cpu_t *);
+void chip_cpu_unassign(cpu_t *);
+void chip_cpu_startup(cpu_t *);
+chip_t *chip_lookup(chipid_t);
+void chip_bootstrap_cpu(cpu_t *);
+
+void chip_cpu_move_part(cpu_t *, struct cpupart *,
+ struct cpupart *);
+
+void chip_kstat_create(chip_t *);
+
+/*
+ * Platform chip operations
+ */
+chipid_t chip_plat_get_chipid(cpu_t *);
+id_t chip_plat_get_coreid(cpu_t *);
+int chip_plat_get_clogid(cpu_t *);
+void chip_plat_define_chip(cpu_t *, chip_def_t *);
+
+#endif /* !_KERNEL && !_KMEMUSER */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _CHIP_H */