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 */
45typedef struct x86_cpu_cache
46{
47    struct x86_cpu_cache *next;		/* next cache at this level/lcpu */
48    struct x86_die	*die;		/* die containing this cache (only for LLC) */
49    uint8_t		maxcpus;	/* maximum # of cpus that can share */
50    uint8_t		nlcpus;		/* # of logical cpus sharing this cache */
51    uint8_t		type;		/* type of cache */
52    uint8_t		level;		/* level of cache */
53    uint16_t		ways;		/* # of ways in cache */
54    uint16_t		partitions;	/* # of partitions in cache */
55    uint16_t		line_size;	/* size of a cache line */
56    uint32_t		cache_size;	/* total size of cache */
57    struct x86_lcpu	*cpus[0];	/* cpus sharing this cache */
58} x86_cpu_cache_t;
59
60#define CPU_CACHE_TYPE_DATA	1	/* data cache */
61#define CPU_CACHE_TYPE_INST	2	/* instruction cache */
62#define CPU_CACHE_TYPE_UNIF	3	/* unified cache */
63
64#define CPU_CACHE_DEPTH_L1	0
65#define CPU_CACHE_DEPTH_L2	1
66#define CPU_CACHE_DEPTH_L3	2
67
68#define MAX_CACHE_DEPTH		3	/* deepest cache */
69
70struct pmc;
71struct cpu_data;
72struct mca_state;
73
74/*
75 * Define the states that a (logical) CPU can be in.
76 *
77 * LCPU_OFF	This indicates that the CPU is "off".  It requires a full
78 *		restart.  This is the state of a CPU when the system first
79 *		boots or when it comes out of "sleep" (aka S3/S5).
80 *
81 * LCPU_HALT	This indicates that the CPU has been "halted".  It has been
82 *		removed from the system but still retains its internal state
83 *		so that it can be quickly brought back on-line.
84 *
85 * LCPU_NONSCHED	This indicates that the CPU is not schedulable.  It
86 *		will still appear in the system as a viable CPU however no
87 *		work will be sceduled on it.
88 *
89 * LCPU_PAUSE	This indicates that the CPU is "paused".  This is usually
90 *		done only during kernel debug.
91 *
92 * LCPU_IDLE	This indicates that the CPU is idle.  The scheduler has
93 *		determined that there is no work for this CPU to do.
94 *
95 * LCPU_RUN	This indicates that the CPU is running code and performing work.
96 *
97 * In normal system operation, CPUs will usually be transitioning between
98 * LCPU_IDLE and LCPU_RUN.
99 */
100typedef enum lcpu_state
101{
102    LCPU_OFF		= 0,	/* 0 so the right thing happens on boot */
103    LCPU_HALT		= 1,
104    LCPU_NONSCHED	= 2,
105    LCPU_PAUSE		= 3,
106    LCPU_IDLE		= 4,
107    LCPU_RUN		= 5,
108} lcpu_state_t;
109
110/*
111 * In each topology structure there are two numbers: a logical number and a
112 * physical number.
113 *
114 * The logical numbers represent the ID of that structure
115 * relative to the enclosing structure and always starts at 0.  So when using
116 * logical numbers, it is necessary to specify all elements in the topology
117 * (ie to "name" a logical CPU using logical numbers, 4 numbers are required:
118 * package, die, core, logical CPU).
119 *
120 * The physical numbers represent the ID of that structure and is unique (for
121 * that structure) across the entire topology.
122 *
123 * The logical CPU structure contains a third number which is the CPU number.
124 * This number is identical to the CPU number used in other parts of the kernel.
125 */
126typedef struct x86_lcpu
127{
128    struct x86_lcpu	*next_in_core;	/* next logical cpu in core */
129    struct x86_lcpu	*next_in_die;	/* next logical cpu in die */
130    struct x86_lcpu	*next_in_pkg;	/* next logical cpu in package */
131    struct x86_lcpu	*lcpu;		/* pointer back to self */
132    struct x86_core	*core;		/* core containing the logical cpu */
133    struct x86_die	*die;		/* die containing the logical cpu */
134    struct x86_pkg	*package;	/* package containing the logical cpu */
135    struct cpu_data	*cpu;		/* cpu_data structure */
136    uint32_t		flags;
137    uint32_t		cpu_num;	/* cpu number */
138    uint32_t		lnum;		/* logical cpu number (within core) */
139    uint32_t		pnum;		/* physical cpu number */
140    boolean_t		master;		/* logical cpu is the master (boot) CPU */
141    boolean_t		primary;	/* logical cpu is primary CPU in package */
142    volatile lcpu_state_t	state;	/* state of the logical CPU */
143    volatile boolean_t	stopped;	/* used to indicate that the CPU has "stopped" */
144    uint64_t		rtcPop;		/* next timer pop programmed */
145    uint64_t		rtcDeadline;	/* next etimer-requested deadline */
146    x86_cpu_cache_t	*caches[MAX_CACHE_DEPTH];
147    void		*pmStats;	/* Power management stats for lcpu */
148    void		*pmState;	/* Power management state for lcpu */
149} x86_lcpu_t;
150
151#define X86CORE_FL_PRESENT	0x80000000	/* core is present */
152#define X86CORE_FL_READY	0x40000000	/* core struct is init'd */
153#define X86CORE_FL_HAS_HPET	0x10000000	/* core has HPET assigned */
154#define X86CORE_FL_HALTED	0x00008000	/* core is halted */
155#define X86CORE_FL_IDLE		0x00004000	/* core is idle */
156
157typedef struct x86_core
158{
159    struct x86_core	*next_in_die;	/* next core in die */
160    struct x86_core	*next_in_pkg;	/* next core in package */
161    struct x86_die	*die;		/* die containing the core */
162    struct x86_pkg	*package;	/* package containing core */
163    struct x86_lcpu	*lcpus;		/* list of logical cpus in core */
164    uint32_t		flags;
165    uint32_t		lcore_num;	/* logical core # (unique within die) */
166    uint32_t		pcore_num;	/* physical core # (globally unique) */
167    uint32_t		num_lcpus;	/* Number of logical cpus */
168    uint32_t		active_lcpus;	/* Number of {running, idle} cpus */
169    void		*pmStats;	/* Power management stats for core */
170    void		*pmState;	/* Power management state for core */
171} x86_core_t;
172
173#define X86DIE_FL_PRESENT	0x80000000	/* die is present */
174#define X86DIE_FL_READY		0x40000000	/* die struct is init'd */
175
176typedef struct x86_die
177{
178    struct x86_die	*next_in_pkg;	/* next die in package */
179    struct x86_lcpu	*lcpus;		/* list of lcpus in die */
180    struct x86_core	*cores;		/* list of cores in die */
181    struct x86_pkg	*package;	/* package containing the die */
182    uint32_t		flags;
183    uint32_t		ldie_num;	/* logical die # (unique to package) */
184    uint32_t		pdie_num;	/* physical die # (globally unique) */
185    uint32_t		num_cores;	/* Number of cores in die */
186    x86_cpu_cache_t	*LLC;		/* LLC contained in this die */
187    void		*pmStats;	/* Power Management stats for die */
188    void		*pmState;	/* Power Management state for die */
189} x86_die_t;
190
191#define X86PKG_FL_PRESENT	0x80000000	/* package is present */
192#define X86PKG_FL_READY		0x40000000	/* package struct init'd */
193#define X86PKG_FL_HAS_HPET	0x10000000	/* package has HPET assigned */
194#define X86PKG_FL_HALTED	0x00008000	/* package is halted */
195#define X86PKG_FL_IDLE		0x00004000	/* package is idle */
196
197typedef struct x86_pkg
198{
199    struct x86_pkg	*next;		/* next package */
200    struct x86_lcpu	*lcpus;		/* list of logical cpus in package */
201    struct x86_core	*cores;		/* list of cores in package */
202    struct x86_die	*dies;		/* list of dies in package */
203    uint32_t		flags;
204    uint32_t		lpkg_num;	/* logical package # */
205    uint32_t		ppkg_num;	/* physical package # */
206    uint32_t		num_dies;	/* number of dies in package */
207    void		*pmStats;	/* Power Management stats for package*/
208    void		*pmState;	/* Power Management state for package*/
209    struct mca_state	*mca_state;	/* MCA state for memory errors */
210    uint64_t		package_idle_exits;
211    uint32_t		num_idle;
212} x86_pkg_t;
213
214extern x86_pkg_t	*x86_pkgs;	/* root of all CPU packages */
215
216typedef struct x86_topology_parameters
217{
218    uint32_t		LLCDepth;
219    uint32_t		nCoresSharingLLC;
220    uint32_t		nLCPUsSharingLLC;
221    uint32_t		maxSharingLLC;
222    uint32_t		nLThreadsPerCore;
223    uint32_t		nPThreadsPerCore;
224    uint32_t		nLCoresPerDie;
225    uint32_t		nPCoresPerDie;
226    uint32_t		nLDiesPerPackage;
227    uint32_t		nPDiesPerPackage;
228    uint32_t		nLThreadsPerDie;
229    uint32_t		nPThreadsPerDie;
230    uint32_t		nLThreadsPerPackage;
231    uint32_t		nPThreadsPerPackage;
232    uint32_t		nLCoresPerPackage;
233    uint32_t		nPCoresPerPackage;
234    uint32_t		nPackages;
235    boolean_t		stable;
236} x86_topology_parameters_t;
237
238/* Called after cpu discovery */
239extern void		cpu_topology_sort(int ncpus);
240extern kern_return_t	cpu_topology_start_cpu(int cpunum);
241
242
243#endif /* _I386_CPU_TOPOLOGY_H_ */
244#endif /* KERNEL_PRIVATE */
245