2008-03-28 14:12:13 -05:00
/*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file " COPYING " in the main directory of this archive
* for more details .
*
* SGI UV architectural definitions
*
2008-05-28 09:51:18 -05:00
* Copyright ( C ) 2007 - 2008 Silicon Graphics , Inc . All rights reserved .
2008-03-28 14:12:13 -05:00
*/
2008-10-23 00:01:39 -07:00
# ifndef _ASM_X86_UV_UV_HUB_H
# define _ASM_X86_UV_UV_HUB_H
2008-03-28 14:12:13 -05:00
# include <linux/numa.h>
# include <linux/percpu.h>
2008-10-30 11:33:19 -07:00
# include <linux/timer.h>
2008-03-28 14:12:13 -05:00
# include <asm/types.h>
# include <asm/percpu.h>
/*
* Addressing Terminology
*
2008-05-28 09:51:18 -05:00
* M - The low M bits of a physical address represent the offset
* into the blade local memory . RAM memory on a blade is physically
* contiguous ( although various IO spaces may punch holes in
* it ) . .
2008-03-28 14:12:13 -05:00
*
2008-05-28 09:51:18 -05:00
* N - Number of bits in the node portion of a socket physical
* address .
*
* NASID - network ID of a router , Mbrick or Cbrick . Nasid values of
* routers always have low bit of 1 , C / MBricks have low bit
* equal to 0. Most addressing macros that target UV hub chips
* right shift the NASID by 1 to exclude the always - zero bit .
* NASIDs contain up to 15 bits .
*
* GNODE - NASID right shifted by 1 bit . Most mmrs contain gnodes instead
* of nasids .
*
* PNODE - the low N bits of the GNODE . The PNODE is the most useful variant
* of the nasid for socket usage .
*
*
* NumaLink Global Physical Address Format :
* + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - +
* | 00. .000 | GNODE | NodeOffset |
* + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - +
* | < - - - - - - - 53 - M bits - - - > | < - - - - - - - - M bits - - - - - >
*
* M - number of node offset bits ( 35 . . 40 )
2008-03-28 14:12:13 -05:00
*
*
* Memory / UV - HUB Processor Socket Address Format :
2008-05-28 09:51:18 -05:00
* + - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - +
* | 00. .000000000000 | PNODE | NodeOffset |
* + - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - +
* < - - - N bits - - - > | < - - - - - - - - M bits - - - - - >
2008-03-28 14:12:13 -05:00
*
2008-05-28 09:51:18 -05:00
* M - number of node offset bits ( 35 . . 40 )
* N - number of PNODE bits ( 0 . . 10 )
2008-03-28 14:12:13 -05:00
*
* Note : M + N cannot currently exceed 44 ( x86_64 ) or 46 ( IA64 ) .
* The actual values are configuration dependent and are set at
2008-05-28 09:51:18 -05:00
* boot time . M & N values are set by the hardware / BIOS at boot .
*
2008-03-28 14:12:13 -05:00
*
* APICID format
* NOTE ! ! ! ! ! ! This is the current format of the APICID . However , code
* should assume that this will change in the future . Use functions
* in this file for all APICID bit manipulations and conversion .
*
* 1111110000000000
* 5432109876543210
2008-05-28 09:51:18 -05:00
* pppppppppplc0cch
2008-03-28 14:12:13 -05:00
* sssssssssss
*
2008-05-28 09:51:18 -05:00
* p = pnode bits
2008-03-28 14:12:13 -05:00
* l = socket number on board
* c = core
* h = hyperthread
2008-05-28 09:51:18 -05:00
* s = bits that are in the SOCKET_ID CSR
2008-03-28 14:12:13 -05:00
*
* Note : Processor only supports 12 bits in the APICID register . The ACPI
* tables hold all 16 bits . Software needs to be aware of this .
*
* Unless otherwise specified , all references to APICID refer to
* the FULL value contained in ACPI tables , not the subset in the
* processor APICID register .
*/
/*
* Maximum number of bricks in all partitions and in all coherency domains .
* This is the total number of bricks accessible in the numalink fabric . It
* includes all C & M bricks . Routers are NOT included .
*
* This value is also the value of the maximum number of non - router NASIDs
* in the numalink fabric .
*
2008-05-28 09:51:18 -05:00
* NOTE : a brick may contain 1 or 2 OS nodes . Don ' t get these confused .
2008-03-28 14:12:13 -05:00
*/
# define UV_MAX_NUMALINK_BLADES 16384
/*
* Maximum number of C / Mbricks within a software SSI ( hardware may support
* more ) .
*/
# define UV_MAX_SSI_BLADES 256
/*
* The largest possible NASID of a C or M brick ( + 2 )
*/
# define UV_MAX_NASID_VALUE (UV_MAX_NUMALINK_NODES * 2)
2008-10-24 15:24:29 -07:00
struct uv_scir_s {
struct timer_list timer ;
unsigned long offset ;
unsigned long last ;
unsigned long idle_on ;
unsigned long idle_off ;
unsigned char state ;
unsigned char enabled ;
} ;
2008-03-28 14:12:13 -05:00
/*
* The following defines attributes of the HUB chip . These attributes are
* frequently referenced and are kept in the per - cpu data areas of each cpu .
* They are kept together in a struct to minimize cache misses .
*/
struct uv_hub_info_s {
2008-10-27 07:51:20 -07:00
unsigned long global_mmr_base ;
unsigned long gpa_mask ;
unsigned long gnode_upper ;
unsigned long lowmem_remap_top ;
unsigned long lowmem_remap_base ;
unsigned short pnode ;
unsigned short pnode_mask ;
unsigned short coherency_domain_number ;
unsigned short numa_blade_id ;
unsigned char blade_processor_id ;
unsigned char m_val ;
unsigned char n_val ;
struct uv_scir_s scir ;
2008-03-28 14:12:13 -05:00
} ;
2008-10-24 15:24:29 -07:00
2008-03-28 14:12:13 -05:00
DECLARE_PER_CPU ( struct uv_hub_info_s , __uv_hub_info ) ;
# define uv_hub_info (&__get_cpu_var(__uv_hub_info))
# define uv_cpu_hub_info(cpu) (&per_cpu(__uv_hub_info, cpu))
/*
* Local & Global MMR space macros .
* Note : macros are intended to be used ONLY by inline functions
* in this file - not by other kernel code .
2008-05-28 09:51:18 -05:00
* n - NASID ( full 15 - bit global nasid )
* g - GNODE ( full 15 - bit global nasid , right shifted 1 )
* p - PNODE ( local part of nsids , right shifted 1 )
2008-03-28 14:12:13 -05:00
*/
2008-05-28 09:51:18 -05:00
# define UV_NASID_TO_PNODE(n) (((n) >> 1) & uv_hub_info->pnode_mask)
# define UV_PNODE_TO_NASID(p) (((p) << 1) | uv_hub_info->gnode_upper)
2008-03-28 14:12:13 -05:00
# define UV_LOCAL_MMR_BASE 0xf4000000UL
# define UV_GLOBAL_MMR32_BASE 0xf8000000UL
# define UV_GLOBAL_MMR64_BASE (uv_hub_info->global_mmr_base)
2008-07-01 14:45:38 -05:00
# define UV_LOCAL_MMR_SIZE (64UL * 1024 * 1024)
# define UV_GLOBAL_MMR32_SIZE (64UL * 1024 * 1024)
2008-03-28 14:12:13 -05:00
2008-05-28 09:51:18 -05:00
# define UV_GLOBAL_MMR32_PNODE_SHIFT 15
# define UV_GLOBAL_MMR64_PNODE_SHIFT 26
2008-03-28 14:12:13 -05:00
2008-05-28 09:51:18 -05:00
# define UV_GLOBAL_MMR32_PNODE_BITS(p) ((p) << (UV_GLOBAL_MMR32_PNODE_SHIFT))
2008-03-28 14:12:13 -05:00
2008-05-28 09:51:18 -05:00
# define UV_GLOBAL_MMR64_PNODE_BITS(p) \
( ( unsigned long ) ( p ) < < UV_GLOBAL_MMR64_PNODE_SHIFT )
# define UV_APIC_PNODE_SHIFT 6
2008-10-24 15:24:29 -07:00
/* Local Bus from cpu's perspective */
# define LOCAL_BUS_BASE 0x1c00000
# define LOCAL_BUS_SIZE (4 * 1024 * 1024)
/*
* System Controller Interface Reg
*
* Note there are NO leds on a UV system . This register is only
* used by the system controller to monitor system - wide operation .
* There are 64 regs per node . With Nahelem cpus ( 2 cores per node ,
* 8 cpus per core , 2 threads per cpu ) there are 32 cpu threads on
* a node .
*
* The window is located at top of ACPI MMR space
*/
# define SCIR_WINDOW_COUNT 64
# define SCIR_LOCAL_MMR_BASE (LOCAL_BUS_BASE + \
LOCAL_BUS_SIZE - \
SCIR_WINDOW_COUNT )
# define SCIR_CPU_HEARTBEAT 0x01 /* timer interrupt */
# define SCIR_CPU_ACTIVITY 0x02 /* not idle */
# define SCIR_CPU_HB_INTERVAL (HZ) /* once per second */
2008-05-28 09:51:18 -05:00
/*
* Macros for converting between kernel virtual addresses , socket local physical
* addresses , and UV global physical addresses .
* Note : use the standard __pa ( ) & __va ( ) macros for converting
* between socket virtual and socket physical addresses .
*/
/* socket phys RAM --> UV global physical address */
static inline unsigned long uv_soc_phys_ram_to_gpa ( unsigned long paddr )
{
if ( paddr < uv_hub_info - > lowmem_remap_top )
paddr + = uv_hub_info - > lowmem_remap_base ;
return paddr | uv_hub_info - > gnode_upper ;
}
/* socket virtual --> UV global physical address */
static inline unsigned long uv_gpa ( void * v )
{
return __pa ( v ) | uv_hub_info - > gnode_upper ;
}
/* socket virtual --> UV global physical address */
static inline void * uv_vgpa ( void * v )
{
return ( void * ) uv_gpa ( v ) ;
}
/* UV global physical address --> socket virtual */
static inline void * uv_va ( unsigned long gpa )
{
return __va ( gpa & uv_hub_info - > gpa_mask ) ;
}
/* pnode, offset --> socket virtual */
static inline void * uv_pnode_offset_to_vaddr ( int pnode , unsigned long offset )
{
return __va ( ( ( unsigned long ) pnode < < uv_hub_info - > m_val ) | offset ) ;
}
2008-03-28 14:12:13 -05:00
/*
2008-05-28 09:51:18 -05:00
* Extract a PNODE from an APICID ( full apicid , not processor subset )
2008-03-28 14:12:13 -05:00
*/
2008-05-28 09:51:18 -05:00
static inline int uv_apicid_to_pnode ( int apicid )
2008-03-28 14:12:13 -05:00
{
2008-05-28 09:51:18 -05:00
return ( apicid > > UV_APIC_PNODE_SHIFT ) ;
2008-03-28 14:12:13 -05:00
}
/*
* Access global MMRs using the low memory MMR32 space . This region supports
* faster MMR access but not all MMRs are accessible in this space .
*/
2008-05-28 09:51:18 -05:00
static inline unsigned long * uv_global_mmr32_address ( int pnode ,
2008-03-28 14:12:13 -05:00
unsigned long offset )
{
return __va ( UV_GLOBAL_MMR32_BASE |
2008-05-28 09:51:18 -05:00
UV_GLOBAL_MMR32_PNODE_BITS ( pnode ) | offset ) ;
2008-03-28 14:12:13 -05:00
}
2008-05-28 09:51:18 -05:00
static inline void uv_write_global_mmr32 ( int pnode , unsigned long offset ,
2008-03-28 14:12:13 -05:00
unsigned long val )
{
2008-05-28 09:51:18 -05:00
* uv_global_mmr32_address ( pnode , offset ) = val ;
2008-03-28 14:12:13 -05:00
}
2008-05-28 09:51:18 -05:00
static inline unsigned long uv_read_global_mmr32 ( int pnode ,
2008-03-28 14:12:13 -05:00
unsigned long offset )
{
2008-05-28 09:51:18 -05:00
return * uv_global_mmr32_address ( pnode , offset ) ;
2008-03-28 14:12:13 -05:00
}
/*
* Access Global MMR space using the MMR space located at the top of physical
* memory .
*/
2008-05-28 09:51:18 -05:00
static inline unsigned long * uv_global_mmr64_address ( int pnode ,
2008-03-28 14:12:13 -05:00
unsigned long offset )
{
return __va ( UV_GLOBAL_MMR64_BASE |
2008-05-28 09:51:18 -05:00
UV_GLOBAL_MMR64_PNODE_BITS ( pnode ) | offset ) ;
2008-03-28 14:12:13 -05:00
}
2008-05-28 09:51:18 -05:00
static inline void uv_write_global_mmr64 ( int pnode , unsigned long offset ,
2008-03-28 14:12:13 -05:00
unsigned long val )
{
2008-05-28 09:51:18 -05:00
* uv_global_mmr64_address ( pnode , offset ) = val ;
2008-03-28 14:12:13 -05:00
}
2008-05-28 09:51:18 -05:00
static inline unsigned long uv_read_global_mmr64 ( int pnode ,
2008-03-28 14:12:13 -05:00
unsigned long offset )
{
2008-05-28 09:51:18 -05:00
return * uv_global_mmr64_address ( pnode , offset ) ;
2008-03-28 14:12:13 -05:00
}
/*
2008-05-28 09:51:18 -05:00
* Access hub local MMRs . Faster than using global space but only local MMRs
2008-03-28 14:12:13 -05:00
* are accessible .
*/
static inline unsigned long * uv_local_mmr_address ( unsigned long offset )
{
return __va ( UV_LOCAL_MMR_BASE | offset ) ;
}
static inline unsigned long uv_read_local_mmr ( unsigned long offset )
{
return * uv_local_mmr_address ( offset ) ;
}
static inline void uv_write_local_mmr ( unsigned long offset , unsigned long val )
{
* uv_local_mmr_address ( offset ) = val ;
}
2008-10-24 15:24:29 -07:00
static inline unsigned char uv_read_local_mmr8 ( unsigned long offset )
{
return * ( ( unsigned char * ) uv_local_mmr_address ( offset ) ) ;
}
static inline void uv_write_local_mmr8 ( unsigned long offset , unsigned char val )
{
* ( ( unsigned char * ) uv_local_mmr_address ( offset ) ) = val ;
}
2008-03-28 14:12:14 -05:00
/*
2008-05-28 09:51:18 -05:00
* Structures and definitions for converting between cpu , node , pnode , and blade
2008-03-28 14:12:14 -05:00
* numbers .
*/
struct uv_blade_info {
2008-05-28 09:51:18 -05:00
unsigned short nr_possible_cpus ;
2008-03-28 14:12:14 -05:00
unsigned short nr_online_cpus ;
2008-05-28 09:51:18 -05:00
unsigned short pnode ;
2008-03-28 14:12:14 -05:00
} ;
2008-05-28 09:51:18 -05:00
extern struct uv_blade_info * uv_blade_info ;
2008-03-28 14:12:14 -05:00
extern short * uv_node_to_blade ;
extern short * uv_cpu_to_blade ;
extern short uv_possible_blades ;
/* Blade-local cpu number of current cpu. Numbered 0 .. <# cpus on the blade> */
static inline int uv_blade_processor_id ( void )
{
return uv_hub_info - > blade_processor_id ;
}
/* Blade number of current cpu. Numnbered 0 .. <#blades -1> */
static inline int uv_numa_blade_id ( void )
{
return uv_hub_info - > numa_blade_id ;
}
/* Convert a cpu number to the the UV blade number */
static inline int uv_cpu_to_blade_id ( int cpu )
{
return uv_cpu_to_blade [ cpu ] ;
}
/* Convert linux node number to the UV blade number */
static inline int uv_node_to_blade_id ( int nid )
{
return uv_node_to_blade [ nid ] ;
}
2008-05-28 09:51:18 -05:00
/* Convert a blade id to the PNODE of the blade */
static inline int uv_blade_to_pnode ( int bid )
2008-03-28 14:12:14 -05:00
{
2008-05-28 09:51:18 -05:00
return uv_blade_info [ bid ] . pnode ;
2008-03-28 14:12:14 -05:00
}
/* Determine the number of possible cpus on a blade */
static inline int uv_blade_nr_possible_cpus ( int bid )
{
2008-05-28 09:51:18 -05:00
return uv_blade_info [ bid ] . nr_possible_cpus ;
2008-03-28 14:12:14 -05:00
}
/* Determine the number of online cpus on a blade */
static inline int uv_blade_nr_online_cpus ( int bid )
{
return uv_blade_info [ bid ] . nr_online_cpus ;
}
2008-05-28 09:51:18 -05:00
/* Convert a cpu id to the PNODE of the blade containing the cpu */
static inline int uv_cpu_to_pnode ( int cpu )
2008-03-28 14:12:14 -05:00
{
2008-05-28 09:51:18 -05:00
return uv_blade_info [ uv_cpu_to_blade_id ( cpu ) ] . pnode ;
2008-03-28 14:12:14 -05:00
}
2008-05-28 09:51:18 -05:00
/* Convert a linux node number to the PNODE of the blade */
static inline int uv_node_to_pnode ( int nid )
2008-03-28 14:12:14 -05:00
{
2008-05-28 09:51:18 -05:00
return uv_blade_info [ uv_node_to_blade_id ( nid ) ] . pnode ;
2008-03-28 14:12:14 -05:00
}
/* Maximum possible number of blades */
static inline int uv_num_possible_blades ( void )
{
return uv_possible_blades ;
}
2008-10-24 15:24:29 -07:00
/* Update SCIR state */
static inline void uv_set_scir_bits ( unsigned char value )
{
if ( uv_hub_info - > scir . state ! = value ) {
uv_hub_info - > scir . state = value ;
uv_write_local_mmr8 ( uv_hub_info - > scir . offset , value ) ;
}
}
static inline void uv_set_cpu_scir_bits ( int cpu , unsigned char value )
{
if ( uv_cpu_hub_info ( cpu ) - > scir . state ! = value ) {
uv_cpu_hub_info ( cpu ) - > scir . state = value ;
uv_write_local_mmr8 ( uv_cpu_hub_info ( cpu ) - > scir . offset , value ) ;
}
}
2008-03-28 14:12:13 -05:00
2008-10-24 15:24:29 -07:00
# endif /* _ASM_X86_UV_UV_HUB_H */