Thursday, April 11, 2013

Blog moved

Work is still going on, but this blog has moved to

Thursday, February 16, 2012

I think I'll go with Isembard for a name.

It turns out that I.K. Brunel's father was French, as well.

Saturday, January 21, 2012

Kernel progress

The kernel is now at a point where code in two separate maps can communicate non-object parameters, provided the maps do not overlap, and only a single thread is supported.

The calling code should:
  • Put the feature identifier into r0 (this number is ignored by the kernel and passed unchanged to the callee)
  • Encode any parameters into the thread transfer block
  • Access the target "object" address using the specific instruction required by the kernel (currently LDR r14, [r14], so load r14 with the object's address and execute the instruction)
Only one register (r13) is preserved over the call, and on return r11 points to the map's thread transfer block which will contain the return values.  (I'm not sure yet whether to have the V bit set on exception, or call an exception handler routine.)

The callee is entered with:
  • r0 containing the value from the caller (nominally the feature number/identifier),
  • r11 pointing to the thread transfer block,
  • r12 containing the object identifier, as provided by code in the destination map when exporting the object handler, and
  • r14 containing the address to which the code should jump in order to return from the call.
The encoding of parameters allows the transfers of objects and simple expanded type values.
Objects local to the caller memory map will be defined by a handler (code) address and object identifier pair, which will be replaced by the kernel with a single pointer to an imported object.  Objects that have been imported into the caller can also be passed as parameters or results of calls, and the kernel will give the recipient access to these values as well.

The next task will be to add interrupt handling and multi-threading.

Friday, January 13, 2012

Name already taken

I just realised that the Brunel name was already taken (also for an Eiffel derivative language), back in 1991.

I'll have to come up with another name, I guess.

Wednesday, December 7, 2011

Starting on threads and memory maps

I finally got the SDRAM responding last night; I'd been writing 100 to a register rather than &100 (0x100), and it didn't like that.  That's what you get from not taking open source code directly!

The next task is to introduce (memory) maps and threads.

Initially, I won't dynamically allocate these things, just create a few example ones with simple interfaces to prove the thread and map management code works.

One map will implement the serial port driver.

There are two ways I can think of where the caches/TLB can get confused:
  Change of thread
  Change of map

In the first case, there is a context switch where one thread moves from the running state to either the runnable or blocked state, and another thread moves from runnable to running.

In the second case, a thread makes a call to an object implemented in another map.  (This will be done by storing the parameters to the call at a known location in thread-local storage and accessing a location in non-user accessible memory associated with the destination object.  The map will be switched to the destination object's map and the thread will continue at a location within that map.)

(Security note: the ARM registers will have to be preserved in the calling map and cleared before entering the called map, to ensure there's no leak of information from one map to another.)

As a simple test of the switching code, I intend to have some threads running that do nothing but increment a single ARM register each while jumping around in their code and, checking their other general purpose registers remain at zero.  If any of these test threads detect changes to registers, other than the one they're manipulating, there's a problem with the cache/TLB flushing.

To test the test, I'll start with a kernel that won't perform any manipulations on the TLB or cache.

Update: First problem was that the boot code (presumably) has set the Nonsecure Vector Base Address Register to 0x00014000, so putting my handlers in zero page meant they weren't called.

Thursday, December 1, 2011

Introducing BrunelOS

I've been working on hacking a BeagleBoard recently, and I've decided to design and implement my own OS to run on it.

I've decided to call my variation on the Eiffel language Brunel (for I.K. Brunel), and this operating system BrunelOS.

I expect to be able to create a GNU/BrunelOS, where GNU software such as GCC can run on the OS, but ideally, I'd like to implement new applications using Brunel instead.

Brunel is an Object Oriented language with design by contract, inline callbacks and with virtually invisible multi-threading/multi-processing facilities built in.

The implementation of multi-threading is quite simple; only one thread at a time may access any of an object's features and subsequent attempts by other threads to enter an object will be blocked until the first thread exits the object.  Deadlock will be automatically detected and cause an exception in the thread that causes it.  The only exception to this system will be Event objects that allow threads to block until the event occurs (or is cancelled).

BrunelOS is an operating system designed to work with the Brunel programming language.

BrunelOS does not have traditional processes, but a combination of memory maps and threads.

Objects and code exist in memory maps, and threads can pass from memory map to memory map within the system, but only ever to interface objects known to the calling memory map.

Tuesday, June 24, 2008

Bootstrap version

In the last week I've managed to get the Eiffel version of the compiler to a state where it will compile itself.

Until now, I've been using a very basic compiler written in C++ to compile the Eiffel code I've been writing, but from now on I should be able to dispense with that and simply work on the Eiffel code. As I add support for more features to the compiler, I will be able to use the features in the code.

Basically, at the moment, I have a single test case; compiling the compiler. The test works in three stages:

1. Use a tested version of the compiler to process the source code

2. Use the new version of the software to process the same code

3. Use the third version of the compiler to process the source code again

4. Check that the generated code from steps 2 and 3 are identical; that version of the code then becomes the tested version for next time.

The output from stages 1 and 2 may be different, because of different code generation strategies or support for more language features.

Some time after the holidays, I intend to put the code in the form of the Eiffel source and generated C onto Source Forge.