kandi X-RAY | raspberry-pi-os Summary
kandi X-RAY | raspberry-pi-os Summary
Learning operating system development using Linux kernel and Raspberry Pi
Top functions reviewed by kandi - BETA
raspberry-pi-os Key Features
raspberry-pi-os Examples and Code Snippets
Trending Discussions on raspberry-pi-os
I am learning ARM baremetal development using QEMU as emulator. I am following this github repo as example.
The vectors are defined for EL1 :...
ANSWERAnswered 2022-Feb-14 at 11:59
A start for debugging this is to turn on the tracing in QEMU of events related to the bcm2835 system timer, which I think is what your code is using. You can do that with the command line option
-d trace:bcm2835_systmr*. In particular the "timer #1 expired" (or whatever timer number it is) messages indicate that the timer has raised its interrupt. If the timer isn't raising the interrupt then you've programmed the timer wrongly; if it is then you've probably not set up the interrupt controller correctly.
You should probably also double-check that you're really executing in EL1 as you expect.
Older versions of QEMU supported the raspi3 board but did not implement this particular system timer device; so if you don't see timer expiry tracing then it's worth checking your QEMU is new enough. 6.2.0 definitely has this device implemented.
I am using
qemu-system-aarch64 to emulate
raspi3 (ARM Cortex A-53) on a x86 host. Here's the command that I use to launch the baremetal image :
ANSWERAnswered 2022-Feb-06 at 15:11
You are running at EL2. The instruction "msr scr_el3, x0" tries to write to an EL3-only register, and it will cause an UNDEF exception if you try it from a lower EL. In other words, the code fragment you're trying to use is written to run at EL3, and needs changes if you want to run it at EL2.
The reason your code is running at EL2 is because you have used QEMU's "-kernel" argument and passed it a binary (non-ELF) file, which is telling QEMU "You should boot me in the way that the Linux kernel booting protocol documents that a Linux kernel should be booted". That protocol says "start me in EL2 or EL1, EL2 is recommended", and so that's what QEMU does.
For more information on the various options QEMU provides for loading guest code, see this answer. Note that QEMU does not provide a "boot this image or ELF file in the way that the Raspberry PI bootrom code would boot it": you may have to adapt code intended to run on real bare-metal boards a little bit.
I have compiled this baremetal example : https://github.com/s-matyukevich/raspberry-pi-os/tree/master/src/lesson01. I modified the Makefile to have debug symbols like below :...
ANSWERAnswered 2022-Jan-27 at 10:53
GDB is placing breakpoints based on where the ELF file says the code is. You can see that in your transcript it thinks the _start function in boot.S is at address 0x0. However, when you tell QEMU to load your binary file, you are not doing that in a way that matches what the ELF file says. So the actual code being executed is at an entirely different address, and the breakpoints are not in addresses that match the executing code, so they don't hit. Since you're not compiling the code to be position-independent, when it runs from this address it is working mostly by luck (because even non-position-independent aarch64 code often doesn't have position-dependent instructions in it).
The reason the addresses don't match up is because your ELF file is saying code starts at address 0x0, but you're passing QEMU a binary file to the -kernel option, which means "I am a Linux kernel, boot me the way the Linux kernel boot protocol says to do that" (see https://www.kernel.org/doc/Documentation/arm64/booting.txt). This means a number of things, including that (for the current QEMU implementation -- this isn't strictly mandated by the booting protocol) we load the image to the address 0x80000, and run a bit of stub code generated by QEMU which sets up some registers and jumps to that location. That is why when you set your linker script to link the image to that address it happens to start working.
The solution to this is to make a choice about how you want to boot your guest code:
- You can make it honour the various requirements of the Linux kernel boot protocol, and pass it as a binary file to -kernel
- You can write it to be a pure bare-metal image that includes a vector table at address 0x0, and load it with the QEMU "generic loader", which will take an ELF file and load all its segments as the ELF headers specify. (It is also possible to pass an ELF file to -kernel, but the generic loader makes more sense in this situation.)
QEMU does not support "load this ELF file and start it in the way that the Raspberry Pi firmware supports running an ELF file that it loads from an SD card". So you may need to make some adjustments to bare-metal code tutorials that were designed only for running on real hardware.
(For more info on the various QEMU options for loading guest code, see this answer.)
No vulnerabilities reported
Reuse Trending Solutions
Subscribe to our newsletter for trending solutions and developer bootcamps
Share this Page