This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Unable to initialise translation tables on cortex A76

I am working on writing a minimalistic bare metal kernel for the raspberry pi 5 (having arm cortex a76). Everything was going on smoothly, until I came to enabling the MMU. I am not sure what I am missing here, but I think I am unable to initialise the translation tables for the MMU appropriately. Here is my bootstrap code for the kernel:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include "system_registers.h"
#include "mmu.h"
.section ".text.boot"
.global _start
_start:
mrs x7, mpidr_el1 // Multi-Processor Identifier(EL1)
lsr x7, x7, #8 // Shift the identifier to the right by 8 bits.
and x7, x7, #7 // Last 3 bits of the identifier extracted. Indicates CPU ID.
cbz x7, intr_init // Proceed if on primary core, else wait for the primary core to initialize.
// The default stub for the Raspberry Pi 5 looks for the first instruction at x80000,
// and runs it on the primary core of the processor (generally core 0), and parks all
// the remaining cores. If the address of a function is written onto the register at
// which the respective core expects it, the core is then woken up from sleep to
// execute that function.
// delay for the secondary cores to wait for the primary core to initialize
mov x0, #10000
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

The code here, fails to branch to `kernel_main()` if it branches to `__create_page_tables`, and I don't understand why. I also had UART prints after every statement in the code, so as to check where the execution is hanging, and it turns out only the `bl kernel_main` statement is not taking place. Following is my linker:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
SECTIONS
{
. = 0x80000; /* Start address of the kernel image */
.text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) }
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) }
/* PROVIDE -> for variables which are referenced but not initialized in the section */
PROVIDE(_data = .); /* Initialize data start address to current location pointer */
.data : { *(.data .data.* .gnu.linkonce.d*) } /* Section for initialized data */
.bss (NOLOAD) : { /* Section for uninitialized data; NOLOAD -> Don't allocate space in linking, will be allocated and initialized in runtime */
. = ALIGN(16); /* Align the current location pointer to the next 16bit boundary */
__bss_start = .; /* Start address of the BSS section */
*(.bss .bss.*)
*(COMMON) /* COMMON -> used for uninitialized global variables that are declared without an explicit section attribute in multiple files. */
__bss_end = .; /* End address of the BSS section */
}
. = ALIGN(0x10000);
id_pg_dir = .;
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

also, for reference, the VA_START variable is a macro which resolves to 0x0 (I'm trying out identity mapping as of now...)

I am not sure as to what I am doing wrong, or what exactly I am missing and failing to understand. Any help would be really helpful...

Thanks!

0