Page 1 of 1

ARM Exception Vector Table, high vectors (Raspberry Pi)

Posted: Sat Nov 21, 2020 12:57 pm
by vhaudiquet
Hello everyone,
I ask again for your help as i find myself stuck, and can't understand what to do after i looked everywhere i could.

I'm trying to implement exception handling on my higher half kernel for Raspberry Pi. (ARMv6)
As i mapped the kernel into higher half (0xC0000000), i wanted to enable high vectors, so the exception vectors table is at 0xFFFF0000.
I mapped 1 MiB arround this address, and everything is fine. Now i need to populate the table.
There comes the problem : this table contains 1 instruction per vector. And branch instructions are relative to PC, +- 32 MiB only. (which isnt enough to go to ~0xC000000, where the rest of my kernel code is)
I can't use a bx instruction, cause i would have to load absolute address on a register before, and that would take 2 instructions.
The way i see it, i have only two options, that i don't like :
- Put every exception handler function just below or above 0xFFFF0000, with some kind of memcpy, copying it from ~0xC0000000 to ~+0xFFFF0000
- Put a function containing 2 instructions just below or above 0xFFFF0000, that does an absolute jump to ~0xC0000000 where the actual handling code is, and put a relative jump to that function in the vector table

Those options looks really bad to me : it feels like a dirty hack, and i don't like the idea of copying pieces of code everywhere and having to worry about relative addresses tranlations and such...

Maybe there is something i don't see, or maybe i didn't understand the exception vectors table well ?

Reading dwelch67's code (which isnt in higher half, so he doesnt have the same problem), it seems like he puts 2 instructions in the handler, and i don't understand how... https://github.com/dwelch67/raspberrypi ... tors.s#L63 but maybe i'm just not understanding what he does.

Thank you for reading, and thank you in advance for any help,
Valou3433

EDIT : I also looked at ARMv8 / 64 bits example, but exception handling there doesnt seem to be the same ; and i'm not familiar with that architecture anyway, i'm just beginning low level arm programming...
EDIT 2 : When i say above 0xFFFF0000, i mean above the table

Re: ARM Exception Vector Table, high vectors (Raspberry Pi)

Posted: Sat Nov 21, 2020 4:09 pm
by zaval
how about putting your kernel at the address, that won't have this problem? how it's said: if the mountain doesn't come to Muhammad, Muhammad does come to the mountain. :D see, this is not a problem with modular kernels (PE), where HAL for example could sit somewhere, comfortable for exception vector placement. and handle it. whereas other modules, could reside far away.

Re: ARM Exception Vector Table, high vectors (Raspberry Pi)

Posted: Sat Nov 21, 2020 4:49 pm
by Octocontrabass
valou3433 wrote:Reading dwelch67's code (which isnt in higher half, so he doesnt have the same problem), it seems like he puts 2 instructions in the handler, and i don't understand how...
LDR is only one instruction. :wink:

Re: ARM Exception Vector Table, high vectors (Raspberry Pi)

Posted: Sat Nov 21, 2020 5:01 pm
by vhaudiquet
@zaval : You're right, i could put the kernel arround there.
If i dont find another solution, i will...
It's just that i liked it better with it mapped to 0xC0000000 because i had done organisation this way, and it was where my x86 kernel was.

@Octocontrabass : Oh okay yes, my bad, i misread his code, but then it can't help me as ldr offset can only be +-4M or smthing i think...
Thanks for pointing that out

Re: ARM Exception Vector Table, high vectors (Raspberry Pi)

Posted: Sat Nov 21, 2020 5:07 pm
by Octocontrabass
LDR loads a value from memory. Yes, the memory must be within 4095 bytes of the LDR instruction, but the value in memory can point to anywhere.

Re: ARM Exception Vector Table, high vectors (Raspberry Pi)

Posted: Sun Nov 22, 2020 12:43 am
by nullplan
valou3433 wrote:As i mapped the kernel into higher half (0xC0000000), i wanted to enable high vectors, so the exception vectors table is at 0xFFFF0000.
I recently read in the ARMv7 ARM that hivec support is being phased out. So you might want to reconsider. You could map a single page to address 0, initialize the vector stuff, then set it to read-only. As for your actual problem, yes, you can just LDR into PC with a PC relative address. You basically double up the exception table:

Code: Select all

data_abort: ldr pc, [pc, dabr_vec - data_abort - 8]
[...]
dabr_vec: .long data_abort_exception /* function in kernel */

Re: ARM Exception Vector Table, high vectors (Raspberry Pi)

Posted: Sun Nov 22, 2020 4:30 pm
by zaval
also, you might consider this solution, it's not hacky at all: :mrgreen: if ELF does support this, you could create another segment, linked at the needed "hi" address, where you put your exception handling code. but I am not sure, because, iirc, this may cause the linker to generate a huge binary, because the gap will be inserted in the file (which is hilarious if to think about it). But I am not sure, ditched ELF a long time ago. personally, I agree, that you'd better off to not rely on a phased out feature.

Re: ARM Exception Vector Table, high vectors (Raspberry Pi)

Posted: Mon Nov 23, 2020 9:07 am
by bzt
valou3433 wrote:I also looked at ARMv8 / 64 bits example, but exception handling there doesnt seem to be the same ; and i'm not familiar with that architecture anyway, i'm just beginning low level arm programming...
Yes, there with the VBAR system register you can replace the vectors. I've only used ARMv8, but if I'm not mistaken with ARMv5-6 you must use the address 0 (as there's no VBAR sr).
valou3433 wrote:As i mapped the kernel into higher half (0xC0000000), i wanted to enable high vectors, so the exception vectors table is at 0xFFFF0000.
This won't work. However since you must waste a page for the vectors table anyway, and the vectors table is smaller than a page, you could do:

Code: Select all

vectors:
; relative, less than 4095 bytes far branches to the low code routine (in jumptohigh)
jumptohigh:
; low code that jumps properly to 0xC0000000 + x
This is guaranteed to work no matter where your kernel is located and what instruction you choose for the jump.

Cheers,
bzt

Re: ARM Exception Vector Table, high vectors (Raspberry Pi)

Posted: Tue Nov 24, 2020 2:08 pm
by nexos
zaval wrote:but I am not sure, because, iirc, this may cause the linker to generate a huge binary, because the gap will be inserted in the file (which is hilarious if to think about it).
Nope, it won't create a huge hole :) . I still like PE better, though. Here is an example linker script from an earlier kernel I made that does this

Code: Select all

ENTRY(entry)
OUTPUT_FORMAT(elf32-i386)
KERNEL_VIRTUAL_BASE = 0xC0000000;

SECTIONS {

   . = 0x00100000;

   .multiboot.data : {
       *(.multiboot.data)
   }

   .multiboot.text : {
       *(.multiboot.text)
   }

   . += KERNEL_VIRTUAL_BASE;

   .text ALIGN(4096) : AT(ADDR(.text) - KERNEL_VIRTUAL_BASE) {
       *(.text)
   }

   .data ALIGN (4096) : AT(ADDR(.data) - KERNEL_VIRTUAL_BASE) {
       *(.data)
       *(.rodata*)
   }

   .bss ALIGN (4096) : AT(ADDR(.bss) - KERNEL_VIRTUAL_BASE) {
       _sbss = .;
       *(COMMON)
       *(.bss)
       _ebss = .;
   }
   end = .; _end = .; __end = .;
}