1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * BIOS run time interface routines. 4 * 5 * Copyright (c) 2008-2009 Silicon Graphics, Inc. All Rights Reserved. 6 * Copyright (c) Russ Anderson <rja@sgi.com> 7 */ 8 9 #include <linux/efi.h> 10 #include <linux/export.h> 11 #include <linux/slab.h> 12 #include <asm/efi.h> 13 #include <linux/io.h> 14 #include <asm/uv/bios.h> 15 #include <asm/uv/uv_hub.h> 16 17 unsigned long uv_systab_phys __ro_after_init = EFI_INVALID_TABLE_ADDR; 18 19 struct uv_systab *uv_systab; 20 21 static s64 __uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, 22 u64 a4, u64 a5) 23 { 24 struct uv_systab *tab = uv_systab; 25 s64 ret; 26 27 if (!tab || !tab->function) 28 /* 29 * BIOS does not support UV systab 30 */ 31 return BIOS_STATUS_UNIMPLEMENTED; 32 33 ret = efi_call_virt_pointer(tab, function, (u64)which, a1, a2, a3, a4, a5); 34 35 return ret; 36 } 37 38 static s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, 39 u64 a5) 40 { 41 s64 ret; 42 43 if (down_interruptible(&__efi_uv_runtime_lock)) 44 return BIOS_STATUS_ABORT; 45 46 ret = __uv_bios_call(which, a1, a2, a3, a4, a5); 47 up(&__efi_uv_runtime_lock); 48 49 return ret; 50 } 51 52 static s64 uv_bios_call_irqsave(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, 53 u64 a4, u64 a5) 54 { 55 unsigned long bios_flags; 56 s64 ret; 57 58 if (down_interruptible(&__efi_uv_runtime_lock)) 59 return BIOS_STATUS_ABORT; 60 61 local_irq_save(bios_flags); 62 ret = __uv_bios_call(which, a1, a2, a3, a4, a5); 63 local_irq_restore(bios_flags); 64 65 up(&__efi_uv_runtime_lock); 66 67 return ret; 68 } 69 70 long sn_partition_id; 71 EXPORT_SYMBOL_GPL(sn_partition_id); 72 long sn_coherency_id; 73 long sn_region_size; 74 EXPORT_SYMBOL_GPL(sn_region_size); 75 long system_serial_number; 76 int uv_type; 77 78 s64 uv_bios_get_sn_info(int fc, int *uvtype, long *partid, long *coher, 79 long *region, long *ssn) 80 { 81 s64 ret; 82 u64 v0, v1; 83 union partition_info_u part; 84 85 ret = uv_bios_call_irqsave(UV_BIOS_GET_SN_INFO, fc, 86 (u64)(&v0), (u64)(&v1), 0, 0); 87 if (ret != BIOS_STATUS_SUCCESS) 88 return ret; 89 90 part.val = v0; 91 if (uvtype) 92 *uvtype = part.hub_version; 93 if (partid) 94 *partid = part.partition_id; 95 if (coher) 96 *coher = part.coherence_id; 97 if (region) 98 *region = part.region_size; 99 if (ssn) 100 *ssn = v1; 101 return ret; 102 } 103 104 int 105 uv_bios_mq_watchlist_alloc(unsigned long addr, unsigned int mq_size, 106 unsigned long *intr_mmr_offset) 107 { 108 u64 watchlist; 109 s64 ret; 110 111 /* 112 * bios returns watchlist number or negative error number. 113 */ 114 ret = (int)uv_bios_call_irqsave(UV_BIOS_WATCHLIST_ALLOC, addr, 115 mq_size, (u64)intr_mmr_offset, 116 (u64)&watchlist, 0); 117 if (ret < BIOS_STATUS_SUCCESS) 118 return ret; 119 120 return watchlist; 121 } 122 EXPORT_SYMBOL_GPL(uv_bios_mq_watchlist_alloc); 123 124 int 125 uv_bios_mq_watchlist_free(int blade, int watchlist_num) 126 { 127 return (int)uv_bios_call_irqsave(UV_BIOS_WATCHLIST_FREE, 128 blade, watchlist_num, 0, 0, 0); 129 } 130 EXPORT_SYMBOL_GPL(uv_bios_mq_watchlist_free); 131 132 s64 133 uv_bios_change_memprotect(u64 paddr, u64 len, enum uv_memprotect perms) 134 { 135 return uv_bios_call_irqsave(UV_BIOS_MEMPROTECT, paddr, len, 136 perms, 0, 0); 137 } 138 EXPORT_SYMBOL_GPL(uv_bios_change_memprotect); 139 140 s64 141 uv_bios_reserved_page_pa(u64 buf, u64 *cookie, u64 *addr, u64 *len) 142 { 143 return uv_bios_call_irqsave(UV_BIOS_GET_PARTITION_ADDR, (u64)cookie, 144 (u64)addr, buf, (u64)len, 0); 145 } 146 EXPORT_SYMBOL_GPL(uv_bios_reserved_page_pa); 147 148 s64 uv_bios_freq_base(u64 clock_type, u64 *ticks_per_second) 149 { 150 return uv_bios_call(UV_BIOS_FREQ_BASE, clock_type, 151 (u64)ticks_per_second, 0, 0, 0); 152 } 153 154 /* 155 * uv_bios_set_legacy_vga_target - Set Legacy VGA I/O Target 156 * @decode: true to enable target, false to disable target 157 * @domain: PCI domain number 158 * @bus: PCI bus number 159 * 160 * Returns: 161 * 0: Success 162 * -EINVAL: Invalid domain or bus number 163 * -ENOSYS: Capability not available 164 * -EBUSY: Legacy VGA I/O cannot be retargeted at this time 165 */ 166 int uv_bios_set_legacy_vga_target(bool decode, int domain, int bus) 167 { 168 return uv_bios_call(UV_BIOS_SET_LEGACY_VGA_TARGET, 169 (u64)decode, (u64)domain, (u64)bus, 0, 0); 170 } 171 172 int uv_bios_init(void) 173 { 174 uv_systab = NULL; 175 if ((uv_systab_phys == EFI_INVALID_TABLE_ADDR) || 176 !uv_systab_phys || efi_runtime_disabled()) { 177 pr_crit("UV: UVsystab: missing\n"); 178 return -EEXIST; 179 } 180 181 uv_systab = ioremap(uv_systab_phys, sizeof(struct uv_systab)); 182 if (!uv_systab || strncmp(uv_systab->signature, UV_SYSTAB_SIG, 4)) { 183 pr_err("UV: UVsystab: bad signature!\n"); 184 iounmap(uv_systab); 185 return -EINVAL; 186 } 187 188 /* Starting with UV4 the UV systab size is variable */ 189 if (uv_systab->revision >= UV_SYSTAB_VERSION_UV4) { 190 int size = uv_systab->size; 191 192 iounmap(uv_systab); 193 uv_systab = ioremap(uv_systab_phys, size); 194 if (!uv_systab) { 195 pr_err("UV: UVsystab: ioremap(%d) failed!\n", size); 196 return -EFAULT; 197 } 198 } 199 pr_info("UV: UVsystab: Revision:%x\n", uv_systab->revision); 200 return 0; 201 } 202