| 1 | /* | 
| 2 |  * Copyright (c) 2003-2010 Apple Inc. All rights reserved. | 
| 3 |  * | 
| 4 |  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ | 
| 5 |  * | 
| 6 |  * This file contains Original Code and/or Modifications of Original Code | 
| 7 |  * as defined in and that are subject to the Apple Public Source License | 
| 8 |  * Version 2.0 (the 'License'). You may not use this file except in | 
| 9 |  * compliance with the License. The rights granted to you under the License | 
| 10 |  * may not be used to create, or enable the creation or redistribution of, | 
| 11 |  * unlawful or unlicensed copies of an Apple operating system, or to | 
| 12 |  * circumvent, violate, or enable the circumvention or violation of, any | 
| 13 |  * terms of an Apple operating system software license agreement. | 
| 14 |  * | 
| 15 |  * Please obtain a copy of the License at | 
| 16 |  * http://www.opensource.apple.com/apsl/ and read it before using this file. | 
| 17 |  * | 
| 18 |  * The Original Code and all software distributed under the License are | 
| 19 |  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | 
| 20 |  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | 
| 21 |  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | 
| 22 |  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | 
| 23 |  * Please see the License for the specific language governing rights and | 
| 24 |  * limitations under the License. | 
| 25 |  * | 
| 26 |  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ | 
| 27 |  */ | 
| 28 | #ifdef KERNEL_PRIVATE | 
| 29 | #ifndef _I386_CPU_TOPOLOGY_H_ | 
| 30 | #define _I386_CPU_TOPOLOGY_H_ | 
| 31 |  | 
| 32 | /* | 
| 33 |  * This was originally part of cpu_threads.h.  It was split out so that | 
| 34 |  * these structures could be referenced without pulling in all of the headers | 
| 35 |  * required for the definition of cpu_data.  These data structures are | 
| 36 |  * used by KEXTs in order to deal with the physical topology. | 
| 37 |  * | 
| 38 |  * NOTE: this header must stand on its own as much as possible | 
| 39 |  * and not be dependent upon any unexported, kernel-private header. | 
| 40 |  */ | 
| 41 |  | 
| 42 | /* | 
| 43 |  * Cache structure that can be used to identify the cache heirarchy. | 
| 44 |  */ | 
| 45 | typedef struct x86_cpu_cache { | 
| 46 | 	struct x86_cpu_cache *next;     /* next cache at this level/lcpu */ | 
| 47 | 	struct x86_die      *die;       /* die containing this cache (only for LLC) */ | 
| 48 | 	uint8_t             maxcpus;    /* maximum # of cpus that can share */ | 
| 49 | 	uint8_t             nlcpus;     /* # of logical cpus sharing this cache */ | 
| 50 | 	uint8_t             type;       /* type of cache */ | 
| 51 | 	uint8_t             level;      /* level of cache */ | 
| 52 | 	uint16_t            ways;       /* # of ways in cache */ | 
| 53 | 	uint16_t            partitions; /* # of partitions in cache */ | 
| 54 | 	uint16_t            line_size;  /* size of a cache line */ | 
| 55 | 	uint32_t            cache_size; /* total size of cache */ | 
| 56 | 	struct x86_lcpu     *cpus[0];   /* cpus sharing this cache */ | 
| 57 | } x86_cpu_cache_t; | 
| 58 |  | 
| 59 | #define CPU_CACHE_TYPE_DATA     1       /* data cache */ | 
| 60 | #define CPU_CACHE_TYPE_INST     2       /* instruction cache */ | 
| 61 | #define CPU_CACHE_TYPE_UNIF     3       /* unified cache */ | 
| 62 |  | 
| 63 | #define CPU_CACHE_DEPTH_L1      0 | 
| 64 | #define CPU_CACHE_DEPTH_L2      1 | 
| 65 | #define CPU_CACHE_DEPTH_L3      2 | 
| 66 |  | 
| 67 | #define MAX_CACHE_DEPTH         3       /* deepest cache */ | 
| 68 |  | 
| 69 | struct pmc; | 
| 70 | struct cpu_data; | 
| 71 | struct mca_state; | 
| 72 |  | 
| 73 | /* | 
| 74 |  * Define the states that a (logical) CPU can be in. | 
| 75 |  * | 
| 76 |  * LCPU_OFF	This indicates that the CPU is "off".  It requires a full | 
| 77 |  *		restart.  This is the state of a CPU when the system first | 
| 78 |  *		boots or when it comes out of "sleep" (aka S3/S5). | 
| 79 |  * | 
| 80 |  * LCPU_HALT	This indicates that the CPU has been "halted".  It has been | 
| 81 |  *		removed from the system but still retains its internal state | 
| 82 |  *		so that it can be quickly brought back on-line. | 
| 83 |  * | 
| 84 |  * LCPU_NONSCHED	This indicates that the CPU is not schedulable.  It | 
| 85 |  *		will still appear in the system as a viable CPU however no | 
| 86 |  *		work will be sceduled on it. | 
| 87 |  * | 
| 88 |  * LCPU_PAUSE	This indicates that the CPU is "paused".  This is usually | 
| 89 |  *		done only during kernel debug. | 
| 90 |  * | 
| 91 |  * LCPU_IDLE	This indicates that the CPU is idle.  The scheduler has | 
| 92 |  *		determined that there is no work for this CPU to do. | 
| 93 |  * | 
| 94 |  * LCPU_RUN	This indicates that the CPU is running code and performing work. | 
| 95 |  * | 
| 96 |  * In normal system operation, CPUs will usually be transitioning between | 
| 97 |  * LCPU_IDLE and LCPU_RUN. | 
| 98 |  */ | 
| 99 | typedef enum lcpu_state { | 
| 100 | 	LCPU_OFF            = 0,/* 0 so the right thing happens on boot */ | 
| 101 | 	LCPU_HALT           = 1, | 
| 102 | 	LCPU_NONSCHED       = 2, | 
| 103 | 	LCPU_PAUSE          = 3, | 
| 104 | 	LCPU_IDLE           = 4, | 
| 105 | 	LCPU_RUN            = 5, | 
| 106 | } lcpu_state_t; | 
| 107 |  | 
| 108 | /* | 
| 109 |  * In each topology structure there are two numbers: a logical number and a | 
| 110 |  * physical number. | 
| 111 |  * | 
| 112 |  * The logical numbers represent the ID of that structure | 
| 113 |  * relative to the enclosing structure and always starts at 0.  So when using | 
| 114 |  * logical numbers, it is necessary to specify all elements in the topology | 
| 115 |  * (ie to "name" a logical CPU using logical numbers, 4 numbers are required: | 
| 116 |  * package, die, core, logical CPU). | 
| 117 |  * | 
| 118 |  * The physical numbers represent the ID of that structure and is unique (for | 
| 119 |  * that structure) across the entire topology. | 
| 120 |  * | 
| 121 |  * The logical CPU structure contains a third number which is the CPU number. | 
| 122 |  * This number is identical to the CPU number used in other parts of the kernel. | 
| 123 |  */ | 
| 124 | typedef struct x86_lcpu { | 
| 125 | 	struct x86_lcpu     *next_in_core;/* next logical cpu in core */ | 
| 126 | 	struct x86_lcpu     *next_in_die;/* next logical cpu in die */ | 
| 127 | 	struct x86_lcpu     *next_in_pkg;/* next logical cpu in package */ | 
| 128 | 	struct x86_lcpu     *lcpu;      /* pointer back to self */ | 
| 129 | 	struct x86_core     *core;      /* core containing the logical cpu */ | 
| 130 | 	struct x86_die      *die;       /* die containing the logical cpu */ | 
| 131 | 	struct x86_pkg      *package;   /* package containing the logical cpu */ | 
| 132 | 	struct cpu_data     *cpu;       /* cpu_data structure */ | 
| 133 | 	uint32_t            flags; | 
| 134 | 	uint32_t            cpu_num;    /* cpu number */ | 
| 135 | 	uint32_t            lnum;       /* logical cpu number (within core) */ | 
| 136 | 	uint32_t            pnum;       /* physical cpu number */ | 
| 137 | 	boolean_t           master;     /* logical cpu is the master (boot) CPU */ | 
| 138 | 	boolean_t           primary;    /* logical cpu is primary CPU in package */ | 
| 139 | 	volatile lcpu_state_t       state;/* state of the logical CPU */ | 
| 140 | 	volatile boolean_t  stopped;    /* used to indicate that the CPU has "stopped" */ | 
| 141 | 	uint64_t            rtcPop;     /* next timer pop programmed */ | 
| 142 | 	uint64_t            rtcDeadline;/* next etimer-requested deadline */ | 
| 143 | 	x86_cpu_cache_t     *caches[MAX_CACHE_DEPTH]; | 
| 144 | 	void                *pmStats;   /* Power management stats for lcpu */ | 
| 145 | 	void                *pmState;   /* Power management state for lcpu */ | 
| 146 | } x86_lcpu_t; | 
| 147 |  | 
| 148 | #define X86CORE_FL_PRESENT      0x80000000      /* core is present */ | 
| 149 | #define X86CORE_FL_READY        0x40000000      /* core struct is init'd */ | 
| 150 | #define X86CORE_FL_HAS_HPET     0x10000000      /* core has HPET assigned */ | 
| 151 | #define X86CORE_FL_HALTED       0x00008000      /* core is halted */ | 
| 152 | #define X86CORE_FL_IDLE         0x00004000      /* core is idle */ | 
| 153 |  | 
| 154 | typedef struct x86_core { | 
| 155 | 	struct x86_core     *next_in_die;/* next core in die */ | 
| 156 | 	struct x86_core     *next_in_pkg;/* next core in package */ | 
| 157 | 	struct x86_die      *die;       /* die containing the core */ | 
| 158 | 	struct x86_pkg      *package;   /* package containing core */ | 
| 159 | 	struct x86_lcpu     *lcpus;     /* list of logical cpus in core */ | 
| 160 | 	uint32_t            flags; | 
| 161 | 	uint32_t            lcore_num;  /* logical core # (unique within die) */ | 
| 162 | 	uint32_t            pcore_num;  /* physical core # (globally unique) */ | 
| 163 | 	uint32_t            num_lcpus;  /* Number of logical cpus */ | 
| 164 | 	uint32_t            active_lcpus;/* Number of {running, idle} cpus */ | 
| 165 | 	void                *pmStats;   /* Power management stats for core */ | 
| 166 | 	void                *pmState;   /* Power management state for core */ | 
| 167 | } x86_core_t; | 
| 168 |  | 
| 169 | #define X86DIE_FL_PRESENT       0x80000000      /* die is present */ | 
| 170 | #define X86DIE_FL_READY         0x40000000      /* die struct is init'd */ | 
| 171 |  | 
| 172 | typedef struct x86_die { | 
| 173 | 	struct x86_die      *next_in_pkg;/* next die in package */ | 
| 174 | 	struct x86_lcpu     *lcpus;     /* list of lcpus in die */ | 
| 175 | 	struct x86_core     *cores;     /* list of cores in die */ | 
| 176 | 	struct x86_pkg      *package;   /* package containing the die */ | 
| 177 | 	uint32_t            flags; | 
| 178 | 	uint32_t            ldie_num;   /* logical die # (unique to package) */ | 
| 179 | 	uint32_t            pdie_num;   /* physical die # (globally unique) */ | 
| 180 | 	uint32_t            num_cores;  /* Number of cores in die */ | 
| 181 | 	x86_cpu_cache_t     *LLC;       /* LLC contained in this die */ | 
| 182 | 	void                *pmStats;   /* Power Management stats for die */ | 
| 183 | 	void                *pmState;   /* Power Management state for die */ | 
| 184 | } x86_die_t; | 
| 185 |  | 
| 186 | #define X86PKG_FL_PRESENT       0x80000000      /* package is present */ | 
| 187 | #define X86PKG_FL_READY         0x40000000      /* package struct init'd */ | 
| 188 | #define X86PKG_FL_HAS_HPET      0x10000000      /* package has HPET assigned */ | 
| 189 | #define X86PKG_FL_HALTED        0x00008000      /* package is halted */ | 
| 190 | #define X86PKG_FL_IDLE          0x00004000      /* package is idle */ | 
| 191 |  | 
| 192 | typedef struct x86_pkg { | 
| 193 | 	struct x86_pkg      *next;      /* next package */ | 
| 194 | 	struct x86_lcpu     *lcpus;     /* list of logical cpus in package */ | 
| 195 | 	struct x86_core     *cores;     /* list of cores in package */ | 
| 196 | 	struct x86_die      *dies;      /* list of dies in package */ | 
| 197 | 	uint32_t            flags; | 
| 198 | 	uint32_t            lpkg_num;   /* logical package # */ | 
| 199 | 	uint32_t            ppkg_num;   /* physical package # */ | 
| 200 | 	uint32_t            num_dies;   /* number of dies in package */ | 
| 201 | 	void                *pmStats;   /* Power Management stats for package*/ | 
| 202 | 	void                *pmState;   /* Power Management state for package*/ | 
| 203 | 	struct mca_state    *mca_state; /* MCA state for memory errors */ | 
| 204 | 	uint64_t            package_idle_exits; | 
| 205 | 	uint32_t            num_idle; | 
| 206 | } x86_pkg_t; | 
| 207 |  | 
| 208 | extern x86_pkg_t        *x86_pkgs;      /* root of all CPU packages */ | 
| 209 |  | 
| 210 | typedef struct x86_topology_parameters { | 
| 211 | 	uint32_t            LLCDepth; | 
| 212 | 	uint32_t            nCoresSharingLLC; | 
| 213 | 	uint32_t            nLCPUsSharingLLC; | 
| 214 | 	uint32_t            maxSharingLLC; | 
| 215 | 	uint32_t            nLThreadsPerCore; | 
| 216 | 	uint32_t            nPThreadsPerCore; | 
| 217 | 	uint32_t            nLCoresPerDie; | 
| 218 | 	uint32_t            nPCoresPerDie; | 
| 219 | 	uint32_t            nLDiesPerPackage; | 
| 220 | 	uint32_t            nPDiesPerPackage; | 
| 221 | 	uint32_t            nLThreadsPerDie; | 
| 222 | 	uint32_t            nPThreadsPerDie; | 
| 223 | 	uint32_t            nLThreadsPerPackage; | 
| 224 | 	uint32_t            nPThreadsPerPackage; | 
| 225 | 	uint32_t            nLCoresPerPackage; | 
| 226 | 	uint32_t            nPCoresPerPackage; | 
| 227 | 	uint32_t            nPackages; | 
| 228 | 	boolean_t           stable; | 
| 229 | } x86_topology_parameters_t; | 
| 230 |  | 
| 231 | /* Called after cpu discovery */ | 
| 232 | extern void             cpu_topology_sort(int ncpus); | 
| 233 | extern kern_return_t    cpu_topology_start_cpu(int cpunum); | 
| 234 |  | 
| 235 |  | 
| 236 | #endif /* _I386_CPU_TOPOLOGY_H_ */ | 
| 237 | #endif /* KERNEL_PRIVATE */ | 
| 238 |  |