CortexA15 - Where's the IVT?

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
avcado
Member
Member
Posts: 29
Joined: Wed Jan 20, 2021 11:32 am
Contact:

CortexA15 - Where's the IVT?

Post by avcado »

Bit embarrased to post this because I feel like I'm one google search away from finding the answer, but at the same time, I also feel like it's gonna take forever to figure this out. I went through the Bare Bones for the Cortex A15 board, set everything up, and got it working with the arm-none-eabi toolchain.

From what I've read of the CoreTile Express TRM, the kernel is loaded into the daughterboard memory (p. 45). I've read that the IVT is located at 0x0, while others say it's located at 0xFFFF0000.

To test, I added a section to my stub.S, exceptions, that would load at 0x0:

Code: Select all

// stub.S
.section exceptions
_VectorTable:
  b .         /* 0x00: Reset vector */
  b .         /* 0x04: Undefined instruction */
  ldr pc, =svc_hdlr  /* 0x08: SVC (software), long jump */
  b .         /* 0x0C: Prefetch */
  b .         /* 0x10: Data abort */
  b .         /* 0x14: Reserved */
  b .         /* 0x18: IRQ */
  b .         /* 0x1C: FIQ */
  
  
// ... later, in section text
svc_hdlr:
  mrs r0, spsr
  stmdb sp!, {r0-r3, lr} /* Save caller-saved registers */

  bl __c_svc_hdlr

  ldmia sp!, {r0-r3, lr} /* Restore */
  subs pc, lr, #4
Then, I make the linker load it to 0x0:

Code: Select all

ENTRY(_start)

SECTIONS {
  . = 0x000;
  .exceptions : { *(.exceptions) }

  /* Kernel code in daughterboard / flash memory. */
  . = 0x80010000;
  
  ...
__c_sv_hdlr looks like this:

Code: Select all

void __c_svc_hdlr(uint32_t r0, uint32_t r1, uint32_t r2,
                uint32_t r3, uint32_t lr){
  printf("r0: %x | r1: %x | r2: %x | r3: %x | lr: %x\n", r0, r1, r2,
      r3, lr);
}
I verify that it is infact being loaded at 0x000:

Code: Select all

$  arm-none-eabi-objdump -x bin/kernel.elf | grep exceptions
  5 exceptions    00000024  00000000  00000000  00001434  2**2
00000000 l    d  exceptions     00000000 exceptions
00000000 l       exceptions     00000000 _VectorTable
It seems like svc_hdlr isn't getting called. Even with

Code: Select all

. = 0xFFFF0000;
.exceptions : { *(.exceptions) }
...
I'm not getting any output. Am I being stupid? What's going on?
Octocontrabass
Member
Member
Posts: 5543
Joined: Mon Mar 25, 2013 7:01 pm

Re: CortexA15 - Where's the IVT?

Post by Octocontrabass »

avcado wrote: Wed Oct 02, 2024 6:14 pmI've read that the IVT is located at 0x0, while others say it's located at 0xFFFF0000.
The location of the vectors is determined by SCTLR.V and VBAR (if your CPU has that register). You'll probably want to use 0xFFFF0000 for the Versatile Express board.

Code: Select all

.section exceptions
You might need to make this section allocatable.
avcado
Member
Member
Posts: 29
Joined: Wed Jan 20, 2021 11:32 am
Contact:

Re: CortexA15 - Where's the IVT?

Post by avcado »

EDIT: turns out I am stupid, and the .exceptions code for the linker script needs to come AFTER everything else. However, my svc_hdlr isn't being called.

Octocontrabass wrote: Wed Oct 02, 2024 9:40 pm You'll probably want to use 0xFFFF0000 for the Versatile Express board.
So something like this?

Code: Select all

  . = 0xFFFF0000;
  .exceptions : { *(.exceptions) }
  
  /* Kernel code in daughterboard / flash memory */
  . = 0x80010000;
  
  ...
Let's check it in objdump

Code: Select all

 3 exceptions    00000024  800103d4  800103d4  000013d4  2**2
Huh, why isn't it loaded at FFFF0000? So I try a different approach:

Code: Select all

IVT_LOCATION = 0xFFFF0000;

MEMORY {
  exceptions (rx) : ORIGIN = IVT_LOCATION, LENGTH = 2048
}

...

  . = 0x80010000;

...

$ arm-none-eabi-objdump -h bin/kernel.elf
Idx Name          Size      VMA       LMA       File off  Algn
  0 .stub         00000024  ffff0000  ffff0000  00002000  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .text         0000031c  ffff0024  ffff0024  00002024  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  2 .rodata       00000093  ffff0340  ffff0340  00002340  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 exceptions    00000024  ffff03d4  ffff03d4  000023d4  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .data         00000040  80010000  80010000  00001000  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  5 .bss          00000004  80010040  80010040  00001040  2**2
                  ALLOC
  6 .ARM.attributes 00000036  00000000  00000000  000023f8  2**0
                  CONTENTS, READONLY
  7 .comment      0000001e  00000000  00000000  0000242e  2**0
                  CONTENTS, READONLY
Huh? Why is .stub, .text, .rodata loading at 0xFFFF0000? And why is .data loading at 0x80010000 (the correct value?) So what if I put .stub in the memory section?

Code: Select all

ENTRY(_start)

IVT_LOCATION = 0xFFFF0000;

MEMORY {
  exceptions (rx) : ORIGIN = IVT_LOCATION, LENGTH = 2048
  .stub (rx) : ORIGIN = 0x8001000, LENGTH = 64k
}
...

Code: Select all

$ arm-none-eabi-objdump -h bin/kernel.elf

bin/kernel.elf:     file format elf32-littlearm

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .stub         00000024  ffff0000  ffff0000  00002000  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .text         0000031c  ffff0024  ffff0024  00002024  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  2 .rodata       00000093  ffff0340  ffff0340  00002340  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 exceptions    00000024  ffff03d4  ffff03d4  000023d4  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .data         00000040  80010000  80010000  00001000  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  5 .bss          00000004  80010040  80010040  00001040  2**2
                  ALLOC
  6 .ARM.attributes 00000036  00000000  00000000  000023f8  2**0
                  CONTENTS, READONLY
  7 .comment      0000001e  00000000  00000000  0000242e  2**0
                  CONTENTS, READONLY
Interesting...? No clue what's going on here...
Octocontrabass
Member
Member
Posts: 5543
Joined: Mon Mar 25, 2013 7:01 pm

Re: CortexA15 - Where's the IVT?

Post by Octocontrabass »

avcado wrote: Thu Oct 03, 2024 4:22 pmEDIT: turns out I am stupid, and the .exceptions code for the linker script needs to come AFTER everything else.
The linker only rearranges sections that aren't allocatable. You probably actually just need to make it allocatable, like so:

Code: Select all

.section exceptions, "a"
Although it's hard to say for sure, since you didn't provide enough objdump output to tell for sure.
avcado wrote: Thu Oct 03, 2024 4:22 pmHowever, my svc_hdlr isn't being called.
There might still be problems with your linker script. Also, did you check SCTLR?
avcado
Member
Member
Posts: 29
Joined: Wed Jan 20, 2021 11:32 am
Contact:

Re: CortexA15 - Where's the IVT?

Post by avcado »

Octocontrabass wrote: Thu Oct 03, 2024 7:41 pm
avcado wrote: Thu Oct 03, 2024 4:22 pmEDIT: turns out I am stupid, and the .exceptions code for the linker script needs to come AFTER everything else.
The linker only rearranges sections that aren't allocatable. You probably actually just need to make it allocatable, like so:

Code: Select all

.section exceptions, "a"
Although it's hard to say for sure, since you didn't provide enough objdump output to tell for sure.
avcado wrote: Thu Oct 03, 2024 4:22 pmHowever, my svc_hdlr isn't being called.
There might still be problems with your linker script. Also, did you check SCTLR?
I managed to get the SVC handler working. I read (in the TRM!!) that the IVT is in fact at 0x0000. I think the reason why it wasn't jumping to my function was because I was trying to manually push registers, when instead I could just do

Code: Select all

__attribute__((interrupt("SWI")))
...
which ended up working for me.
Post Reply