Path: blob/master/arch/x86/kernel/apic/x2apic_uv_x.c
17679 views
/*1* This file is subject to the terms and conditions of the GNU General Public2* License. See the file "COPYING" in the main directory of this archive3* for more details.4*5* SGI UV APIC functions (note: not an Intel compatible APIC)6*7* Copyright (C) 2007-2010 Silicon Graphics, Inc. All rights reserved.8*/9#include <linux/cpumask.h>10#include <linux/hardirq.h>11#include <linux/proc_fs.h>12#include <linux/threads.h>13#include <linux/kernel.h>14#include <linux/module.h>15#include <linux/string.h>16#include <linux/ctype.h>17#include <linux/sched.h>18#include <linux/timer.h>19#include <linux/slab.h>20#include <linux/cpu.h>21#include <linux/init.h>22#include <linux/io.h>23#include <linux/pci.h>24#include <linux/kdebug.h>25#include <linux/delay.h>26#include <linux/crash_dump.h>2728#include <asm/uv/uv_mmrs.h>29#include <asm/uv/uv_hub.h>30#include <asm/current.h>31#include <asm/pgtable.h>32#include <asm/uv/bios.h>33#include <asm/uv/uv.h>34#include <asm/apic.h>35#include <asm/ipi.h>36#include <asm/smp.h>37#include <asm/x86_init.h>38#include <asm/emergency-restart.h>39#include <asm/nmi.h>4041/* BMC sets a bit this MMR non-zero before sending an NMI */42#define UVH_NMI_MMR UVH_SCRATCH543#define UVH_NMI_MMR_CLEAR (UVH_NMI_MMR + 8)44#define UV_NMI_PENDING_MASK (1UL << 63)45DEFINE_PER_CPU(unsigned long, cpu_last_nmi_count);4647DEFINE_PER_CPU(int, x2apic_extra_bits);4849#define PR_DEVEL(fmt, args...) pr_devel("%s: " fmt, __func__, args)5051static enum uv_system_type uv_system_type;52static u64 gru_start_paddr, gru_end_paddr;53static union uvh_apicid uvh_apicid;54int uv_min_hub_revision_id;55EXPORT_SYMBOL_GPL(uv_min_hub_revision_id);56unsigned int uv_apicid_hibits;57EXPORT_SYMBOL_GPL(uv_apicid_hibits);58static DEFINE_SPINLOCK(uv_nmi_lock);5960static struct apic apic_x2apic_uv_x;6162static unsigned long __init uv_early_read_mmr(unsigned long addr)63{64unsigned long val, *mmr;6566mmr = early_ioremap(UV_LOCAL_MMR_BASE | addr, sizeof(*mmr));67val = *mmr;68early_iounmap(mmr, sizeof(*mmr));69return val;70}7172static inline bool is_GRU_range(u64 start, u64 end)73{74return start >= gru_start_paddr && end <= gru_end_paddr;75}7677static bool uv_is_untracked_pat_range(u64 start, u64 end)78{79return is_ISA_range(start, end) || is_GRU_range(start, end);80}8182static int __init early_get_pnodeid(void)83{84union uvh_node_id_u node_id;85union uvh_rh_gam_config_mmr_u m_n_config;86int pnode;8788/* Currently, all blades have same revision number */89node_id.v = uv_early_read_mmr(UVH_NODE_ID);90m_n_config.v = uv_early_read_mmr(UVH_RH_GAM_CONFIG_MMR);91uv_min_hub_revision_id = node_id.s.revision;9293if (node_id.s.part_number == UV2_HUB_PART_NUMBER)94uv_min_hub_revision_id += UV2_HUB_REVISION_BASE - 1;9596uv_hub_info->hub_revision = uv_min_hub_revision_id;97pnode = (node_id.s.node_id >> 1) & ((1 << m_n_config.s.n_skt) - 1);98return pnode;99}100101static void __init early_get_apic_pnode_shift(void)102{103uvh_apicid.v = uv_early_read_mmr(UVH_APICID);104if (!uvh_apicid.v)105/*106* Old bios, use default value107*/108uvh_apicid.s.pnode_shift = UV_APIC_PNODE_SHIFT;109}110111/*112* Add an extra bit as dictated by bios to the destination apicid of113* interrupts potentially passing through the UV HUB. This prevents114* a deadlock between interrupts and IO port operations.115*/116static void __init uv_set_apicid_hibit(void)117{118union uv1h_lb_target_physical_apic_id_mask_u apicid_mask;119120if (is_uv1_hub()) {121apicid_mask.v =122uv_early_read_mmr(UV1H_LB_TARGET_PHYSICAL_APIC_ID_MASK);123uv_apicid_hibits =124apicid_mask.s1.bit_enables & UV_APICID_HIBIT_MASK;125}126}127128static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id)129{130int pnodeid, is_uv1, is_uv2;131132is_uv1 = !strcmp(oem_id, "SGI");133is_uv2 = !strcmp(oem_id, "SGI2");134if (is_uv1 || is_uv2) {135uv_hub_info->hub_revision =136is_uv1 ? UV1_HUB_REVISION_BASE : UV2_HUB_REVISION_BASE;137pnodeid = early_get_pnodeid();138early_get_apic_pnode_shift();139x86_platform.is_untracked_pat_range = uv_is_untracked_pat_range;140x86_platform.nmi_init = uv_nmi_init;141if (!strcmp(oem_table_id, "UVL"))142uv_system_type = UV_LEGACY_APIC;143else if (!strcmp(oem_table_id, "UVX"))144uv_system_type = UV_X2APIC;145else if (!strcmp(oem_table_id, "UVH")) {146__this_cpu_write(x2apic_extra_bits,147pnodeid << uvh_apicid.s.pnode_shift);148uv_system_type = UV_NON_UNIQUE_APIC;149uv_set_apicid_hibit();150return 1;151}152}153return 0;154}155156enum uv_system_type get_uv_system_type(void)157{158return uv_system_type;159}160161int is_uv_system(void)162{163return uv_system_type != UV_NONE;164}165EXPORT_SYMBOL_GPL(is_uv_system);166167DEFINE_PER_CPU(struct uv_hub_info_s, __uv_hub_info);168EXPORT_PER_CPU_SYMBOL_GPL(__uv_hub_info);169170struct uv_blade_info *uv_blade_info;171EXPORT_SYMBOL_GPL(uv_blade_info);172173short *uv_node_to_blade;174EXPORT_SYMBOL_GPL(uv_node_to_blade);175176short *uv_cpu_to_blade;177EXPORT_SYMBOL_GPL(uv_cpu_to_blade);178179short uv_possible_blades;180EXPORT_SYMBOL_GPL(uv_possible_blades);181182unsigned long sn_rtc_cycles_per_second;183EXPORT_SYMBOL(sn_rtc_cycles_per_second);184185static const struct cpumask *uv_target_cpus(void)186{187return cpu_online_mask;188}189190static void uv_vector_allocation_domain(int cpu, struct cpumask *retmask)191{192cpumask_clear(retmask);193cpumask_set_cpu(cpu, retmask);194}195196static int __cpuinit uv_wakeup_secondary(int phys_apicid, unsigned long start_rip)197{198#ifdef CONFIG_SMP199unsigned long val;200int pnode;201202pnode = uv_apicid_to_pnode(phys_apicid);203phys_apicid |= uv_apicid_hibits;204val = (1UL << UVH_IPI_INT_SEND_SHFT) |205(phys_apicid << UVH_IPI_INT_APIC_ID_SHFT) |206((start_rip << UVH_IPI_INT_VECTOR_SHFT) >> 12) |207APIC_DM_INIT;208uv_write_global_mmr64(pnode, UVH_IPI_INT, val);209mdelay(10);210211val = (1UL << UVH_IPI_INT_SEND_SHFT) |212(phys_apicid << UVH_IPI_INT_APIC_ID_SHFT) |213((start_rip << UVH_IPI_INT_VECTOR_SHFT) >> 12) |214APIC_DM_STARTUP;215uv_write_global_mmr64(pnode, UVH_IPI_INT, val);216217atomic_set(&init_deasserted, 1);218#endif219return 0;220}221222static void uv_send_IPI_one(int cpu, int vector)223{224unsigned long apicid;225int pnode;226227apicid = per_cpu(x86_cpu_to_apicid, cpu);228pnode = uv_apicid_to_pnode(apicid);229uv_hub_send_ipi(pnode, apicid, vector);230}231232static void uv_send_IPI_mask(const struct cpumask *mask, int vector)233{234unsigned int cpu;235236for_each_cpu(cpu, mask)237uv_send_IPI_one(cpu, vector);238}239240static void uv_send_IPI_mask_allbutself(const struct cpumask *mask, int vector)241{242unsigned int this_cpu = smp_processor_id();243unsigned int cpu;244245for_each_cpu(cpu, mask) {246if (cpu != this_cpu)247uv_send_IPI_one(cpu, vector);248}249}250251static void uv_send_IPI_allbutself(int vector)252{253unsigned int this_cpu = smp_processor_id();254unsigned int cpu;255256for_each_online_cpu(cpu) {257if (cpu != this_cpu)258uv_send_IPI_one(cpu, vector);259}260}261262static void uv_send_IPI_all(int vector)263{264uv_send_IPI_mask(cpu_online_mask, vector);265}266267static int uv_apic_id_registered(void)268{269return 1;270}271272static void uv_init_apic_ldr(void)273{274}275276static unsigned int uv_cpu_mask_to_apicid(const struct cpumask *cpumask)277{278/*279* We're using fixed IRQ delivery, can only return one phys APIC ID.280* May as well be the first.281*/282int cpu = cpumask_first(cpumask);283284if ((unsigned)cpu < nr_cpu_ids)285return per_cpu(x86_cpu_to_apicid, cpu) | uv_apicid_hibits;286else287return BAD_APICID;288}289290static unsigned int291uv_cpu_mask_to_apicid_and(const struct cpumask *cpumask,292const struct cpumask *andmask)293{294int cpu;295296/*297* We're using fixed IRQ delivery, can only return one phys APIC ID.298* May as well be the first.299*/300for_each_cpu_and(cpu, cpumask, andmask) {301if (cpumask_test_cpu(cpu, cpu_online_mask))302break;303}304return per_cpu(x86_cpu_to_apicid, cpu) | uv_apicid_hibits;305}306307static unsigned int x2apic_get_apic_id(unsigned long x)308{309unsigned int id;310311WARN_ON(preemptible() && num_online_cpus() > 1);312id = x | __this_cpu_read(x2apic_extra_bits);313314return id;315}316317static unsigned long set_apic_id(unsigned int id)318{319unsigned long x;320321/* maskout x2apic_extra_bits ? */322x = id;323return x;324}325326static unsigned int uv_read_apic_id(void)327{328329return x2apic_get_apic_id(apic_read(APIC_ID));330}331332static int uv_phys_pkg_id(int initial_apicid, int index_msb)333{334return uv_read_apic_id() >> index_msb;335}336337static void uv_send_IPI_self(int vector)338{339apic_write(APIC_SELF_IPI, vector);340}341342static int uv_probe(void)343{344return apic == &apic_x2apic_uv_x;345}346347static struct apic __refdata apic_x2apic_uv_x = {348349.name = "UV large system",350.probe = uv_probe,351.acpi_madt_oem_check = uv_acpi_madt_oem_check,352.apic_id_registered = uv_apic_id_registered,353354.irq_delivery_mode = dest_Fixed,355.irq_dest_mode = 0, /* physical */356357.target_cpus = uv_target_cpus,358.disable_esr = 0,359.dest_logical = APIC_DEST_LOGICAL,360.check_apicid_used = NULL,361.check_apicid_present = NULL,362363.vector_allocation_domain = uv_vector_allocation_domain,364.init_apic_ldr = uv_init_apic_ldr,365366.ioapic_phys_id_map = NULL,367.setup_apic_routing = NULL,368.multi_timer_check = NULL,369.cpu_present_to_apicid = default_cpu_present_to_apicid,370.apicid_to_cpu_present = NULL,371.setup_portio_remap = NULL,372.check_phys_apicid_present = default_check_phys_apicid_present,373.enable_apic_mode = NULL,374.phys_pkg_id = uv_phys_pkg_id,375.mps_oem_check = NULL,376377.get_apic_id = x2apic_get_apic_id,378.set_apic_id = set_apic_id,379.apic_id_mask = 0xFFFFFFFFu,380381.cpu_mask_to_apicid = uv_cpu_mask_to_apicid,382.cpu_mask_to_apicid_and = uv_cpu_mask_to_apicid_and,383384.send_IPI_mask = uv_send_IPI_mask,385.send_IPI_mask_allbutself = uv_send_IPI_mask_allbutself,386.send_IPI_allbutself = uv_send_IPI_allbutself,387.send_IPI_all = uv_send_IPI_all,388.send_IPI_self = uv_send_IPI_self,389390.wakeup_secondary_cpu = uv_wakeup_secondary,391.trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,392.trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,393.wait_for_init_deassert = NULL,394.smp_callin_clear_local_apic = NULL,395.inquire_remote_apic = NULL,396397.read = native_apic_msr_read,398.write = native_apic_msr_write,399.icr_read = native_x2apic_icr_read,400.icr_write = native_x2apic_icr_write,401.wait_icr_idle = native_x2apic_wait_icr_idle,402.safe_wait_icr_idle = native_safe_x2apic_wait_icr_idle,403};404405static __cpuinit void set_x2apic_extra_bits(int pnode)406{407__this_cpu_write(x2apic_extra_bits, pnode << uvh_apicid.s.pnode_shift);408}409410/*411* Called on boot cpu.412*/413static __init int boot_pnode_to_blade(int pnode)414{415int blade;416417for (blade = 0; blade < uv_num_possible_blades(); blade++)418if (pnode == uv_blade_info[blade].pnode)419return blade;420BUG();421}422423struct redir_addr {424unsigned long redirect;425unsigned long alias;426};427428#define DEST_SHIFT UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR_DEST_BASE_SHFT429430static __initdata struct redir_addr redir_addrs[] = {431{UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR, UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR},432{UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR, UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR},433{UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR, UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR},434};435436static __init void get_lowmem_redirect(unsigned long *base, unsigned long *size)437{438union uvh_rh_gam_alias210_overlay_config_2_mmr_u alias;439union uvh_rh_gam_alias210_redirect_config_2_mmr_u redirect;440int i;441442for (i = 0; i < ARRAY_SIZE(redir_addrs); i++) {443alias.v = uv_read_local_mmr(redir_addrs[i].alias);444if (alias.s.enable && alias.s.base == 0) {445*size = (1UL << alias.s.m_alias);446redirect.v = uv_read_local_mmr(redir_addrs[i].redirect);447*base = (unsigned long)redirect.s.dest_base << DEST_SHIFT;448return;449}450}451*base = *size = 0;452}453454enum map_type {map_wb, map_uc};455456static __init void map_high(char *id, unsigned long base, int pshift,457int bshift, int max_pnode, enum map_type map_type)458{459unsigned long bytes, paddr;460461paddr = base << pshift;462bytes = (1UL << bshift) * (max_pnode + 1);463printk(KERN_INFO "UV: Map %s_HI 0x%lx - 0x%lx\n", id, paddr,464paddr + bytes);465if (map_type == map_uc)466init_extra_mapping_uc(paddr, bytes);467else468init_extra_mapping_wb(paddr, bytes);469470}471static __init void map_gru_high(int max_pnode)472{473union uvh_rh_gam_gru_overlay_config_mmr_u gru;474int shift = UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT;475476gru.v = uv_read_local_mmr(UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR);477if (gru.s.enable) {478map_high("GRU", gru.s.base, shift, shift, max_pnode, map_wb);479gru_start_paddr = ((u64)gru.s.base << shift);480gru_end_paddr = gru_start_paddr + (1UL << shift) * (max_pnode + 1);481482}483}484485static __init void map_mmr_high(int max_pnode)486{487union uvh_rh_gam_mmr_overlay_config_mmr_u mmr;488int shift = UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_SHFT;489490mmr.v = uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR);491if (mmr.s.enable)492map_high("MMR", mmr.s.base, shift, shift, max_pnode, map_uc);493}494495static __init void map_mmioh_high(int max_pnode)496{497union uvh_rh_gam_mmioh_overlay_config_mmr_u mmioh;498int shift;499500mmioh.v = uv_read_local_mmr(UVH_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR);501if (is_uv1_hub() && mmioh.s1.enable) {502shift = UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_BASE_SHFT;503map_high("MMIOH", mmioh.s1.base, shift, mmioh.s1.m_io,504max_pnode, map_uc);505}506if (is_uv2_hub() && mmioh.s2.enable) {507shift = UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_BASE_SHFT;508map_high("MMIOH", mmioh.s2.base, shift, mmioh.s2.m_io,509max_pnode, map_uc);510}511}512513static __init void map_low_mmrs(void)514{515init_extra_mapping_uc(UV_GLOBAL_MMR32_BASE, UV_GLOBAL_MMR32_SIZE);516init_extra_mapping_uc(UV_LOCAL_MMR_BASE, UV_LOCAL_MMR_SIZE);517}518519static __init void uv_rtc_init(void)520{521long status;522u64 ticks_per_sec;523524status = uv_bios_freq_base(BIOS_FREQ_BASE_REALTIME_CLOCK,525&ticks_per_sec);526if (status != BIOS_STATUS_SUCCESS || ticks_per_sec < 100000) {527printk(KERN_WARNING528"unable to determine platform RTC clock frequency, "529"guessing.\n");530/* BIOS gives wrong value for clock freq. so guess */531sn_rtc_cycles_per_second = 1000000000000UL / 30000UL;532} else533sn_rtc_cycles_per_second = ticks_per_sec;534}535536/*537* percpu heartbeat timer538*/539static void uv_heartbeat(unsigned long ignored)540{541struct timer_list *timer = &uv_hub_info->scir.timer;542unsigned char bits = uv_hub_info->scir.state;543544/* flip heartbeat bit */545bits ^= SCIR_CPU_HEARTBEAT;546547/* is this cpu idle? */548if (idle_cpu(raw_smp_processor_id()))549bits &= ~SCIR_CPU_ACTIVITY;550else551bits |= SCIR_CPU_ACTIVITY;552553/* update system controller interface reg */554uv_set_scir_bits(bits);555556/* enable next timer period */557mod_timer_pinned(timer, jiffies + SCIR_CPU_HB_INTERVAL);558}559560static void __cpuinit uv_heartbeat_enable(int cpu)561{562while (!uv_cpu_hub_info(cpu)->scir.enabled) {563struct timer_list *timer = &uv_cpu_hub_info(cpu)->scir.timer;564565uv_set_cpu_scir_bits(cpu, SCIR_CPU_HEARTBEAT|SCIR_CPU_ACTIVITY);566setup_timer(timer, uv_heartbeat, cpu);567timer->expires = jiffies + SCIR_CPU_HB_INTERVAL;568add_timer_on(timer, cpu);569uv_cpu_hub_info(cpu)->scir.enabled = 1;570571/* also ensure that boot cpu is enabled */572cpu = 0;573}574}575576#ifdef CONFIG_HOTPLUG_CPU577static void __cpuinit uv_heartbeat_disable(int cpu)578{579if (uv_cpu_hub_info(cpu)->scir.enabled) {580uv_cpu_hub_info(cpu)->scir.enabled = 0;581del_timer(&uv_cpu_hub_info(cpu)->scir.timer);582}583uv_set_cpu_scir_bits(cpu, 0xff);584}585586/*587* cpu hotplug notifier588*/589static __cpuinit int uv_scir_cpu_notify(struct notifier_block *self,590unsigned long action, void *hcpu)591{592long cpu = (long)hcpu;593594switch (action) {595case CPU_ONLINE:596uv_heartbeat_enable(cpu);597break;598case CPU_DOWN_PREPARE:599uv_heartbeat_disable(cpu);600break;601default:602break;603}604return NOTIFY_OK;605}606607static __init void uv_scir_register_cpu_notifier(void)608{609hotcpu_notifier(uv_scir_cpu_notify, 0);610}611612#else /* !CONFIG_HOTPLUG_CPU */613614static __init void uv_scir_register_cpu_notifier(void)615{616}617618static __init int uv_init_heartbeat(void)619{620int cpu;621622if (is_uv_system())623for_each_online_cpu(cpu)624uv_heartbeat_enable(cpu);625return 0;626}627628late_initcall(uv_init_heartbeat);629630#endif /* !CONFIG_HOTPLUG_CPU */631632/* Direct Legacy VGA I/O traffic to designated IOH */633int uv_set_vga_state(struct pci_dev *pdev, bool decode,634unsigned int command_bits, u32 flags)635{636int domain, bus, rc;637638PR_DEVEL("devfn %x decode %d cmd %x flags %d\n",639pdev->devfn, decode, command_bits, flags);640641if (!(flags & PCI_VGA_STATE_CHANGE_BRIDGE))642return 0;643644if ((command_bits & PCI_COMMAND_IO) == 0)645return 0;646647domain = pci_domain_nr(pdev->bus);648bus = pdev->bus->number;649650rc = uv_bios_set_legacy_vga_target(decode, domain, bus);651PR_DEVEL("vga decode %d %x:%x, rc: %d\n", decode, domain, bus, rc);652653return rc;654}655656/*657* Called on each cpu to initialize the per_cpu UV data area.658* FIXME: hotplug not supported yet659*/660void __cpuinit uv_cpu_init(void)661{662/* CPU 0 initilization will be done via uv_system_init. */663if (!uv_blade_info)664return;665666uv_blade_info[uv_numa_blade_id()].nr_online_cpus++;667668if (get_uv_system_type() == UV_NON_UNIQUE_APIC)669set_x2apic_extra_bits(uv_hub_info->pnode);670}671672/*673* When NMI is received, print a stack trace.674*/675int uv_handle_nmi(struct notifier_block *self, unsigned long reason, void *data)676{677unsigned long real_uv_nmi;678int bid;679680if (reason != DIE_NMIUNKNOWN)681return NOTIFY_OK;682683if (in_crash_kexec)684/* do nothing if entering the crash kernel */685return NOTIFY_OK;686687/*688* Each blade has an MMR that indicates when an NMI has been sent689* to cpus on the blade. If an NMI is detected, atomically690* clear the MMR and update a per-blade NMI count used to691* cause each cpu on the blade to notice a new NMI.692*/693bid = uv_numa_blade_id();694real_uv_nmi = (uv_read_local_mmr(UVH_NMI_MMR) & UV_NMI_PENDING_MASK);695696if (unlikely(real_uv_nmi)) {697spin_lock(&uv_blade_info[bid].nmi_lock);698real_uv_nmi = (uv_read_local_mmr(UVH_NMI_MMR) & UV_NMI_PENDING_MASK);699if (real_uv_nmi) {700uv_blade_info[bid].nmi_count++;701uv_write_local_mmr(UVH_NMI_MMR_CLEAR, UV_NMI_PENDING_MASK);702}703spin_unlock(&uv_blade_info[bid].nmi_lock);704}705706if (likely(__get_cpu_var(cpu_last_nmi_count) == uv_blade_info[bid].nmi_count))707return NOTIFY_DONE;708709__get_cpu_var(cpu_last_nmi_count) = uv_blade_info[bid].nmi_count;710711/*712* Use a lock so only one cpu prints at a time.713* This prevents intermixed output.714*/715spin_lock(&uv_nmi_lock);716pr_info("UV NMI stack dump cpu %u:\n", smp_processor_id());717dump_stack();718spin_unlock(&uv_nmi_lock);719720return NOTIFY_STOP;721}722723static struct notifier_block uv_dump_stack_nmi_nb = {724.notifier_call = uv_handle_nmi,725.priority = NMI_LOCAL_LOW_PRIOR - 1,726};727728void uv_register_nmi_notifier(void)729{730if (register_die_notifier(&uv_dump_stack_nmi_nb))731printk(KERN_WARNING "UV NMI handler failed to register\n");732}733734void uv_nmi_init(void)735{736unsigned int value;737738/*739* Unmask NMI on all cpus740*/741value = apic_read(APIC_LVT1) | APIC_DM_NMI;742value &= ~APIC_LVT_MASKED;743apic_write(APIC_LVT1, value);744}745746void __init uv_system_init(void)747{748union uvh_rh_gam_config_mmr_u m_n_config;749union uvh_rh_gam_mmioh_overlay_config_mmr_u mmioh;750union uvh_node_id_u node_id;751unsigned long gnode_upper, lowmem_redir_base, lowmem_redir_size;752int bytes, nid, cpu, lcpu, pnode, blade, i, j, m_val, n_val, n_io;753int gnode_extra, max_pnode = 0;754unsigned long mmr_base, present, paddr;755unsigned short pnode_mask, pnode_io_mask;756757printk(KERN_INFO "UV: Found %s hub\n", is_uv1_hub() ? "UV1" : "UV2");758map_low_mmrs();759760m_n_config.v = uv_read_local_mmr(UVH_RH_GAM_CONFIG_MMR );761m_val = m_n_config.s.m_skt;762n_val = m_n_config.s.n_skt;763mmioh.v = uv_read_local_mmr(UVH_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR);764n_io = is_uv1_hub() ? mmioh.s1.n_io : mmioh.s2.n_io;765mmr_base =766uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR) &767~UV_MMR_ENABLE;768pnode_mask = (1 << n_val) - 1;769pnode_io_mask = (1 << n_io) - 1;770771node_id.v = uv_read_local_mmr(UVH_NODE_ID);772gnode_extra = (node_id.s.node_id & ~((1 << n_val) - 1)) >> 1;773gnode_upper = ((unsigned long)gnode_extra << m_val);774printk(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",775n_val, m_val, n_io, gnode_upper, gnode_extra, pnode_mask, pnode_io_mask);776777printk(KERN_DEBUG "UV: global MMR base 0x%lx\n", mmr_base);778779for(i = 0; i < UVH_NODE_PRESENT_TABLE_DEPTH; i++)780uv_possible_blades +=781hweight64(uv_read_local_mmr( UVH_NODE_PRESENT_TABLE + i * 8));782printk(KERN_DEBUG "UV: Found %d blades\n", uv_num_possible_blades());783784bytes = sizeof(struct uv_blade_info) * uv_num_possible_blades();785uv_blade_info = kzalloc(bytes, GFP_KERNEL);786BUG_ON(!uv_blade_info);787788for (blade = 0; blade < uv_num_possible_blades(); blade++)789uv_blade_info[blade].memory_nid = -1;790791get_lowmem_redirect(&lowmem_redir_base, &lowmem_redir_size);792793bytes = sizeof(uv_node_to_blade[0]) * num_possible_nodes();794uv_node_to_blade = kmalloc(bytes, GFP_KERNEL);795BUG_ON(!uv_node_to_blade);796memset(uv_node_to_blade, 255, bytes);797798bytes = sizeof(uv_cpu_to_blade[0]) * num_possible_cpus();799uv_cpu_to_blade = kmalloc(bytes, GFP_KERNEL);800BUG_ON(!uv_cpu_to_blade);801memset(uv_cpu_to_blade, 255, bytes);802803blade = 0;804for (i = 0; i < UVH_NODE_PRESENT_TABLE_DEPTH; i++) {805present = uv_read_local_mmr(UVH_NODE_PRESENT_TABLE + i * 8);806for (j = 0; j < 64; j++) {807if (!test_bit(j, &present))808continue;809pnode = (i * 64 + j) & pnode_mask;810uv_blade_info[blade].pnode = pnode;811uv_blade_info[blade].nr_possible_cpus = 0;812uv_blade_info[blade].nr_online_cpus = 0;813spin_lock_init(&uv_blade_info[blade].nmi_lock);814max_pnode = max(pnode, max_pnode);815blade++;816}817}818819uv_bios_init();820uv_bios_get_sn_info(0, &uv_type, &sn_partition_id, &sn_coherency_id,821&sn_region_size, &system_serial_number);822uv_rtc_init();823824for_each_present_cpu(cpu) {825int apicid = per_cpu(x86_cpu_to_apicid, cpu);826827nid = cpu_to_node(cpu);828/*829* apic_pnode_shift must be set before calling uv_apicid_to_pnode();830*/831uv_cpu_hub_info(cpu)->pnode_mask = pnode_mask;832uv_cpu_hub_info(cpu)->apic_pnode_shift = uvh_apicid.s.pnode_shift;833uv_cpu_hub_info(cpu)->hub_revision = uv_hub_info->hub_revision;834835pnode = uv_apicid_to_pnode(apicid);836blade = boot_pnode_to_blade(pnode);837lcpu = uv_blade_info[blade].nr_possible_cpus;838uv_blade_info[blade].nr_possible_cpus++;839840/* Any node on the blade, else will contain -1. */841uv_blade_info[blade].memory_nid = nid;842843uv_cpu_hub_info(cpu)->lowmem_remap_base = lowmem_redir_base;844uv_cpu_hub_info(cpu)->lowmem_remap_top = lowmem_redir_size;845uv_cpu_hub_info(cpu)->m_val = m_val;846uv_cpu_hub_info(cpu)->n_val = n_val;847uv_cpu_hub_info(cpu)->numa_blade_id = blade;848uv_cpu_hub_info(cpu)->blade_processor_id = lcpu;849uv_cpu_hub_info(cpu)->pnode = pnode;850uv_cpu_hub_info(cpu)->gpa_mask = (1UL << (m_val + n_val)) - 1;851uv_cpu_hub_info(cpu)->gnode_upper = gnode_upper;852uv_cpu_hub_info(cpu)->gnode_extra = gnode_extra;853uv_cpu_hub_info(cpu)->global_mmr_base = mmr_base;854uv_cpu_hub_info(cpu)->coherency_domain_number = sn_coherency_id;855uv_cpu_hub_info(cpu)->scir.offset = uv_scir_offset(apicid);856uv_node_to_blade[nid] = blade;857uv_cpu_to_blade[cpu] = blade;858}859860/* Add blade/pnode info for nodes without cpus */861for_each_online_node(nid) {862if (uv_node_to_blade[nid] >= 0)863continue;864paddr = node_start_pfn(nid) << PAGE_SHIFT;865paddr = uv_soc_phys_ram_to_gpa(paddr);866pnode = (paddr >> m_val) & pnode_mask;867blade = boot_pnode_to_blade(pnode);868uv_node_to_blade[nid] = blade;869}870871map_gru_high(max_pnode);872map_mmr_high(max_pnode);873map_mmioh_high(max_pnode & pnode_io_mask);874875uv_cpu_init();876uv_scir_register_cpu_notifier();877uv_register_nmi_notifier();878proc_mkdir("sgi_uv", NULL);879880/* register Legacy VGA I/O redirection handler */881pci_register_set_vga_state(uv_set_vga_state);882883/*884* For a kdump kernel the reset must be BOOT_ACPI, not BOOT_EFI, as885* EFI is not enabled in the kdump kernel.886*/887if (is_kdump_kernel())888reboot_type = BOOT_ACPI;889}890891apic_driver(apic_x2apic_uv_x);892893894