Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Raspberry Pi Zero (BCM2835) #76

Open
3 tasks
fayalalebrun opened this issue Feb 22, 2021 · 9 comments
Open
3 tasks

Add support for Raspberry Pi Zero (BCM2835) #76

fayalalebrun opened this issue Feb 22, 2021 · 9 comments

Comments

@fayalalebrun
Copy link
Collaborator

I've been attempting to modify the OS in order to be able to run it on an RPi Zero. Thus far, these are the problems I've identified will need to be solved:

  • In the startup.s file, the other cores of the processor are firstly disabled. Since the BCM2835 doesn't have extra cores, it just hangs when this happens. We'll have to handle this another way, possibly after detecting the board type.
  • Assembly part of memory detection goes into an infinite loop, even after setting the reserved region interval correctly. Perhaps this will have to be moved to after the board is detected, since the reserved region changes per board.
  • Timer implementation is not compatible. The system timer will have to be used instead, which lives inside the main peripheral region in both BCM2835 and BCM2836.
@jdonszelmann
Copy link
Collaborator

it's interesting to find out why it hangs in startup.s. Because I believe it could just work. We're testing if the coreID is zero, and if not it passes through. You might want to find out what the value in the register is on a zero and so what it thinks the core ID is.

@fayalalebrun
Copy link
Collaborator Author

fayalalebrun commented Feb 22, 2021

The problem seems to be that the specific coprocessor register is not implemented on the BCM2835's cpu. This is the register we're checking on the BCM2836, while these are the registers on the BCM2835.

@jdonszelmann
Copy link
Collaborator

What would happen if you set up a temporary interrupt handler first so when you execute the instruction (which I'm sure will trigger some kind of trap handler) you will just return to normal execution. It's a cursed idea but it might work and work for both kinds of systems. Alternatively you could have a seperate start.s file for every kind of chipset/architecture which might be the more sensical solution. Just a little more annoying if we ever want to support more architectures.

@fayalalebrun
Copy link
Collaborator Author

Are you sure that the instruction will trigger a trap handler? It is a valid instruction, mrc, but we are simply reading from a register which does not exist in the BCM2835's CPU, and which returns (I assume) garbage.

Also, I have read that on boot-up, the bootloader passes a dtb file which defines the system, including how many cores are present and the addresses of MMIO devices. How this happens exactly, I am not sure. But this would provide quite accurate system identification, and if we ever want to support more ARM boards, would be needed. Right now we are just checking what CPU we're using, and of course that's not ideal, since we're not even identifying the board.

@jdonszelmann
Copy link
Collaborator

If it's possible to get access to that it'd be awesome

@fayalalebrun
Copy link
Collaborator Author

According to this, the bootloader should place a pointer to the DTB data structure in r2. Not sure if its worth it to implement a parser for it though.

@fayalalebrun
Copy link
Collaborator Author

I have been to retrieve the address where the DTB file is loaded by QEMU with no luck. First of all, it seems like the register r2 is loaded with no address. I found out that you should pass the DTB file to QEMU (On a real raspberry pi this is done by the bootloader), via the -dtb command. However, even after passing the correct dtb file for the rpi2 there is nothing in r2.

In the qemu manual, there is an entry for a "virt" board, which is also an arm board. It says there that if you give qemu a .elf file, the DTB will instead be loaded at a certain address. Based on the assumption that the RPi works in a similar way, this lead me to scan the entire memory for the DTB's magic string with gdb (0xd00dfeed), and I found nothing.

So either GDB is not reading from the memory correctly or QEMU is bugged. Or perhaps I am missing something else. Not entirely certain what else I can try at this point.

@fayalalebrun
Copy link
Collaborator Author

I just managed to attach a JTAG debugger to a real pi zero. I can now confirm that the bootloader does indeed place a pointer to the dtb in r2 on kernel startup. I believe emulating this will be an indispensable part of our OS, if we plan to support several versions of the RPi and even more so to support other ARM boards. Right now I can think of two ways to achieve this:

  1. Run the bootloader in QEMU before running the kernel. This would be the best option if it's possible.
  2. Place the correct DTB file somewhere in memory, and use it if r2 is set to zero, as then we know that we are running in QEMU.

@fayalalebrun
Copy link
Collaborator Author

I was looking into extracting the available memory from the device tree, and if you decompile the DTBs provided by the RPi foundation, then you will find that memory size is set to a value of zero. This was very odd, so I dumped the device tree from a running raspberry pi, and those fields were populated, despite the boot partition holding the a DTB file with memory size set to zero.

So it looks like the bootloader populates this part of the DTB to the correct value. This means we won't be able to use the DTB's provided by RPi in QEMU, but instead only manually dumped DTB files, which is annoying.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants