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