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 * (C) Copyright 2020 Hewlett Packard Enterprise Development LP
7 * Copyright (c) 2008 Silicon Graphics, Inc.  All Rights Reserved.
8 */
9
10/*
11 * Cross Partition (XP) uv-based functions.
12 *
13 *      Architecture specific implementation of common functions.
14 *
15 */
16
17#include <linux/device.h>
18#include <asm/uv/uv_hub.h>
19#if defined CONFIG_X86_64
20#include <asm/uv/bios.h>
21#elif defined CONFIG_IA64_SGI_UV
22#include <asm/sn/sn_sal.h>
23#endif
24#include "../sgi-gru/grukservices.h"
25#include "xp.h"
26
27/*
28 * Convert a virtual memory address to a physical memory address.
29 */
30static unsigned long
31xp_pa_uv(void *addr)
32{
33	return uv_gpa(addr);
34}
35
36/*
37 * Convert a global physical to socket physical address.
38 */
39static unsigned long
40xp_socket_pa_uv(unsigned long gpa)
41{
42	return uv_gpa_to_soc_phys_ram(gpa);
43}
44
45static enum xp_retval
46xp_remote_mmr_read(unsigned long dst_gpa, const unsigned long src_gpa,
47		   size_t len)
48{
49	int ret;
50	unsigned long *dst_va = __va(uv_gpa_to_soc_phys_ram(dst_gpa));
51
52	BUG_ON(!uv_gpa_in_mmr_space(src_gpa));
53	BUG_ON(len != 8);
54
55	ret = gru_read_gpa(dst_va, src_gpa);
56	if (ret == 0)
57		return xpSuccess;
58
59	dev_err(xp, "gru_read_gpa() failed, dst_gpa=0x%016lx src_gpa=0x%016lx "
60		"len=%ld\n", dst_gpa, src_gpa, len);
61	return xpGruCopyError;
62}
63
64
65static enum xp_retval
66xp_remote_memcpy_uv(unsigned long dst_gpa, const unsigned long src_gpa,
67		    size_t len)
68{
69	int ret;
70
71	if (uv_gpa_in_mmr_space(src_gpa))
72		return xp_remote_mmr_read(dst_gpa, src_gpa, len);
73
74	ret = gru_copy_gpa(dst_gpa, src_gpa, len);
75	if (ret == 0)
76		return xpSuccess;
77
78	dev_err(xp, "gru_copy_gpa() failed, dst_gpa=0x%016lx src_gpa=0x%016lx "
79		"len=%ld\n", dst_gpa, src_gpa, len);
80	return xpGruCopyError;
81}
82
83static int
84xp_cpu_to_nasid_uv(int cpuid)
85{
86	/* ??? Is this same as sn2 nasid in mach/part bitmaps set up by SAL? */
87	return UV_PNODE_TO_NASID(uv_cpu_to_pnode(cpuid));
88}
89
90static enum xp_retval
91xp_expand_memprotect_uv(unsigned long phys_addr, unsigned long size)
92{
93	int ret;
94
95#if defined CONFIG_X86_64
96	ret = uv_bios_change_memprotect(phys_addr, size, UV_MEMPROT_ALLOW_RW);
97	if (ret != BIOS_STATUS_SUCCESS) {
98		dev_err(xp, "uv_bios_change_memprotect(,, "
99			"UV_MEMPROT_ALLOW_RW) failed, ret=%d\n", ret);
100		return xpBiosError;
101	}
102
103#elif defined CONFIG_IA64_SGI_UV
104	u64 nasid_array;
105
106	ret = sn_change_memprotect(phys_addr, size, SN_MEMPROT_ACCESS_CLASS_1,
107				   &nasid_array);
108	if (ret != 0) {
109		dev_err(xp, "sn_change_memprotect(,, "
110			"SN_MEMPROT_ACCESS_CLASS_1,) failed ret=%d\n", ret);
111		return xpSalError;
112	}
113#else
114	#error not a supported configuration
115#endif
116	return xpSuccess;
117}
118
119static enum xp_retval
120xp_restrict_memprotect_uv(unsigned long phys_addr, unsigned long size)
121{
122	int ret;
123
124#if defined CONFIG_X86_64
125	ret = uv_bios_change_memprotect(phys_addr, size,
126					UV_MEMPROT_RESTRICT_ACCESS);
127	if (ret != BIOS_STATUS_SUCCESS) {
128		dev_err(xp, "uv_bios_change_memprotect(,, "
129			"UV_MEMPROT_RESTRICT_ACCESS) failed, ret=%d\n", ret);
130		return xpBiosError;
131	}
132
133#elif defined CONFIG_IA64_SGI_UV
134	u64 nasid_array;
135
136	ret = sn_change_memprotect(phys_addr, size, SN_MEMPROT_ACCESS_CLASS_0,
137				   &nasid_array);
138	if (ret != 0) {
139		dev_err(xp, "sn_change_memprotect(,, "
140			"SN_MEMPROT_ACCESS_CLASS_0,) failed ret=%d\n", ret);
141		return xpSalError;
142	}
143#else
144	#error not a supported configuration
145#endif
146	return xpSuccess;
147}
148
149enum xp_retval
150xp_init_uv(void)
151{
152	WARN_ON(!is_uv_system());
153	if (!is_uv_system())
154		return xpUnsupported;
155
156	xp_max_npartitions = XP_MAX_NPARTITIONS_UV;
157#ifdef CONFIG_X86
158	xp_partition_id = sn_partition_id;
159	xp_region_size = sn_region_size;
160#endif
161	xp_pa = xp_pa_uv;
162	xp_socket_pa = xp_socket_pa_uv;
163	xp_remote_memcpy = xp_remote_memcpy_uv;
164	xp_cpu_to_nasid = xp_cpu_to_nasid_uv;
165	xp_expand_memprotect = xp_expand_memprotect_uv;
166	xp_restrict_memprotect = xp_restrict_memprotect_uv;
167
168	return xpSuccess;
169}
170
171void
172xp_exit_uv(void)
173{
174	WARN_ON(!is_uv_system());
175}
176