How VSTa boots

From: Andrew Valencia <vandys_at_nospam.org>
Date: Wed Sep 15 1993 - 10:00:14 PDT

This is an overview of the booting process for VSTa. It covers the booting
process from boot.exe through the login: prompt.

1. Load kernel and server images

    VSTa is booted from DOS using a large-model DOS program called boot.exe.
boot.exe takes a single argument which is the kernel image to load. It
opens this file using the usual DOS calls, and reads the image into free
memory just after the end of boot.exe's memory. It also zeroes out the
BSS portion.

    boot.exe now opens boot.lst, and reads in a list of files, one per
line. For each file, boot.exe opens the file and reads its a.out image
into successive memory just after the end of the kernel memory image.
After this process, low memory looks like this:

| DOS | boot.exe | kernel | cons | keybd | wd | dos | ...
+--------------------------------------------------------
   0 ->

2. Build bootstrap 386 32-bit protected mode data structures

    The i386 defines numerous arcane data structures which need to be
present to switch from 16-bit real mode to 32-bit protected mode. These
data structures must remain intact throughout the gyrations needed to
get VSTa running, until VSTa is sufficiently "up" to take over with its
own data structures. If these structures were tacked onto the end of
low memory (from our picture, after "dos"), there would be a danger
that they would be overwritten by VSTa data structures during bootup.
Therefore, these structures are allocated at the top of low memory,
from 640K coming down.

... | Copy() | GDT | TSS16 | TSS32 | Data-L2PTEs | Text-L2PTEs | L1PTEs | Stack
- ------------------------------------------------------------------------------+
                                                                        <- 640K

    "Stack" is a single page of memory used as a stack while switching modes.
The top couple of words contain parameters which DOS passes to the VSTA kernel.
These are the size of the kernel plus all boot servers, size of extended
memory, size of base memory, and the address at which the kernel was loaded.
L1PTEs is the root of the page tables (CR3), and Text and Data PTEs are the
the second level PTEs. Text maps memory 1:1, and Data maps the a.out data
virtual address (4 Mb) onto the data memory for the kernel image loaded
in low memory. GDT, TSS16, and TSS32 are the data structures for describing
the 32-bit text and data segments, as well as the 32-bit task (used to enter
32-bit mode).

    Copy() is some position-independent 16-bit code which is the last
16-bit code executed during bootup of VSTa. The VSTa kernel image was
loaded above boot.exe's memory, but the VSTa kernel expects to run from
a 0 base. Copy() disables interrupts, copies the VSTa kernel down to
physical memory starting at 0, switches into protected mode, and jumps
through the 32-bit TSS to becomes a 32-bit task running in the VSTa
kernel's locore.s at _start.

3. Initial VSTa instructions

    VSTa first pops the four DOS parameters off its stack. It switches
to its own stack, and calls main(). We are now running in C code. main()
will call a number of init routines, discussed below.

    init_machdep() handles the grotty intial setup of memory. It uses the
DOS-passed parameters, and sets up machine-independent descriptions of
the memory available. It also scans the images of the boot servers which
were concatentated onto the end of the kernel image, and builds a machine-
independent description of them. This description will be used soon to
create the initial processes which allow VSTa to boot.

    Finally, init_machdep() sets up its own level 1 and 2 page tables,
and switches to them. At this point, VSTa is now able to manage its
own virtual memory. It calls init_trap() to complete machine-dependent
initialization with the initialization of the interrupt system.

4. Further initialization

    init_trap() creates a GDT (and null LDT, as only the GDT is used).
It sets the PC interrupt controller to a mode compatible with protected
mode, and puts together an IDT (interrupt descriptor table). By default,
each interrupt slot is hooked to a routine which will push the trap ID,
and call the common interrupt code.

    init_trap() then uses a table to override this default action with
calls to more appropriate routines. For instance, the page fault vector
is rewired to call the page fault handler. The system call vector is
hooked to the system call handler.

    Next, init_page() and init_malloc() are called to set up the
hardware-independent parts of the VM system. After these, the general-
purpose memory routines can be used to allocate, free, and map memory.
init_qio() and init_sched() set up the queued I/O facility and the
scheduler.

    init_proc() now takes the list of boot servers found in init_machdep(),
and creates a new process for each server, with its state set to RUN.
After this routine, VSTa has a process for each boot server, with each
server flagged as waiting to run.

    init_msg(), init_swap(), init_wire() all initialize various other
machine-independent parts of the system. start_clock() enables
the PC clock and also enables interrupts. From here, the clock will
tick and system time will advance. main() finishes by calling swtch(),
which will never return.

5. Running

    swtch() enters the scheduler. The current "process" (which isn't
really, but it's close enough for the scheduler) releases the CPU,
and swtch() hunts for a new process to run. It finds the first of
the boot servers, switches to its context, and "returns" to user mode
(which will be at the first instruction in the a.out). VSTa is now
"up", and all further system activity will be handled by VSTa through
the usual services of memory management, message passing, scheduling,
and so forth.

                                        Regards,
                                        Andy
Received on Wed Sep 15 10:31:23 1993

This archive was generated by hypermail 2.1.8 : Wed Sep 21 2005 - 19:37:12 PDT