The TUNES i386 Subproject
NOTE: existing code and corresponding technical comments lie in directory src/LLL/i386 of the source distribution.
Implement the Tunes project on "industry standard" computers equipped with an Intel 80386 or compatible 32-bit CPU.
The implementation should be faithful to the LLL specifications, and device drivers should be provided to allow basic memory management, human interaction, and access to mass storage.
Use of the MMU
Run most code in ring 0 to reduce all the I/O and ring switching overhead. This is safe because we use safe code. If some features of paging (write-protect) in code 0 is not possible (386 computers), use ring 1 with IO rights (IOPL).
Use segments only as a way to achieve quick pointer arithmetics for large objects worth the descriptor table mangling and all the overhead resulting from different memory management.
Emulation boxes and other unsecure programs of course use ring 3.
Small programs (most of them) don't need a full personal address space and share their MMU pagetables with their calling program. If a program grows large, migration can still make a full task for it.
Programs that we know will be large and little interacting with other (or not be trusted) will be given an address space for them alone. There must be some way to share code whatsoever. The first thing an experienced user may want to do is create a task for him alone.
paging can be used to use wired service address valid both in PL0 as well as other levels.
DOS emulation
Run DOS in real low memory, even if using vm86 mode, so DOS programs can use DMA and such. Perhaps even run in true real-mode.
Here are a few trick to free as much DOS memory as possible:
- TUNES installs as high as possible in real and extended memory
- We can intercept all interrupts, with the real-mode IDT being in extended memory; real-mode interrupts jump to the same physical code portion that just jumps into protected mode for PM interrupt management; interrupts are differentiated by the code segment with which the code portion was reached: 5F21 for int 21, 5F33 for int 33, etc: the same few bytes need not be replicated 256 times.
- See LLL issues.
- Having some efficient code, but limit hardware dependence to the least possible.
- Supporting all the various kinds of existing hardware on PC-compatible stuff.
- Perhaps supporting DOS running below TUNES.
- We need some standard object encoding for our modules. See GOOSE subproject.
Only the very first steps of the boot sequence have already been implemented, and the initial kernel is still to be completed.
Here are the first steps of the boot sequence:
- The ROM-based BIOS, or some boot multiplexer (e.g. LILO the LInux LOader, or OS/2's boot manager) loads our 512-byte long boot sector at 0:7C00, and jumps into it.
- The boot sector just chains into the ~2K boot loader that it read from disk according to information written in the boot sector during the TUNES installation. It also installs a BIOS extension to allow reading floppies that were overformatted (>1.44MB), using fdformat, or Linux utilities.
- The boot loader tests the CPU type, the amount of available memory, and retrieves a small kernel from disk, and jumps into it with proper parameters.
- Alternatively, LILO or LOADLIN (from DOS prompt) loaded the kernel, that was faking a Linux kernel, and jumped into the boot loader. The boot loader is able to detect it and will load the small kernel from memory rather than disk; it will even recognize command-line parameters given by such a loader.
- A simple initial kernel, as loaded by the loader, is run. It manages:
- real-mode<->protected-mode switching
- A 32-bit FORTH kernel
- hooks for TUNES to intercept hardware interrupts
- calling the BIOS from protected mode
- A simple console video output module using the BIOS
- A simple console keyboard input module using the BIOS
- A simple disk I/O module using the BIOS
- real-memory/extended-memory dynamic linking
- loading of the remaining of TUNES according to modules that were concatenated to the initial kernel.
- When the initial kernel finished installing itself, it consecutively installs all the modules that were concatenated to it during system installation, and loaded after it by the boot loader. The last one will presumably load ever more modules until all wanted modules are installed, and the system is ready to begin or resume actual work. Some of these modules will be i386 specific; others may be architecture-independent.
Here is a list of implemented i386-specific modules:
- Booting
- The boot record and boot loader, with corresponding installation tools.
- A very simple protected mode program that makes segment, paging, tasking, and interrupt management, and transmode (real/protected) calling just possible. reflects interrupts to real-mode and allows to call real-mode routines or interrupts.
Here is a list of i386-specific modules to implement:
- Memory management
- An interface to the i386 MMU
- An interface to the i386 segmenting
- Interrupt sharing manager
- i386 specializations of more generic modules
- An i386-optimized instance of the generational garbage collector that checkpoints objects for persistency.
- support for chunks i386 executable binary.
- full support for GOOSE modules.
- Raw drivers for console interface
- A simple parametrizable raw keyboard manager
- Some keyboard cooking to obtain national keyboard mapping
- A simple interface to text-mode video
- I/O drivers:
- Generic and specific disk drivers, that may be using the BIOS, or directly talking to the adapter, using a SCSI interface, etc. Perhaps stealing it from Linux.
- Drivers for serial ports
- Drivers for parallel ports
- Drivers for ethernet adapters
- Sound drivers
- Graphic card drivers
See the OS page of the Wiki, particularly the Code section.
To Do
- Use Flux as a BIOS replacement that gives us Linux and BSD drivers.
- set up standard memory segmenting and mapping.
- set up GC implementation.
- set up calling conventions.
- Write the i386 stuff as a Linux kernel module?