Skip to content

Commit

Permalink
x86, uv: Enable Westmere support on SGI UV
Browse files Browse the repository at this point in the history
Enable Westmere support on SGI UV.  The UV initialization code is dependent on
the APICID bits.  Westmere-EX uses different APIC bit mapping than Nehalem-EX.
This code reads the apic shift value from a UV MMR to do the proper bit
decoding to determint the pnode.

Signed-off-by: Russ Anderson <rja@sgi.com>
LKML-Reference: <20101026212728.GB15071@sgi.com>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
  • Loading branch information
Russ Anderson authored and H. Peter Anvin committed Oct 26, 2010
1 parent b365a85 commit c8f730b
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 5 deletions.
21 changes: 18 additions & 3 deletions arch/x86/include/asm/uv/uv_hub.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*
* SGI UV architectural definitions
*
* Copyright (C) 2007-2008 Silicon Graphics, Inc. All rights reserved.
* Copyright (C) 2007-2010 Silicon Graphics, Inc. All rights reserved.
*/

#ifndef _ASM_X86_UV_UV_HUB_H
Expand Down Expand Up @@ -77,7 +77,8 @@
*
* 1111110000000000
* 5432109876543210
* pppppppppplc0cch
* pppppppppplc0cch Nehalem-EX
* ppppppppplcc0cch Westmere-EX
* sssssssssss
*
* p = pnode bits
Expand Down Expand Up @@ -148,12 +149,25 @@ struct uv_hub_info_s {
unsigned char m_val;
unsigned char n_val;
struct uv_scir_s scir;
unsigned char apic_pnode_shift;
};

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))

union uvh_apicid {
unsigned long v;
struct uvh_apicid_s {
unsigned long local_apic_mask : 24;
unsigned long local_apic_shift : 5;
unsigned long unused1 : 3;
unsigned long pnode_mask : 24;
unsigned long pnode_shift : 5;
unsigned long unused2 : 3;
} s;
};

/*
* Local & Global MMR space macros.
* Note: macros are intended to be used ONLY by inline functions
Expand Down Expand Up @@ -182,6 +196,7 @@ DECLARE_PER_CPU(struct uv_hub_info_s, __uv_hub_info);
#define UV_GLOBAL_MMR64_PNODE_BITS(p) \
(((unsigned long)(p)) << UV_GLOBAL_MMR64_PNODE_SHIFT)

#define UVH_APICID 0x002D0E00L
#define UV_APIC_PNODE_SHIFT 6

/* Local Bus from cpu's perspective */
Expand Down Expand Up @@ -280,7 +295,7 @@ static inline void *uv_pnode_offset_to_vaddr(int pnode, unsigned long offset)
*/
static inline int uv_apicid_to_pnode(int apicid)
{
return (apicid >> UV_APIC_PNODE_SHIFT);
return (apicid >> uv_hub_info->apic_pnode_shift);
}

/*
Expand Down
25 changes: 23 additions & 2 deletions arch/x86/kernel/apic/x2apic_uv_x.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*
* SGI UV APIC functions (note: not an Intel compatible APIC)
*
* Copyright (C) 2007-2009 Silicon Graphics, Inc. All rights reserved.
* Copyright (C) 2007-2010 Silicon Graphics, Inc. All rights reserved.
*/
#include <linux/cpumask.h>
#include <linux/hardirq.h>
Expand Down Expand Up @@ -41,6 +41,7 @@ DEFINE_PER_CPU(int, x2apic_extra_bits);

static enum uv_system_type uv_system_type;
static u64 gru_start_paddr, gru_end_paddr;
static union uvh_apicid uvh_apicid;
int uv_min_hub_revision_id;
EXPORT_SYMBOL_GPL(uv_min_hub_revision_id);
static DEFINE_SPINLOCK(uv_nmi_lock);
Expand Down Expand Up @@ -70,6 +71,22 @@ static int early_get_nodeid(void)
return node_id.s.node_id;
}

static int __init early_get_apic_pnode_shift(void)
{
unsigned long *mmr;

mmr = early_ioremap(UV_LOCAL_MMR_BASE | UVH_APICID, sizeof(*mmr));
uvh_apicid.v = *mmr;
early_iounmap(mmr, sizeof(*mmr));
if (!uvh_apicid.v)
/*
* Old bios, use default value
*/
uvh_apicid.s.pnode_shift = UV_APIC_PNODE_SHIFT;

return uvh_apicid.s.pnode_shift;
}

static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
{
int nodeid;
Expand All @@ -84,7 +101,7 @@ static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
uv_system_type = UV_X2APIC;
else if (!strcmp(oem_table_id, "UVH")) {
__get_cpu_var(x2apic_extra_bits) =
nodeid << (UV_APIC_PNODE_SHIFT - 1);
nodeid << (early_get_apic_pnode_shift() - 1);
uv_system_type = UV_NON_UNIQUE_APIC;
return 1;
}
Expand Down Expand Up @@ -716,6 +733,10 @@ void __init uv_system_init(void)
int apicid = per_cpu(x86_cpu_to_apicid, cpu);

nid = cpu_to_node(cpu);
/*
* apic_pnode_shift must be set before calling uv_apicid_to_pnode();
*/
uv_cpu_hub_info(cpu)->apic_pnode_shift = uvh_apicid.s.pnode_shift;
pnode = uv_apicid_to_pnode(apicid);
blade = boot_pnode_to_blade(pnode);
lcpu = uv_blade_info[blade].nr_possible_cpus;
Expand Down

0 comments on commit c8f730b

Please sign in to comment.