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 | #endif |
22 | #include "../sgi-gru/grukservices.h" |
23 | #include "xp.h" |
24 | |
25 | /* |
26 | * Convert a virtual memory address to a physical memory address. |
27 | */ |
28 | static unsigned long |
29 | xp_pa_uv(void *addr) |
30 | { |
31 | return uv_gpa(v: addr); |
32 | } |
33 | |
34 | /* |
35 | * Convert a global physical to socket physical address. |
36 | */ |
37 | static unsigned long |
38 | xp_socket_pa_uv(unsigned long gpa) |
39 | { |
40 | return uv_gpa_to_soc_phys_ram(gpa); |
41 | } |
42 | |
43 | static enum xp_retval |
44 | xp_remote_mmr_read(unsigned long dst_gpa, const unsigned long src_gpa, |
45 | size_t len) |
46 | { |
47 | int ret; |
48 | unsigned long *dst_va = __va(uv_gpa_to_soc_phys_ram(dst_gpa)); |
49 | |
50 | BUG_ON(!uv_gpa_in_mmr_space(src_gpa)); |
51 | BUG_ON(len != 8); |
52 | |
53 | ret = gru_read_gpa(value: dst_va, gpa: src_gpa); |
54 | if (ret == 0) |
55 | return xpSuccess; |
56 | |
57 | dev_err(xp, "gru_read_gpa() failed, dst_gpa=0x%016lx src_gpa=0x%016lx " |
58 | "len=%ld\n" , dst_gpa, src_gpa, len); |
59 | return xpGruCopyError; |
60 | } |
61 | |
62 | |
63 | static enum xp_retval |
64 | xp_remote_memcpy_uv(unsigned long dst_gpa, const unsigned long src_gpa, |
65 | size_t len) |
66 | { |
67 | int ret; |
68 | |
69 | if (uv_gpa_in_mmr_space(gpa: src_gpa)) |
70 | return xp_remote_mmr_read(dst_gpa, src_gpa, len); |
71 | |
72 | ret = gru_copy_gpa(dest_gpa: dst_gpa, src_gpa, bytes: len); |
73 | if (ret == 0) |
74 | return xpSuccess; |
75 | |
76 | dev_err(xp, "gru_copy_gpa() failed, dst_gpa=0x%016lx src_gpa=0x%016lx " |
77 | "len=%ld\n" , dst_gpa, src_gpa, len); |
78 | return xpGruCopyError; |
79 | } |
80 | |
81 | static int |
82 | xp_cpu_to_nasid_uv(int cpuid) |
83 | { |
84 | /* ??? Is this same as sn2 nasid in mach/part bitmaps set up by SAL? */ |
85 | return UV_PNODE_TO_NASID(uv_cpu_to_pnode(cpuid)); |
86 | } |
87 | |
88 | static enum xp_retval |
89 | xp_expand_memprotect_uv(unsigned long phys_addr, unsigned long size) |
90 | { |
91 | int ret; |
92 | |
93 | #if defined CONFIG_X86_64 |
94 | ret = uv_bios_change_memprotect(phys_addr, size, UV_MEMPROT_ALLOW_RW); |
95 | if (ret != BIOS_STATUS_SUCCESS) { |
96 | dev_err(xp, "uv_bios_change_memprotect(,, " |
97 | "UV_MEMPROT_ALLOW_RW) failed, ret=%d\n" , ret); |
98 | return xpBiosError; |
99 | } |
100 | #else |
101 | #error not a supported configuration |
102 | #endif |
103 | return xpSuccess; |
104 | } |
105 | |
106 | static enum xp_retval |
107 | xp_restrict_memprotect_uv(unsigned long phys_addr, unsigned long size) |
108 | { |
109 | int ret; |
110 | |
111 | #if defined CONFIG_X86_64 |
112 | ret = uv_bios_change_memprotect(phys_addr, size, |
113 | UV_MEMPROT_RESTRICT_ACCESS); |
114 | if (ret != BIOS_STATUS_SUCCESS) { |
115 | dev_err(xp, "uv_bios_change_memprotect(,, " |
116 | "UV_MEMPROT_RESTRICT_ACCESS) failed, ret=%d\n" , ret); |
117 | return xpBiosError; |
118 | } |
119 | #else |
120 | #error not a supported configuration |
121 | #endif |
122 | return xpSuccess; |
123 | } |
124 | |
125 | enum xp_retval |
126 | xp_init_uv(void) |
127 | { |
128 | WARN_ON(!is_uv_system()); |
129 | if (!is_uv_system()) |
130 | return xpUnsupported; |
131 | |
132 | xp_max_npartitions = XP_MAX_NPARTITIONS_UV; |
133 | #ifdef CONFIG_X86 |
134 | xp_partition_id = sn_partition_id; |
135 | xp_region_size = sn_region_size; |
136 | #endif |
137 | xp_pa = xp_pa_uv; |
138 | xp_socket_pa = xp_socket_pa_uv; |
139 | xp_remote_memcpy = xp_remote_memcpy_uv; |
140 | xp_cpu_to_nasid = xp_cpu_to_nasid_uv; |
141 | xp_expand_memprotect = xp_expand_memprotect_uv; |
142 | xp_restrict_memprotect = xp_restrict_memprotect_uv; |
143 | |
144 | return xpSuccess; |
145 | } |
146 | |
147 | void |
148 | xp_exit_uv(void) |
149 | { |
150 | WARN_ON(!is_uv_system()); |
151 | } |
152 | |