| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * SGI NMI support routines |
|---|
| 3 | 4 | * |
|---|
| 4 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 5 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 6 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 7 | | - * (at your option) any later version. |
|---|
| 8 | | - * |
|---|
| 9 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 10 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 11 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 12 | | - * GNU General Public License for more details. |
|---|
| 13 | | - * |
|---|
| 14 | | - * You should have received a copy of the GNU General Public License |
|---|
| 15 | | - * along with this program; if not, write to the Free Software |
|---|
| 16 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 17 | | - * |
|---|
| 18 | | - * Copyright (c) 2009-2013 Silicon Graphics, Inc. All Rights Reserved. |
|---|
| 19 | | - * Copyright (c) Mike Travis |
|---|
| 5 | + * (C) Copyright 2020 Hewlett Packard Enterprise Development LP |
|---|
| 6 | + * Copyright (C) 2007-2017 Silicon Graphics, Inc. All rights reserved. |
|---|
| 7 | + * Copyright (c) Mike Travis |
|---|
| 20 | 8 | */ |
|---|
| 21 | 9 | |
|---|
| 22 | 10 | #include <linux/cpu.h> |
|---|
| .. | .. |
|---|
| 66 | 54 | static struct uv_hub_nmi_s **uv_hub_nmi_list; |
|---|
| 67 | 55 | |
|---|
| 68 | 56 | DEFINE_PER_CPU(struct uv_cpu_nmi_s, uv_cpu_nmi); |
|---|
| 57 | + |
|---|
| 58 | +/* Newer SMM NMI handler, not present in all systems */ |
|---|
| 59 | +static unsigned long uvh_nmi_mmrx; /* UVH_EVENT_OCCURRED0/1 */ |
|---|
| 60 | +static unsigned long uvh_nmi_mmrx_clear; /* UVH_EVENT_OCCURRED0/1_ALIAS */ |
|---|
| 61 | +static int uvh_nmi_mmrx_shift; /* UVH_EVENT_OCCURRED0/1_EXTIO_INT0_SHFT */ |
|---|
| 62 | +static char *uvh_nmi_mmrx_type; /* "EXTIO_INT0" */ |
|---|
| 63 | + |
|---|
| 64 | +/* Non-zero indicates newer SMM NMI handler present */ |
|---|
| 65 | +static unsigned long uvh_nmi_mmrx_supported; /* UVH_EXTIO_INT0_BROADCAST */ |
|---|
| 66 | + |
|---|
| 67 | +/* Indicates to BIOS that we want to use the newer SMM NMI handler */ |
|---|
| 68 | +static unsigned long uvh_nmi_mmrx_req; /* UVH_BIOS_KERNEL_MMR_ALIAS_2 */ |
|---|
| 69 | +static int uvh_nmi_mmrx_req_shift; /* 62 */ |
|---|
| 69 | 70 | |
|---|
| 70 | 71 | /* UV hubless values */ |
|---|
| 71 | 72 | #define NMI_CONTROL_PORT 0x70 |
|---|
| .. | .. |
|---|
| 240 | 241 | /* Setup which NMI support is present in system */ |
|---|
| 241 | 242 | static void uv_nmi_setup_mmrs(void) |
|---|
| 242 | 243 | { |
|---|
| 243 | | - if (uv_read_local_mmr(UVH_NMI_MMRX_SUPPORTED)) { |
|---|
| 244 | | - uv_write_local_mmr(UVH_NMI_MMRX_REQ, |
|---|
| 245 | | - 1UL << UVH_NMI_MMRX_REQ_SHIFT); |
|---|
| 246 | | - nmi_mmr = UVH_NMI_MMRX; |
|---|
| 247 | | - nmi_mmr_clear = UVH_NMI_MMRX_CLEAR; |
|---|
| 248 | | - nmi_mmr_pending = 1UL << UVH_NMI_MMRX_SHIFT; |
|---|
| 249 | | - pr_info("UV: SMI NMI support: %s\n", UVH_NMI_MMRX_TYPE); |
|---|
| 244 | + /* First determine arch specific MMRs to handshake with BIOS */ |
|---|
| 245 | + if (UVH_EVENT_OCCURRED0_EXTIO_INT0_MASK) { |
|---|
| 246 | + uvh_nmi_mmrx = UVH_EVENT_OCCURRED0; |
|---|
| 247 | + uvh_nmi_mmrx_clear = UVH_EVENT_OCCURRED0_ALIAS; |
|---|
| 248 | + uvh_nmi_mmrx_shift = UVH_EVENT_OCCURRED0_EXTIO_INT0_SHFT; |
|---|
| 249 | + uvh_nmi_mmrx_type = "OCRD0-EXTIO_INT0"; |
|---|
| 250 | + |
|---|
| 251 | + uvh_nmi_mmrx_supported = UVH_EXTIO_INT0_BROADCAST; |
|---|
| 252 | + uvh_nmi_mmrx_req = UVH_BIOS_KERNEL_MMR_ALIAS_2; |
|---|
| 253 | + uvh_nmi_mmrx_req_shift = 62; |
|---|
| 254 | + |
|---|
| 255 | + } else if (UVH_EVENT_OCCURRED1_EXTIO_INT0_MASK) { |
|---|
| 256 | + uvh_nmi_mmrx = UVH_EVENT_OCCURRED1; |
|---|
| 257 | + uvh_nmi_mmrx_clear = UVH_EVENT_OCCURRED1_ALIAS; |
|---|
| 258 | + uvh_nmi_mmrx_shift = UVH_EVENT_OCCURRED1_EXTIO_INT0_SHFT; |
|---|
| 259 | + uvh_nmi_mmrx_type = "OCRD1-EXTIO_INT0"; |
|---|
| 260 | + |
|---|
| 261 | + uvh_nmi_mmrx_supported = UVH_EXTIO_INT0_BROADCAST; |
|---|
| 262 | + uvh_nmi_mmrx_req = UVH_BIOS_KERNEL_MMR_ALIAS_2; |
|---|
| 263 | + uvh_nmi_mmrx_req_shift = 62; |
|---|
| 264 | + |
|---|
| 265 | + } else { |
|---|
| 266 | + pr_err("UV:%s:cannot find EVENT_OCCURRED*_EXTIO_INT0\n", |
|---|
| 267 | + __func__); |
|---|
| 268 | + return; |
|---|
| 269 | + } |
|---|
| 270 | + |
|---|
| 271 | + /* Then find out if new NMI is supported */ |
|---|
| 272 | + if (likely(uv_read_local_mmr(uvh_nmi_mmrx_supported))) { |
|---|
| 273 | + uv_write_local_mmr(uvh_nmi_mmrx_req, |
|---|
| 274 | + 1UL << uvh_nmi_mmrx_req_shift); |
|---|
| 275 | + nmi_mmr = uvh_nmi_mmrx; |
|---|
| 276 | + nmi_mmr_clear = uvh_nmi_mmrx_clear; |
|---|
| 277 | + nmi_mmr_pending = 1UL << uvh_nmi_mmrx_shift; |
|---|
| 278 | + pr_info("UV: SMI NMI support: %s\n", uvh_nmi_mmrx_type); |
|---|
| 250 | 279 | } else { |
|---|
| 251 | 280 | nmi_mmr = UVH_NMI_MMR; |
|---|
| 252 | 281 | nmi_mmr_clear = UVH_NMI_MMR_CLEAR; |
|---|
| .. | .. |
|---|
| 560 | 589 | } |
|---|
| 561 | 590 | } |
|---|
| 562 | 591 | |
|---|
| 563 | | -/* Ping non-responding CPU's attemping to force them into the NMI handler */ |
|---|
| 592 | +/* Ping non-responding CPU's attempting to force them into the NMI handler */ |
|---|
| 564 | 593 | static void uv_nmi_nr_cpus_ping(void) |
|---|
| 565 | 594 | { |
|---|
| 566 | 595 | int cpu; |
|---|
| .. | .. |
|---|
| 1062 | 1091 | /* Ensure NMI enabled in Processor Interface Reg: */ |
|---|
| 1063 | 1092 | uv_reassert_nmi(); |
|---|
| 1064 | 1093 | uv_register_nmi_notifier(); |
|---|
| 1065 | | - pr_info("UV: Hubless NMI enabled\n"); |
|---|
| 1094 | + pr_info("UV: PCH NMI enabled\n"); |
|---|
| 1066 | 1095 | } |
|---|