1*b5351a43STom Rini // SPDX-License-Identifier: GPL-2.0+ 285b46921SHeinrich Schuchardt /* 385b46921SHeinrich Schuchardt * efi_selftest_unaligned 485b46921SHeinrich Schuchardt * 585b46921SHeinrich Schuchardt * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de> 685b46921SHeinrich Schuchardt * 785b46921SHeinrich Schuchardt * Test unaligned memory access on ARMv7. 885b46921SHeinrich Schuchardt */ 985b46921SHeinrich Schuchardt 1085b46921SHeinrich Schuchardt #include <efi_selftest.h> 1185b46921SHeinrich Schuchardt 1285b46921SHeinrich Schuchardt struct aligned_buffer { 1385b46921SHeinrich Schuchardt char a[8] __aligned(8); 1485b46921SHeinrich Schuchardt }; 1585b46921SHeinrich Schuchardt 1685b46921SHeinrich Schuchardt /* 1785b46921SHeinrich Schuchardt * Return an u32 at a give address. 1885b46921SHeinrich Schuchardt * If the address is not four byte aligned, an unaligned memory access 1985b46921SHeinrich Schuchardt * occurs. 2085b46921SHeinrich Schuchardt * 2185b46921SHeinrich Schuchardt * @addr: address to read 2285b46921SHeinrich Schuchardt * @return: value at the address 2385b46921SHeinrich Schuchardt */ 2485b46921SHeinrich Schuchardt static inline u32 deref(u32 *addr) 2585b46921SHeinrich Schuchardt { 2685b46921SHeinrich Schuchardt int ret; 2785b46921SHeinrich Schuchardt 2885b46921SHeinrich Schuchardt asm( 2985b46921SHeinrich Schuchardt "ldr %[out], [%[in]]\n\t" 3085b46921SHeinrich Schuchardt : [out] "=r" (ret) 3185b46921SHeinrich Schuchardt : [in] "r" (addr) 3285b46921SHeinrich Schuchardt ); 3385b46921SHeinrich Schuchardt return ret; 3485b46921SHeinrich Schuchardt } 3585b46921SHeinrich Schuchardt 3685b46921SHeinrich Schuchardt /* 3785b46921SHeinrich Schuchardt * Execute unit test. 3885b46921SHeinrich Schuchardt * An unaligned memory access is executed. The result is checked. 3985b46921SHeinrich Schuchardt * 4085b46921SHeinrich Schuchardt * @return: EFI_ST_SUCCESS for success 4185b46921SHeinrich Schuchardt */ 4285b46921SHeinrich Schuchardt static int execute(void) 4385b46921SHeinrich Schuchardt { 4485b46921SHeinrich Schuchardt struct aligned_buffer buf = { 4585b46921SHeinrich Schuchardt {0, 1, 2, 3, 4, 5, 6, 7}, 4685b46921SHeinrich Schuchardt }; 4785b46921SHeinrich Schuchardt void *v = &buf; 4885b46921SHeinrich Schuchardt u32 r = 0; 4985b46921SHeinrich Schuchardt 5085b46921SHeinrich Schuchardt /* Read an unaligned address */ 5185b46921SHeinrich Schuchardt r = deref(v + 1); 5285b46921SHeinrich Schuchardt 5385b46921SHeinrich Schuchardt /* UEFI only supports low endian systems */ 5485b46921SHeinrich Schuchardt if (r != 0x04030201) { 5585b46921SHeinrich Schuchardt efi_st_error("Unaligned access failed"); 5685b46921SHeinrich Schuchardt return EFI_ST_FAILURE; 5785b46921SHeinrich Schuchardt } 5885b46921SHeinrich Schuchardt 5985b46921SHeinrich Schuchardt return EFI_ST_SUCCESS; 6085b46921SHeinrich Schuchardt } 6185b46921SHeinrich Schuchardt 6285b46921SHeinrich Schuchardt EFI_UNIT_TEST(unaligned) = { 6385b46921SHeinrich Schuchardt .name = "unaligned memory access", 6485b46921SHeinrich Schuchardt .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, 6585b46921SHeinrich Schuchardt .execute = execute, 6685b46921SHeinrich Schuchardt }; 67