* Cleanup different aspects of the UV code and start adding support for

the new UV5 class of systems, by Mike Travis.
 
 * Use a flexible array for a dynamically sized struct uv_rtc_timer_head,
 by Gustavo A. R. Silva.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEzv7L6UO9uDPlPSfHEsHwGGHeVUoFAl+EKuMACgkQEsHwGGHe
 VUp5pA//WHU9Xp3LGAL6FWaKGdiN4KA4+MZyl892LtWUy0RqPSSOP/hovyLfwOo8
 aXsaYdm2nlMXNBWNZd0CY+ZsEVV8XOJdbXiqi+Em1QINk3VLJM9rEN9QCALCPAkd
 kFdRC6ajJrgTFASa0agBToJiaNndPacZ2ndI8Bx+WIsbBsYx4oln3pCKtmeZNrNk
 bWnMTOK+sylILIScmhdgV/czMECAc4sMFF/W/rJdBpoA7duoa6yDycD7E3928o8H
 JtMc2wwBLXZSSh3YI7/Z80n7xopQgq3/WRqOjhNHVqRa5rR4ZnleQkXYw1MG2W0H
 Gk34aEcFA+M2xJZ2voL/YjngFEgMZG0HNg+AJJBX7K/+B3HvfTjWheTMMdaae7Wr
 iW4YFFxaJ5FoB2qFz8sZpln8tbniYxiwxJq9aESjwVqlEPoQ13ZTohAVXBJq+CsZ
 NufRJyY7bB5SoDiIucWNdAnJ4bUQDs+UouUqrSORtPqQg/+gJ17krZxQY+oST1I+
 BDmAInBzcdScyjAKui7+csgSWW4lgHDUzqYGnFogcpvJc3s9HnqebTNqTwQQvrDM
 e8VbuH2X3z5/xgbtE9W3ND3Rf+4CLTMbd6J8SKAceI9sQ1ZOZzLZlJU4TQCbXXoW
 vSI5Gv9B3AlI4PGIphdt4M3Sm78fG11PMwuUQEO3WSLjOt5amrM=
 =llxK
 -----END PGP SIGNATURE-----

Merge tag 'x86_platform_for_v5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 platform updates from Borislav Petkov:

 - Cleanup different aspects of the UV code and start adding support for
   the new UV5 class of systems (Mike Travis)

 - Use a flexible array for a dynamically sized struct uv_rtc_timer_head
   (Gustavo A. R. Silva)

* tag 'x86_platform_for_v5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/platform/uv: Update Copyrights to conform to HPE standards
  x86/platform/uv: Update for UV5 NMI MMR changes
  x86/platform/uv: Update UV5 TSC checking
  x86/platform/uv: Update node present counting
  x86/platform/uv: Update UV5 MMR references in UV GRU
  x86/platform/uv: Adjust GAM MMR references affected by UV5 updates
  x86/platform/uv: Update MMIOH references based on new UV5 MMRs
  x86/platform/uv: Add and decode Arch Type in UVsystab
  x86/platform/uv: Add UV5 direct references
  x86/platform/uv: Update UV MMRs for UV5
  drivers/misc/sgi-xp: Adjust references in UV kernel modules
  x86/platform/uv: Remove SCIR MMR references for UV systems
  x86/platform/uv: Remove UV BAU TLB Shootdown Handler
  x86/uv/time: Use a flexible array in struct uv_rtc_timer_head
This commit is contained in:
Linus Torvalds 2020-10-12 10:31:18 -07:00
commit 8b6591fd0a
21 changed files with 4886 additions and 6978 deletions

View file

@ -591,10 +591,6 @@ DECLARE_IDTENTRY_SYSVEC(CALL_FUNCTION_VECTOR, sysvec_call_function);
#endif
#ifdef CONFIG_X86_LOCAL_APIC
# ifdef CONFIG_X86_UV
DECLARE_IDTENTRY_SYSVEC(UV_BAU_MESSAGE, sysvec_uv_bau_message);
# endif
# ifdef CONFIG_X86_MCE_THRESHOLD
DECLARE_IDTENTRY_SYSVEC(THRESHOLD_APIC_VECTOR, sysvec_threshold);
# endif

View file

@ -5,8 +5,9 @@
/*
* UV BIOS layer definitions.
*
* Copyright (c) 2008-2009 Silicon Graphics, Inc. All Rights Reserved.
* Copyright (c) Russ Anderson <rja@sgi.com>
* (C) Copyright 2020 Hewlett Packard Enterprise Development LP
* Copyright (C) 2007-2017 Silicon Graphics, Inc. All rights reserved.
* Copyright (c) Russ Anderson <rja@sgi.com>
*/
#include <linux/rtc.h>
@ -71,6 +72,11 @@ struct uv_gam_range_entry {
u32 limit; /* PA bits 56:26 (UV_GAM_RANGE_SHFT) */
};
#define UV_AT_SIZE 8 /* 7 character arch type + NULL char */
struct uv_arch_type_entry {
char archtype[UV_AT_SIZE];
};
#define UV_SYSTAB_SIG "UVST"
#define UV_SYSTAB_VERSION_1 1 /* UV2/3 BIOS version */
#define UV_SYSTAB_VERSION_UV4 0x400 /* UV4 BIOS base version */
@ -79,10 +85,14 @@ struct uv_gam_range_entry {
#define UV_SYSTAB_VERSION_UV4_3 0x403 /* - GAM Range PXM Value */
#define UV_SYSTAB_VERSION_UV4_LATEST UV_SYSTAB_VERSION_UV4_3
#define UV_SYSTAB_VERSION_UV5 0x500 /* UV5 GAM base version */
#define UV_SYSTAB_VERSION_UV5_LATEST UV_SYSTAB_VERSION_UV5
#define UV_SYSTAB_TYPE_UNUSED 0 /* End of table (offset == 0) */
#define UV_SYSTAB_TYPE_GAM_PARAMS 1 /* GAM PARAM conversions */
#define UV_SYSTAB_TYPE_GAM_RNG_TBL 2 /* GAM entry table */
#define UV_SYSTAB_TYPE_MAX 3
#define UV_SYSTAB_TYPE_ARCH_TYPE 3 /* UV arch type */
#define UV_SYSTAB_TYPE_MAX 4
/*
* The UV system table describes specific firmware
@ -133,6 +143,7 @@ extern s64 uv_bios_reserved_page_pa(u64, u64 *, u64 *, u64 *);
extern int uv_bios_set_legacy_vga_target(bool decode, int domain, int bus);
extern int uv_bios_init(void);
extern unsigned long get_uv_systab_phys(bool msg);
extern unsigned long sn_rtc_cycles_per_second;
extern int uv_type;

View file

@ -35,10 +35,8 @@ extern int is_uv_hubbed(int uvtype);
extern void uv_cpu_init(void);
extern void uv_nmi_init(void);
extern void uv_system_init(void);
extern const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
const struct flush_tlb_info *info);
#else /* X86_UV */
#else /* !X86_UV */
static inline enum uv_system_type get_uv_system_type(void) { return UV_NONE; }
static inline bool is_early_uv_system(void) { return 0; }

View file

@ -1,755 +0,0 @@
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* SGI UV Broadcast Assist Unit definitions
*
* Copyright (C) 2008-2011 Silicon Graphics, Inc. All rights reserved.
*/
#ifndef _ASM_X86_UV_UV_BAU_H
#define _ASM_X86_UV_UV_BAU_H
#include <linux/bitmap.h>
#include <asm/idtentry.h>
#define BITSPERBYTE 8
/*
* Broadcast Assist Unit messaging structures
*
* Selective Broadcast activations are induced by software action
* specifying a particular 8-descriptor "set" via a 6-bit index written
* to an MMR.
* Thus there are 64 unique 512-byte sets of SB descriptors - one set for
* each 6-bit index value. These descriptor sets are mapped in sequence
* starting with set 0 located at the address specified in the
* BAU_SB_DESCRIPTOR_BASE register, set 1 is located at BASE + 512,
* set 2 is at BASE + 2*512, set 3 at BASE + 3*512, and so on.
*
* We will use one set for sending BAU messages from each of the
* cpu's on the uvhub.
*
* TLB shootdown will use the first of the 8 descriptors of each set.
* Each of the descriptors is 64 bytes in size (8*64 = 512 bytes in a set).
*/
#define MAX_CPUS_PER_UVHUB 128
#define MAX_CPUS_PER_SOCKET 64
#define ADP_SZ 64 /* hardware-provided max. */
#define UV_CPUS_PER_AS 32 /* hardware-provided max. */
#define ITEMS_PER_DESC 8
/* the 'throttle' to prevent the hardware stay-busy bug */
#define MAX_BAU_CONCURRENT 3
#define UV_ACT_STATUS_MASK 0x3
#define UV_ACT_STATUS_SIZE 2
#define UV_DISTRIBUTION_SIZE 256
#define UV_SW_ACK_NPENDING 8
#define UV_NET_ENDPOINT_INTD 0x28
#define UV_PAYLOADQ_GNODE_SHIFT 49
#define UV_PTC_BASENAME "sgi_uv/ptc_statistics"
#define UV_BAU_BASENAME "sgi_uv/bau_tunables"
#define UV_BAU_TUNABLES_DIR "sgi_uv"
#define UV_BAU_TUNABLES_FILE "bau_tunables"
#define WHITESPACE " \t\n"
#define cpubit_isset(cpu, bau_local_cpumask) \
test_bit((cpu), (bau_local_cpumask).bits)
/* [19:16] SOFT_ACK timeout period 19: 1 is urgency 7 17:16 1 is multiplier */
/*
* UV2: Bit 19 selects between
* (0): 10 microsecond timebase and
* (1): 80 microseconds
* we're using 560us
*/
#define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD (15UL)
/* assuming UV3 is the same */
#define BAU_MISC_CONTROL_MULT_MASK 3
#define UVH_AGING_PRESCALE_SEL 0x000000b000UL
/* [30:28] URGENCY_7 an index into a table of times */
#define BAU_URGENCY_7_SHIFT 28
#define BAU_URGENCY_7_MASK 7
#define UVH_TRANSACTION_TIMEOUT 0x000000b200UL
/* [45:40] BAU - BAU transaction timeout select - a multiplier */
#define BAU_TRANS_SHIFT 40
#define BAU_TRANS_MASK 0x3f
/*
* shorten some awkward names
*/
#define AS_PUSH_SHIFT UVH_LB_BAU_SB_ACTIVATION_CONTROL_PUSH_SHFT
#define SOFTACK_MSHIFT UVH_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_SHFT
#define SOFTACK_PSHIFT UVH_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHFT
#define SOFTACK_TIMEOUT_PERIOD UV_INTD_SOFT_ACK_TIMEOUT_PERIOD
#define PREFETCH_HINT_SHFT UV3H_LB_BAU_MISC_CONTROL_ENABLE_INTD_PREFETCH_HINT_SHFT
#define SB_STATUS_SHFT UV3H_LB_BAU_MISC_CONTROL_ENABLE_EXTENDED_SB_STATUS_SHFT
#define write_gmmr uv_write_global_mmr64
#define write_lmmr uv_write_local_mmr
#define read_lmmr uv_read_local_mmr
#define read_gmmr uv_read_global_mmr64
/*
* bits in UVH_LB_BAU_SB_ACTIVATION_STATUS_0/1
*/
#define DS_IDLE 0
#define DS_ACTIVE 1
#define DS_DESTINATION_TIMEOUT 2
#define DS_SOURCE_TIMEOUT 3
/*
* bits put together from HRP_LB_BAU_SB_ACTIVATION_STATUS_0/1/2
* values 1 and 3 will not occur
* Decoded meaning ERROR BUSY AUX ERR
* ------------------------------- ---- ----- -------
* IDLE 0 0 0
* BUSY (active) 0 1 0
* SW Ack Timeout (destination) 1 0 0
* SW Ack INTD rejected (strong NACK) 1 0 1
* Source Side Time Out Detected 1 1 0
* Destination Side PUT Failed 1 1 1
*/
#define UV2H_DESC_IDLE 0
#define UV2H_DESC_BUSY 2
#define UV2H_DESC_DEST_TIMEOUT 4
#define UV2H_DESC_DEST_STRONG_NACK 5
#define UV2H_DESC_SOURCE_TIMEOUT 6
#define UV2H_DESC_DEST_PUT_ERR 7
/*
* delay for 'plugged' timeout retries, in microseconds
*/
#define PLUGGED_DELAY 10
/*
* threshholds at which to use IPI to free resources
*/
/* after this # consecutive 'plugged' timeouts, use IPI to release resources */
#define PLUGSB4RESET 100
/* after this many consecutive timeouts, use IPI to release resources */
#define TIMEOUTSB4RESET 1
/* at this number uses of IPI to release resources, giveup the request */
#define IPI_RESET_LIMIT 1
/* after this # consecutive successes, bump up the throttle if it was lowered */
#define COMPLETE_THRESHOLD 5
/* after this # of giveups (fall back to kernel IPI's) disable the use of
the BAU for a period of time */
#define GIVEUP_LIMIT 100
#define UV_LB_SUBNODEID 0x10
#define UV_SA_SHFT UVH_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHFT
#define UV_SA_MASK UVH_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_MASK
/* 4 bits of software ack period */
#define UV2_ACK_MASK 0x7UL
#define UV2_ACK_UNITS_SHFT 3
#define UV2_EXT_SHFT UV2H_LB_BAU_MISC_CONTROL_ENABLE_EXTENDED_SB_STATUS_SHFT
/*
* number of entries in the destination side payload queue
*/
#define DEST_Q_SIZE 20
/*
* number of destination side software ack resources
*/
#define DEST_NUM_RESOURCES 8
/*
* completion statuses for sending a TLB flush message
*/
#define FLUSH_RETRY_PLUGGED 1
#define FLUSH_RETRY_TIMEOUT 2
#define FLUSH_GIVEUP 3
#define FLUSH_COMPLETE 4
/*
* tuning the action when the numalink network is extremely delayed
*/
#define CONGESTED_RESPONSE_US 1000 /* 'long' response time, in
microseconds */
#define CONGESTED_REPS 10 /* long delays averaged over
this many broadcasts */
#define DISABLED_PERIOD 10 /* time for the bau to be
disabled, in seconds */
/* see msg_type: */
#define MSG_NOOP 0
#define MSG_REGULAR 1
#define MSG_RETRY 2
#define BAU_DESC_QUALIFIER 0x534749
enum uv_bau_version {
UV_BAU_V2 = 2,
UV_BAU_V3,
UV_BAU_V4,
};
/*
* Distribution: 32 bytes (256 bits) (bytes 0-0x1f of descriptor)
* If the 'multilevel' flag in the header portion of the descriptor
* has been set to 0, then endpoint multi-unicast mode is selected.
* The distribution specification (32 bytes) is interpreted as a 256-bit
* distribution vector. Adjacent bits correspond to consecutive even numbered
* nodeIDs. The result of adding the index of a given bit to the 15-bit
* 'base_dest_nasid' field of the header corresponds to the
* destination nodeID associated with that specified bit.
*/
struct pnmask {
unsigned long bits[BITS_TO_LONGS(UV_DISTRIBUTION_SIZE)];
};
/*
* mask of cpu's on a uvhub
* (during initialization we need to check that unsigned long has
* enough bits for max. cpu's per uvhub)
*/
struct bau_local_cpumask {
unsigned long bits;
};
/*
* Payload: 16 bytes (128 bits) (bytes 0x20-0x2f of descriptor)
* only 12 bytes (96 bits) of the payload area are usable.
* An additional 3 bytes (bits 27:4) of the header address are carried
* to the next bytes of the destination payload queue.
* And an additional 2 bytes of the header Suppl_A field are also
* carried to the destination payload queue.
* But the first byte of the Suppl_A becomes bits 127:120 (the 16th byte)
* of the destination payload queue, which is written by the hardware
* with the s/w ack resource bit vector.
* [ effective message contents (16 bytes (128 bits) maximum), not counting
* the s/w ack bit vector ]
*/
/**
* struct uv2_3_bau_msg_payload - defines payload for INTD transactions
* @address: Signifies a page or all TLB's of the cpu
* @sending_cpu: CPU from which the message originates
* @acknowledge_count: CPUs on the destination Hub that received the interrupt
*/
struct uv2_3_bau_msg_payload {
u64 address;
u16 sending_cpu;
u16 acknowledge_count;
};
/**
* struct uv4_bau_msg_payload - defines payload for INTD transactions
* @address: Signifies a page or all TLB's of the cpu
* @sending_cpu: CPU from which the message originates
* @acknowledge_count: CPUs on the destination Hub that received the interrupt
* @qualifier: Set by source to verify origin of INTD broadcast
*/
struct uv4_bau_msg_payload {
u64 address;
u16 sending_cpu;
u16 acknowledge_count;
u32 reserved:8;
u32 qualifier:24;
};
/*
* UV2 Message header: 16 bytes (128 bits) (bytes 0x30-0x3f of descriptor)
* see figure 9-2 of harp_sys.pdf
* assuming UV3 is the same
*/
struct uv2_3_bau_msg_header {
unsigned int base_dest_nasid:15; /* nasid of the first bit */
/* bits 14:0 */ /* in uvhub map */
unsigned int dest_subnodeid:5; /* must be 0x10, for the LB */
/* bits 19:15 */
unsigned int rsvd_1:1; /* must be zero */
/* bit 20 */
/* Address bits 59:21 */
/* bits 25:2 of address (44:21) are payload */
/* these next 24 bits become bytes 12-14 of msg */
/* bits 28:21 land in byte 12 */
unsigned int replied_to:1; /* sent as 0 by the source to
byte 12 */
/* bit 21 */
unsigned int msg_type:3; /* software type of the
message */
/* bits 24:22 */
unsigned int canceled:1; /* message canceled, resource
is to be freed*/
/* bit 25 */
unsigned int payload_1:3; /* not currently used */
/* bits 28:26 */
/* bits 36:29 land in byte 13 */
unsigned int payload_2a:3; /* not currently used */
unsigned int payload_2b:5; /* not currently used */
/* bits 36:29 */
/* bits 44:37 land in byte 14 */
unsigned int payload_3:8; /* not currently used */
/* bits 44:37 */
unsigned int rsvd_2:7; /* reserved */
/* bits 51:45 */
unsigned int swack_flag:1; /* software acknowledge flag */
/* bit 52 */
unsigned int rsvd_3a:3; /* must be zero */
unsigned int rsvd_3b:8; /* must be zero */
unsigned int rsvd_3c:8; /* must be zero */
unsigned int rsvd_3d:3; /* must be zero */
/* bits 74:53 */
unsigned int fairness:3; /* usually zero */
/* bits 77:75 */
unsigned int sequence:16; /* message sequence number */
/* bits 93:78 Suppl_A */
unsigned int chaining:1; /* next descriptor is part of
this activation*/
/* bit 94 */
unsigned int multilevel:1; /* multi-level multicast
format */
/* bit 95 */
unsigned int rsvd_4:24; /* ordered / source node /
source subnode / aging
must be zero */
/* bits 119:96 */
unsigned int command:8; /* message type */
/* bits 127:120 */
};
/*
* The activation descriptor:
* The format of the message to send, plus all accompanying control
* Should be 64 bytes
*/
struct bau_desc {
struct pnmask distribution;
/*
* message template, consisting of header and payload:
*/
union bau_msg_header {
struct uv2_3_bau_msg_header uv2_3_hdr;
} header;
union bau_payload_header {
struct uv2_3_bau_msg_payload uv2_3;
struct uv4_bau_msg_payload uv4;
} payload;
};
/* UV2:
* -payload-- ---------header------
* bytes 0-11 bits 70-78 bits 21-44
* A B (2) C (3)
*
* A/B/C are moved to:
* A C B
* bytes 0-11 bytes 12-14 bytes 16-17 (byte 15 filled in by hw as vector)
* ------------payload queue-----------
*/
/*
* The payload queue on the destination side is an array of these.
* With BAU_MISC_CONTROL set for software acknowledge mode, the messages
* are 32 bytes (2 micropackets) (256 bits) in length, but contain only 17
* bytes of usable data, including the sw ack vector in byte 15 (bits 127:120)
* (12 bytes come from bau_msg_payload, 3 from payload_1, 2 from
* swack_vec and payload_2)
* "Enabling Software Acknowledgment mode (see Section 4.3.3 Software
* Acknowledge Processing) also selects 32 byte (17 bytes usable) payload
* operation."
*/
struct bau_pq_entry {
unsigned long address; /* signifies a page or all TLB's
of the cpu */
/* 64 bits, bytes 0-7 */
unsigned short sending_cpu; /* cpu that sent the message */
/* 16 bits, bytes 8-9 */
unsigned short acknowledge_count; /* filled in by destination */
/* 16 bits, bytes 10-11 */
/* these next 3 bytes come from bits 58-81 of the message header */
unsigned short replied_to:1; /* sent as 0 by the source */
unsigned short msg_type:3; /* software message type */
unsigned short canceled:1; /* sent as 0 by the source */
unsigned short unused1:3; /* not currently using */
/* byte 12 */
unsigned char unused2a; /* not currently using */
/* byte 13 */
unsigned char unused2; /* not currently using */
/* byte 14 */
unsigned char swack_vec; /* filled in by the hardware */
/* byte 15 (bits 127:120) */
unsigned short sequence; /* message sequence number */
/* bytes 16-17 */
unsigned char unused4[2]; /* not currently using bytes 18-19 */
/* bytes 18-19 */
int number_of_cpus; /* filled in at destination */
/* 32 bits, bytes 20-23 (aligned) */
unsigned char unused5[8]; /* not using */
/* bytes 24-31 */
};
struct msg_desc {
struct bau_pq_entry *msg;
int msg_slot;
struct bau_pq_entry *queue_first;
struct bau_pq_entry *queue_last;
};
struct reset_args {
int sender;
};
/*
* This structure is allocated per_cpu for UV TLB shootdown statistics.
*/
struct ptc_stats {
/* sender statistics */
unsigned long s_giveup; /* number of fall backs to
IPI-style flushes */
unsigned long s_requestor; /* number of shootdown
requests */
unsigned long s_stimeout; /* source side timeouts */
unsigned long s_dtimeout; /* destination side timeouts */
unsigned long s_strongnacks; /* number of strong nack's */
unsigned long s_time; /* time spent in sending side */
unsigned long s_retriesok; /* successful retries */
unsigned long s_ntargcpu; /* total number of cpu's
targeted */
unsigned long s_ntargself; /* times the sending cpu was
targeted */
unsigned long s_ntarglocals; /* targets of cpus on the local
blade */
unsigned long s_ntargremotes; /* targets of cpus on remote
blades */
unsigned long s_ntarglocaluvhub; /* targets of the local hub */
unsigned long s_ntargremoteuvhub; /* remotes hubs targeted */
unsigned long s_ntarguvhub; /* total number of uvhubs
targeted */
unsigned long s_ntarguvhub16; /* number of times target
hubs >= 16*/
unsigned long s_ntarguvhub8; /* number of times target
hubs >= 8 */
unsigned long s_ntarguvhub4; /* number of times target
hubs >= 4 */
unsigned long s_ntarguvhub2; /* number of times target
hubs >= 2 */
unsigned long s_ntarguvhub1; /* number of times target
hubs == 1 */
unsigned long s_resets_plug; /* ipi-style resets from plug
state */
unsigned long s_resets_timeout; /* ipi-style resets from
timeouts */
unsigned long s_busy; /* status stayed busy past
s/w timer */
unsigned long s_throttles; /* waits in throttle */
unsigned long s_retry_messages; /* retry broadcasts */
unsigned long s_bau_reenabled; /* for bau enable/disable */
unsigned long s_bau_disabled; /* for bau enable/disable */
unsigned long s_uv2_wars; /* uv2 workaround, perm. busy */
unsigned long s_uv2_wars_hw; /* uv2 workaround, hiwater */
unsigned long s_uv2_war_waits; /* uv2 workaround, long waits */
unsigned long s_overipilimit; /* over the ipi reset limit */
unsigned long s_giveuplimit; /* disables, over giveup limit*/
unsigned long s_enters; /* entries to the driver */
unsigned long s_ipifordisabled; /* fall back to IPI; disabled */
unsigned long s_plugged; /* plugged by h/w bug*/
unsigned long s_congested; /* giveup on long wait */
/* destination statistics */
unsigned long d_alltlb; /* times all tlb's on this
cpu were flushed */
unsigned long d_onetlb; /* times just one tlb on this
cpu was flushed */
unsigned long d_multmsg; /* interrupts with multiple
messages */
unsigned long d_nomsg; /* interrupts with no message */
unsigned long d_time; /* time spent on destination
side */
unsigned long d_requestee; /* number of messages
processed */
unsigned long d_retries; /* number of retry messages
processed */
unsigned long d_canceled; /* number of messages canceled
by retries */
unsigned long d_nocanceled; /* retries that found nothing
to cancel */
unsigned long d_resets; /* number of ipi-style requests
processed */
unsigned long d_rcanceled; /* number of messages canceled
by resets */
};
struct tunables {
int *tunp;
int deflt;
};
struct hub_and_pnode {
short uvhub;
short pnode;
};
struct socket_desc {
short num_cpus;
short cpu_number[MAX_CPUS_PER_SOCKET];
};
struct uvhub_desc {
unsigned short socket_mask;
short num_cpus;
short uvhub;
short pnode;
struct socket_desc socket[2];
};
/**
* struct bau_control
* @status_mmr: location of status mmr, determined by uvhub_cpu
* @status_index: index of ERR|BUSY bits in status mmr, determined by uvhub_cpu
*
* Per-cpu control struct containing CPU topology information and BAU tuneables.
*/
struct bau_control {
struct bau_desc *descriptor_base;
struct bau_pq_entry *queue_first;
struct bau_pq_entry *queue_last;
struct bau_pq_entry *bau_msg_head;
struct bau_control *uvhub_master;
struct bau_control *socket_master;
struct ptc_stats *statp;
cpumask_t *cpumask;
unsigned long timeout_interval;
unsigned long set_bau_on_time;
atomic_t active_descriptor_count;
int plugged_tries;
int timeout_tries;
int ipi_attempts;
int conseccompletes;
u64 status_mmr;
int status_index;
bool nobau;
short baudisabled;
short cpu;
short osnode;
short uvhub_cpu;
short uvhub;
short uvhub_version;
short cpus_in_socket;
short cpus_in_uvhub;
short partition_base_pnode;
short busy; /* all were busy (war) */
unsigned short message_number;
unsigned short uvhub_quiesce;
short socket_acknowledge_count[DEST_Q_SIZE];
cycles_t send_message;
cycles_t period_end;
cycles_t period_time;
spinlock_t uvhub_lock;
spinlock_t queue_lock;
spinlock_t disable_lock;
/* tunables */
int max_concurr;
int max_concurr_const;
int plugged_delay;
int plugsb4reset;
int timeoutsb4reset;
int ipi_reset_limit;
int complete_threshold;
int cong_response_us;
int cong_reps;
cycles_t disabled_period;
int period_giveups;
int giveup_limit;
long period_requests;
struct hub_and_pnode *thp;
};
/* Abstracted BAU functions */
struct bau_operations {
unsigned long (*read_l_sw_ack)(void);
unsigned long (*read_g_sw_ack)(int pnode);
unsigned long (*bau_gpa_to_offset)(unsigned long vaddr);
void (*write_l_sw_ack)(unsigned long mmr);
void (*write_g_sw_ack)(int pnode, unsigned long mmr);
void (*write_payload_first)(int pnode, unsigned long mmr);
void (*write_payload_last)(int pnode, unsigned long mmr);
int (*wait_completion)(struct bau_desc*,
struct bau_control*, long try);
};
static inline void write_mmr_data_broadcast(int pnode, unsigned long mmr_image)
{
write_gmmr(pnode, UVH_BAU_DATA_BROADCAST, mmr_image);
}
static inline void write_mmr_descriptor_base(int pnode, unsigned long mmr_image)
{
write_gmmr(pnode, UVH_LB_BAU_SB_DESCRIPTOR_BASE, mmr_image);
}
static inline void write_mmr_activation(unsigned long index)
{
write_lmmr(UVH_LB_BAU_SB_ACTIVATION_CONTROL, index);
}
static inline void write_gmmr_activation(int pnode, unsigned long mmr_image)
{
write_gmmr(pnode, UVH_LB_BAU_SB_ACTIVATION_CONTROL, mmr_image);
}
static inline void write_mmr_proc_payload_first(int pnode, unsigned long mmr_image)
{
write_gmmr(pnode, UV4H_LB_PROC_INTD_QUEUE_FIRST, mmr_image);
}
static inline void write_mmr_proc_payload_last(int pnode, unsigned long mmr_image)
{
write_gmmr(pnode, UV4H_LB_PROC_INTD_QUEUE_LAST, mmr_image);
}
static inline void write_mmr_payload_first(int pnode, unsigned long mmr_image)
{
write_gmmr(pnode, UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST, mmr_image);
}
static inline void write_mmr_payload_tail(int pnode, unsigned long mmr_image)
{
write_gmmr(pnode, UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL, mmr_image);
}
static inline void write_mmr_payload_last(int pnode, unsigned long mmr_image)
{
write_gmmr(pnode, UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST, mmr_image);
}
static inline void write_mmr_misc_control(int pnode, unsigned long mmr_image)
{
write_gmmr(pnode, UVH_LB_BAU_MISC_CONTROL, mmr_image);
}
static inline unsigned long read_mmr_misc_control(int pnode)
{
return read_gmmr(pnode, UVH_LB_BAU_MISC_CONTROL);
}
static inline void write_mmr_sw_ack(unsigned long mr)
{
uv_write_local_mmr(UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS, mr);
}
static inline void write_gmmr_sw_ack(int pnode, unsigned long mr)
{
write_gmmr(pnode, UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS, mr);
}
static inline unsigned long read_mmr_sw_ack(void)
{
return read_lmmr(UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE);
}
static inline unsigned long read_gmmr_sw_ack(int pnode)
{
return read_gmmr(pnode, UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE);
}
static inline void write_mmr_proc_sw_ack(unsigned long mr)
{
uv_write_local_mmr(UV4H_LB_PROC_INTD_SOFT_ACK_CLEAR, mr);
}
static inline void write_gmmr_proc_sw_ack(int pnode, unsigned long mr)
{
write_gmmr(pnode, UV4H_LB_PROC_INTD_SOFT_ACK_CLEAR, mr);
}
static inline unsigned long read_mmr_proc_sw_ack(void)
{
return read_lmmr(UV4H_LB_PROC_INTD_SOFT_ACK_PENDING);
}
static inline unsigned long read_gmmr_proc_sw_ack(int pnode)
{
return read_gmmr(pnode, UV4H_LB_PROC_INTD_SOFT_ACK_PENDING);
}
static inline void write_mmr_data_config(int pnode, unsigned long mr)
{
uv_write_global_mmr64(pnode, UVH_BAU_DATA_CONFIG, mr);
}
static inline int bau_uvhub_isset(int uvhub, struct pnmask *dstp)
{
return constant_test_bit(uvhub, &dstp->bits[0]);
}
static inline void bau_uvhub_set(int pnode, struct pnmask *dstp)
{
__set_bit(pnode, &dstp->bits[0]);
}
static inline void bau_uvhubs_clear(struct pnmask *dstp,
int nbits)
{
bitmap_zero(&dstp->bits[0], nbits);
}
static inline int bau_uvhub_weight(struct pnmask *dstp)
{
return bitmap_weight((unsigned long *)&dstp->bits[0],
UV_DISTRIBUTION_SIZE);
}
static inline void bau_cpubits_clear(struct bau_local_cpumask *dstp, int nbits)
{
bitmap_zero(&dstp->bits, nbits);
}
struct atomic_short {
short counter;
};
/*
* atomic_read_short - read a short atomic variable
* @v: pointer of type atomic_short
*
* Atomically reads the value of @v.
*/
static inline int atomic_read_short(const struct atomic_short *v)
{
return v->counter;
}
/*
* atom_asr - add and return a short int
* @i: short value to add
* @v: pointer of type atomic_short
*
* Atomically adds @i to @v and returns @i + @v
*/
static inline int atom_asr(short i, struct atomic_short *v)
{
short __i = i;
asm volatile(LOCK_PREFIX "xaddw %0, %1"
: "+r" (i), "+m" (v->counter)
: : "memory");
return i + __i;
}
/*
* conditionally add 1 to *v, unless *v is >= u
* return 0 if we cannot add 1 to *v because it is >= u
* return 1 if we can add 1 to *v because it is < u
* the add is atomic
*
* This is close to atomic_add_unless(), but this allows the 'u' value
* to be lowered below the current 'v'. atomic_add_unless can only stop
* on equal.
*/
static inline int atomic_inc_unless_ge(spinlock_t *lock, atomic_t *v, int u)
{
spin_lock(lock);
if (atomic_read(v) >= u) {
spin_unlock(lock);
return 0;
}
atomic_inc(v);
spin_unlock(lock);
return 1;
}
void uv_bau_message_interrupt(struct pt_regs *regs);
#endif /* _ASM_X86_UV_UV_BAU_H */

View file

@ -5,6 +5,7 @@
*
* SGI UV architectural definitions
*
* (C) Copyright 2020 Hewlett Packard Enterprise Development LP
* Copyright (C) 2007-2014 Silicon Graphics, Inc. All rights reserved.
*/
@ -129,17 +130,6 @@
*/
#define UV_MAX_NASID_VALUE (UV_MAX_NUMALINK_BLADES * 2)
/* System Controller Interface Reg info */
struct uv_scir_s {
struct timer_list timer;
unsigned long offset;
unsigned long last;
unsigned long idle_on;
unsigned long idle_off;
unsigned char state;
unsigned char enabled;
};
/* GAM (globally addressed memory) range table */
struct uv_gam_range_s {
u32 limit; /* PA bits 56:26 (GAM_RANGE_SHFT) */
@ -155,6 +145,8 @@ struct uv_gam_range_s {
* available in the L3 cache on the cpu socket for the node.
*/
struct uv_hub_info_s {
unsigned int hub_type;
unsigned char hub_revision;
unsigned long global_mmr_base;
unsigned long global_mmr_shift;
unsigned long gpa_mask;
@ -167,9 +159,9 @@ struct uv_hub_info_s {
unsigned char m_val;
unsigned char n_val;
unsigned char gr_table_len;
unsigned char hub_revision;
unsigned char apic_pnode_shift;
unsigned char gpa_shift;
unsigned char nasid_shift;
unsigned char m_shift;
unsigned char n_lshift;
unsigned int gnode_extra;
@ -191,16 +183,13 @@ struct uv_hub_info_s {
struct uv_cpu_info_s {
void *p_uv_hub_info;
unsigned char blade_cpu_id;
struct uv_scir_s scir;
void *reserved;
};
DECLARE_PER_CPU(struct uv_cpu_info_s, __uv_cpu_info);
#define uv_cpu_info this_cpu_ptr(&__uv_cpu_info)
#define uv_cpu_info_per(cpu) (&per_cpu(__uv_cpu_info, cpu))
#define uv_scir_info (&uv_cpu_info->scir)
#define uv_cpu_scir_info(cpu) (&uv_cpu_info_per(cpu)->scir)
/* Node specific hub common info struct */
extern void **__uv_hub_info_list;
static inline struct uv_hub_info_s *uv_hub_info_list(int node)
@ -219,6 +208,17 @@ static inline struct uv_hub_info_s *uv_cpu_hub_info(int cpu)
return (struct uv_hub_info_s *)uv_cpu_info_per(cpu)->p_uv_hub_info;
}
static inline int uv_hub_type(void)
{
return uv_hub_info->hub_type;
}
static inline __init void uv_hub_type_set(int uvmask)
{
uv_hub_info->hub_type = uvmask;
}
/*
* HUB revision ranges for each UV HUB architecture.
* This is a software convention - NOT the hardware revision numbers in
@ -228,39 +228,31 @@ static inline struct uv_hub_info_s *uv_cpu_hub_info(int cpu)
#define UV3_HUB_REVISION_BASE 5
#define UV4_HUB_REVISION_BASE 7
#define UV4A_HUB_REVISION_BASE 8 /* UV4 (fixed) rev 2 */
#define UV5_HUB_REVISION_BASE 9
static inline int is_uv2_hub(void)
{
return is_uv_hubbed(uv(2));
}
static inline int is_uv(int uvmask) { return uv_hub_type() & uvmask; }
static inline int is_uv1_hub(void) { return 0; }
static inline int is_uv2_hub(void) { return is_uv(UV2); }
static inline int is_uv3_hub(void) { return is_uv(UV3); }
static inline int is_uv4a_hub(void) { return is_uv(UV4A); }
static inline int is_uv4_hub(void) { return is_uv(UV4); }
static inline int is_uv5_hub(void) { return is_uv(UV5); }
static inline int is_uv3_hub(void)
{
return is_uv_hubbed(uv(3));
}
/*
* UV4A is a revision of UV4. So on UV4A, both is_uv4_hub() and
* is_uv4a_hub() return true, While on UV4, only is_uv4_hub()
* returns true. So to get true results, first test if is UV4A,
* then test if is UV4.
*/
/* First test "is UV4A", then "is UV4" */
static inline int is_uv4a_hub(void)
{
if (is_uv_hubbed(uv(4)))
return (uv_hub_info->hub_revision == UV4A_HUB_REVISION_BASE);
return 0;
}
/* UVX class: UV2,3,4 */
static inline int is_uvx_hub(void) { return is_uv(UVX); }
static inline int is_uv4_hub(void)
{
return is_uv_hubbed(uv(4));
}
/* UVY class: UV5,..? */
static inline int is_uvy_hub(void) { return is_uv(UVY); }
static inline int is_uvx_hub(void)
{
return (is_uv_hubbed(-2) >= uv(2));
}
static inline int is_uv_hub(void)
{
return is_uvx_hub();
}
/* Any UV Hubbed System */
static inline int is_uv_hub(void) { return is_uv(UV_ANY); }
union uvh_apicid {
unsigned long v;
@ -282,9 +274,11 @@ union uvh_apicid {
* g - GNODE (full 15-bit global nasid, right shifted 1)
* p - PNODE (local part of nsids, right shifted 1)
*/
#define UV_NASID_TO_PNODE(n) (((n) >> 1) & uv_hub_info->pnode_mask)
#define UV_NASID_TO_PNODE(n) \
(((n) >> uv_hub_info->nasid_shift) & uv_hub_info->pnode_mask)
#define UV_PNODE_TO_GNODE(p) ((p) |uv_hub_info->gnode_extra)
#define UV_PNODE_TO_NASID(p) (UV_PNODE_TO_GNODE(p) << 1)
#define UV_PNODE_TO_NASID(p) \
(UV_PNODE_TO_GNODE(p) << uv_hub_info->nasid_shift)
#define UV2_LOCAL_MMR_BASE 0xfa000000UL
#define UV2_GLOBAL_MMR32_BASE 0xfc000000UL
@ -297,29 +291,42 @@ union uvh_apicid {
#define UV3_GLOBAL_MMR32_SIZE (32UL * 1024 * 1024)
#define UV4_LOCAL_MMR_BASE 0xfa000000UL
#define UV4_GLOBAL_MMR32_BASE 0xfc000000UL
#define UV4_GLOBAL_MMR32_BASE 0
#define UV4_LOCAL_MMR_SIZE (32UL * 1024 * 1024)
#define UV4_GLOBAL_MMR32_SIZE (16UL * 1024 * 1024)
#define UV4_GLOBAL_MMR32_SIZE 0
#define UV5_LOCAL_MMR_BASE 0xfa000000UL
#define UV5_GLOBAL_MMR32_BASE 0
#define UV5_LOCAL_MMR_SIZE (32UL * 1024 * 1024)
#define UV5_GLOBAL_MMR32_SIZE 0
#define UV_LOCAL_MMR_BASE ( \
is_uv2_hub() ? UV2_LOCAL_MMR_BASE : \
is_uv3_hub() ? UV3_LOCAL_MMR_BASE : \
/*is_uv4_hub*/ UV4_LOCAL_MMR_BASE)
is_uv(UV2) ? UV2_LOCAL_MMR_BASE : \
is_uv(UV3) ? UV3_LOCAL_MMR_BASE : \
is_uv(UV4) ? UV4_LOCAL_MMR_BASE : \
is_uv(UV5) ? UV5_LOCAL_MMR_BASE : \
0)
#define UV_GLOBAL_MMR32_BASE ( \
is_uv2_hub() ? UV2_GLOBAL_MMR32_BASE : \
is_uv3_hub() ? UV3_GLOBAL_MMR32_BASE : \
/*is_uv4_hub*/ UV4_GLOBAL_MMR32_BASE)
is_uv(UV2) ? UV2_GLOBAL_MMR32_BASE : \
is_uv(UV3) ? UV3_GLOBAL_MMR32_BASE : \
is_uv(UV4) ? UV4_GLOBAL_MMR32_BASE : \
is_uv(UV5) ? UV5_GLOBAL_MMR32_BASE : \
0)
#define UV_LOCAL_MMR_SIZE ( \
is_uv2_hub() ? UV2_LOCAL_MMR_SIZE : \
is_uv3_hub() ? UV3_LOCAL_MMR_SIZE : \
/*is_uv4_hub*/ UV4_LOCAL_MMR_SIZE)
is_uv(UV2) ? UV2_LOCAL_MMR_SIZE : \
is_uv(UV3) ? UV3_LOCAL_MMR_SIZE : \
is_uv(UV4) ? UV4_LOCAL_MMR_SIZE : \
is_uv(UV5) ? UV5_LOCAL_MMR_SIZE : \
0)
#define UV_GLOBAL_MMR32_SIZE ( \
is_uv2_hub() ? UV2_GLOBAL_MMR32_SIZE : \
is_uv3_hub() ? UV3_GLOBAL_MMR32_SIZE : \
/*is_uv4_hub*/ UV4_GLOBAL_MMR32_SIZE)
is_uv(UV2) ? UV2_GLOBAL_MMR32_SIZE : \
is_uv(UV3) ? UV3_GLOBAL_MMR32_SIZE : \
is_uv(UV4) ? UV4_GLOBAL_MMR32_SIZE : \
is_uv(UV5) ? UV5_GLOBAL_MMR32_SIZE : \
0)
#define UV_GLOBAL_MMR64_BASE (uv_hub_info->global_mmr_base)
@ -720,7 +727,7 @@ extern void uv_nmi_setup_hubless(void);
#define UVH_TSC_SYNC_SHIFT_UV2K 16 /* UV2/3k have different bits */
#define UVH_TSC_SYNC_MASK 3 /* 0011 */
#define UVH_TSC_SYNC_VALID 3 /* 0011 */
#define UVH_TSC_SYNC_INVALID 2 /* 0010 */
#define UVH_TSC_SYNC_UNKNOWN 0 /* 0000 */
/* BMC sets a bit this MMR non-zero before sending an NMI */
#define UVH_NMI_MMR UVH_BIOS_KERNEL_MMR
@ -728,19 +735,6 @@ extern void uv_nmi_setup_hubless(void);
#define UVH_NMI_MMR_SHIFT 63
#define UVH_NMI_MMR_TYPE "SCRATCH5"
/* Newer SMM NMI handler, not present in all systems */
#define UVH_NMI_MMRX UVH_EVENT_OCCURRED0
#define UVH_NMI_MMRX_CLEAR UVH_EVENT_OCCURRED0_ALIAS
#define UVH_NMI_MMRX_SHIFT UVH_EVENT_OCCURRED0_EXTIO_INT0_SHFT
#define UVH_NMI_MMRX_TYPE "EXTIO_INT0"
/* Non-zero indicates newer SMM NMI handler present */
#define UVH_NMI_MMRX_SUPPORTED UVH_EXTIO_INT0_BROADCAST
/* Indicates to BIOS that we want to use the newer SMM NMI handler */
#define UVH_NMI_MMRX_REQ UVH_BIOS_KERNEL_MMR_ALIAS_2
#define UVH_NMI_MMRX_REQ_SHIFT 62
struct uv_hub_nmi_s {
raw_spinlock_t nmi_lock;
atomic_t in_nmi; /* flag this node in UV NMI IRQ */
@ -772,29 +766,6 @@ DECLARE_PER_CPU(struct uv_cpu_nmi_s, uv_cpu_nmi);
#define UV_NMI_STATE_DUMP 2
#define UV_NMI_STATE_DUMP_DONE 3
/* Update SCIR state */
static inline void uv_set_scir_bits(unsigned char value)
{
if (uv_scir_info->state != value) {
uv_scir_info->state = value;
uv_write_local_mmr8(uv_scir_info->offset, value);
}
}
static inline unsigned long uv_scir_offset(int apicid)
{
return SCIR_LOCAL_MMR_BASE | (apicid & 0x3f);
}
static inline void uv_set_cpu_scir_bits(int cpu, unsigned char value)
{
if (uv_cpu_scir_info(cpu)->state != value) {
uv_write_global_mmr8(uv_cpu_to_pnode(cpu),
uv_cpu_scir_info(cpu)->offset, value);
uv_cpu_scir_info(cpu)->state = value;
}
}
/*
* Get the minimum revision number of the hub chips within the partition.
* (See UVx_HUB_REVISION_BASE above for specific values.)

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -148,9 +148,6 @@ static const __initconst struct idt_data apic_idts[] = {
# endif
# ifdef CONFIG_IRQ_WORK
INTG(IRQ_WORK_VECTOR, asm_sysvec_irq_work),
# endif
# ifdef CONFIG_X86_UV
INTG(UV_BAU_MESSAGE, asm_sysvec_uv_bau_message),
# endif
INTG(SPURIOUS_APIC_VECTOR, asm_sysvec_spurious_apic_interrupt),
INTG(ERROR_APIC_VECTOR, asm_sysvec_error_interrupt),

View file

@ -14,7 +14,6 @@
#include <asm/nospec-branch.h>
#include <asm/cache.h>
#include <asm/apic.h>
#include <asm/uv/uv.h>
#include "mm_internal.h"
@ -800,29 +799,6 @@ STATIC_NOPV void native_flush_tlb_others(const struct cpumask *cpumask,
trace_tlb_flush(TLB_REMOTE_SEND_IPI,
(info->end - info->start) >> PAGE_SHIFT);
if (is_uv_system()) {
/*
* This whole special case is confused. UV has a "Broadcast
* Assist Unit", which seems to be a fancy way to send IPIs.
* Back when x86 used an explicit TLB flush IPI, UV was
* optimized to use its own mechanism. These days, x86 uses
* smp_call_function_many(), but UV still uses a manual IPI,
* and that IPI's action is out of date -- it does a manual
* flush instead of calling flush_tlb_func_remote(). This
* means that the percpu tlb_gen variables won't be updated
* and we'll do pointless flushes on future context switches.
*
* Rather than hooking native_flush_tlb_others() here, I think
* that UV should be updated so that smp_call_function_many(),
* etc, are optimal on UV.
*/
cpumask = uv_flush_tlb_others(cpumask, info);
if (cpumask)
smp_call_function_many(cpumask, flush_tlb_func_remote,
(void *)info, 1);
return;
}
/*
* If no page tables were freed, we can skip sending IPIs to
* CPUs in lazy TLB mode. They will flush the CPU themselves

View file

@ -1,2 +1,2 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_X86_UV) += tlb_uv.o bios_uv.o uv_irq.o uv_sysfs.o uv_time.o uv_nmi.o
obj-$(CONFIG_X86_UV) += bios_uv.o uv_irq.o uv_sysfs.o uv_time.o uv_nmi.o

View file

@ -2,8 +2,9 @@
/*
* BIOS run time interface routines.
*
* Copyright (c) 2008-2009 Silicon Graphics, Inc. All Rights Reserved.
* Copyright (c) Russ Anderson <rja@sgi.com>
* (C) Copyright 2020 Hewlett Packard Enterprise Development LP
* Copyright (C) 2007-2017 Silicon Graphics, Inc. All rights reserved.
* Copyright (c) Russ Anderson <rja@sgi.com>
*/
#include <linux/efi.h>
@ -170,16 +171,27 @@ int uv_bios_set_legacy_vga_target(bool decode, int domain, int bus)
(u64)decode, (u64)domain, (u64)bus, 0, 0);
}
int uv_bios_init(void)
unsigned long get_uv_systab_phys(bool msg)
{
uv_systab = NULL;
if ((uv_systab_phys == EFI_INVALID_TABLE_ADDR) ||
!uv_systab_phys || efi_runtime_disabled()) {
pr_crit("UV: UVsystab: missing\n");
return -EEXIST;
if (msg)
pr_crit("UV: UVsystab: missing\n");
return 0;
}
return uv_systab_phys;
}
uv_systab = ioremap(uv_systab_phys, sizeof(struct uv_systab));
int uv_bios_init(void)
{
unsigned long uv_systab_phys_addr;
uv_systab = NULL;
uv_systab_phys_addr = get_uv_systab_phys(1);
if (!uv_systab_phys_addr)
return -EEXIST;
uv_systab = ioremap(uv_systab_phys_addr, sizeof(struct uv_systab));
if (!uv_systab || strncmp(uv_systab->signature, UV_SYSTAB_SIG, 4)) {
pr_err("UV: UVsystab: bad signature!\n");
iounmap(uv_systab);
@ -191,7 +203,7 @@ int uv_bios_init(void)
int size = uv_systab->size;
iounmap(uv_systab);
uv_systab = ioremap(uv_systab_phys, size);
uv_systab = ioremap(uv_systab_phys_addr, size);
if (!uv_systab) {
pr_err("UV: UVsystab: ioremap(%d) failed!\n", size);
return -EFAULT;

File diff suppressed because it is too large Load diff

View file

@ -2,8 +2,9 @@
/*
* SGI NMI support routines
*
* Copyright (c) 2009-2013 Silicon Graphics, Inc. All Rights Reserved.
* Copyright (c) Mike Travis
* (C) Copyright 2020 Hewlett Packard Enterprise Development LP
* Copyright (C) 2007-2017 Silicon Graphics, Inc. All rights reserved.
* Copyright (c) Mike Travis
*/
#include <linux/cpu.h>
@ -54,6 +55,20 @@ static struct uv_hub_nmi_s **uv_hub_nmi_list;
DEFINE_PER_CPU(struct uv_cpu_nmi_s, uv_cpu_nmi);
/* Newer SMM NMI handler, not present in all systems */
static unsigned long uvh_nmi_mmrx; /* UVH_EVENT_OCCURRED0/1 */
static unsigned long uvh_nmi_mmrx_clear; /* UVH_EVENT_OCCURRED0/1_ALIAS */
static int uvh_nmi_mmrx_shift; /* UVH_EVENT_OCCURRED0/1_EXTIO_INT0_SHFT */
static int uvh_nmi_mmrx_mask; /* UVH_EVENT_OCCURRED0/1_EXTIO_INT0_MASK */
static char *uvh_nmi_mmrx_type; /* "EXTIO_INT0" */
/* Non-zero indicates newer SMM NMI handler present */
static unsigned long uvh_nmi_mmrx_supported; /* UVH_EXTIO_INT0_BROADCAST */
/* Indicates to BIOS that we want to use the newer SMM NMI handler */
static unsigned long uvh_nmi_mmrx_req; /* UVH_BIOS_KERNEL_MMR_ALIAS_2 */
static int uvh_nmi_mmrx_req_shift; /* 62 */
/* UV hubless values */
#define NMI_CONTROL_PORT 0x70
#define NMI_DUMMY_PORT 0x71
@ -227,13 +242,43 @@ static inline bool uv_nmi_action_is(const char *action)
/* Setup which NMI support is present in system */
static void uv_nmi_setup_mmrs(void)
{
if (uv_read_local_mmr(UVH_NMI_MMRX_SUPPORTED)) {
uv_write_local_mmr(UVH_NMI_MMRX_REQ,
1UL << UVH_NMI_MMRX_REQ_SHIFT);
nmi_mmr = UVH_NMI_MMRX;
nmi_mmr_clear = UVH_NMI_MMRX_CLEAR;
nmi_mmr_pending = 1UL << UVH_NMI_MMRX_SHIFT;
pr_info("UV: SMI NMI support: %s\n", UVH_NMI_MMRX_TYPE);
/* First determine arch specific MMRs to handshake with BIOS */
if (UVH_EVENT_OCCURRED0_EXTIO_INT0_MASK) {
uvh_nmi_mmrx = UVH_EVENT_OCCURRED0;
uvh_nmi_mmrx_clear = UVH_EVENT_OCCURRED0_ALIAS;
uvh_nmi_mmrx_shift = UVH_EVENT_OCCURRED0_EXTIO_INT0_SHFT;
uvh_nmi_mmrx_mask = UVH_EVENT_OCCURRED0_EXTIO_INT0_MASK;
uvh_nmi_mmrx_type = "OCRD0-EXTIO_INT0";
uvh_nmi_mmrx_supported = UVH_EXTIO_INT0_BROADCAST;
uvh_nmi_mmrx_req = UVH_BIOS_KERNEL_MMR_ALIAS_2;
uvh_nmi_mmrx_req_shift = 62;
} else if (UVH_EVENT_OCCURRED1_EXTIO_INT0_MASK) {
uvh_nmi_mmrx = UVH_EVENT_OCCURRED1;
uvh_nmi_mmrx_clear = UVH_EVENT_OCCURRED1_ALIAS;
uvh_nmi_mmrx_shift = UVH_EVENT_OCCURRED1_EXTIO_INT0_SHFT;
uvh_nmi_mmrx_mask = UVH_EVENT_OCCURRED1_EXTIO_INT0_MASK;
uvh_nmi_mmrx_type = "OCRD1-EXTIO_INT0";
uvh_nmi_mmrx_supported = UVH_EXTIO_INT0_BROADCAST;
uvh_nmi_mmrx_req = UVH_BIOS_KERNEL_MMR_ALIAS_2;
uvh_nmi_mmrx_req_shift = 62;
} else {
pr_err("UV:%s:cannot find EVENT_OCCURRED*_EXTIO_INT0\n",
__func__);
return;
}
/* Then find out if new NMI is supported */
if (likely(uv_read_local_mmr(uvh_nmi_mmrx_supported))) {
uv_write_local_mmr(uvh_nmi_mmrx_req,
1UL << uvh_nmi_mmrx_req_shift);
nmi_mmr = uvh_nmi_mmrx;
nmi_mmr_clear = uvh_nmi_mmrx_clear;
nmi_mmr_pending = 1UL << uvh_nmi_mmrx_shift;
pr_info("UV: SMI NMI support: %s\n", uvh_nmi_mmrx_type);
} else {
nmi_mmr = UVH_NMI_MMR;
nmi_mmr_clear = UVH_NMI_MMR_CLEAR;
@ -1049,5 +1094,5 @@ void __init uv_nmi_setup_hubless(void)
/* Ensure NMI enabled in Processor Interface Reg: */
uv_reassert_nmi();
uv_register_nmi_notifier();
pr_info("UV: Hubless NMI enabled\n");
pr_info("UV: PCH NMI enabled\n");
}

View file

@ -2,6 +2,7 @@
/*
* SGI RTC clock/timer routines.
*
* (C) Copyright 2020 Hewlett Packard Enterprise Development LP
* Copyright (c) 2009-2013 Silicon Graphics, Inc. All Rights Reserved.
* Copyright (c) Dimitri Sivanich
*/
@ -52,7 +53,7 @@ struct uv_rtc_timer_head {
struct {
int lcpu; /* systemwide logical cpu number */
u64 expires; /* next timer expiration for this cpu */
} cpu[1];
} cpu[];
};
/*
@ -84,10 +85,8 @@ static void uv_rtc_send_IPI(int cpu)
/* Check for an RTC interrupt pending */
static int uv_intr_pending(int pnode)
{
if (is_uvx_hub())
return uv_read_global_mmr64(pnode, UVXH_EVENT_OCCURRED2) &
UVXH_EVENT_OCCURRED2_RTC_1_MASK;
return 0;
return uv_read_global_mmr64(pnode, UVH_EVENT_OCCURRED2) &
UVH_EVENT_OCCURRED2_RTC_1_MASK;
}
/* Setup interrupt and return non-zero if early expiration occurred. */
@ -101,8 +100,8 @@ static int uv_setup_intr(int cpu, u64 expires)
UVH_RTC1_INT_CONFIG_M_MASK);
uv_write_global_mmr64(pnode, UVH_INT_CMPB, -1L);
uv_write_global_mmr64(pnode, UVXH_EVENT_OCCURRED2_ALIAS,
UVXH_EVENT_OCCURRED2_RTC_1_MASK);
uv_write_global_mmr64(pnode, UVH_EVENT_OCCURRED2_ALIAS,
UVH_EVENT_OCCURRED2_RTC_1_MASK);
val = (X86_PLATFORM_IPI_VECTOR << UVH_RTC1_INT_CONFIG_VECTOR_SHFT) |
((u64)apicid << UVH_RTC1_INT_CONFIG_APIC_ID_SHFT);
@ -148,9 +147,8 @@ static __init int uv_rtc_allocate_timers(void)
struct uv_rtc_timer_head *head = blade_info[bid];
if (!head) {
head = kmalloc_node(sizeof(struct uv_rtc_timer_head) +
(uv_blade_nr_possible_cpus(bid) *
2 * sizeof(u64)),
head = kmalloc_node(struct_size(head, cpu,
uv_blade_nr_possible_cpus(bid)),
GFP_KERNEL, nid);
if (!head) {
uv_rtc_deallocate_timers();

View file

@ -7,6 +7,7 @@
* This file supports the user system call for file open, close, mmap, etc.
* This also incudes the driver initialization code.
*
* (C) Copyright 2020 Hewlett Packard Enterprise Development LP
* Copyright (c) 2008-2014 Silicon Graphics, Inc. All Rights Reserved.
*/
@ -516,7 +517,7 @@ static int __init gru_init(void)
#if defined CONFIG_IA64
gru_start_paddr = 0xd000000000UL; /* ZZZZZZZZZZZZZZZZZZZ fixme */
#else
gru_start_paddr = uv_read_local_mmr(UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR) &
gru_start_paddr = uv_read_local_mmr(UVH_RH_GAM_GRU_OVERLAY_CONFIG) &
0x7fffffffffffUL;
#endif
gru_start_vaddr = __va(gru_start_paddr);

View file

@ -3,6 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* (C) Copyright 2020 Hewlett Packard Enterprise Development LP
* Copyright (C) 2004-2008 Silicon Graphics, Inc. All rights reserved.
*/
@ -17,11 +18,6 @@
#if defined CONFIG_X86_UV || defined CONFIG_IA64_SGI_UV
#include <asm/uv/uv.h>
#define is_uv() is_uv_system()
#endif
#ifndef is_uv
#define is_uv() 0
#endif
#ifdef USE_DBUG_ON
@ -79,7 +75,7 @@
#define XPC_MSG_SIZE(_payload_size) \
ALIGN(XPC_MSG_HDR_MAX_SIZE + (_payload_size), \
is_uv() ? 64 : 128)
is_uv_system() ? 64 : 128)
/*

View file

@ -3,6 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* (C) Copyright 2020 Hewlett Packard Enterprise Development LP
* Copyright (c) 2004-2008 Silicon Graphics, Inc. All Rights Reserved.
*/
@ -233,7 +234,7 @@ xp_init(void)
for (ch_number = 0; ch_number < XPC_MAX_NCHANNELS; ch_number++)
mutex_init(&xpc_registrations[ch_number].mutex);
if (is_uv())
if (is_uv_system())
ret = xp_init_uv();
else
ret = 0;
@ -249,7 +250,7 @@ module_init(xp_init);
static void __exit
xp_exit(void)
{
if (is_uv())
if (is_uv_system())
xp_exit_uv();
}

View file

@ -3,6 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* (C) Copyright 2020 Hewlett Packard Enterprise Development LP
* Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved.
*/
@ -148,7 +149,9 @@ xp_restrict_memprotect_uv(unsigned long phys_addr, unsigned long size)
enum xp_retval
xp_init_uv(void)
{
BUG_ON(!is_uv());
WARN_ON(!is_uv_system());
if (!is_uv_system())
return xpUnsupported;
xp_max_npartitions = XP_MAX_NPARTITIONS_UV;
#ifdef CONFIG_X86
@ -168,5 +171,5 @@ xp_init_uv(void)
void
xp_exit_uv(void)
{
BUG_ON(!is_uv());
WARN_ON(!is_uv_system());
}

View file

@ -3,6 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* (C) Copyright 2020 Hewlett Packard Enterprise Development LP
* Copyright (c) 2004-2009 Silicon Graphics, Inc. All Rights Reserved.
*/
@ -1043,7 +1044,7 @@ xpc_do_exit(enum xp_retval reason)
xpc_teardown_partitions();
if (is_uv())
if (is_uv_system())
xpc_exit_uv();
}
@ -1226,7 +1227,7 @@ xpc_init(void)
dev_set_name(xpc_part, "part");
dev_set_name(xpc_chan, "chan");
if (is_uv()) {
if (is_uv_system()) {
ret = xpc_init_uv();
} else {
@ -1312,7 +1313,7 @@ out_2:
xpc_teardown_partitions();
out_1:
if (is_uv())
if (is_uv_system())
xpc_exit_uv();
return ret;
}

View file

@ -3,6 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* (C) Copyright 2020 Hewlett Packard Enterprise Development LP
* Copyright (c) 2004-2008 Silicon Graphics, Inc. All Rights Reserved.
*/
@ -433,7 +434,7 @@ xpc_discovery(void)
*/
region_size = xp_region_size;
if (is_uv())
if (is_uv_system())
max_regions = 256;
else {
max_regions = 64;

View file

@ -3,6 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* (C) Copyright 2020 Hewlett Packard Enterprise Development LP
* Copyright (C) 1999-2009 Silicon Graphics, Inc. All rights reserved.
*/
@ -515,7 +516,7 @@ xpnet_init(void)
{
int result;
if (!is_uv())
if (!is_uv_system())
return -ENODEV;
dev_info(xpnet, "registering network device %s\n", XPNET_DEVICE_NAME);