xref: /openbmc/linux/drivers/misc/sgi-xp/xp_uv.c (revision cbecf716ca618fd44feda6bd9a64a8179d031fc5)
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
xp_pa_uv(void * addr)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
xp_socket_pa_uv(unsigned long gpa)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
xp_remote_mmr_read(unsigned long dst_gpa,const unsigned long src_gpa,size_t len)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
xp_remote_memcpy_uv(unsigned long dst_gpa,const unsigned long src_gpa,size_t len)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
xp_cpu_to_nasid_uv(int cpuid)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
xp_expand_memprotect_uv(unsigned long phys_addr,unsigned long size)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
xp_restrict_memprotect_uv(unsigned long phys_addr,unsigned long size)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
xp_init_uv(void)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
xp_exit_uv(void)172bc63d387SDean Nelson xp_exit_uv(void)
173bc63d387SDean Nelson {
174788b66e3SMike Travis 	WARN_ON(!is_uv_system());
175bc63d387SDean Nelson }
176