diff options
author | Jack Steiner <steiner@sgi.com> | 2010-11-30 14:55:40 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-12-22 06:31:15 -0500 |
commit | d8850ba425d9823d3184bd52f065899dac4689f9 (patch) | |
tree | 8a45d12459523f521967fd2def2935ff769692a4 | |
parent | e681041388e61ecd7f99dba66b3c1db11a564d92 (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.c | 33 |
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 | ||
71 | static int __init early_get_nodeid(void) | 71 | static 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 | ||
82 | static void __init early_get_apic_pnode_shift(void) | 86 | static void __init early_get_apic_pnode_shift(void) |
@@ -104,10 +108,10 @@ static void __init uv_set_apicid_hibit(void) | |||
104 | 108 | ||
105 | static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | 109 | static 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) | |||
680 | void __init uv_system_init(void) | 684 | void __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(); |