1*85b46921SHeinrich Schuchardt /* 2*85b46921SHeinrich Schuchardt * efi_selftest_unaligned 3*85b46921SHeinrich Schuchardt * 4*85b46921SHeinrich Schuchardt * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de> 5*85b46921SHeinrich Schuchardt * 6*85b46921SHeinrich Schuchardt * SPDX-License-Identifier: GPL-2.0+ 7*85b46921SHeinrich Schuchardt * 8*85b46921SHeinrich Schuchardt * Test unaligned memory access on ARMv7. 9*85b46921SHeinrich Schuchardt */ 10*85b46921SHeinrich Schuchardt 11*85b46921SHeinrich Schuchardt #include <efi_selftest.h> 12*85b46921SHeinrich Schuchardt 13*85b46921SHeinrich Schuchardt struct aligned_buffer { 14*85b46921SHeinrich Schuchardt char a[8] __aligned(8); 15*85b46921SHeinrich Schuchardt }; 16*85b46921SHeinrich Schuchardt 17*85b46921SHeinrich Schuchardt /* 18*85b46921SHeinrich Schuchardt * Return an u32 at a give address. 19*85b46921SHeinrich Schuchardt * If the address is not four byte aligned, an unaligned memory access 20*85b46921SHeinrich Schuchardt * occurs. 21*85b46921SHeinrich Schuchardt * 22*85b46921SHeinrich Schuchardt * @addr: address to read 23*85b46921SHeinrich Schuchardt * @return: value at the address 24*85b46921SHeinrich Schuchardt */ 25*85b46921SHeinrich Schuchardt static inline u32 deref(u32 *addr) 26*85b46921SHeinrich Schuchardt { 27*85b46921SHeinrich Schuchardt int ret; 28*85b46921SHeinrich Schuchardt 29*85b46921SHeinrich Schuchardt asm( 30*85b46921SHeinrich Schuchardt "ldr %[out], [%[in]]\n\t" 31*85b46921SHeinrich Schuchardt : [out] "=r" (ret) 32*85b46921SHeinrich Schuchardt : [in] "r" (addr) 33*85b46921SHeinrich Schuchardt ); 34*85b46921SHeinrich Schuchardt return ret; 35*85b46921SHeinrich Schuchardt } 36*85b46921SHeinrich Schuchardt 37*85b46921SHeinrich Schuchardt /* 38*85b46921SHeinrich Schuchardt * Execute unit test. 39*85b46921SHeinrich Schuchardt * An unaligned memory access is executed. The result is checked. 40*85b46921SHeinrich Schuchardt * 41*85b46921SHeinrich Schuchardt * @return: EFI_ST_SUCCESS for success 42*85b46921SHeinrich Schuchardt */ 43*85b46921SHeinrich Schuchardt static int execute(void) 44*85b46921SHeinrich Schuchardt { 45*85b46921SHeinrich Schuchardt struct aligned_buffer buf = { 46*85b46921SHeinrich Schuchardt {0, 1, 2, 3, 4, 5, 6, 7}, 47*85b46921SHeinrich Schuchardt }; 48*85b46921SHeinrich Schuchardt void *v = &buf; 49*85b46921SHeinrich Schuchardt u32 r = 0; 50*85b46921SHeinrich Schuchardt 51*85b46921SHeinrich Schuchardt /* Read an unaligned address */ 52*85b46921SHeinrich Schuchardt r = deref(v + 1); 53*85b46921SHeinrich Schuchardt 54*85b46921SHeinrich Schuchardt /* UEFI only supports low endian systems */ 55*85b46921SHeinrich Schuchardt if (r != 0x04030201) { 56*85b46921SHeinrich Schuchardt efi_st_error("Unaligned access failed"); 57*85b46921SHeinrich Schuchardt return EFI_ST_FAILURE; 58*85b46921SHeinrich Schuchardt } 59*85b46921SHeinrich Schuchardt 60*85b46921SHeinrich Schuchardt return EFI_ST_SUCCESS; 61*85b46921SHeinrich Schuchardt } 62*85b46921SHeinrich Schuchardt 63*85b46921SHeinrich Schuchardt EFI_UNIT_TEST(unaligned) = { 64*85b46921SHeinrich Schuchardt .name = "unaligned memory access", 65*85b46921SHeinrich Schuchardt .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, 66*85b46921SHeinrich Schuchardt .execute = execute, 67*85b46921SHeinrich Schuchardt }; 68