|
From: | sanjana gogte |
Subject: | Re: Assistance Required for QEMU Hardfault Error with Cortex-M33 on MPS2AN505 |
Date: | Tue, 30 Jan 2024 13:18:36 +0530 |
I wanted to express my gratitude for your insightful solution concerning the INVSTATE fault I was encountering. After recompiling my code with the -mthumb
compiler flag, the exception is no longer being raised, which marks a significant step forward in my project.
However, I've encountered another challenge while working with a specific version of QEMU (QEMU emulator version 7.1.0, v2.6.0-55433-g23b643ba16). While the code runs flawlessly on QEMU version 8.1.50 (v8.1.0-2375-g516fffc993), the earlier version throws a hard fault, which is critical to my use case.
The use case involves attaching a remote port to the MPS2-AN505, and for this, I need to utilize Xilinx’s fork of QEMU, which is based on version 7.1.0 (v2.6.0-55433-g23b643ba16). The error I encounter during emulation is as follows:
Loaded reset SP 0x0 PC 0x0 from vector table
Loaded reset SP 0x10080000 PC 0x10000009 from vector table
Taking exception 3 [Prefetch Abort] on CPU 0
...at fault address 0x10800000
...with CFSR.IBUSERR
...taking pending secure exception 3
...loading from element 3 000000c
...loaded new PC 0x10000011 of secure vector table at 0x1
Taking exception 3 [Prefetch Abort] on CPU 0
...at fault address 0x10800000
...with CFSR.IBUSERR
qemu: fatal: Lockup: can't escalate 3 to HardFault (current priority -1)
Observations: When I trace it using the GDB:
Remote debugging using: 1234
Reset_Handler () at boot.s:20
20 blx helper
(gdb) l
15 blx R0
16
17 .type Reset_Handler, function
18 .global Reset_Handler
19 Reset_Handler:
20 blx helper
21 bx lr
22
(gdb) s
Remote connection closed
It goes to prefetch abort as soon as I step into reset handler and the connection gets closed.
What I do not understand is:
1) Why is my PC going to address 0x10800000?
2) When I use Qemu version 8.1.50 (v8.1.0-2375-g516fffc993), the PC goes to the right address and does not throw a prefetch abort.
Please give me your insights on how I can fix this.
Some of my code for your reference:
My startup code :
.syntax unified
.thumb
.section .isr_vector
.long __StackTop
.long Reset_Handler
.text
.type helper,function
.global helper
helper :
ldr R0, = main
blx R0
.type Reset_Handler, function
.global Reset_Handler
Reset_Handler:
blx helper
bx lr
( Like you mentioned previously , In the .isr_vector section I tried making the other exception handlers point to branch-to-self instructions but that gives me the same error )
My linker code :
/* Linker script to configure memory regions. */
MEMORY
{
NS_CODE (rx) : ORIGIN = 0x00000000, LENGTH = 512K
S_CODE_BOOT (rx) : ORIGIN = 0x10000000, LENGTH = 512K
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 512K
}
/* Entry Point */
ENTRY(Reset_Handler)
SECTIONS
{
.text :
{
KEEP(*(.isr_vector))
*(.text)
*(.data)
*(.bss)
} > S_CODE_BOOT
/* Set stack top to end of S_CODE_BOOT. */
__StackTop = ORIGIN(S_CODE_BOOT) + LENGTH(S_CODE_BOOT);
}
kernel.list file :
kernel.elf: file format elf32-littlearm
Disassembly of section .text:
10000000 <helper-0x8>:
10000000: 10080000 .word 0x10080000
10000004: 1000000d .word 0x1000000d
10000008 <helper>:
10000008: 4802 ldr r0, [pc, #8] @ (10000014 <Reset_Handler+0x8>)
1000000a: 4780 blx r0
1000000c <Reset_Handler>:
1000000c: f7ff fffc bl 10000008 <helper>
10000010: 4770 bx lr
10000012: 0000 .short 0x0000
10000014: 10000019 .word 0x10000019
10000018 <main>:
10000018: b480 push {r7}
1000001a: af00 add r7, sp, #0
1000001c: e7fe b.n 1000001c <main+0x4>
On Thu, 18 Jan 2024 at 06:30, sanjana gogte <sanj27272@gmail.com> wrote:
>
> Hi,
> 1) I am using QEMU Version 7.1.0. I am currently using this version with a plan to connect the remote port from Xilinx to the mps2an505 board. The decision to use this specific version is heavily influenced by the fact that it is the same version utilized by Xilinx's QEMU.
>
> 2) Debug Logs :
> guest_errors:
>
> Invalid read at addr 0x10000000, size 4, region '(null)', reason: rejected
> Invalid read at addr 0x10000004, size 4, region '(null)', reason: rejected
> Invalid read at addr 0x10800000, size 2, region '(null)', reason: rejected
> qemu: fatal: Lockup: can't escalate 3 to HardFault (current priority -1)
>
> in_asm:
>
> IN:
> 0x10000008:
> OBJD-T: 00480047
Whoever built your QEMU didn't do it with libcapstone-dev
installed, so the debug logs have only binary dumps of
instructions, not the actual instructions, which is a pity
(--enable-capstone will force configure to either find the
necessary library or else give you an error message.)
Also, I did not mean "do logs of every -d option separately",
I meant "do a single log, with -d
in_asm,exec,cpu,int,cpu_reset,unimp,guest_errors,nochain"
That way you get the different bits of logging in their
correct sequence relative to each other.
Luckily, this bit is enough to figure out what's going on:
> Loaded reset SP 0x0 PC 0x0 from vector table
> Loaded reset SP 0x10080000 PC 0x10000008 from vector table
We load the PC from the vector table, but it does not
have the low bit set, which is not correct. (All entries
in the vector table must be function pointers in the
usual Thumb convention, where the lowest bit is set to
indicate Thumb mode and clear to indicate Arm mode.)
This means that we will start without the Thumb T bit set...
> Taking exception 18 [v7M INVSTATE UsageFault] on CPU 0
...which on M-profile means we immediately take a fault trying
to execute the first instruction...
> ...taking pending secure exception 3
> ...loading from element 3 of secure vector table at 0x1000000c
> ...loaded new PC 0x10000011
...but because your vector table includes no entry for
the hardfault vector, we instead load a PC value which
doesn't point anywhere useful...
> Taking exception 3 [Prefetch Abort] on CPU 0
> ...at fault address 0x10800000
> ...with CFSR.IBUSERR
> qemu: fatal: Lockup: can't escalate 3 to HardFault (current priority -1)
...and eventually we execute off the end of the ROM memory,
and then take a bus fault on the instruction fetch. This
is a Lockup because we were already in a HardFault handler
when we took this fault.
> 3) You said the vector table is too small so I tried something like this from your reference files but it gives me the same error:
>
> Boot.s ( Startup file )
>
> .thumb
> .syntax unified
>
> .section .isr_vector
> .long __StackTop
> .long Reset_Handler
> .word 0
Zeroes here aren't very helpful because the CPU will try
to jump to address 0 (and then immediately take another
fault because the Thumb bit isn't set, which will be
a Lockup condition again). If you at least make them point to
branch-to-self instructions it'll be a bit clearer when
you take an exception you weren't expecting, because in
the debugger you'll see execution looping at that insn.
> .word 0
> .rept 7
> .word 0
> .endr
> .word 0
> .word 0
> .word 0
> .word 0
> .word 0
> .rept 32
> .word 0
> .endr
>
>
> .text
> .global Reset_Handler
> Reset_Handler:
> ldr R0, = main
> bx R0
But really your problem is here. You haven't told the assembler
that "Reset_Handler" is a function entry point, and so it treats
it like a data label. That means that the least significant bit
is not set when you reference it in the vector table.
Something like this will do what you want:
.type Reset_Handler, function
.global Reset_Handler
Reset_Handler:
PS: a hint for later: your code here does not do anything
to enable the FPU before it jumps into C code. If your
C compiler is generating code to use the FPU this will
mean it will take an exception. So either make sure the
C compiler is configured not to use the FPU, or else enable
the FPU first.
thanks
-- PMM
[Prev in Thread] | Current Thread | [Next in Thread] |