1bc63d387SDean Nelson /* 2bc63d387SDean Nelson * This file is subject to the terms and conditions of the GNU General Public 3bc63d387SDean Nelson * License. See the file "COPYING" in the main directory of this archive 4bc63d387SDean Nelson * for more details. 5bc63d387SDean Nelson * 6*7a6d94f0SMike Travis * (C) Copyright 2020 Hewlett Packard Enterprise Development LP 7bc63d387SDean Nelson * Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved. 8bc63d387SDean Nelson */ 9bc63d387SDean Nelson 10bc63d387SDean Nelson /* 11bc63d387SDean Nelson * Cross Partition (XP) uv-based functions. 12bc63d387SDean Nelson * 13bc63d387SDean Nelson * Architecture specific implementation of common functions. 14bc63d387SDean Nelson * 15bc63d387SDean Nelson */ 16bc63d387SDean Nelson 17a812dcc3SDean Nelson #include <linux/device.h> 18a812dcc3SDean Nelson #include <asm/uv/uv_hub.h> 196c1c325dSDean Nelson #if defined CONFIG_X86_64 206c1c325dSDean Nelson #include <asm/uv/bios.h> 21df41017eSChristoph Hellwig #elif defined CONFIG_IA64_SGI_UV 226c1c325dSDean Nelson #include <asm/sn/sn_sal.h> 236c1c325dSDean Nelson #endif 24a812dcc3SDean Nelson #include "../sgi-gru/grukservices.h" 25bc63d387SDean Nelson #include "xp.h" 26bc63d387SDean Nelson 27a812dcc3SDean Nelson /* 28a812dcc3SDean Nelson * Convert a virtual memory address to a physical memory address. 29a812dcc3SDean Nelson */ 30a812dcc3SDean Nelson static unsigned long 31a812dcc3SDean Nelson xp_pa_uv(void *addr) 32908787dbSDean Nelson { 33a812dcc3SDean Nelson return uv_gpa(addr); 34a812dcc3SDean Nelson } 35a812dcc3SDean Nelson 3668212893SRobin Holt /* 3768212893SRobin Holt * Convert a global physical to socket physical address. 3868212893SRobin Holt */ 3968212893SRobin Holt static unsigned long 4068212893SRobin Holt xp_socket_pa_uv(unsigned long gpa) 4168212893SRobin Holt { 4268212893SRobin Holt return uv_gpa_to_soc_phys_ram(gpa); 4368212893SRobin Holt } 4468212893SRobin Holt 45a812dcc3SDean Nelson static enum xp_retval 46c2c9f115SRobin Holt xp_remote_mmr_read(unsigned long dst_gpa, const unsigned long src_gpa, 47c2c9f115SRobin Holt size_t len) 48c2c9f115SRobin Holt { 49c2c9f115SRobin Holt int ret; 50c2c9f115SRobin Holt unsigned long *dst_va = __va(uv_gpa_to_soc_phys_ram(dst_gpa)); 51c2c9f115SRobin Holt 52c2c9f115SRobin Holt BUG_ON(!uv_gpa_in_mmr_space(src_gpa)); 53c2c9f115SRobin Holt BUG_ON(len != 8); 54c2c9f115SRobin Holt 55c2c9f115SRobin Holt ret = gru_read_gpa(dst_va, src_gpa); 56c2c9f115SRobin Holt if (ret == 0) 57c2c9f115SRobin Holt return xpSuccess; 58c2c9f115SRobin Holt 59c2c9f115SRobin Holt dev_err(xp, "gru_read_gpa() failed, dst_gpa=0x%016lx src_gpa=0x%016lx " 60c2c9f115SRobin Holt "len=%ld\n", dst_gpa, src_gpa, len); 61c2c9f115SRobin Holt return xpGruCopyError; 62c2c9f115SRobin Holt } 63c2c9f115SRobin Holt 64c2c9f115SRobin Holt 65c2c9f115SRobin Holt static enum xp_retval 66a812dcc3SDean Nelson xp_remote_memcpy_uv(unsigned long dst_gpa, const unsigned long src_gpa, 67a812dcc3SDean Nelson size_t len) 68a812dcc3SDean Nelson { 69a812dcc3SDean Nelson int ret; 70a812dcc3SDean Nelson 71c2c9f115SRobin Holt if (uv_gpa_in_mmr_space(src_gpa)) 72c2c9f115SRobin Holt return xp_remote_mmr_read(dst_gpa, src_gpa, len); 73c2c9f115SRobin Holt 74a812dcc3SDean Nelson ret = gru_copy_gpa(dst_gpa, src_gpa, len); 75a812dcc3SDean Nelson if (ret == 0) 76a812dcc3SDean Nelson return xpSuccess; 77a812dcc3SDean Nelson 78a812dcc3SDean Nelson dev_err(xp, "gru_copy_gpa() failed, dst_gpa=0x%016lx src_gpa=0x%016lx " 79a812dcc3SDean Nelson "len=%ld\n", dst_gpa, src_gpa, len); 80a812dcc3SDean Nelson return xpGruCopyError; 81908787dbSDean Nelson } 82908787dbSDean Nelson 835b8669dfSDean Nelson static int 845b8669dfSDean Nelson xp_cpu_to_nasid_uv(int cpuid) 855b8669dfSDean Nelson { 865b8669dfSDean Nelson /* ??? Is this same as sn2 nasid in mach/part bitmaps set up by SAL? */ 875b8669dfSDean Nelson return UV_PNODE_TO_NASID(uv_cpu_to_pnode(cpuid)); 885b8669dfSDean Nelson } 895b8669dfSDean Nelson 906c1c325dSDean Nelson static enum xp_retval 916c1c325dSDean Nelson xp_expand_memprotect_uv(unsigned long phys_addr, unsigned long size) 926c1c325dSDean Nelson { 936c1c325dSDean Nelson int ret; 946c1c325dSDean Nelson 956c1c325dSDean Nelson #if defined CONFIG_X86_64 966c1c325dSDean Nelson ret = uv_bios_change_memprotect(phys_addr, size, UV_MEMPROT_ALLOW_RW); 976c1c325dSDean Nelson if (ret != BIOS_STATUS_SUCCESS) { 986c1c325dSDean Nelson dev_err(xp, "uv_bios_change_memprotect(,, " 996c1c325dSDean Nelson "UV_MEMPROT_ALLOW_RW) failed, ret=%d\n", ret); 1006c1c325dSDean Nelson return xpBiosError; 1016c1c325dSDean Nelson } 1026c1c325dSDean Nelson 103df41017eSChristoph Hellwig #elif defined CONFIG_IA64_SGI_UV 1046c1c325dSDean Nelson u64 nasid_array; 1056c1c325dSDean Nelson 1066c1c325dSDean Nelson ret = sn_change_memprotect(phys_addr, size, SN_MEMPROT_ACCESS_CLASS_1, 1076c1c325dSDean Nelson &nasid_array); 1086c1c325dSDean Nelson if (ret != 0) { 1096c1c325dSDean Nelson dev_err(xp, "sn_change_memprotect(,, " 1106c1c325dSDean Nelson "SN_MEMPROT_ACCESS_CLASS_1,) failed ret=%d\n", ret); 1116c1c325dSDean Nelson return xpSalError; 1126c1c325dSDean Nelson } 1136c1c325dSDean Nelson #else 1146c1c325dSDean Nelson #error not a supported configuration 1156c1c325dSDean Nelson #endif 1166c1c325dSDean Nelson return xpSuccess; 1176c1c325dSDean Nelson } 1186c1c325dSDean Nelson 1196c1c325dSDean Nelson static enum xp_retval 1206c1c325dSDean Nelson xp_restrict_memprotect_uv(unsigned long phys_addr, unsigned long size) 1216c1c325dSDean Nelson { 1226c1c325dSDean Nelson int ret; 1236c1c325dSDean Nelson 1246c1c325dSDean Nelson #if defined CONFIG_X86_64 1256c1c325dSDean Nelson ret = uv_bios_change_memprotect(phys_addr, size, 1266c1c325dSDean Nelson UV_MEMPROT_RESTRICT_ACCESS); 1276c1c325dSDean Nelson if (ret != BIOS_STATUS_SUCCESS) { 1286c1c325dSDean Nelson dev_err(xp, "uv_bios_change_memprotect(,, " 1296c1c325dSDean Nelson "UV_MEMPROT_RESTRICT_ACCESS) failed, ret=%d\n", ret); 1306c1c325dSDean Nelson return xpBiosError; 1316c1c325dSDean Nelson } 1326c1c325dSDean Nelson 133df41017eSChristoph Hellwig #elif defined CONFIG_IA64_SGI_UV 1346c1c325dSDean Nelson u64 nasid_array; 1356c1c325dSDean Nelson 1366c1c325dSDean Nelson ret = sn_change_memprotect(phys_addr, size, SN_MEMPROT_ACCESS_CLASS_0, 1376c1c325dSDean Nelson &nasid_array); 1386c1c325dSDean Nelson if (ret != 0) { 1396c1c325dSDean Nelson dev_err(xp, "sn_change_memprotect(,, " 1406c1c325dSDean Nelson "SN_MEMPROT_ACCESS_CLASS_0,) failed ret=%d\n", ret); 1416c1c325dSDean Nelson return xpSalError; 1426c1c325dSDean Nelson } 1436c1c325dSDean Nelson #else 1446c1c325dSDean Nelson #error not a supported configuration 1456c1c325dSDean Nelson #endif 1466c1c325dSDean Nelson return xpSuccess; 1476c1c325dSDean Nelson } 1486c1c325dSDean Nelson 149bc63d387SDean Nelson enum xp_retval 150bc63d387SDean Nelson xp_init_uv(void) 151bc63d387SDean Nelson { 152788b66e3SMike Travis WARN_ON(!is_uv_system()); 153788b66e3SMike Travis if (!is_uv_system()) 154788b66e3SMike Travis return xpUnsupported; 155bc63d387SDean Nelson 156bc63d387SDean Nelson xp_max_npartitions = XP_MAX_NPARTITIONS_UV; 1579726bfcdSChristoph Hellwig #ifdef CONFIG_X86 15831de5eceSDean Nelson xp_partition_id = sn_partition_id; 15931de5eceSDean Nelson xp_region_size = sn_region_size; 1609726bfcdSChristoph Hellwig #endif 161a812dcc3SDean Nelson xp_pa = xp_pa_uv; 16268212893SRobin Holt xp_socket_pa = xp_socket_pa_uv; 163908787dbSDean Nelson xp_remote_memcpy = xp_remote_memcpy_uv; 1645b8669dfSDean Nelson xp_cpu_to_nasid = xp_cpu_to_nasid_uv; 1656c1c325dSDean Nelson xp_expand_memprotect = xp_expand_memprotect_uv; 1666c1c325dSDean Nelson xp_restrict_memprotect = xp_restrict_memprotect_uv; 167908787dbSDean Nelson 168908787dbSDean Nelson return xpSuccess; 169bc63d387SDean Nelson } 170bc63d387SDean Nelson 171bc63d387SDean Nelson void 172bc63d387SDean Nelson xp_exit_uv(void) 173bc63d387SDean Nelson { 174788b66e3SMike Travis WARN_ON(!is_uv_system()); 175bc63d387SDean Nelson } 176