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 15:34, Peter Maydell <[email protected]>
wrote:
> On Thu, 18 Jan 2024 at 06:30, sanjana gogte <[email protected]> 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
>