All times are UTC-06:00




Post new topic  Reply to topic  [ 8 posts ] 
Author Message
PostPosted: Fri Dec 09, 2005 10:33 am 
Offline

Joined: Fri Sep 24, 2004 1:39 am
Posts: 103
Location: Gothenburg, Sweden
Background
About a year ago I decided that I wanted to learn some supervisor level programming on the PowerPC and what better/other way to do it than to write my own kernel. I started digging through the source code of various kernel projects (with PowerPC ports) that I could find on the internet as well as reading the excellent PowerPC manuals provided by Motorola/Freescale. After a couple of weeks of hard work I had managed to construct something that could boot on the Pegasos, and more importantly I had reached that glorious point where I felt that I understood what happened in my code and that it no longer consisted of ideas stolen from others but rather was based on my own knowledge of how the CPU worked. At that point I decided that it would be a great idea to write a guide on how to make your own kernel for the Pegasos/PowerPC platform. That turned out to be a bad idea because I never had enough time to write the guide while the kernel (and my head) contained a lot of information that others would have found useful. I held off releasing the source code as I felt users might get lost in there without the guide and it just sat there collecting dust.
It took me some time but I finally realized (mostly thanks to BBRV and Neko) that I should release the source code here on PPCZone and start a forum post (as opposed to writing the guide). That way I can get the source code out into the hands of the developers all the while I'll be able to provide guidance via the forum and this thread. Everything is released under a BSD-style to give you the maximum freedom in order to reuse it for your own project(s).

Introduction
There are two source trees which I am going to make available. One is called loader and it consists of the bare minimum required to produce a bootable kernel which is able to communicate with the Open Firmware implementation known as SmartFirmware on the Pegasos. It should work on other Open Firmware implementations as well (such as Apple's) but I have only tried it once so your mileage may vary.
The other is CrabOS which is an unfinished micro kernel mostly based on the L4 design. Right now only two syscalls are implemented, a very basic IPC method, sc_ipc, and a call to switch threads, sc_thread_switch. The kernel can do some basic memory management but most of it is supposed to happen in the unimplemented pager module.
All the source code has been written by me except for the vsprintf method which I borrowed from the Sanos project and queue.h which I borrowed from NetBSD.
I'm going to assume that you have some basic PowerPC assembly knowledge as well as C programming knowledge. If anything seems confusing and you cannot find an answer in the PowerPC reference manual please ask me.

Compilation
You need a GCC compiler (others might work but you are on your own) capable of producing ppc code. I have written all the code on my Pegasos using Linux. If you intend to use Linux on another arch than ppc, or some other OS (i.e. MorphOS) you might have to modify config.mak.

Loader
Loader contains the basics for producing a bootable kernel, in C, which can communicate with SmartFirmware. Booting loader on a Pegasos should produce "Welcome to loader 1.0.0" followed by "End of the line". It will not return to the firmware at that point and you will have to reset your Pegasos.

crt0.S
crt0 is where it all starts. On boot execution is transferred to the _start label as defined by LDFLAGS in config.mak ("-e_start"). The first thing that happens there is to clear the BSS section. This is required by ANSI C if you want to be standards conforming but you can get away with skipping this although personally I prefer sticking with accepted standards. The __bss_start and _end labels are defined by the linker (GNU ld) so you do not need to worry about defining these yourself. @ha means you only want the upper 16 bits of the value, @l signifies the lower 16 bits. The reason why we cannot load a 32-bit value in one operation is because of the RISC design of the PowerPC. Each instruction in the PowerPC occupies exactly 32-bits, this includes the operation identifier, register indices etc, and because of that you simply cannot fit a load operation identifier, register index and a 32-bit constant into one operation.
The next step is to load the stack pointer into the second general purpose register (r1). The PowerPC ABI specifies that the stack pointer should be stored in r1 and if you want to store it in a different register you will have to modify GCC as it assumes the stack is always available via r1. We have already allocated 4kB of memory in the BSS section which we will use as our stack. Please note that if your kernel ever needs more than 4kB of stack space you will be in trouble with this kind of static stack allocation. r2 and r13 are not used by us so we set them to 0, please see the PowerPC ABI for further information about the use of these registers.
Finally we jump to the label loader which is where we switch from assembly to C.

Note that while programming in assembly you aren't forced to adhere to the PowerPC ABI, but it can be a good thing, especially if you intend to mix assembly and C and don't want to modify GCC. If you do decide to make your own standard and you allow others to write code for your kernel you better make sure they understand that you do not follow the PowerPC ABI standard or otherwise they will be in big trouble.
There is one register which you should refrain from trashing at this point and that is r5. r5 holds the Open Firmware entry point and without the address stored in it you will be unable to call the firmware! When calling the firmware you must always use the PowerPC ABI.

loader.c
This file contains the loader function which is called by crt0. As specified by Open Firmware the firmware entry point is passed as the third parameter (argument) when loading a kernel. According to the PowerPC ABI paramters are passed via general purpose registers r3 through r10 making r5 the third one. Since GCC (ppc-elf) conforms to the PowerPC ABI that means the first argument in a function call is stored in r3, the second one in r4 and so on. Since we are only interested in r5 there are two ways to access it in our C-function. The way I'm doing it is to define the function as "void loader(int r3 __attribute__((unused)), int r4 __attribute__((unused)), unsigned int r5)". __attribute__((unused)) tells GCC that we really aren't interested in these variables and that it is free to use the registers they are occupying any way it likes. Please don't attempt to access the variables "r3" and "r4" (regard them as variables and not as registers) without removing these attributes first, otherwise you might get unexpected behaviour in your code.
The other way of accessing r5 would be to have declared the function as "void loader(void)" and then declare a variable that is bound to the r5 register. This is done by declaring a variable like "int openfirmware asm("r5");". This tells GCC that the int variable "openfirmware" should represents register r5. Any of the two methods is fine and it's up to you which one you prefer.
Of course you do not need to name your variables "rX" or "openfirmware" I just did so for the sake of readability. Avoid considering the variable rX to be synonymous with the register rX.

CrabOS
On booting CrabOS it will enable the MMU and load a page table in order to control access to memory and to prepare paging for the pager process. It will also load two tasks, pager and init. pager is supposed to handle memory pages for everything in the system whereas init is supposed to be the task that does all the necessary work to boot the rest of the OS, which amounts to everything but the kernel and pager.

Running tasks are scheduled based on their IPC paths and when the kernel runs out of active paths it will deadlock. The idea was to implement preemption so that scheduling could be based on the real time clock rather than IPC paths but I didn't have time to finish that.

Source code
Loader
CrabOS

Recommended reading
Open Firmware
IEEE-1275 This is an old version of the Open Firmware specification, but it's free. I found this to cover more than I needed and I have never read a newer version of it.

Freescale
PowerPC Reference Manual
PowerPC Programming Environment Manual
PowerPC ABI

Postlude
I'm running out of time and I wanted to post this before the weekend. I will add more information to this post, hopefully next week.
Feel free to ask any questions regarding kernels on the Pegasos that you like in this thread and we will do our best to answer them. As time goes by I will fill in more and more information in this original post and perhaps some day it will reach an "article"-stage.


Last edited by dholm on Sun Dec 11, 2005 11:53 am, edited 3 times in total.

Top
   
 Post subject:
PostPosted: Sat Dec 10, 2005 3:33 am 
Offline
Genesi

Joined: Fri Sep 24, 2004 1:39 am
Posts: 1422
David, this is great. We hope there are more than a few people that will take up this effort. Thanks for posting this!

R&B :D

_________________
http://bbrv.blogspot.com


Top
   
 Post subject:
PostPosted: Sat Dec 24, 2005 6:48 am 
Offline

Joined: Tue Dec 14, 2004 3:52 am
Posts: 42
Location: Italy - from Mexico
I don't have the "minimal requirements" to understand it all, but would it be possible to write a loader to boot (or at least TRY to boot) a PPC version of BeOS?
Since BeOS officially supported PPC processors only up to 603s, would that mean the needed assembler code would have to be a bit different?

I found this link related to BeOS on G3-4-5 processors: http://www.computing.net/beos/wwwboard/forum/1037.html

EDIT: Read this http://haikunews.org/226 and this http://haikunews.org/1144 too...

_________________
--------------->
RockmanX
<---------------


Top
   
 Post subject:
PostPosted: Fri Jan 06, 2006 9:36 am 
Offline
Site Admin

Joined: Fri Sep 24, 2004 1:39 am
Posts: 1589
Location: Austin, TX
Quote:
I don't have the "minimal requirements" to understand it all, but would it be possible to write a loader to boot (or at least TRY to boot) a PPC version of BeOS?
Since BeOS officially supported PPC processors only up to 603s, would that mean the needed assembler code would have to be a bit different?

I found this link related to BeOS on G3-4-5 processors: http://www.computing.net/beos/wwwboard/forum/1037.html

EDIT: Read this http://haikunews.org/226 and this http://haikunews.org/1144 too...
Do you know where we could get a PPC version of BeOS from? The major problem would be driver support beyond using OpenFirmware callbacks, I am sure BeOS made some assumptions about the make-up of Macs at the time.

The BeOS port to Macintosh would have used OpenFirmware to boot so I assume it used COFF or XCOFF binary to load. If it is ELF that is even easier.

I have had a small chat with the guys at YellowTAB and they are interested but not immediately excited about a return to PowerPC. All this information would be needed, before we can make an answer :)


Top
   
 Post subject:
PostPosted: Mon Jan 09, 2006 10:48 am 
Offline

Joined: Tue Dec 14, 2004 3:52 am
Posts: 42
Location: Italy - from Mexico
Every version of BeOS came with two partitions on the cd: one for ppc and one for x86!
What's more, I'm nearly sure it used ELF binaries.
The only problem is that G3 and G4 specs were never been sent to Be Inc., so they're officially unsupported. It has been said that someone eventually did run BeOS on these newer machines, but nothing sure.
I guess the YellowTab guys wouldn't have very hard times trying to make a ppc version of Zeta, since they have access to all the sources...

_________________
--------------->
RockmanX
<---------------


Top
   
 Post subject:
PostPosted: Mon Jan 09, 2006 3:25 pm 
Offline

Joined: Mon Dec 19, 2005 5:45 am
Posts: 23
Quote:
Every version of BeOS came with two partitions on the cd: one for ppc and one for x86!
What's more, I'm nearly sure it used ELF binaries.
Well.. only the versions, which supported both architectures. (R3,R4,R5 I think).
And BeOS PPC used COFF, not ELF. Unfortunately. The PPC version never moved to gcc.


Top
   
 Post subject:
PostPosted: Wed Jan 11, 2006 5:53 am 
Offline

Joined: Fri Sep 24, 2004 1:39 am
Posts: 103
Location: Gothenburg, Sweden
The PPC version of BeOS requires a special loader which you have to run in MacOS classic if I recall correctly. I tried running it on my first gen PowerBook/G4 but it wasn't supported and wouldn't even boot.


Updates to the original article coming soon.


Top
   
 Post subject:
PostPosted: Thu Jan 12, 2006 4:16 am 
Offline

Joined: Mon Dec 19, 2005 5:45 am
Posts: 23
Quote:
The PPC version of BeOS requires a special loader which you have to run in MacOS classic if I recall correctly.
Not when running on a BeBox.


Top
   
Display posts from previous:  Sort by  
Post new topic  Reply to topic  [ 8 posts ] 

All times are UTC-06:00


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  
PowerDeveloper.org: Copyright © 2004-2012, Genesi USA, Inc. The Power Architecture and Power.org wordmarks and the Power and Power.org logos and related marks are trademarks and service marks licensed by Power.org.
All other names and trademarks used are property of their respective owners. Privacy Policy
Powered by phpBB® Forum Software © phpBB Group