xref: /linux/drivers/misc/sgi-xp/xp_uv.c (revision bcefe12eff5dca6fdfa94ed85e5bee66380d5cd9)
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (c) 2008 Silicon Graphics, Inc.  All Rights Reserved.
7  */
8 
9 /*
10  * Cross Partition (XP) uv-based functions.
11  *
12  *      Architecture specific implementation of common functions.
13  *
14  */
15 
16 #include <linux/device.h>
17 #include <asm/uv/uv_hub.h>
18 #if defined CONFIG_X86_64
19 #include <asm/uv/bios.h>
20 #elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
21 #include <asm/sn/sn_sal.h>
22 #endif
23 #include "../sgi-gru/grukservices.h"
24 #include "xp.h"
25 
26 /*
27  * Convert a virtual memory address to a physical memory address.
28  */
29 static unsigned long
30 xp_pa_uv(void *addr)
31 {
32 	return uv_gpa(addr);
33 }
34 
35 static enum xp_retval
36 xp_remote_memcpy_uv(unsigned long dst_gpa, const unsigned long src_gpa,
37 		    size_t len)
38 {
39 	int ret;
40 
41 	ret = gru_copy_gpa(dst_gpa, src_gpa, len);
42 	if (ret == 0)
43 		return xpSuccess;
44 
45 	dev_err(xp, "gru_copy_gpa() failed, dst_gpa=0x%016lx src_gpa=0x%016lx "
46 		"len=%ld\n", dst_gpa, src_gpa, len);
47 	return xpGruCopyError;
48 }
49 
50 static int
51 xp_cpu_to_nasid_uv(int cpuid)
52 {
53 	/* ??? Is this same as sn2 nasid in mach/part bitmaps set up by SAL? */
54 	return UV_PNODE_TO_NASID(uv_cpu_to_pnode(cpuid));
55 }
56 
57 static enum xp_retval
58 xp_expand_memprotect_uv(unsigned long phys_addr, unsigned long size)
59 {
60 	int ret;
61 
62 #if defined CONFIG_X86_64
63 	ret = uv_bios_change_memprotect(phys_addr, size, UV_MEMPROT_ALLOW_RW);
64 	if (ret != BIOS_STATUS_SUCCESS) {
65 		dev_err(xp, "uv_bios_change_memprotect(,, "
66 			"UV_MEMPROT_ALLOW_RW) failed, ret=%d\n", ret);
67 		return xpBiosError;
68 	}
69 
70 #elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
71 	u64 nasid_array;
72 
73 	ret = sn_change_memprotect(phys_addr, size, SN_MEMPROT_ACCESS_CLASS_1,
74 				   &nasid_array);
75 	if (ret != 0) {
76 		dev_err(xp, "sn_change_memprotect(,, "
77 			"SN_MEMPROT_ACCESS_CLASS_1,) failed ret=%d\n", ret);
78 		return xpSalError;
79 	}
80 #else
81 	#error not a supported configuration
82 #endif
83 	return xpSuccess;
84 }
85 
86 static enum xp_retval
87 xp_restrict_memprotect_uv(unsigned long phys_addr, unsigned long size)
88 {
89 	int ret;
90 
91 #if defined CONFIG_X86_64
92 	ret = uv_bios_change_memprotect(phys_addr, size,
93 					UV_MEMPROT_RESTRICT_ACCESS);
94 	if (ret != BIOS_STATUS_SUCCESS) {
95 		dev_err(xp, "uv_bios_change_memprotect(,, "
96 			"UV_MEMPROT_RESTRICT_ACCESS) failed, ret=%d\n", ret);
97 		return xpBiosError;
98 	}
99 
100 #elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
101 	u64 nasid_array;
102 
103 	ret = sn_change_memprotect(phys_addr, size, SN_MEMPROT_ACCESS_CLASS_0,
104 				   &nasid_array);
105 	if (ret != 0) {
106 		dev_err(xp, "sn_change_memprotect(,, "
107 			"SN_MEMPROT_ACCESS_CLASS_0,) failed ret=%d\n", ret);
108 		return xpSalError;
109 	}
110 #else
111 	#error not a supported configuration
112 #endif
113 	return xpSuccess;
114 }
115 
116 enum xp_retval
117 xp_init_uv(void)
118 {
119 	BUG_ON(!is_uv());
120 
121 	xp_max_npartitions = XP_MAX_NPARTITIONS_UV;
122 	xp_partition_id = sn_partition_id;
123 	xp_region_size = sn_region_size;
124 
125 	xp_pa = xp_pa_uv;
126 	xp_remote_memcpy = xp_remote_memcpy_uv;
127 	xp_cpu_to_nasid = xp_cpu_to_nasid_uv;
128 	xp_expand_memprotect = xp_expand_memprotect_uv;
129 	xp_restrict_memprotect = xp_restrict_memprotect_uv;
130 
131 	return xpSuccess;
132 }
133 
134 void
135 xp_exit_uv(void)
136 {
137 	BUG_ON(!is_uv());
138 }
139