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

ARM: 8985/1: efi/decompressor: deal with HYP mode boot gracefully

EFI on ARM only supports short descriptors, and given that it mandates
that the MMU and caches are on, it is implied that booting in HYP mode
is not supported.

However, implementations of EFI exist (i.e., U-Boot) that ignore this
requirement, which is not entirely unreasonable, given that it makes
HYP mode inaccessible to the operating system.

So let's make sure that we can deal with this condition gracefully.
We already tolerate booting the EFI stub with the caches off (even
though this violates the EFI spec as well), and so we should deal
with HYP mode boot with MMU and caches either on or off.

- When the MMU and caches are on, we can ignore the HYP stub altogether,
since we can carry on executing at HYP. We do need to ensure that we
disable the MMU at HYP before entering the kernel proper.

- When the MMU and caches are off, we have to drop to SVC mode so that
we can set up the page tables using short descriptors. In this case,
we need to install the HYP stub as usual, so that we can return to HYP
mode before handing over to the kernel proper.

Tested-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>

authored by

Ard Biesheuvel and committed by
Russell King
db227c19 39c3e304

+62
+62
arch/arm/boot/compressed/head.S
··· 1410 1410 __hyp_reentry_vectors: 1411 1411 W(b) . @ reset 1412 1412 W(b) . @ undef 1413 + #ifdef CONFIG_EFI_STUB 1414 + W(b) __enter_kernel_from_hyp @ hvc from HYP 1415 + #else 1413 1416 W(b) . @ svc 1417 + #endif 1414 1418 W(b) . @ pabort 1415 1419 W(b) . @ dabort 1416 1420 W(b) __enter_kernel @ hyp ··· 1433 1429 reloc_code_end: 1434 1430 1435 1431 #ifdef CONFIG_EFI_STUB 1432 + __enter_kernel_from_hyp: 1433 + mrc p15, 4, r0, c1, c0, 0 @ read HSCTLR 1434 + bic r0, r0, #0x5 @ disable MMU and caches 1435 + mcr p15, 4, r0, c1, c0, 0 @ write HSCTLR 1436 + isb 1437 + b __enter_kernel 1438 + 1436 1439 ENTRY(efi_enter_kernel) 1437 1440 mov r4, r0 @ preserve image base 1438 1441 mov r8, r1 @ preserve DT pointer 1439 1442 1443 + ARM( adrl r0, call_cache_fn ) 1444 + THUMB( adr r0, call_cache_fn ) 1445 + adr r1, 0f @ clean the region of code we 1446 + bl cache_clean_flush @ may run with the MMU off 1447 + 1448 + #ifdef CONFIG_ARM_VIRT_EXT 1449 + @ 1450 + @ The EFI spec does not support booting on ARM in HYP mode, 1451 + @ since it mandates that the MMU and caches are on, with all 1452 + @ 32-bit addressable DRAM mapped 1:1 using short descriptors. 1453 + @ 1454 + @ While the EDK2 reference implementation adheres to this, 1455 + @ U-Boot might decide to enter the EFI stub in HYP mode 1456 + @ anyway, with the MMU and caches either on or off. 1457 + @ 1458 + mrs r0, cpsr @ get the current mode 1459 + msr spsr_cxsf, r0 @ record boot mode 1460 + and r0, r0, #MODE_MASK @ are we running in HYP mode? 1461 + cmp r0, #HYP_MODE 1462 + bne .Lefi_svc 1463 + 1464 + mrc p15, 4, r1, c1, c0, 0 @ read HSCTLR 1465 + tst r1, #0x1 @ MMU enabled at HYP? 1466 + beq 1f 1467 + 1468 + @ 1469 + @ When running in HYP mode with the caches on, we're better 1470 + @ off just carrying on using the cached 1:1 mapping that the 1471 + @ firmware provided. Set up the HYP vectors so HVC instructions 1472 + @ issued from HYP mode take us to the correct handler code. We 1473 + @ will disable the MMU before jumping to the kernel proper. 1474 + @ 1475 + adr r0, __hyp_reentry_vectors 1476 + mcr p15, 4, r0, c12, c0, 0 @ set HYP vector base (HVBAR) 1477 + isb 1478 + b .Lefi_hyp 1479 + 1480 + @ 1481 + @ When running in HYP mode with the caches off, we need to drop 1482 + @ into SVC mode now, and let the decompressor set up its cached 1483 + @ 1:1 mapping as usual. 1484 + @ 1485 + 1: mov r9, r4 @ preserve image base 1486 + bl __hyp_stub_install @ install HYP stub vectors 1487 + safe_svcmode_maskall r1 @ drop to SVC mode 1488 + msr spsr_cxsf, r0 @ record boot mode 1489 + orr r4, r9, #1 @ restore image base and set LSB 1490 + b .Lefi_hyp 1491 + .Lefi_svc: 1492 + #endif 1440 1493 mrc p15, 0, r0, c1, c0, 0 @ read SCTLR 1441 1494 tst r0, #0x1 @ MMU enabled? 1442 1495 orreq r4, r4, #1 @ set LSB if not 1443 1496 1497 + .Lefi_hyp: 1444 1498 mov r0, r8 @ DT start 1445 1499 add r1, r8, r2 @ DT end 1446 1500 bl cache_clean_flush