cpu_topology.h   [plain text]


/*
 * Copyright (c) 2003-2007 Apple Inc. All rights reserved.
 *
 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
 * 
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Apple Public Source License
 * Version 2.0 (the 'License'). You may not use this file except in
 * compliance with the License. The rights granted to you under the License
 * may not be used to create, or enable the creation or redistribution of,
 * unlawful or unlicensed copies of an Apple operating system, or to
 * circumvent, violate, or enable the circumvention or violation of, any
 * terms of an Apple operating system software license agreement.
 * 
 * Please obtain a copy of the License at
 * http://www.opensource.apple.com/apsl/ and read it before using this file.
 * 
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 * Please see the License for the specific language governing rights and
 * limitations under the License.
 * 
 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
 */
#ifdef KERNEL_PRIVATE
#ifndef _I386_CPU_TOPOLOGY_H_
#define _I386_CPU_TOPOLOGY_H_

/*
 * This was originally part of cpu_threads.h.  It was split out so that
 * these structures could be referenced without pulling in all of the headers
 * required for the definition of cpu_data.  These data structures are
 * used by KEXTs in order to deal with the physical topology.
 *
 * NOTE: this header must stand on its own as much as possible
 * and not be dependent upon any unexported, kernel-private header.
 */

/*
 * Cache structure that can be used to identify the cache heirarchy.
 */
typedef struct x86_cpu_cache
{
    struct x86_cpu_cache *next;		/* next cache at this level/lcpu */
    uint8_t		maxcpus;	/* maximum # of cpus that can share */
    uint8_t		nlcpus;		/* # of logical cpus sharing this cache */
    uint8_t		type;		/* type of cache */
    uint8_t		level;		/* level of cache */
    uint16_t		ways;		/* # of ways in cache */
    uint16_t		partitions;	/* # of partitions in cache */
    uint16_t		line_size;	/* size of a cache line */
    uint32_t		cache_size;	/* total size of cache */
    struct x86_lcpu	*cpus[0];	/* cpus sharing this cache */
} x86_cpu_cache_t;

#define CPU_CACHE_TYPE_DATA	1	/* data cache */
#define CPU_CACHE_TYPE_INST	2	/* instruction cache */
#define CPU_CACHE_TYPE_UNIF	3	/* unified cache */

#define CPU_CACHE_DEPTH_L1	0
#define CPU_CACHE_DEPTH_L2	1
#define CPU_CACHE_DEPTH_L3	2

#define MAX_CACHE_DEPTH		3	/* deepest cache */

struct pmc;
struct cpu_data;

typedef struct x86_lcpu
{
    struct x86_lcpu	*next;	/* next logical cpu in core */
    struct x86_lcpu	*lcpu;	/* pointer back to self */
    struct x86_core	*core;	/* core containing the logical cpu */
    struct cpu_data	*cpu;	/* cpu_data structure */
    uint32_t		lnum;	/* logical cpu number */
    uint32_t		pnum;	/* physical cpu number */
    boolean_t		master;	/* logical cpu is the master (boot) CPU */
    boolean_t		primary;/* logical cpu is primary CPU in package */
    boolean_t		halted;	/* logical cpu is halted */
    boolean_t		idle;	/* logical cpu is idle */
    uint64_t		rtcPop;	/* when etimer wants a timer pop */
    uint64_t		rtcDeadline;
    x86_cpu_cache_t	*caches[MAX_CACHE_DEPTH];
} x86_lcpu_t;

#define X86CORE_FL_PRESENT	0x80000000	/* core is present */
#define X86CORE_FL_READY	0x40000000	/* core struct is init'd */
#define X86CORE_FL_HALTED	0x00008000	/* core is halted */
#define X86CORE_FL_IDLE		0x00004000	/* core is idle */

typedef struct x86_core
{
    struct x86_core	*next;		/* next core in package */
    struct x86_lcpu	*lcpus;		/* list of logical cpus in core */
    struct x86_pkg	*package;	/* package containing core */
    uint32_t		flags;
    uint32_t		lcore_num;	/* logical core # (unique to package) */
    uint32_t		pcore_num;	/* physical core # (globally unique) */
    uint32_t		num_lcpus;	/* Number of logical cpus */
    uint32_t		active_lcpus;	/* Number of non-halted cpus */
    struct pmc		*pmc;		/* Pointer to perfmon data */
    struct hpetTimer	*Hpet;		/* Address of the HPET for this core */
    uint32_t		HpetVec;	/* Interrupt vector for HPET */
    uint64_t		HpetInt;	/* Number of HPET Interrupts */
    uint64_t		HpetCmp;	/* HPET Comparitor */
    uint64_t		HpetCfg;	/* HPET configuration */
    uint64_t		HpetTime;
    void		*pmStats;	/* Power management stats for core */
    void		*pmState;	/* Power management state for core */
} x86_core_t;

#define X86PKG_FL_PRESENT	0x80000000	/* package is present */
#define X86PKG_FL_READY		0x40000000	/* package struct init'd */
#define X86PKG_FL_HAS_HPET	0x10000000	/* package has HPET assigned */
#define X86PKG_FL_HALTED	0x00008000	/* package is halted */
#define X86PKG_FL_IDLE		0x00004000	/* package is idle */

typedef struct x86_pkg
{
    struct x86_pkg	*next;		/* next package */
    struct x86_core	*cores;		/* list of cores in package */
    uint32_t		flags;
    uint32_t		lpkg_num;	/* logical package # */
    uint32_t		ppkg_num;	/* physical package # */
    uint32_t		num_cores;	/* number of cores in package */
    struct hpetTimer	*Hpet;		/* address of HPET for this package */
    uint32_t		HpetVec;	/* Interrupt vector for HPET */
    uint64_t		HpetInt;	/* Number of HPET interrupts */
    uint64_t		HpetCmp;	/* HPET comparitor */
    uint64_t		HpetCfg;	/* HPET configuration */
    uint64_t		HpetTime;
    void		*pmStats;	/* Power Management stats for package*/
    void		*pmState;	/* Power Management state for package*/
} x86_pkg_t;

extern x86_pkg_t	*x86_pkgs;	/* root of all CPU packages */

/* Called after cpu discovery */
extern void		cpu_topology_start(void);

extern int idlehalt;

#endif /* _I386_CPU_TOPOLOGY_H_ */
#endif /* KERNEL_PRIVATE */