1bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson/*
2bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson * This file is subject to the terms and conditions of the GNU General Public
3bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson * License.  See the file "COPYING" in the main directory of this archive
4bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson * for more details.
5bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson *
6bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson * Copyright (c) 2008 Silicon Graphics, Inc.  All Rights Reserved.
7bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson */
8bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson
9bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson/*
10bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson * Cross Partition (XP) uv-based functions.
11bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson *
12bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson *      Architecture specific implementation of common functions.
13bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson *
14bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson */
15bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson
16a812dcc3a298eef650c381e094e2cf41a4ecc9adDean Nelson#include <linux/device.h>
17a812dcc3a298eef650c381e094e2cf41a4ecc9adDean Nelson#include <asm/uv/uv_hub.h>
186c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson#if defined CONFIG_X86_64
196c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson#include <asm/uv/bios.h>
206c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson#elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
216c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson#include <asm/sn/sn_sal.h>
226c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson#endif
23a812dcc3a298eef650c381e094e2cf41a4ecc9adDean Nelson#include "../sgi-gru/grukservices.h"
24bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson#include "xp.h"
25bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson
26a812dcc3a298eef650c381e094e2cf41a4ecc9adDean Nelson/*
27a812dcc3a298eef650c381e094e2cf41a4ecc9adDean Nelson * Convert a virtual memory address to a physical memory address.
28a812dcc3a298eef650c381e094e2cf41a4ecc9adDean Nelson */
29a812dcc3a298eef650c381e094e2cf41a4ecc9adDean Nelsonstatic unsigned long
30a812dcc3a298eef650c381e094e2cf41a4ecc9adDean Nelsonxp_pa_uv(void *addr)
31a812dcc3a298eef650c381e094e2cf41a4ecc9adDean Nelson{
32a812dcc3a298eef650c381e094e2cf41a4ecc9adDean Nelson	return uv_gpa(addr);
33a812dcc3a298eef650c381e094e2cf41a4ecc9adDean Nelson}
34a812dcc3a298eef650c381e094e2cf41a4ecc9adDean Nelson
35682128939f546e3a9cdd9fef392b932dd9c41a65Robin Holt/*
36682128939f546e3a9cdd9fef392b932dd9c41a65Robin Holt * Convert a global physical to socket physical address.
37682128939f546e3a9cdd9fef392b932dd9c41a65Robin Holt */
38682128939f546e3a9cdd9fef392b932dd9c41a65Robin Holtstatic unsigned long
39682128939f546e3a9cdd9fef392b932dd9c41a65Robin Holtxp_socket_pa_uv(unsigned long gpa)
40682128939f546e3a9cdd9fef392b932dd9c41a65Robin Holt{
41682128939f546e3a9cdd9fef392b932dd9c41a65Robin Holt	return uv_gpa_to_soc_phys_ram(gpa);
42682128939f546e3a9cdd9fef392b932dd9c41a65Robin Holt}
43682128939f546e3a9cdd9fef392b932dd9c41a65Robin Holt
44908787db9b95f548270af18d83d62b9d2020ca10Dean Nelsonstatic enum xp_retval
45c2c9f115741453715d6b4da1cd2de65af8c7ad86Robin Holtxp_remote_mmr_read(unsigned long dst_gpa, const unsigned long src_gpa,
46c2c9f115741453715d6b4da1cd2de65af8c7ad86Robin Holt		   size_t len)
47c2c9f115741453715d6b4da1cd2de65af8c7ad86Robin Holt{
48c2c9f115741453715d6b4da1cd2de65af8c7ad86Robin Holt	int ret;
49c2c9f115741453715d6b4da1cd2de65af8c7ad86Robin Holt	unsigned long *dst_va = __va(uv_gpa_to_soc_phys_ram(dst_gpa));
50c2c9f115741453715d6b4da1cd2de65af8c7ad86Robin Holt
51c2c9f115741453715d6b4da1cd2de65af8c7ad86Robin Holt	BUG_ON(!uv_gpa_in_mmr_space(src_gpa));
52c2c9f115741453715d6b4da1cd2de65af8c7ad86Robin Holt	BUG_ON(len != 8);
53c2c9f115741453715d6b4da1cd2de65af8c7ad86Robin Holt
54c2c9f115741453715d6b4da1cd2de65af8c7ad86Robin Holt	ret = gru_read_gpa(dst_va, src_gpa);
55c2c9f115741453715d6b4da1cd2de65af8c7ad86Robin Holt	if (ret == 0)
56c2c9f115741453715d6b4da1cd2de65af8c7ad86Robin Holt		return xpSuccess;
57c2c9f115741453715d6b4da1cd2de65af8c7ad86Robin Holt
58c2c9f115741453715d6b4da1cd2de65af8c7ad86Robin Holt	dev_err(xp, "gru_read_gpa() failed, dst_gpa=0x%016lx src_gpa=0x%016lx "
59c2c9f115741453715d6b4da1cd2de65af8c7ad86Robin Holt		"len=%ld\n", dst_gpa, src_gpa, len);
60c2c9f115741453715d6b4da1cd2de65af8c7ad86Robin Holt	return xpGruCopyError;
61c2c9f115741453715d6b4da1cd2de65af8c7ad86Robin Holt}
62c2c9f115741453715d6b4da1cd2de65af8c7ad86Robin Holt
63c2c9f115741453715d6b4da1cd2de65af8c7ad86Robin Holt
64c2c9f115741453715d6b4da1cd2de65af8c7ad86Robin Holtstatic enum xp_retval
65a812dcc3a298eef650c381e094e2cf41a4ecc9adDean Nelsonxp_remote_memcpy_uv(unsigned long dst_gpa, const unsigned long src_gpa,
66a812dcc3a298eef650c381e094e2cf41a4ecc9adDean Nelson		    size_t len)
67908787db9b95f548270af18d83d62b9d2020ca10Dean Nelson{
68a812dcc3a298eef650c381e094e2cf41a4ecc9adDean Nelson	int ret;
69a812dcc3a298eef650c381e094e2cf41a4ecc9adDean Nelson
70c2c9f115741453715d6b4da1cd2de65af8c7ad86Robin Holt	if (uv_gpa_in_mmr_space(src_gpa))
71c2c9f115741453715d6b4da1cd2de65af8c7ad86Robin Holt		return xp_remote_mmr_read(dst_gpa, src_gpa, len);
72c2c9f115741453715d6b4da1cd2de65af8c7ad86Robin Holt
73a812dcc3a298eef650c381e094e2cf41a4ecc9adDean Nelson	ret = gru_copy_gpa(dst_gpa, src_gpa, len);
74a812dcc3a298eef650c381e094e2cf41a4ecc9adDean Nelson	if (ret == 0)
75a812dcc3a298eef650c381e094e2cf41a4ecc9adDean Nelson		return xpSuccess;
76a812dcc3a298eef650c381e094e2cf41a4ecc9adDean Nelson
77a812dcc3a298eef650c381e094e2cf41a4ecc9adDean Nelson	dev_err(xp, "gru_copy_gpa() failed, dst_gpa=0x%016lx src_gpa=0x%016lx "
78a812dcc3a298eef650c381e094e2cf41a4ecc9adDean Nelson		"len=%ld\n", dst_gpa, src_gpa, len);
79a812dcc3a298eef650c381e094e2cf41a4ecc9adDean Nelson	return xpGruCopyError;
80908787db9b95f548270af18d83d62b9d2020ca10Dean Nelson}
81908787db9b95f548270af18d83d62b9d2020ca10Dean Nelson
825b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic int
835b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxp_cpu_to_nasid_uv(int cpuid)
845b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{
855b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	/* ??? Is this same as sn2 nasid in mach/part bitmaps set up by SAL? */
865b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	return UV_PNODE_TO_NASID(uv_cpu_to_pnode(cpuid));
875b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson}
885b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
896c1c325de908cbc444cf284f59c3a892161012e9Dean Nelsonstatic enum xp_retval
906c1c325de908cbc444cf284f59c3a892161012e9Dean Nelsonxp_expand_memprotect_uv(unsigned long phys_addr, unsigned long size)
916c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson{
926c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson	int ret;
936c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson
946c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson#if defined CONFIG_X86_64
956c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson	ret = uv_bios_change_memprotect(phys_addr, size, UV_MEMPROT_ALLOW_RW);
966c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson	if (ret != BIOS_STATUS_SUCCESS) {
976c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson		dev_err(xp, "uv_bios_change_memprotect(,, "
986c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson			"UV_MEMPROT_ALLOW_RW) failed, ret=%d\n", ret);
996c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson		return xpBiosError;
1006c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson	}
1016c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson
1026c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson#elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
1036c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson	u64 nasid_array;
1046c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson
1056c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson	ret = sn_change_memprotect(phys_addr, size, SN_MEMPROT_ACCESS_CLASS_1,
1066c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson				   &nasid_array);
1076c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson	if (ret != 0) {
1086c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson		dev_err(xp, "sn_change_memprotect(,, "
1096c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson			"SN_MEMPROT_ACCESS_CLASS_1,) failed ret=%d\n", ret);
1106c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson		return xpSalError;
1116c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson	}
1126c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson#else
1136c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson	#error not a supported configuration
1146c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson#endif
1156c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson	return xpSuccess;
1166c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson}
1176c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson
1186c1c325de908cbc444cf284f59c3a892161012e9Dean Nelsonstatic enum xp_retval
1196c1c325de908cbc444cf284f59c3a892161012e9Dean Nelsonxp_restrict_memprotect_uv(unsigned long phys_addr, unsigned long size)
1206c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson{
1216c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson	int ret;
1226c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson
1236c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson#if defined CONFIG_X86_64
1246c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson	ret = uv_bios_change_memprotect(phys_addr, size,
1256c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson					UV_MEMPROT_RESTRICT_ACCESS);
1266c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson	if (ret != BIOS_STATUS_SUCCESS) {
1276c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson		dev_err(xp, "uv_bios_change_memprotect(,, "
1286c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson			"UV_MEMPROT_RESTRICT_ACCESS) failed, ret=%d\n", ret);
1296c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson		return xpBiosError;
1306c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson	}
1316c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson
1326c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson#elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
1336c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson	u64 nasid_array;
1346c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson
1356c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson	ret = sn_change_memprotect(phys_addr, size, SN_MEMPROT_ACCESS_CLASS_0,
1366c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson				   &nasid_array);
1376c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson	if (ret != 0) {
1386c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson		dev_err(xp, "sn_change_memprotect(,, "
1396c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson			"SN_MEMPROT_ACCESS_CLASS_0,) failed ret=%d\n", ret);
1406c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson		return xpSalError;
1416c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson	}
1426c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson#else
1436c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson	#error not a supported configuration
1446c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson#endif
1456c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson	return xpSuccess;
1466c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson}
1476c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson
148bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelsonenum xp_retval
149bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelsonxp_init_uv(void)
150bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson{
151bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson	BUG_ON(!is_uv());
152bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson
153bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson	xp_max_npartitions = XP_MAX_NPARTITIONS_UV;
15431de5ece351a218a35b9bf83ab05a14373261bb6Dean Nelson	xp_partition_id = sn_partition_id;
15531de5ece351a218a35b9bf83ab05a14373261bb6Dean Nelson	xp_region_size = sn_region_size;
156908787db9b95f548270af18d83d62b9d2020ca10Dean Nelson
157a812dcc3a298eef650c381e094e2cf41a4ecc9adDean Nelson	xp_pa = xp_pa_uv;
158682128939f546e3a9cdd9fef392b932dd9c41a65Robin Holt	xp_socket_pa = xp_socket_pa_uv;
159908787db9b95f548270af18d83d62b9d2020ca10Dean Nelson	xp_remote_memcpy = xp_remote_memcpy_uv;
1605b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xp_cpu_to_nasid = xp_cpu_to_nasid_uv;
1616c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson	xp_expand_memprotect = xp_expand_memprotect_uv;
1626c1c325de908cbc444cf284f59c3a892161012e9Dean Nelson	xp_restrict_memprotect = xp_restrict_memprotect_uv;
163908787db9b95f548270af18d83d62b9d2020ca10Dean Nelson
164908787db9b95f548270af18d83d62b9d2020ca10Dean Nelson	return xpSuccess;
165bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson}
166bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson
167bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelsonvoid
168bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelsonxp_exit_uv(void)
169bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson{
170bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson	BUG_ON(!is_uv());
171bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson}
172