lib: ramdetect: Register exception handlers for ARMv8
Register exception handlers to avoid a Synchronous External Abort that is raised when you try to access a non-memory address on ARMv8. An exception handler can jump over the faulting instruction. This is the feature only for QEMU/AArch64. Signed-off-by: Asami Doi <d0iasm.pub@gmail.com> Change-Id: I09a306ca307ba4027d9758c3debc2e7c844c66b8 Reviewed-on: https://review.coreboot.org/c/coreboot/+/34774 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Raul Rangel <rrangel@chromium.org>
This commit is contained in:
		
				
					committed by
					
						 Patrick Georgi
						Patrick Georgi
					
				
			
			
				
	
			
			
			
						parent
						
							b0b99058cc
						
					
				
				
					commit
					06993ee729
				
			| @@ -107,6 +107,7 @@ romstage-$(CONFIG_ARM64_USE_ARCH_TIMER) += arch_timer.c | ||||
| romstage-y += memset.S | ||||
| romstage-y += memcpy.S | ||||
| romstage-y += memmove.S | ||||
| romstage-y += ramdetect.c | ||||
| romstage-y += romstage.c | ||||
| romstage-y += transition.c transition_asm.S | ||||
|  | ||||
| @@ -131,6 +132,7 @@ ramstage-y += div0.c | ||||
| ramstage-y += eabi_compat.c | ||||
| ramstage-y += boot.c | ||||
| ramstage-y += tables.c | ||||
| ramstage-y += ramdetect.c | ||||
| ramstage-$(CONFIG_ARM64_USE_ARCH_TIMER) += arch_timer.c | ||||
| ramstage-y += memset.S | ||||
| ramstage-y += memcpy.S | ||||
|   | ||||
							
								
								
									
										41
									
								
								src/arch/arm64/ramdetect.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/arch/arm64/ramdetect.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| /* | ||||
|  * This file is part of the coreboot project. | ||||
|  * | ||||
|  * SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  */ | ||||
|  | ||||
| #include <types.h> | ||||
| #include <device/mmio.h> | ||||
| #include <ramdetect.h> | ||||
| #include <arch/exception.h> | ||||
| #include <arch/transition.h> | ||||
|  | ||||
| static enum { | ||||
| 	ABORT_CHECKER_NOT_TRIGGERED, | ||||
| 	ABORT_CHECKER_TRIGGERED, | ||||
| } abort_state = ABORT_CHECKER_NOT_TRIGGERED; | ||||
|  | ||||
| static int abort_checker(struct exc_state *state, uint64_t vector_id) | ||||
| { | ||||
| 	if (raw_read_esr_el3() >> 26 != 0x25) | ||||
| 		return EXC_RET_IGNORED; /* Not a data abort. */ | ||||
|  | ||||
| 	abort_state = ABORT_CHECKER_TRIGGERED; | ||||
| 	state->elx.elr += sizeof(uint32_t); /* Jump over faulting instruction. */ | ||||
| 	raw_write_elr_el3(state->elx.elr); | ||||
| 	return EXC_RET_HANDLED; | ||||
| } | ||||
|  | ||||
| static struct exception_handler sync_el0 = {.handler = &abort_checker}; | ||||
|  | ||||
| int probe_mb(const uintptr_t dram_start, const uintptr_t size) | ||||
| { | ||||
| 	uintptr_t addr = dram_start + (size * MiB) - sizeof(uint32_t); | ||||
| 	void *ptr = (void *)addr; | ||||
|  | ||||
| 	abort_state = ABORT_CHECKER_NOT_TRIGGERED; | ||||
| 	exception_handler_register(EXC_VID_CUR_SP_EL0_SYNC, &sync_el0); | ||||
| 	read32(ptr); | ||||
| 	exception_handler_unregister(EXC_VID_CUR_SP_EL0_SYNC, &sync_el0); | ||||
| 	return abort_state == ABORT_CHECKER_NOT_TRIGGERED; | ||||
| } | ||||
| @@ -11,6 +11,12 @@ | ||||
|  * GNU General Public License for more details. | ||||
|  */ | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Used in probe_ramsize(). This is a weak function and it's overridden for | ||||
|  * ARMv8. Return 1 when DRAM exists at the address, otherwise return 0. | ||||
|  */ | ||||
| int probe_mb(const uintptr_t dram_start, const uintptr_t size); | ||||
| /* | ||||
|  * Probe an area if it's read/writable. | ||||
|  * Primary use case is the detection of DRAM amount on emulators. | ||||
|   | ||||
| @@ -19,7 +19,7 @@ | ||||
|  | ||||
| #define OVERLAP(a, b, s, e) ((b) > (s) && (a) < (e)) | ||||
|  | ||||
| static int probe_mb(const uintptr_t dram_start, const uintptr_t size) | ||||
| int __weak probe_mb(const uintptr_t dram_start, const uintptr_t size) | ||||
| { | ||||
| 	uintptr_t addr = dram_start + (size * MiB) - sizeof(uint32_t); | ||||
| 	static const uint32_t patterns[] = { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user