Merge tag 'arm64-perf' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
[linux-2.6-block.git] / drivers / firmware / efi / runtime-wrappers.c
CommitLineData
022ee6c5
AB
1/*
2 * runtime-wrappers.c - Runtime Services function call wrappers
3 *
4 * Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
5 *
6 * Split off from arch/x86/platform/efi/efi.c
7 *
8 * Copyright (C) 1999 VA Linux Systems
9 * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
10 * Copyright (C) 1999-2002 Hewlett-Packard Co.
11 * Copyright (C) 2005-2008 Intel Co.
12 * Copyright (C) 2013 SuSE Labs
13 *
14 * This file is released under the GPLv2.
15 */
16
161485e8 17#include <linux/bug.h>
022ee6c5 18#include <linux/efi.h>
1d04ba17 19#include <linux/irqflags.h>
161485e8
AB
20#include <linux/mutex.h>
21#include <linux/spinlock.h>
1d04ba17 22#include <linux/stringify.h>
022ee6c5
AB
23#include <asm/efi.h>
24
1d04ba17
MR
25static void efi_call_virt_check_flags(unsigned long flags, const char *call)
26{
27 unsigned long cur_flags, mismatch;
28
29 local_save_flags(cur_flags);
30
31 mismatch = flags ^ cur_flags;
32 if (!WARN_ON_ONCE(mismatch & ARCH_EFI_IRQ_FLAGS_MASK))
33 return;
34
35 add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_NOW_UNRELIABLE);
36 pr_err_ratelimited(FW_BUG "IRQ flags corrupted (0x%08lx=>0x%08lx) by EFI %s\n",
37 flags, cur_flags, call);
38 local_irq_restore(flags);
39}
1d04ba17 40
f51c35f2
MR
41/*
42 * Arch code can implement the following three template macros, avoiding
43 * reptition for the void/non-void return cases of {__,}efi_call_virt:
44 *
45 * * arch_efi_call_virt_setup
46 *
47 * Sets up the environment for the call (e.g. switching page tables,
48 * allowing kernel-mode use of floating point, if required).
49 *
50 * * arch_efi_call_virt
51 *
52 * Performs the call. The last expression in the macro must be the call
53 * itself, allowing the logic to be shared by the void and non-void
54 * cases.
55 *
56 * * arch_efi_call_virt_teardown
57 *
58 * Restores the usual kernel environment once the call has returned.
59 */
60
f51c35f2
MR
61#define efi_call_virt(f, args...) \
62({ \
63 efi_status_t __s; \
1d04ba17 64 unsigned long flags; \
f51c35f2 65 arch_efi_call_virt_setup(); \
1d04ba17 66 local_save_flags(flags); \
f51c35f2 67 __s = arch_efi_call_virt(f, args); \
1d04ba17 68 efi_call_virt_check_flags(flags, __stringify(f)); \
f51c35f2
MR
69 arch_efi_call_virt_teardown(); \
70 __s; \
71})
f51c35f2 72
f51c35f2
MR
73#define __efi_call_virt(f, args...) \
74({ \
1d04ba17 75 unsigned long flags; \
f51c35f2 76 arch_efi_call_virt_setup(); \
1d04ba17 77 local_save_flags(flags); \
f51c35f2 78 arch_efi_call_virt(f, args); \
1d04ba17 79 efi_call_virt_check_flags(flags, __stringify(f)); \
f51c35f2
MR
80 arch_efi_call_virt_teardown(); \
81})
f51c35f2 82
161485e8
AB
83/*
84 * According to section 7.1 of the UEFI spec, Runtime Services are not fully
85 * reentrant, and there are particular combinations of calls that need to be
86 * serialized. (source: UEFI Specification v2.4A)
87 *
88 * Table 31. Rules for Reentry Into Runtime Services
89 * +------------------------------------+-------------------------------+
90 * | If previous call is busy in | Forbidden to call |
91 * +------------------------------------+-------------------------------+
92 * | Any | SetVirtualAddressMap() |
93 * +------------------------------------+-------------------------------+
94 * | ConvertPointer() | ConvertPointer() |
95 * +------------------------------------+-------------------------------+
96 * | SetVariable() | ResetSystem() |
97 * | UpdateCapsule() | |
98 * | SetTime() | |
99 * | SetWakeupTime() | |
100 * | GetNextHighMonotonicCount() | |
101 * +------------------------------------+-------------------------------+
102 * | GetVariable() | GetVariable() |
103 * | GetNextVariableName() | GetNextVariableName() |
104 * | SetVariable() | SetVariable() |
105 * | QueryVariableInfo() | QueryVariableInfo() |
106 * | UpdateCapsule() | UpdateCapsule() |
107 * | QueryCapsuleCapabilities() | QueryCapsuleCapabilities() |
108 * | GetNextHighMonotonicCount() | GetNextHighMonotonicCount() |
109 * +------------------------------------+-------------------------------+
110 * | GetTime() | GetTime() |
111 * | SetTime() | SetTime() |
112 * | GetWakeupTime() | GetWakeupTime() |
113 * | SetWakeupTime() | SetWakeupTime() |
114 * +------------------------------------+-------------------------------+
115 *
116 * Due to the fact that the EFI pstore may write to the variable store in
117 * interrupt context, we need to use a spinlock for at least the groups that
118 * contain SetVariable() and QueryVariableInfo(). That leaves little else, as
119 * none of the remaining functions are actually ever called at runtime.
120 * So let's just use a single spinlock to serialize all Runtime Services calls.
121 */
122static DEFINE_SPINLOCK(efi_runtime_lock);
123
022ee6c5
AB
124static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
125{
022ee6c5
AB
126 efi_status_t status;
127
fe324494 128 spin_lock(&efi_runtime_lock);
022ee6c5 129 status = efi_call_virt(get_time, tm, tc);
fe324494 130 spin_unlock(&efi_runtime_lock);
022ee6c5
AB
131 return status;
132}
133
134static efi_status_t virt_efi_set_time(efi_time_t *tm)
135{
022ee6c5
AB
136 efi_status_t status;
137
fe324494 138 spin_lock(&efi_runtime_lock);
022ee6c5 139 status = efi_call_virt(set_time, tm);
fe324494 140 spin_unlock(&efi_runtime_lock);
022ee6c5
AB
141 return status;
142}
143
144static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled,
145 efi_bool_t *pending,
146 efi_time_t *tm)
147{
022ee6c5
AB
148 efi_status_t status;
149
fe324494 150 spin_lock(&efi_runtime_lock);
022ee6c5 151 status = efi_call_virt(get_wakeup_time, enabled, pending, tm);
fe324494 152 spin_unlock(&efi_runtime_lock);
022ee6c5
AB
153 return status;
154}
155
156static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
157{
022ee6c5
AB
158 efi_status_t status;
159
fe324494 160 spin_lock(&efi_runtime_lock);
022ee6c5 161 status = efi_call_virt(set_wakeup_time, enabled, tm);
fe324494 162 spin_unlock(&efi_runtime_lock);
022ee6c5
AB
163 return status;
164}
165
166static efi_status_t virt_efi_get_variable(efi_char16_t *name,
167 efi_guid_t *vendor,
168 u32 *attr,
169 unsigned long *data_size,
170 void *data)
171{
161485e8
AB
172 efi_status_t status;
173
fe324494 174 spin_lock(&efi_runtime_lock);
161485e8
AB
175 status = efi_call_virt(get_variable, name, vendor, attr, data_size,
176 data);
fe324494 177 spin_unlock(&efi_runtime_lock);
161485e8 178 return status;
022ee6c5
AB
179}
180
181static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,
182 efi_char16_t *name,
183 efi_guid_t *vendor)
184{
161485e8
AB
185 efi_status_t status;
186
fe324494 187 spin_lock(&efi_runtime_lock);
161485e8 188 status = efi_call_virt(get_next_variable, name_size, name, vendor);
fe324494 189 spin_unlock(&efi_runtime_lock);
161485e8 190 return status;
022ee6c5
AB
191}
192
193static efi_status_t virt_efi_set_variable(efi_char16_t *name,
194 efi_guid_t *vendor,
195 u32 attr,
196 unsigned long data_size,
197 void *data)
198{
161485e8 199 efi_status_t status;
161485e8 200
fe324494 201 spin_lock(&efi_runtime_lock);
161485e8
AB
202 status = efi_call_virt(set_variable, name, vendor, attr, data_size,
203 data);
fe324494 204 spin_unlock(&efi_runtime_lock);
161485e8 205 return status;
022ee6c5
AB
206}
207
6d80dba1
MF
208static efi_status_t
209virt_efi_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor,
210 u32 attr, unsigned long data_size,
211 void *data)
212{
6d80dba1
MF
213 efi_status_t status;
214
fe324494 215 if (!spin_trylock(&efi_runtime_lock))
6d80dba1
MF
216 return EFI_NOT_READY;
217
218 status = efi_call_virt(set_variable, name, vendor, attr, data_size,
219 data);
fe324494 220 spin_unlock(&efi_runtime_lock);
6d80dba1
MF
221 return status;
222}
223
224
022ee6c5
AB
225static efi_status_t virt_efi_query_variable_info(u32 attr,
226 u64 *storage_space,
227 u64 *remaining_space,
228 u64 *max_variable_size)
229{
161485e8 230 efi_status_t status;
161485e8 231
022ee6c5
AB
232 if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
233 return EFI_UNSUPPORTED;
234
fe324494 235 spin_lock(&efi_runtime_lock);
161485e8
AB
236 status = efi_call_virt(query_variable_info, attr, storage_space,
237 remaining_space, max_variable_size);
fe324494 238 spin_unlock(&efi_runtime_lock);
161485e8 239 return status;
022ee6c5
AB
240}
241
d3cac1f8
AB
242static efi_status_t
243virt_efi_query_variable_info_nonblocking(u32 attr,
244 u64 *storage_space,
245 u64 *remaining_space,
246 u64 *max_variable_size)
247{
d3cac1f8
AB
248 efi_status_t status;
249
250 if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
251 return EFI_UNSUPPORTED;
252
fe324494 253 if (!spin_trylock(&efi_runtime_lock))
d3cac1f8
AB
254 return EFI_NOT_READY;
255
256 status = efi_call_virt(query_variable_info, attr, storage_space,
257 remaining_space, max_variable_size);
fe324494 258 spin_unlock(&efi_runtime_lock);
d3cac1f8
AB
259 return status;
260}
261
022ee6c5
AB
262static efi_status_t virt_efi_get_next_high_mono_count(u32 *count)
263{
161485e8
AB
264 efi_status_t status;
265
fe324494 266 spin_lock(&efi_runtime_lock);
161485e8 267 status = efi_call_virt(get_next_high_mono_count, count);
fe324494 268 spin_unlock(&efi_runtime_lock);
161485e8 269 return status;
022ee6c5
AB
270}
271
272static void virt_efi_reset_system(int reset_type,
273 efi_status_t status,
274 unsigned long data_size,
275 efi_char16_t *data)
276{
fe324494 277 spin_lock(&efi_runtime_lock);
022ee6c5 278 __efi_call_virt(reset_system, reset_type, status, data_size, data);
fe324494 279 spin_unlock(&efi_runtime_lock);
022ee6c5
AB
280}
281
282static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
283 unsigned long count,
284 unsigned long sg_list)
285{
161485e8
AB
286 efi_status_t status;
287
022ee6c5
AB
288 if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
289 return EFI_UNSUPPORTED;
290
fe324494 291 spin_lock(&efi_runtime_lock);
161485e8 292 status = efi_call_virt(update_capsule, capsules, count, sg_list);
fe324494 293 spin_unlock(&efi_runtime_lock);
161485e8 294 return status;
022ee6c5
AB
295}
296
297static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules,
298 unsigned long count,
299 u64 *max_size,
300 int *reset_type)
301{
161485e8
AB
302 efi_status_t status;
303
022ee6c5
AB
304 if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
305 return EFI_UNSUPPORTED;
306
fe324494 307 spin_lock(&efi_runtime_lock);
161485e8
AB
308 status = efi_call_virt(query_capsule_caps, capsules, count, max_size,
309 reset_type);
fe324494 310 spin_unlock(&efi_runtime_lock);
161485e8 311 return status;
022ee6c5
AB
312}
313
314void efi_native_runtime_setup(void)
315{
316 efi.get_time = virt_efi_get_time;
317 efi.set_time = virt_efi_set_time;
318 efi.get_wakeup_time = virt_efi_get_wakeup_time;
319 efi.set_wakeup_time = virt_efi_set_wakeup_time;
320 efi.get_variable = virt_efi_get_variable;
321 efi.get_next_variable = virt_efi_get_next_variable;
322 efi.set_variable = virt_efi_set_variable;
6d80dba1 323 efi.set_variable_nonblocking = virt_efi_set_variable_nonblocking;
022ee6c5
AB
324 efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count;
325 efi.reset_system = virt_efi_reset_system;
326 efi.query_variable_info = virt_efi_query_variable_info;
d3cac1f8 327 efi.query_variable_info_nonblocking = virt_efi_query_variable_info_nonblocking;
022ee6c5
AB
328 efi.update_capsule = virt_efi_update_capsule;
329 efi.query_capsule_caps = virt_efi_query_capsule_caps;
330}