aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Steiner <steiner@sgi.com>2010-11-30 14:55:40 -0500
committerIngo Molnar <mingo@elte.hu>2010-12-22 06:31:15 -0500
commitd8850ba425d9823d3184bd52f065899dac4689f9 (patch)
tree8a45d12459523f521967fd2def2935ff769692a4
parente681041388e61ecd7f99dba66b3c1db11a564d92 (diff)
x86, UV: Fix the effect of extra bits in the hub nodeid register
UV systems can be partitioned into multiple independent SSIs. Large partitioned systems may have extra bits in the node_id register. These bits are used when the total memory on all SSIs exceeds 16TB. These extra bits need to be ignored when calculating x2apic_extra_bits. Signed-off-by: Jack Steiner <steiner@sgi.com> LKML-Reference: <20101130195926.972776133@sgi.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--arch/x86/kernel/apic/x2apic_uv_x.c33
1 files changed, 21 insertions, 12 deletions
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
index 0c3675f0474f..2a3f2a7db243 100644
--- a/arch/x86/kernel/apic/x2apic_uv_x.c
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -68,15 +68,19 @@ static bool uv_is_untracked_pat_range(u64 start, u64 end)
68 return is_ISA_range(start, end) || is_GRU_range(start, end); 68 return is_ISA_range(start, end) || is_GRU_range(start, end);
69} 69}
70 70
71static int __init early_get_nodeid(void) 71static int __init early_get_pnodeid(void)
72{ 72{
73 union uvh_node_id_u node_id; 73 union uvh_node_id_u node_id;
74 union uvh_rh_gam_config_mmr_u m_n_config;
75 int pnode;
74 76
75 /* Currently, all blades have same revision number */ 77 /* Currently, all blades have same revision number */
76 node_id.v = uv_early_read_mmr(UVH_NODE_ID); 78 node_id.v = uv_early_read_mmr(UVH_NODE_ID);
79 m_n_config.v = uv_early_read_mmr(UVH_RH_GAM_CONFIG_MMR);
77 uv_min_hub_revision_id = node_id.s.revision; 80 uv_min_hub_revision_id = node_id.s.revision;
78 81
79 return node_id.s.node_id; 82 pnode = (node_id.s.node_id >> 1) & ((1 << m_n_config.s.n_skt) - 1);
83 return pnode;
80} 84}
81 85
82static void __init early_get_apic_pnode_shift(void) 86static void __init early_get_apic_pnode_shift(void)
@@ -104,10 +108,10 @@ static void __init uv_set_apicid_hibit(void)
104 108
105static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id) 109static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
106{ 110{
107 int nodeid; 111 int pnodeid;
108 112
109 if (!strcmp(oem_id, "SGI")) { 113 if (!strcmp(oem_id, "SGI")) {
110 nodeid = early_get_nodeid(); 114 pnodeid = early_get_pnodeid();
111 early_get_apic_pnode_shift(); 115 early_get_apic_pnode_shift();
112 x86_platform.is_untracked_pat_range = uv_is_untracked_pat_range; 116 x86_platform.is_untracked_pat_range = uv_is_untracked_pat_range;
113 x86_platform.nmi_init = uv_nmi_init; 117 x86_platform.nmi_init = uv_nmi_init;
@@ -117,7 +121,7 @@ static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
117 uv_system_type = UV_X2APIC; 121 uv_system_type = UV_X2APIC;
118 else if (!strcmp(oem_table_id, "UVH")) { 122 else if (!strcmp(oem_table_id, "UVH")) {
119 __get_cpu_var(x2apic_extra_bits) = 123 __get_cpu_var(x2apic_extra_bits) =
120 nodeid << (uvh_apicid.s.pnode_shift - 1); 124 pnodeid << uvh_apicid.s.pnode_shift;
121 uv_system_type = UV_NON_UNIQUE_APIC; 125 uv_system_type = UV_NON_UNIQUE_APIC;
122 uv_set_apicid_hibit(); 126 uv_set_apicid_hibit();
123 return 1; 127 return 1;
@@ -680,27 +684,32 @@ void uv_nmi_init(void)
680void __init uv_system_init(void) 684void __init uv_system_init(void)
681{ 685{
682 union uvh_rh_gam_config_mmr_u m_n_config; 686 union uvh_rh_gam_config_mmr_u m_n_config;
687 union uvh_rh_gam_mmioh_overlay_config_mmr_u mmioh;
683 union uvh_node_id_u node_id; 688 union uvh_node_id_u node_id;
684 unsigned long gnode_upper, lowmem_redir_base, lowmem_redir_size; 689 unsigned long gnode_upper, lowmem_redir_base, lowmem_redir_size;
685 int bytes, nid, cpu, lcpu, pnode, blade, i, j, m_val, n_val; 690 int bytes, nid, cpu, lcpu, pnode, blade, i, j, m_val, n_val, n_io;
686 int gnode_extra, max_pnode = 0; 691 int gnode_extra, max_pnode = 0;
687 unsigned long mmr_base, present, paddr; 692 unsigned long mmr_base, present, paddr;
688 unsigned short pnode_mask; 693 unsigned short pnode_mask, pnode_io_mask;
689 694
690 map_low_mmrs(); 695 map_low_mmrs();
691 696
692 m_n_config.v = uv_read_local_mmr(UVH_RH_GAM_CONFIG_MMR ); 697 m_n_config.v = uv_read_local_mmr(UVH_RH_GAM_CONFIG_MMR );
693 m_val = m_n_config.s.m_skt; 698 m_val = m_n_config.s.m_skt;
694 n_val = m_n_config.s.n_skt; 699 n_val = m_n_config.s.n_skt;
700 mmioh.v = uv_read_local_mmr(UVH_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR);
701 n_io = mmioh.s.n_io;
695 mmr_base = 702 mmr_base =
696 uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR) & 703 uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR) &
697 ~UV_MMR_ENABLE; 704 ~UV_MMR_ENABLE;
698 pnode_mask = (1 << n_val) - 1; 705 pnode_mask = (1 << n_val) - 1;
706 pnode_io_mask = (1 << n_io) - 1;
707
699 node_id.v = uv_read_local_mmr(UVH_NODE_ID); 708 node_id.v = uv_read_local_mmr(UVH_NODE_ID);
700 gnode_extra = (node_id.s.node_id & ~((1 << n_val) - 1)) >> 1; 709 gnode_extra = (node_id.s.node_id & ~((1 << n_val) - 1)) >> 1;
701 gnode_upper = ((unsigned long)gnode_extra << m_val); 710 gnode_upper = ((unsigned long)gnode_extra << m_val);
702 printk(KERN_DEBUG "UV: N %d, M %d, gnode_upper 0x%lx, gnode_extra 0x%x\n", 711 printk(KERN_INFO "UV: N %d, M %d, N_IO: %d, gnode_upper 0x%lx, gnode_extra 0x%x, pnode_mask 0x%x, pnode_io_mask 0x%x\n",
703 n_val, m_val, gnode_upper, gnode_extra); 712 n_val, m_val, n_io, gnode_upper, gnode_extra, pnode_mask, pnode_io_mask);
704 713
705 printk(KERN_DEBUG "UV: global MMR base 0x%lx\n", mmr_base); 714 printk(KERN_DEBUG "UV: global MMR base 0x%lx\n", mmr_base);
706 715
@@ -733,7 +742,7 @@ void __init uv_system_init(void)
733 for (j = 0; j < 64; j++) { 742 for (j = 0; j < 64; j++) {
734 if (!test_bit(j, &present)) 743 if (!test_bit(j, &present))
735 continue; 744 continue;
736 pnode = (i * 64 + j); 745 pnode = (i * 64 + j) & pnode_mask;
737 uv_blade_info[blade].pnode = pnode; 746 uv_blade_info[blade].pnode = pnode;
738 uv_blade_info[blade].nr_possible_cpus = 0; 747 uv_blade_info[blade].nr_possible_cpus = 0;
739 uv_blade_info[blade].nr_online_cpus = 0; 748 uv_blade_info[blade].nr_online_cpus = 0;
@@ -754,6 +763,7 @@ void __init uv_system_init(void)
754 /* 763 /*
755 * apic_pnode_shift must be set before calling uv_apicid_to_pnode(); 764 * apic_pnode_shift must be set before calling uv_apicid_to_pnode();
756 */ 765 */
766 uv_cpu_hub_info(cpu)->pnode_mask = pnode_mask;
757 uv_cpu_hub_info(cpu)->apic_pnode_shift = uvh_apicid.s.pnode_shift; 767 uv_cpu_hub_info(cpu)->apic_pnode_shift = uvh_apicid.s.pnode_shift;
758 pnode = uv_apicid_to_pnode(apicid); 768 pnode = uv_apicid_to_pnode(apicid);
759 blade = boot_pnode_to_blade(pnode); 769 blade = boot_pnode_to_blade(pnode);
@@ -770,7 +780,6 @@ void __init uv_system_init(void)
770 uv_cpu_hub_info(cpu)->numa_blade_id = blade; 780 uv_cpu_hub_info(cpu)->numa_blade_id = blade;
771 uv_cpu_hub_info(cpu)->blade_processor_id = lcpu; 781 uv_cpu_hub_info(cpu)->blade_processor_id = lcpu;
772 uv_cpu_hub_info(cpu)->pnode = pnode; 782 uv_cpu_hub_info(cpu)->pnode = pnode;
773 uv_cpu_hub_info(cpu)->pnode_mask = pnode_mask;
774 uv_cpu_hub_info(cpu)->gpa_mask = (1UL << (m_val + n_val)) - 1; 783 uv_cpu_hub_info(cpu)->gpa_mask = (1UL << (m_val + n_val)) - 1;
775 uv_cpu_hub_info(cpu)->gnode_upper = gnode_upper; 784 uv_cpu_hub_info(cpu)->gnode_upper = gnode_upper;
776 uv_cpu_hub_info(cpu)->gnode_extra = gnode_extra; 785 uv_cpu_hub_info(cpu)->gnode_extra = gnode_extra;
@@ -794,7 +803,7 @@ void __init uv_system_init(void)
794 803
795 map_gru_high(max_pnode); 804 map_gru_high(max_pnode);
796 map_mmr_high(max_pnode); 805 map_mmr_high(max_pnode);
797 map_mmioh_high(max_pnode); 806 map_mmioh_high(max_pnode & pnode_io_mask);
798 807
799 uv_cpu_init(); 808 uv_cpu_init();
800 uv_scir_register_cpu_notifier(); 809 uv_scir_register_cpu_notifier();