Back to home page

Quest Cross Reference

 
 

    


0001 Assorted notes about Quest:
0002 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
0003 
0004 Boot:
0005 
0006 Multiboot-compliant bootloader.  Sets up the first 4 entries in GDT
0007 the usual way: kernel code, kernel data, user code, user data.
0008 Enables 4MB pages and uses that to map the first 4MB, and APICs @ 0xFEC.
0009 Writes entry for the kernel page-table at index 0xFFC in the page global dir.
0010 
0011 Calls into init.c: init().  Uses the Multiboot structure to setup the
0012 free-frame bitmap.  Uses the "loadable module" Multiboot specification
0013 to load additional functionality.  Initializes SMP, sound, ATA, filesystem.
0014 Loads a dummy TSS and far jumps into the shell module.  This enables
0015 interrupts and switches the system to usermode, after which the normal
0016 scheduling takes over.
0017 
0018 
0019 
0020 SMP:
0021 
0022 smp_init() tries to early-initialize ACPICA the Intel reference
0023 implementation of ACPI.  If that fails it probes for the Intel
0024 Multiprocessor Specification table and parses it. 
0025 
0026 Either way it is looking for info on the configuration of the system.
0027 Number of enabled processors, buses, interrupt routing, etc.
0028 
0029 Then it boots the Application Processors (AP) with the code in
0030 boot-smp.S and they enter ap_init() in smp.c.  They re-use the
0031 Bootstrap Processor's (BSP) GDT and IDT.  Local APICs are configured
0032 so that each processor has a logical destination address mask 0x1,
0033 0x2, 0x4, up to 0x80 (so MAX_CPUS = 8 for now).
0034 
0035 smp_secondary_init() will disable the 8529A and enable the IO-APIC but
0036 program it with no routing.  Later drivers will add routing for IRQs
0037 they use.  Also it will complete the ACPICA init sequence if possible.
0038 
0039 If there is no IO-APIC then mp_ISA_mode will be enabled and drivers
0040 will be expected to utilize the 8259A PIC instead.
0041 
0042 This is not ideal, the choice of vectors should use more priority
0043 levels.  CPUs assign priority to an interrupt vector based on the most
0044 significant 4-bits, so vector 0xE0 and 0xE4 have the same priority.  A
0045 website suggests mapping two IRQs per priority level.
0046 
0047 Each CPU can set the Task Priority Register (TPR) in its LAPIC to mask
0048 out interrupts.  Right now the BSP has TPR=0x0 and the APs have
0049 TPR=0x20.  So the BSP is receiving pretty much every IRQ exclusively.
0050 
0051 End-of-Interrupt (EOI) is now in a function send_eoi() which either
0052 prods the 8259A or the LAPIC depending on whether MP is enabled.
0053 
0054 The IO-APIC and Local APIC registers are memory-mapped by default to
0055 0xFEC00000 and 0xFEE00000 so these regions need to be identity mapped
0056 in the page directory.  This is accomplished with a 4MB page @ entry
0057 0xFEC.  Whenever new page directories are created this needs to be
0058 setup along with the kernel page tables.  I modified exec and
0059 load_module accordingly.
0060 
0061 The Intel MP tables (or the ACPI tables) are supposed to specify the
0062 configuration of the IO-APIC(s) and this needs to be handled properly.
0063 This is handled to some extent now, though not well tested.  It tries
0064 to understand and obey any interrupt routing entries present.  For
0065 example, IRQ0 timer is often re-routed to Global System Interrupt 2,
0066 and this is handled.
0067 
0068 There's a rudimentary implementation of spinlocks in spinlock.h using
0069 atomic operations defined in atomic.h.
0070 
0071 The global kernel lock and task switches across SMP are dealt with:
0072 
0073 Assertion: whenever a process is put back on the runqueue, it has
0074 first grabbed the kernel lock.  Therefore, whenever it wakes up again,
0075 it should release the kernel lock.  Effectively, while one process
0076 grabs the lock, then a task switch happens, the new task will release
0077 the lock.
0078 
0079 I've adjusted _fork so that when it creates a new TSS, it starts off
0080 in kernel land instead of jumping directly to userspace.  It can test
0081 whether the child is the current task, in which case it just unlocks
0082 the kernel and then proceeds to IRET to userspace.
0083 
0084 Now, whenever the kernel invokes schedule() to sleep, whatever wakes
0085 up will unlock the kernel.
0086 
0087 There is only a single dummy TSS and its only purpose is to be a
0088 scratch pad when there is no current task and we need to switch to a
0089 task.  It is considered a resource protected by the kernel lock
0090 because only one CPU can use it at a time.
0091 
0092 Each CPU gets its own dedicated IDLE task.  Since it is now possible
0093 for a CPU to have nothing to do.  Idle task is a kernelspace process
0094 that sets interrupts enabled and loops on the HLT instruction.  It is
0095 kernelspace because when it is first started it needs to unlock the
0096 kernel.
0097 
0098 Drivers:
0099 
0100 The keyboard driver is now interrupt driven.  I have separated keymap
0101 translation from keyboard event handling.  The keyboard IRQ handler
0102 queues a special struct (on a circular buffer) which captures the
0103 current state of the keyboard.  This is pulled off the buffer and
0104 translated into a char whenever getchar is called.
0105 
0106 ATA drivers have been moved into their own file.  These are PIO and
0107 IRQ driven.  There is support for probing attached devices, and also
0108 for reading from ATAPI drives.
0109 
0110 Filesystems:
0111 
0112 Supports rudimentary file operations: dir and read.  dir acts like
0113 open but there is only one process-global file handle variable.  The
0114 reason for this is because ext2 support is ripped from GRUB and this
0115 is what they do.
0116 
0117 The ISO9660 fs support is enough to support these operations.  Luckily
0118 this format is generally pretty simple because file contents are
0119 stored in consecutive sectors.
0120 
0121 There is a simple VFS stub which switches FS based on probing of boot
0122 drive.
0123 
0124 
0125 
0126