Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

efi/runtime-wrappers: Don't duplicate setup/teardown code

Avoid duplicating the EFI arch setup and teardown routine calls numerous
times in efi_call_rts(). Instead, expand the efi_call_virt_pointer()
macro into efi_call_rts(), taking the pre and post parts out of the
switch.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>

+22 -10
+18 -8
drivers/firmware/efi/runtime-wrappers.c
··· 40 40 * code doesn't get too cluttered: 41 41 */ 42 42 #define efi_call_virt(f, args...) \ 43 - efi_call_virt_pointer(efi.runtime, f, args) 43 + arch_efi_call_virt(efi.runtime, f, args) 44 44 45 45 union efi_rts_args { 46 46 struct { ··· 139 139 return flags; 140 140 } 141 141 142 - void efi_call_virt_check_flags(unsigned long flags, const char *call) 142 + void efi_call_virt_check_flags(unsigned long flags, const void *caller) 143 143 { 144 144 unsigned long cur_flags, mismatch; 145 145 ··· 150 150 return; 151 151 152 152 add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_NOW_UNRELIABLE); 153 - pr_err_ratelimited(FW_BUG "IRQ flags corrupted (0x%08lx=>0x%08lx) by EFI %s\n", 154 - flags, cur_flags, call); 153 + pr_err_ratelimited(FW_BUG "IRQ flags corrupted (0x%08lx=>0x%08lx) by EFI call from %pS\n", 154 + flags, cur_flags, caller ?: __builtin_return_address(0)); 155 155 arch_efi_restore_flags(flags); 156 156 } 157 157 ··· 211 211 { 212 212 const union efi_rts_args *args = efi_rts_work.args; 213 213 efi_status_t status = EFI_NOT_FOUND; 214 + unsigned long flags; 215 + 216 + arch_efi_call_virt_setup(); 217 + flags = efi_call_virt_save_flags(); 214 218 215 219 switch (efi_rts_work.efi_rts_id) { 216 220 case EFI_GET_TIME: ··· 291 287 */ 292 288 pr_err("Requested executing invalid EFI Runtime Service.\n"); 293 289 } 290 + 291 + efi_call_virt_check_flags(flags, efi_rts_work.caller); 292 + arch_efi_call_virt_teardown(); 293 + 294 294 efi_rts_work.status = status; 295 295 complete(&efi_rts_work.efi_rts_comp); 296 296 } ··· 304 296 { 305 297 efi_rts_work.efi_rts_id = id; 306 298 efi_rts_work.args = args; 299 + efi_rts_work.caller = __builtin_return_address(0); 307 300 efi_rts_work.status = EFI_ABORTED; 308 301 309 302 if (!efi_enabled(EFI_RUNTIME_SERVICES)) { ··· 432 423 if (down_trylock(&efi_runtime_lock)) 433 424 return EFI_NOT_READY; 434 425 435 - status = efi_call_virt(set_variable, name, vendor, attr, data_size, 436 - data); 426 + status = efi_call_virt_pointer(efi.runtime, set_variable, name, vendor, 427 + attr, data_size, data); 437 428 up(&efi_runtime_lock); 438 429 return status; 439 430 } ··· 471 462 if (down_trylock(&efi_runtime_lock)) 472 463 return EFI_NOT_READY; 473 464 474 - status = efi_call_virt(query_variable_info, attr, storage_space, 475 - remaining_space, max_variable_size); 465 + status = efi_call_virt_pointer(efi.runtime, query_variable_info, attr, 466 + storage_space, remaining_space, 467 + max_variable_size); 476 468 up(&efi_runtime_lock); 477 469 return status; 478 470 }
+4 -2
include/linux/efi.h
··· 1129 1129 static inline bool efi_runtime_disabled(void) { return true; } 1130 1130 #endif 1131 1131 1132 - extern void efi_call_virt_check_flags(unsigned long flags, const char *call); 1132 + extern void efi_call_virt_check_flags(unsigned long flags, const void *caller); 1133 1133 extern unsigned long efi_call_virt_save_flags(void); 1134 1134 1135 1135 enum efi_secureboot_mode { ··· 1196 1196 \ 1197 1197 __flags = efi_call_virt_save_flags(); \ 1198 1198 __s = arch_efi_call_virt(p, f, args); \ 1199 - efi_call_virt_check_flags(__flags, __stringify(f)); \ 1199 + efi_call_virt_check_flags(__flags, NULL); \ 1200 1200 \ 1201 1201 arch_efi_call_virt_teardown(); \ 1202 1202 \ ··· 1257 1257 * @status: Status of executing EFI Runtime Service 1258 1258 * @efi_rts_id: EFI Runtime Service function identifier 1259 1259 * @efi_rts_comp: Struct used for handling completions 1260 + * @caller: The caller of the runtime service 1260 1261 */ 1261 1262 struct efi_runtime_work { 1262 1263 union efi_rts_args *args; ··· 1265 1264 struct work_struct work; 1266 1265 enum efi_rts_ids efi_rts_id; 1267 1266 struct completion efi_rts_comp; 1267 + const void *caller; 1268 1268 }; 1269 1269 1270 1270 extern struct efi_runtime_work efi_rts_work;