Skip to content

Instantly share code, notes, and snippets.

@leafstorm
Created August 30, 2013 15:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save leafstorm/6391252 to your computer and use it in GitHub Desktop.
Save leafstorm/6391252 to your computer and use it in GitHub Desktop.
Ideas for the Brickyard PC environment.

Brickyard

Brickyard is a design for a simple (simulated) personal computer environment, to be used for OS development. It presents a highly simplified and idealized set of hardware (display, input, storage) to the CPU, so that people interested in OS development can focus on writing critical OS features like scheduling, interrupt handling, and memory management, without having to wade through the complexities of modern (or classical) hardware.

The CPU

Brickyard will use a MIPS32 CPU. This means that it will have to be emulated on almost all target platforms. However, even if ARM or x86 were selected, emulation would still be necessary on the "other" platform, and even on the host platform, highly platform- and OS-specific code would be necessary to allow for the needed degree of virtualization. Given that emulation is almost a requirement, MIPS was selected because it is easier to write emulators for than ARM or x86, but it still has a full GNU toolchain available.

A 32-bit CPU is used so that emulation is feasible on 32-bit platforms like most ARM devices (including the Raspberry Pi), and because the light, "hobbyist" applications of Brickyard do not require the full 64-bit address space. In addition, the memory map and assembly language are simpler on 32-bit MIPS than on 64-bit.

The CPU will have an intact write-back cache and TLB, whose precise sizes are implementation-defined, as well as a floating-point unit. Supervisor mode will be left in so that people can experiment with it (since that's the whole point of Brickyard).

Decisions to be Made

  • The MIPS32 standard allows cache aliases to occur. Should Brickyard require the detection and prevention of cache aliases, to remove the necessity of working around it in software? What about cache consistency for DMA?

Peripherals

The following hardware should definitely be part of the design (though implementation might be optional):

Console: A teletype console, assumed to be connected over a serial port. This can be used as a basic I/O device in the early stages of OS development (and Brickyard implementation). Other serial ports could also be provided, for multiple emulated consoles or modems.

Clock: It should provide access to the current time of day, with at least microsecond precision. Also, a monotonic "time since boot" counter, and a timer interrupt.

Disk drives: Floppy disks (or some sort of removable storage) and hard disks should both be simulated.

Video controller: Ideally, this would at least have a character-cell mode and a framebuffer mode. A sprite-processing mode like that found in video game consoles could also be useful, but would probably be an optional feature.

Keyboard controller: There should be a standard set of scan codes, so that differences in people's keyboard setups don't manifest to Brickyard. There probably shouldn't be a lot of extra interpretation (like actually handling Caps Lock) though.

Mouse controller: This should work with mice, trackballs, trackpads, weird ThinkPad nub pointers, and all sorts of other pointing devices.

Game controller controller: For making games! This should normalize inputs like the keyboard and mouse controllers, and support at least four players. (A similar priority to the sprite-processing mode of the video controller.)

GPIO: If Brickyard is ever ported to Raspberry Pi, access to the GPIO pins is practically mandatory.

Magical host interface: Provides access to the host OS's filesystem and TCP/IP stack. Both of these are useful for application development, but require a lot of grunt work to implement. (Both should be disablable and sandboxable.)

Memory Map

The 4 GiB space of physical memory addresses is split into three sections:

  • 0x0000 0000 to 0xFFFF FFFF (256 MiB) is standard RAM. There may be 64 MiB, 128 MiB, or 256 MiB present.
  • 0x1000 0000 to 0x1FFF FFFF (256 MiB) is peripheral space, which shouldn't contain any RAM that doesn't belong to a peripheral.
  • 0x2000 0000 to 0xFFFF FFFF (3.5 GiB) is high RAM. This probably won't exist, but if you feel the need to allocate more RAM to your system, you can do that here.

Both standard RAM and the peripheral space fit in the MIPS kseg1 and kseg2, so the kernel can access all of the RAM and peripherals without needing to bother with the TLB.

Boot ROM

The system will include a certain amount of boot ROM, ranging from 0x1FC0 0000 to 0x1DFF FFFF (2 MiB). It contains some basic MIPS exception handlers, but they just print a message to the console and stop the system: it's really only intended for use during system startup.

The startup handler in the boot ROM:

  • Initializes the status register.
  • Performs some basic sanity checks on the hardware.
  • Initializes the cache and the TLB.
  • Probes for CPU configuration like the cache and TLB size, and writes it to memory somewhere.
  • Initializes the disk drive controller and console controller.
  • Searches the disk drives for a bootable OS, copies it into memory, and starts running.

The boot ROM intentionally does not contain functions for OSes and user programs to use, like the classical BIOS of the IBM PC. Ideally, the hardware presented should be at a sufficiently high level of abstraction that a BIOS isn't necessary just to talk to it. And for things which aren't really the hardware's job -- like keyboard input decoding and console management -- we have the benefits of plenty of RAM and a toolchain outside the system, so they can be provided as linkable C or assembly modules (a standard set of which may be maintained with the Brickyard documentation).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment