no /* */ comments
This commit is contained in:
parent
9e9bcaf143
commit
f552738889
22 changed files with 347 additions and 371 deletions
57
bootmain.c
57
bootmain.c
|
@ -1,34 +1,31 @@
|
|||
#include "types.h"
|
||||
#include "elf.h"
|
||||
#include "x86.h"
|
||||
|
||||
/**********************************************************************
|
||||
* This a dirt simple boot loader, whose sole job is to boot
|
||||
* an elf kernel image from the first IDE hard disk.
|
||||
*
|
||||
* DISK LAYOUT
|
||||
* * This program(boot.S and main.c) is the bootloader. It should
|
||||
* be stored in the first sector of the disk.
|
||||
*
|
||||
* * The 2nd sector onward holds the kernel image.
|
||||
*
|
||||
* * The kernel image must be in ELF format.
|
||||
*
|
||||
* BOOT UP STEPS
|
||||
* * when the CPU boots it loads the BIOS into memory and executes it
|
||||
*
|
||||
* * the BIOS intializes devices, sets of the interrupt routines, and
|
||||
* reads the first sector of the boot device(e.g., hard-drive)
|
||||
* into memory and jumps to it.
|
||||
*
|
||||
* * Assuming this boot loader is stored in the first sector of the
|
||||
* hard-drive, this code takes over...
|
||||
*
|
||||
* * control starts in bootloader.S -- which sets up protected mode,
|
||||
* and a stack so C code then run, then calls cmain()
|
||||
*
|
||||
* * cmain() in this file takes over, reads in the kernel and jumps to it.
|
||||
**********************************************************************/
|
||||
// This a dirt simple boot loader, whose sole job is to boot
|
||||
// an elf kernel image from the first IDE hard disk.
|
||||
//
|
||||
// DISK LAYOUT
|
||||
// * This program(boot.S and main.c) is the bootloader. It should
|
||||
// be stored in the first sector of the disk.
|
||||
//
|
||||
// * The 2nd sector onward holds the kernel image.
|
||||
//
|
||||
// * The kernel image must be in ELF format.
|
||||
//
|
||||
// BOOT UP STEPS
|
||||
// * when the CPU boots it loads the BIOS into memory and executes it
|
||||
//
|
||||
// * the BIOS intializes devices, sets of the interrupt routines, and
|
||||
// reads the first sector of the boot device(e.g., hard-drive)
|
||||
// into memory and jumps to it.
|
||||
//
|
||||
// * Assuming this boot loader is stored in the first sector of the
|
||||
// hard-drive, this code takes over...
|
||||
//
|
||||
// * control starts in bootloader.S -- which sets up protected mode,
|
||||
// and a stack so C code then run, then calls cmain()
|
||||
//
|
||||
// * cmain() in this file takes over, reads in the kernel and jumps to it.
|
||||
|
||||
#define SECTSIZE 512
|
||||
#define ELFHDR ((struct elfhdr*) 0x10000) // scratch space
|
||||
|
@ -62,7 +59,7 @@ bad:
|
|||
outw(0x8A00, 0x8A00);
|
||||
outw(0x8A00, 0x8E00);
|
||||
while(1)
|
||||
/* do nothing */;
|
||||
;
|
||||
}
|
||||
|
||||
// Read 'count' bytes at 'offset' from kernel into virtual address 'va'.
|
||||
|
@ -96,7 +93,7 @@ waitdisk(void)
|
|||
{
|
||||
// wait for disk reaady
|
||||
while((inb(0x1F7) & 0xC0) != 0x40)
|
||||
/* do nothing */;
|
||||
;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
71
console.c
71
console.c
|
@ -10,11 +10,9 @@ struct spinlock console_lock;
|
|||
int panicked = 0;
|
||||
int use_console_lock = 0;
|
||||
|
||||
/*
|
||||
* copy console output to parallel port, which you can tell
|
||||
* .bochsrc to copy to the stdout:
|
||||
* parport1: enabled=1, file="/dev/stdout"
|
||||
*/
|
||||
// Copy console output to parallel port, which you can tell
|
||||
// .bochsrc to copy to the stdout:
|
||||
// parport1: enabled=1, file="/dev/stdout"
|
||||
static void
|
||||
lpt_putc(int c)
|
||||
{
|
||||
|
@ -97,9 +95,7 @@ printint(int xx, int base, int sgn)
|
|||
cons_putc(buf[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* print to the console. only understands %d, %x, %p, %s.
|
||||
*/
|
||||
// Print to the console. only understands %d, %x, %p, %s.
|
||||
void
|
||||
cprintf(char *fmt, ...)
|
||||
{
|
||||
|
@ -182,10 +178,10 @@ console_write(int minor, char *buf, int n)
|
|||
}
|
||||
|
||||
|
||||
/* This is i8042reg.h + kbdreg.h from NetBSD. */
|
||||
#define KBSTATP 0x64 /* kbd controller status port(I) */
|
||||
#define KBS_DIB 0x01 /* kbd data in buffer */
|
||||
#define KBDATAP 0x60 /* kbd data port(I) */
|
||||
// This is i8042reg.h + kbdreg.h from NetBSD.
|
||||
#define KBSTATP 0x64 // kbd controller status port(I)
|
||||
#define KBS_DIB 0x01 // kbd data in buffer
|
||||
#define KBDATAP 0x60 // kbd data port(I)
|
||||
|
||||
#define NO 0
|
||||
|
||||
|
@ -241,12 +237,18 @@ static uchar normalmap[256] =
|
|||
NO, NO, NO, NO, NO, NO, NO, '7', // 0x40
|
||||
'8', '9', '-', '4', '5', '6', '+', '1',
|
||||
'2', '3', '0', '.', NO, NO, NO, NO, // 0x50
|
||||
[0x97] KEY_HOME, [0x9C] '\n' /*KP_Enter*/,
|
||||
[0xB5] '/' /*KP_Div*/, [0xC8] KEY_UP,
|
||||
[0xC9] KEY_PGUP, [0xCB] KEY_LF,
|
||||
[0xCD] KEY_RT, [0xCF] KEY_END,
|
||||
[0xD0] KEY_DN, [0xD1] KEY_PGDN,
|
||||
[0xD2] KEY_INS, [0xD3] KEY_DEL
|
||||
[0x97] KEY_HOME,
|
||||
[0x9C] '\n', // KP_Enter
|
||||
[0xB5] '/', // KP_Div
|
||||
[0xC8] KEY_UP,
|
||||
[0xC9] KEY_PGUP,
|
||||
[0xCB] KEY_LF,
|
||||
[0xCD] KEY_RT,
|
||||
[0xCF] KEY_END,
|
||||
[0xD0] KEY_DN,
|
||||
[0xD1] KEY_PGDN,
|
||||
[0xD2] KEY_INS,
|
||||
[0xD3] KEY_DEL
|
||||
};
|
||||
|
||||
static uchar shiftmap[256] =
|
||||
|
@ -262,12 +264,18 @@ static uchar shiftmap[256] =
|
|||
NO, NO, NO, NO, NO, NO, NO, '7', // 0x40
|
||||
'8', '9', '-', '4', '5', '6', '+', '1',
|
||||
'2', '3', '0', '.', NO, NO, NO, NO, // 0x50
|
||||
[0x97] KEY_HOME, [0x9C] '\n' /*KP_Enter*/,
|
||||
[0xB5] '/' /*KP_Div*/, [0xC8] KEY_UP,
|
||||
[0xC9] KEY_PGUP, [0xCB] KEY_LF,
|
||||
[0xCD] KEY_RT, [0xCF] KEY_END,
|
||||
[0xD0] KEY_DN, [0xD1] KEY_PGDN,
|
||||
[0xD2] KEY_INS, [0xD3] KEY_DEL
|
||||
[0x97] KEY_HOME,
|
||||
[0x9C] '\n', // KP_Enter
|
||||
[0xB5] '/', // KP_Div
|
||||
[0xC8] KEY_UP,
|
||||
[0xC9] KEY_PGUP,
|
||||
[0xCB] KEY_LF,
|
||||
[0xCD] KEY_RT,
|
||||
[0xCF] KEY_END,
|
||||
[0xD0] KEY_DN,
|
||||
[0xD1] KEY_PGDN,
|
||||
[0xD2] KEY_INS,
|
||||
[0xD3] KEY_DEL
|
||||
};
|
||||
|
||||
#define C(x) (x - '@')
|
||||
|
@ -282,11 +290,16 @@ static uchar ctlmap[256] =
|
|||
NO, NO, NO, C('\\'), C('Z'), C('X'), C('C'), C('V'),
|
||||
C('B'), C('N'), C('M'), NO, NO, C('/'), NO, NO,
|
||||
[0x97] KEY_HOME,
|
||||
[0xB5] C('/'), [0xC8] KEY_UP,
|
||||
[0xC9] KEY_PGUP, [0xCB] KEY_LF,
|
||||
[0xCD] KEY_RT, [0xCF] KEY_END,
|
||||
[0xD0] KEY_DN, [0xD1] KEY_PGDN,
|
||||
[0xD2] KEY_INS, [0xD3] KEY_DEL
|
||||
[0xB5] C('/'), // KP_Div
|
||||
[0xC8] KEY_UP,
|
||||
[0xC9] KEY_PGUP,
|
||||
[0xCB] KEY_LF,
|
||||
[0xCD] KEY_RT,
|
||||
[0xCF] KEY_END,
|
||||
[0xD0] KEY_DN,
|
||||
[0xD1] KEY_PGDN,
|
||||
[0xD2] KEY_INS,
|
||||
[0xD3] KEY_DEL
|
||||
};
|
||||
|
||||
static uchar *charcode[4] = {
|
||||
|
|
2
elf.h
2
elf.h
|
@ -2,7 +2,7 @@
|
|||
// format of an ELF executable file
|
||||
//
|
||||
|
||||
#define ELF_MAGIC 0x464C457FU /* "\x7FELF" in little endian */
|
||||
#define ELF_MAGIC 0x464C457FU // "\x7FELF" in little endian
|
||||
|
||||
struct elfhdr {
|
||||
uint magic; // must equal ELF_MAGIC
|
||||
|
|
17
fd.c
17
fd.c
|
@ -22,9 +22,7 @@ fd_init(void)
|
|||
initlock(&fd_table_lock, "fd_table");
|
||||
}
|
||||
|
||||
/*
|
||||
* allocate a file descriptor number for curproc.
|
||||
*/
|
||||
// Allocate a file descriptor number for curproc.
|
||||
int
|
||||
fd_ualloc(void)
|
||||
{
|
||||
|
@ -36,9 +34,7 @@ fd_ualloc(void)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* allocate a file descriptor structure
|
||||
*/
|
||||
// Allocate a file descriptor structure
|
||||
struct fd*
|
||||
fd_alloc(void)
|
||||
{
|
||||
|
@ -57,9 +53,8 @@ fd_alloc(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* addr is a kernel address, pointing into some process's p->mem.
|
||||
*/
|
||||
// Write to file descriptor;
|
||||
// addr is a kernel address, pointing into some process's p->mem.
|
||||
int
|
||||
fd_write(struct fd *fd, char *addr, int n)
|
||||
{
|
||||
|
@ -81,6 +76,7 @@ fd_write(struct fd *fd, char *addr, int n)
|
|||
}
|
||||
}
|
||||
|
||||
// Read from file descriptor.
|
||||
int
|
||||
fd_read(struct fd *fd, char *addr, int n)
|
||||
{
|
||||
|
@ -101,6 +97,7 @@ fd_read(struct fd *fd, char *addr, int n)
|
|||
}
|
||||
}
|
||||
|
||||
// Close file descriptor.
|
||||
void
|
||||
fd_close(struct fd *fd)
|
||||
{
|
||||
|
@ -128,6 +125,7 @@ fd_close(struct fd *fd)
|
|||
}
|
||||
}
|
||||
|
||||
// Get metadata about file descriptor.
|
||||
int
|
||||
fd_stat(struct fd *fd, struct stat *st)
|
||||
{
|
||||
|
@ -140,6 +138,7 @@ fd_stat(struct fd *fd, struct stat *st)
|
|||
return -1;
|
||||
}
|
||||
|
||||
// Increment file descriptor reference count.
|
||||
void
|
||||
fd_incref(struct fd *fd)
|
||||
{
|
||||
|
|
14
fs.c
14
fs.c
|
@ -24,9 +24,7 @@ iinit(void)
|
|||
initlock(&inode_table_lock, "inode_table");
|
||||
}
|
||||
|
||||
/*
|
||||
* allocate a disk block
|
||||
*/
|
||||
// Allocate a disk block.
|
||||
static uint
|
||||
balloc(uint dev)
|
||||
{
|
||||
|
@ -90,11 +88,11 @@ bfree(int dev, uint b)
|
|||
brelse(bp);
|
||||
}
|
||||
|
||||
/*
|
||||
* fetch an inode, from the in-core table if it's already
|
||||
* in use, otherwise read from the disk.
|
||||
* returns an inode with busy set and incremented reference count.
|
||||
*/
|
||||
// Find the inode with number inum on device dev
|
||||
// and return an in-memory copy. Loads the inode
|
||||
// from disk into the in-core table if necessary.
|
||||
// The returned inode has busy set and has its ref count incremented.
|
||||
// Caller must iput the return value when done with it.
|
||||
struct inode*
|
||||
iget(uint dev, uint inum)
|
||||
{
|
||||
|
|
8
ide.c
8
ide.c
|
@ -1,6 +1,4 @@
|
|||
/*
|
||||
* Simple PIO-based (non-DMA) IDE driver code.
|
||||
*/
|
||||
// Simple PIO-based (non-DMA) IDE driver code.
|
||||
|
||||
#include "types.h"
|
||||
#include "param.h"
|
||||
|
@ -38,7 +36,7 @@ ide_wait_ready(int check_error)
|
|||
int r;
|
||||
|
||||
while(((r = inb(0x1F7)) & (IDE_BSY|IDE_DRDY)) != IDE_DRDY)
|
||||
/* do nothing */;
|
||||
;
|
||||
|
||||
if(check_error && (r & (IDE_DF|IDE_ERR)) != 0)
|
||||
return -1;
|
||||
|
@ -75,7 +73,7 @@ ide_probe_disk1(void)
|
|||
|
||||
// check for Device 1 to be ready for a while
|
||||
for(x = 0; x < 1000 && (r = inb(0x1F7)) == 0; x++)
|
||||
/* do nothing */;
|
||||
;
|
||||
|
||||
// switch back to Device 0
|
||||
outb(0x1F6, 0xE0 | (0<<4));
|
||||
|
|
2
init.c
2
init.c
|
@ -4,7 +4,7 @@
|
|||
#include "fs.h"
|
||||
#include "fcntl.h"
|
||||
|
||||
/* The initial user-level program */
|
||||
// init: The initial user-level program
|
||||
|
||||
char *sh_args[] = { "sh", 0 };
|
||||
|
||||
|
|
68
ioapic.h
68
ioapic.h
|
@ -1,7 +1,7 @@
|
|||
#define IO_APIC_BASE 0xFEC00000 /* default physical locations of an IO APIC */
|
||||
#define IOAPIC_WINDOW 0x10 /* window register offset */
|
||||
#define IO_APIC_BASE 0xFEC00000 // default physical locations of an IO APIC
|
||||
#define IOAPIC_WINDOW 0x10 // window register offset
|
||||
|
||||
/* constants relating to APIC ID registers */
|
||||
// Constants relating to APIC ID registers
|
||||
#define APIC_ID_MASK 0xff000000
|
||||
#define APIC_ID_SHIFT 24
|
||||
#define APIC_ID_CLUSTER 0xf0
|
||||
|
@ -10,12 +10,12 @@
|
|||
#define APIC_MAX_INTRACLUSTER_ID 3
|
||||
#define APIC_ID_CLUSTER_SHIFT 4
|
||||
|
||||
/* fields in VER */
|
||||
// Fields in VER
|
||||
#define APIC_VER_VERSION 0x000000ff
|
||||
#define APIC_VER_MAXLVT 0x00ff0000
|
||||
#define MAXLVTSHIFT 16
|
||||
|
||||
/* Indexes into IO APIC */
|
||||
// Indexes into IO APIC
|
||||
#define IOAPIC_ID 0x00
|
||||
#define IOAPIC_VER 0x01
|
||||
#define IOAPIC_ARB 0x02
|
||||
|
@ -45,46 +45,44 @@
|
|||
#define IOAPIC_REDTBL22 (IOAPIC_REDTBL+0x2c)
|
||||
#define IOAPIC_REDTBL23 (IOAPIC_REDTBL+0x2e)
|
||||
|
||||
/*
|
||||
* fields in the IO APIC's redirection table entries
|
||||
*/
|
||||
#define IOART_DEST APIC_ID_MASK /* broadcast addr: all APICs */
|
||||
// Fields in the IO APIC's redirection table entries
|
||||
#define IOART_DEST APIC_ID_MASK // broadcast addr: all APICs
|
||||
|
||||
#define IOART_RESV 0x00fe0000 /* reserved */
|
||||
#define IOART_RESV 0x00fe0000 // reserved
|
||||
|
||||
#define IOART_INTMASK 0x00010000 /* R/W: INTerrupt mask */
|
||||
#define IOART_INTMCLR 0x00000000 /* clear, allow INTs */
|
||||
#define IOART_INTMSET 0x00010000 /* set, inhibit INTs */
|
||||
#define IOART_INTMASK 0x00010000 // R/W: INTerrupt mask
|
||||
#define IOART_INTMCLR 0x00000000 // clear, allow INTs
|
||||
#define IOART_INTMSET 0x00010000 // set, inhibit INTs
|
||||
|
||||
#define IOART_TRGRMOD 0x00008000 /* R/W: trigger mode */
|
||||
#define IOART_TRGREDG 0x00000000 /* edge */
|
||||
#define IOART_TRGRLVL 0x00008000 /* level */
|
||||
#define IOART_TRGRMOD 0x00008000 // R/W: trigger mode
|
||||
#define IOART_TRGREDG 0x00000000 // edge
|
||||
#define IOART_TRGRLVL 0x00008000 // level
|
||||
|
||||
#define IOART_REM_IRR 0x00004000 /* RO: remote IRR */
|
||||
#define IOART_REM_IRR 0x00004000 // RO: remote IRR
|
||||
|
||||
#define IOART_INTPOL 0x00002000 /* R/W: INT input pin polarity */
|
||||
#define IOART_INTAHI 0x00000000 /* active high */
|
||||
#define IOART_INTALO 0x00002000 /* active low */
|
||||
#define IOART_INTPOL 0x00002000 // R/W: INT input pin polarity
|
||||
#define IOART_INTAHI 0x00000000 // active high
|
||||
#define IOART_INTALO 0x00002000 // active low
|
||||
|
||||
#define IOART_DELIVS 0x00001000 /* RO: delivery status */
|
||||
#define IOART_DELIVS 0x00001000 // RO: delivery status
|
||||
|
||||
#define IOART_DESTMOD 0x00000800 /* R/W: destination mode */
|
||||
#define IOART_DESTPHY 0x00000000 /* physical */
|
||||
#define IOART_DESTLOG 0x00000800 /* logical */
|
||||
#define IOART_DESTMOD 0x00000800 // R/W: destination mode
|
||||
#define IOART_DESTPHY 0x00000000 // physical
|
||||
#define IOART_DESTLOG 0x00000800 // logical
|
||||
|
||||
#define IOART_DELMOD 0x00000700 /* R/W: delivery mode */
|
||||
#define IOART_DELFIXED 0x00000000 /* fixed */
|
||||
#define IOART_DELLOPRI 0x00000100 /* lowest priority */
|
||||
#define IOART_DELSMI 0x00000200 /* System Management INT */
|
||||
#define IOART_DELRSV1 0x00000300 /* reserved */
|
||||
#define IOART_DELNMI 0x00000400 /* NMI signal */
|
||||
#define IOART_DELINIT 0x00000500 /* INIT signal */
|
||||
#define IOART_DELRSV2 0x00000600 /* reserved */
|
||||
#define IOART_DELEXINT 0x00000700 /* External INTerrupt */
|
||||
#define IOART_DELMOD 0x00000700 // R/W: delivery mode
|
||||
#define IOART_DELFIXED 0x00000000 // fixed
|
||||
#define IOART_DELLOPRI 0x00000100 // lowest priority
|
||||
#define IOART_DELSMI 0x00000200 // System Management INT
|
||||
#define IOART_DELRSV1 0x00000300 // reserved
|
||||
#define IOART_DELNMI 0x00000400 // NMI signal
|
||||
#define IOART_DELINIT 0x00000500 // INIT signal
|
||||
#define IOART_DELRSV2 0x00000600 // reserved
|
||||
#define IOART_DELEXINT 0x00000700 // External INTerrupt
|
||||
|
||||
#define IOART_INTVEC 0x000000ff /* R/W: INTerrupt vector field */
|
||||
#define IOART_INTVEC 0x000000ff // R/W: INTerrupt vector field
|
||||
|
||||
/* fields in VER */
|
||||
// Fields in VER
|
||||
#define IOART_VER_VERSION 0x000000ff
|
||||
#define IOART_VER_MAXREDIR 0x00ff0000
|
||||
#define MAXREDIRSHIFT 16
|
||||
|
|
31
kalloc.c
31
kalloc.c
|
@ -1,11 +1,9 @@
|
|||
/*
|
||||
* physical memory allocator, intended to be used to allocate
|
||||
* memory for user processes. allocates in 4096-byte "pages".
|
||||
* free list is sorted and combines adjacent pages into
|
||||
* long runs, to make it easier to allocate big segments.
|
||||
* one reason the page size is 4k is that the x86 segment size
|
||||
* granularity is 4k.
|
||||
*/
|
||||
// Physical memory allocator, intended to allocate
|
||||
// memory for user processes. Allocates in 4096-byte "pages".
|
||||
// Free list is kept sorted and combines adjacent pages into
|
||||
// long runs, to make it easier to allocate big segments.
|
||||
// One reason the page size is 4k is that the x86 segment size
|
||||
// granularity is 4k.
|
||||
|
||||
#include "param.h"
|
||||
#include "types.h"
|
||||
|
@ -23,11 +21,10 @@ struct run {
|
|||
};
|
||||
struct run *freelist;
|
||||
|
||||
/*
|
||||
* initialize free list of physical pages. this code
|
||||
* cheats by just considering the one megabyte of pages
|
||||
* after _end.
|
||||
*/
|
||||
// Initialize free list of physical pages.
|
||||
// This code cheats by just considering one megabyte of
|
||||
// pages after _end. Real systems would determine the
|
||||
// amount of memory available in the system and use it all.
|
||||
void
|
||||
kinit(void)
|
||||
{
|
||||
|
@ -95,11 +92,9 @@ kfree(char *cp, int len)
|
|||
release(&kalloc_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* allocate n bytes of physical memory.
|
||||
* returns a kernel-segment pointer.
|
||||
* returns 0 if there's no run that's big enough.
|
||||
*/
|
||||
// Allocate n bytes of physical memory.
|
||||
// Returns a kernel-segment pointer.
|
||||
// Returns 0 if the memory cannot be allocated.
|
||||
char*
|
||||
kalloc(int n)
|
||||
{
|
||||
|
|
136
lapic.c
136
lapic.c
|
@ -7,84 +7,84 @@
|
|||
#include "mmu.h"
|
||||
#include "proc.h"
|
||||
|
||||
enum { /* Local APIC registers */
|
||||
LAPIC_ID = 0x0020, /* ID */
|
||||
LAPIC_VER = 0x0030, /* Version */
|
||||
LAPIC_TPR = 0x0080, /* Task Priority */
|
||||
LAPIC_APR = 0x0090, /* Arbitration Priority */
|
||||
LAPIC_PPR = 0x00A0, /* Processor Priority */
|
||||
LAPIC_EOI = 0x00B0, /* EOI */
|
||||
LAPIC_LDR = 0x00D0, /* Logical Destination */
|
||||
LAPIC_DFR = 0x00E0, /* Destination Format */
|
||||
LAPIC_SVR = 0x00F0, /* Spurious Interrupt Vector */
|
||||
LAPIC_ISR = 0x0100, /* Interrupt Status (8 registers) */
|
||||
LAPIC_TMR = 0x0180, /* Trigger Mode (8 registers) */
|
||||
LAPIC_IRR = 0x0200, /* Interrupt Request (8 registers) */
|
||||
LAPIC_ESR = 0x0280, /* Error Status */
|
||||
LAPIC_ICRLO = 0x0300, /* Interrupt Command */
|
||||
LAPIC_ICRHI = 0x0310, /* Interrupt Command [63:32] */
|
||||
LAPIC_TIMER = 0x0320, /* Local Vector Table 0 (TIMER) */
|
||||
LAPIC_PCINT = 0x0340, /* Performance Counter LVT */
|
||||
LAPIC_LINT0 = 0x0350, /* Local Vector Table 1 (LINT0) */
|
||||
LAPIC_LINT1 = 0x0360, /* Local Vector Table 2 (LINT1) */
|
||||
LAPIC_ERROR = 0x0370, /* Local Vector Table 3 (ERROR) */
|
||||
LAPIC_TICR = 0x0380, /* Timer Initial Count */
|
||||
LAPIC_TCCR = 0x0390, /* Timer Current Count */
|
||||
LAPIC_TDCR = 0x03E0, /* Timer Divide Configuration */
|
||||
enum { // Local APIC registers
|
||||
LAPIC_ID = 0x0020, // ID
|
||||
LAPIC_VER = 0x0030, // Version
|
||||
LAPIC_TPR = 0x0080, // Task Priority
|
||||
LAPIC_APR = 0x0090, // Arbitration Priority
|
||||
LAPIC_PPR = 0x00A0, // Processor Priority
|
||||
LAPIC_EOI = 0x00B0, // EOI
|
||||
LAPIC_LDR = 0x00D0, // Logical Destination
|
||||
LAPIC_DFR = 0x00E0, // Destination Format
|
||||
LAPIC_SVR = 0x00F0, // Spurious Interrupt Vector
|
||||
LAPIC_ISR = 0x0100, // Interrupt Status (8 registers)
|
||||
LAPIC_TMR = 0x0180, // Trigger Mode (8 registers)
|
||||
LAPIC_IRR = 0x0200, // Interrupt Request (8 registers)
|
||||
LAPIC_ESR = 0x0280, // Error Status
|
||||
LAPIC_ICRLO = 0x0300, // Interrupt Command
|
||||
LAPIC_ICRHI = 0x0310, // Interrupt Command [63:32]
|
||||
LAPIC_TIMER = 0x0320, // Local Vector Table 0 (TIMER)
|
||||
LAPIC_PCINT = 0x0340, // Performance Counter LVT
|
||||
LAPIC_LINT0 = 0x0350, // Local Vector Table 1 (LINT0)
|
||||
LAPIC_LINT1 = 0x0360, // Local Vector Table 2 (LINT1)
|
||||
LAPIC_ERROR = 0x0370, // Local Vector Table 3 (ERROR)
|
||||
LAPIC_TICR = 0x0380, // Timer Initial Count
|
||||
LAPIC_TCCR = 0x0390, // Timer Current Count
|
||||
LAPIC_TDCR = 0x03E0, // Timer Divide Configuration
|
||||
};
|
||||
|
||||
enum { /* LAPIC_SVR */
|
||||
LAPIC_ENABLE = 0x00000100, /* Unit Enable */
|
||||
LAPIC_FOCUS = 0x00000200, /* Focus Processor Checking Disable */
|
||||
enum { // LAPIC_SVR
|
||||
LAPIC_ENABLE = 0x00000100, // Unit Enable
|
||||
LAPIC_FOCUS = 0x00000200, // Focus Processor Checking Disable
|
||||
};
|
||||
|
||||
enum { /* LAPIC_ICRLO */
|
||||
/* [14] IPI Trigger Mode Level (RW) */
|
||||
LAPIC_DEASSERT = 0x00000000, /* Deassert level-sensitive interrupt */
|
||||
LAPIC_ASSERT = 0x00004000, /* Assert level-sensitive interrupt */
|
||||
enum { // LAPIC_ICRLO
|
||||
// [14] IPI Trigger Mode Level (RW)
|
||||
LAPIC_DEASSERT = 0x00000000, // Deassert level-sensitive interrupt
|
||||
LAPIC_ASSERT = 0x00004000, // Assert level-sensitive interrupt
|
||||
|
||||
/* [17:16] Remote Read Status */
|
||||
LAPIC_INVALID = 0x00000000, /* Invalid */
|
||||
LAPIC_WAIT = 0x00010000, /* In-Progress */
|
||||
LAPIC_VALID = 0x00020000, /* Valid */
|
||||
// [17:16] Remote Read Status
|
||||
LAPIC_INVALID = 0x00000000, // Invalid
|
||||
LAPIC_WAIT = 0x00010000, // In-Progress
|
||||
LAPIC_VALID = 0x00020000, // Valid
|
||||
|
||||
/* [19:18] Destination Shorthand */
|
||||
LAPIC_FIELD = 0x00000000, /* No shorthand */
|
||||
LAPIC_SELF = 0x00040000, /* Self is single destination */
|
||||
LAPIC_ALLINC = 0x00080000, /* All including self */
|
||||
LAPIC_ALLEXC = 0x000C0000, /* All Excluding self */
|
||||
// [19:18] Destination Shorthand
|
||||
LAPIC_FIELD = 0x00000000, // No shorthand
|
||||
LAPIC_SELF = 0x00040000, // Self is single destination
|
||||
LAPIC_ALLINC = 0x00080000, // All including self
|
||||
LAPIC_ALLEXC = 0x000C0000, // All Excluding self
|
||||
};
|
||||
|
||||
enum { /* LAPIC_ESR */
|
||||
LAPIC_SENDCS = 0x00000001, /* Send CS Error */
|
||||
LAPIC_RCVCS = 0x00000002, /* Receive CS Error */
|
||||
LAPIC_SENDACCEPT = 0x00000004, /* Send Accept Error */
|
||||
LAPIC_RCVACCEPT = 0x00000008, /* Receive Accept Error */
|
||||
LAPIC_SENDVECTOR = 0x00000020, /* Send Illegal Vector */
|
||||
LAPIC_RCVVECTOR = 0x00000040, /* Receive Illegal Vector */
|
||||
LAPIC_REGISTER = 0x00000080, /* Illegal Register Address */
|
||||
enum { // LAPIC_ESR
|
||||
LAPIC_SENDCS = 0x00000001, // Send CS Error
|
||||
LAPIC_RCVCS = 0x00000002, // Receive CS Error
|
||||
LAPIC_SENDACCEPT = 0x00000004, // Send Accept Error
|
||||
LAPIC_RCVACCEPT = 0x00000008, // Receive Accept Error
|
||||
LAPIC_SENDVECTOR = 0x00000020, // Send Illegal Vector
|
||||
LAPIC_RCVVECTOR = 0x00000040, // Receive Illegal Vector
|
||||
LAPIC_REGISTER = 0x00000080, // Illegal Register Address
|
||||
};
|
||||
|
||||
enum { /* LAPIC_TIMER */
|
||||
/* [17] Timer Mode (RW) */
|
||||
LAPIC_ONESHOT = 0x00000000, /* One-shot */
|
||||
LAPIC_PERIODIC = 0x00020000, /* Periodic */
|
||||
enum { // LAPIC_TIMER
|
||||
// [17] Timer Mode (RW)
|
||||
LAPIC_ONESHOT = 0x00000000, // One-shot
|
||||
LAPIC_PERIODIC = 0x00020000, // Periodic
|
||||
|
||||
/* [19:18] Timer Base (RW) */
|
||||
LAPIC_CLKIN = 0x00000000, /* use CLKIN as input */
|
||||
LAPIC_TMBASE = 0x00040000, /* use TMBASE */
|
||||
LAPIC_DIVIDER = 0x00080000, /* use output of the divider */
|
||||
// [19:18] Timer Base (RW)
|
||||
LAPIC_CLKIN = 0x00000000, // use CLKIN as input
|
||||
LAPIC_TMBASE = 0x00040000, // use TMBASE
|
||||
LAPIC_DIVIDER = 0x00080000, // use output of the divider
|
||||
};
|
||||
|
||||
enum { /* LAPIC_TDCR */
|
||||
LAPIC_X2 = 0x00000000, /* divide by 2 */
|
||||
LAPIC_X4 = 0x00000001, /* divide by 4 */
|
||||
LAPIC_X8 = 0x00000002, /* divide by 8 */
|
||||
LAPIC_X16 = 0x00000003, /* divide by 16 */
|
||||
LAPIC_X32 = 0x00000008, /* divide by 32 */
|
||||
LAPIC_X64 = 0x00000009, /* divide by 64 */
|
||||
LAPIC_X128 = 0x0000000A, /* divide by 128 */
|
||||
LAPIC_X1 = 0x0000000B, /* divide by 1 */
|
||||
enum { // LAPIC_TDCR
|
||||
LAPIC_X2 = 0x00000000, // divide by 2
|
||||
LAPIC_X4 = 0x00000001, // divide by 4
|
||||
LAPIC_X8 = 0x00000002, // divide by 8
|
||||
LAPIC_X16 = 0x00000003, // divide by 16
|
||||
LAPIC_X32 = 0x00000008, // divide by 32
|
||||
LAPIC_X64 = 0x00000009, // divide by 64
|
||||
LAPIC_X128 = 0x0000000A, // divide by 128
|
||||
LAPIC_X1 = 0x0000000B, // divide by 1
|
||||
};
|
||||
|
||||
uint *lapicaddr;
|
||||
|
@ -128,7 +128,7 @@ lapic_init(int c)
|
|||
lapic_write(LAPIC_TPR, 0xFF); // no interrupts for now
|
||||
lapic_write(LAPIC_SVR, LAPIC_ENABLE|(IRQ_OFFSET+IRQ_SPURIOUS)); // enable APIC
|
||||
|
||||
// in virtual wire mode, set up the LINT0 and LINT1 as follows:
|
||||
// In virtual wire mode, set up the LINT0 and LINT1 as follows:
|
||||
lapic_write(LAPIC_LINT0, APIC_IMASK | APIC_EXTINT);
|
||||
lapic_write(LAPIC_LINT1, APIC_IMASK | APIC_NMI);
|
||||
|
||||
|
@ -141,9 +141,7 @@ lapic_init(int c)
|
|||
lapic_write(LAPIC_ESR, 0);
|
||||
lapic_read(LAPIC_ESR);
|
||||
|
||||
/*
|
||||
* Issue an INIT Level De-Assert to synchronise arbitration ID's.
|
||||
*/
|
||||
// Issue an INIT Level De-Assert to synchronise arbitration ID's.
|
||||
lapic_write(LAPIC_ICRHI, 0);
|
||||
lapic_write(LAPIC_ICRLO, LAPIC_ALLINC|APIC_LEVEL|LAPIC_DEASSERT|APIC_INIT);
|
||||
while(lapic_read(LAPIC_ICRLO) & APIC_DELIVS)
|
||||
|
|
4
mmu.h
4
mmu.h
|
@ -1,6 +1,4 @@
|
|||
/*
|
||||
* This file contains definitions for the x86 memory management unit (MMU).
|
||||
*/
|
||||
// This file contains definitions for the x86 memory management unit (MMU).
|
||||
|
||||
// Eflags register
|
||||
#define FL_CF 0x00000001 // Carry Flag
|
||||
|
|
44
mp.c
44
mp.c
|
@ -55,6 +55,11 @@ mp_scan(uchar *addr, int len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
// Search for the MP Floating Pointer Structure, which according to the
|
||||
// spec is in one of the following three locations:
|
||||
// 1) in the first KB of the EBDA;
|
||||
// 2) in the last KB of system base memory;
|
||||
// 3) in the BIOS ROM between 0xE0000 and 0xFFFFF.
|
||||
static struct mp*
|
||||
mp_search(void)
|
||||
{
|
||||
|
@ -62,13 +67,6 @@ mp_search(void)
|
|||
uint p;
|
||||
struct mp *mp;
|
||||
|
||||
/*
|
||||
* Search for the MP Floating Pointer Structure, which according to the
|
||||
* spec is in one of the following three locations:
|
||||
* 1) in the first KB of the EBDA;
|
||||
* 2) in the last KB of system base memory;
|
||||
* 3) in the BIOS ROM between 0xE0000 and 0xFFFFF.
|
||||
*/
|
||||
bda = (uchar*) 0x400;
|
||||
if((p = (bda[0x0F]<<8)|bda[0x0E])){
|
||||
if((mp = mp_scan((uchar*) p, 1024)))
|
||||
|
@ -82,6 +80,11 @@ mp_search(void)
|
|||
return mp_scan((uchar*)0xF0000, 0x10000);
|
||||
}
|
||||
|
||||
// Search for an MP configuration table. For now,
|
||||
// don't accept the default configurations (physaddr == 0).
|
||||
// Check for correct signature, calculate the checksum and,
|
||||
// if correct, check the version.
|
||||
// To do: check extended table checksum.
|
||||
static int
|
||||
mp_detect(void)
|
||||
{
|
||||
|
@ -89,13 +92,6 @@ mp_detect(void)
|
|||
uchar *p, sum;
|
||||
uint length;
|
||||
|
||||
/*
|
||||
* Search for an MP configuration table. For now,
|
||||
* don't accept the default configurations (physaddr == 0).
|
||||
* Check for correct signature, calculate the checksum and,
|
||||
* if correct, check the version.
|
||||
* To do: check extended table checksum.
|
||||
*/
|
||||
if((mp = mp_search()) == 0 || mp->physaddr == 0)
|
||||
return 1;
|
||||
|
||||
|
@ -128,13 +124,13 @@ mp_init(void)
|
|||
uchar byte;
|
||||
|
||||
ncpu = 0;
|
||||
if((r = mp_detect()) != 0) return;
|
||||
if((r = mp_detect()) != 0)
|
||||
return;
|
||||
|
||||
// Run through the table saving information needed for starting
|
||||
// application processors and initialising any I/O APICs. The table
|
||||
// is guaranteed to be in order such that only one pass is necessary.
|
||||
|
||||
/*
|
||||
* Run through the table saving information needed for starting
|
||||
* application processors and initialising any I/O APICs. The table
|
||||
* is guaranteed to be in order such that only one pass is necessary.
|
||||
*/
|
||||
mpctb = (struct mpctb*) mp->physaddr;
|
||||
lapicaddr = (uint*) mpctb->lapicaddr;
|
||||
p = ((uchar*)mpctb)+sizeof(struct mpctb);
|
||||
|
@ -179,10 +175,10 @@ mp_init(void)
|
|||
}
|
||||
|
||||
if(mp->imcrp) { // it appears that bochs doesn't support IMCR, and code won't run
|
||||
outb(0x22, 0x70); /* select IMCR */
|
||||
byte = inb(0x23); /* current contents */
|
||||
byte |= 0x01; /* mask external INTR */
|
||||
outb(0x23, byte); /* disconnect 8259s/NMI */
|
||||
outb(0x22, 0x70); // select IMCR
|
||||
byte = inb(0x23); // current contents
|
||||
byte |= 0x01; // mask external INTR
|
||||
outb(0x23, byte); // disconnect 8259s/NMI
|
||||
}
|
||||
}
|
||||
|
||||
|
|
171
mp.h
171
mp.h
|
@ -1,123 +1,118 @@
|
|||
/*
|
||||
* See MultiProcessor Specification Version 1.[14].
|
||||
*
|
||||
*/
|
||||
// See MultiProcessor Specification Version 1.[14].
|
||||
|
||||
struct mp { /* floating pointer */
|
||||
uchar signature[4]; /* "_MP_" */
|
||||
void *physaddr; /* physical address of MP configuration table */
|
||||
uchar length; /* 1 */
|
||||
uchar specrev; /* [14] */
|
||||
uchar checksum; /* all bytes must add up to 0 */
|
||||
uchar type; /* MP system configuration type */
|
||||
struct mp { // floating pointer
|
||||
uchar signature[4]; // "_MP_"
|
||||
void *physaddr; // physical address of MP configuration table
|
||||
uchar length; // 1
|
||||
uchar specrev; // [14]
|
||||
uchar checksum; // all bytes must add up to 0
|
||||
uchar type; // MP system configuration type
|
||||
uchar imcrp;
|
||||
uchar reserved[3];
|
||||
};
|
||||
|
||||
struct mpctb { /* configuration table header */
|
||||
uchar signature[4]; /* "PCMP" */
|
||||
ushort length; /* total table length */
|
||||
uchar version; /* [14] */
|
||||
uchar checksum; /* all bytes must add up to 0 */
|
||||
uchar product[20]; /* product id */
|
||||
uint *oemtable; /* OEM table pointer */
|
||||
ushort oemlength; /* OEM table length */
|
||||
ushort entry; /* entry count */
|
||||
uint *lapicaddr; /* address of local APIC */
|
||||
ushort xlength; /* extended table length */
|
||||
uchar xchecksum; /* extended table checksum */
|
||||
struct mpctb { // configuration table header
|
||||
uchar signature[4]; // "PCMP"
|
||||
ushort length; // total table length
|
||||
uchar version; // [14]
|
||||
uchar checksum; // all bytes must add up to 0
|
||||
uchar product[20]; // product id
|
||||
uint *oemtable; // OEM table pointer
|
||||
ushort oemlength; // OEM table length
|
||||
ushort entry; // entry count
|
||||
uint *lapicaddr; // address of local APIC
|
||||
ushort xlength; // extended table length
|
||||
uchar xchecksum; // extended table checksum
|
||||
uchar reserved;
|
||||
};
|
||||
|
||||
struct mppe { /* processor table entry */
|
||||
uchar type; /* entry type (0) */
|
||||
uchar apicid; /* local APIC id */
|
||||
uchar version; /* local APIC verison */
|
||||
uchar flags; /* CPU flags */
|
||||
uchar signature[4]; /* CPU signature */
|
||||
uint feature; /* feature flags from CPUID instruction */
|
||||
struct mppe { // processor table entry
|
||||
uchar type; // entry type (0)
|
||||
uchar apicid; // local APIC id
|
||||
uchar version; // local APIC verison
|
||||
uchar flags; // CPU flags
|
||||
uchar signature[4]; // CPU signature
|
||||
uint feature; // feature flags from CPUID instruction
|
||||
uchar reserved[8];
|
||||
};
|
||||
|
||||
struct mpbe { /* bus table entry */
|
||||
uchar type; /* entry type (1) */
|
||||
uchar busno; /* bus id */
|
||||
char string[6]; /* bus type string */
|
||||
struct mpbe { // bus table entry
|
||||
uchar type; // entry type (1)
|
||||
uchar busno; // bus id
|
||||
char string[6]; // bus type string
|
||||
};
|
||||
|
||||
struct mpioapic { /* I/O APIC table entry */
|
||||
uchar type; /* entry type (2) */
|
||||
uchar apicno; /* I/O APIC id */
|
||||
uchar version; /* I/O APIC version */
|
||||
uchar flags; /* I/O APIC flags */
|
||||
uint *addr; /* I/O APIC address */
|
||||
struct mpioapic { // I/O APIC table entry
|
||||
uchar type; // entry type (2)
|
||||
uchar apicno; // I/O APIC id
|
||||
uchar version; // I/O APIC version
|
||||
uchar flags; // I/O APIC flags
|
||||
uint *addr; // I/O APIC address
|
||||
};
|
||||
|
||||
struct mpie { /* interrupt table entry */
|
||||
uchar type; /* entry type ([34]) */
|
||||
uchar intr; /* interrupt type */
|
||||
ushort flags; /* interrupt flag */
|
||||
uchar busno; /* source bus id */
|
||||
uchar irq; /* source bus irq */
|
||||
uchar apicno; /* destination APIC id */
|
||||
uchar intin; /* destination APIC [L]INTIN# */
|
||||
struct mpie { // interrupt table entry
|
||||
uchar type; // entry type ([34])
|
||||
uchar intr; // interrupt type
|
||||
ushort flags; // interrupt flag
|
||||
uchar busno; // source bus id
|
||||
uchar irq; // source bus irq
|
||||
uchar apicno; // destination APIC id
|
||||
uchar intin; // destination APIC [L]INTIN#
|
||||
};
|
||||
|
||||
enum { /* table entry types */
|
||||
MPPROCESSOR = 0x00, /* one entry per processor */
|
||||
MPBUS = 0x01, /* one entry per bus */
|
||||
MPIOAPIC = 0x02, /* one entry per I/O APIC */
|
||||
MPIOINTR = 0x03, /* one entry per bus interrupt source */
|
||||
MPLINTR = 0x04, /* one entry per system interrupt source */
|
||||
enum { // table entry types
|
||||
MPPROCESSOR = 0x00, // one entry per processor
|
||||
MPBUS = 0x01, // one entry per bus
|
||||
MPIOAPIC = 0x02, // one entry per I/O APIC
|
||||
MPIOINTR = 0x03, // one entry per bus interrupt source
|
||||
MPLINTR = 0x04, // one entry per system interrupt source
|
||||
|
||||
MPSASM = 0x80,
|
||||
MPHIERARCHY = 0x81,
|
||||
MPCBASM = 0x82,
|
||||
|
||||
/* PCMPprocessor and PCMPioapic flags */
|
||||
MPEN = 0x01, /* enabled */
|
||||
MPBP = 0x02, /* bootstrap processor */
|
||||
// PCMPprocessor and PCMPioapic flags
|
||||
MPEN = 0x01, // enabled
|
||||
MPBP = 0x02, // bootstrap processor
|
||||
|
||||
/* PCMPiointr and PCMPlintr flags */
|
||||
MPPOMASK = 0x03, /* polarity conforms to specifications of bus */
|
||||
MPHIGH = 0x01, /* active high */
|
||||
MPLOW = 0x03, /* active low */
|
||||
MPELMASK = 0x0C, /* trigger mode of APIC input signals */
|
||||
MPEDGE = 0x04, /* edge-triggered */
|
||||
MPLEVEL = 0x0C, /* level-triggered */
|
||||
// PCMPiointr and PCMPlintr flags
|
||||
MPPOMASK = 0x03, // polarity conforms to specifications of bus
|
||||
MPHIGH = 0x01, // active high
|
||||
MPLOW = 0x03, // active low
|
||||
MPELMASK = 0x0C, // trigger mode of APIC input signals
|
||||
MPEDGE = 0x04, // edge-triggered
|
||||
MPLEVEL = 0x0C, // level-triggered
|
||||
|
||||
/* PCMPiointr and PCMPlintr interrupt type */
|
||||
MPINT = 0x00, /* vectored interrupt from APIC Rdt */
|
||||
MPNMI = 0x01, /* non-maskable interrupt */
|
||||
MPSMI = 0x02, /* system management interrupt */
|
||||
MPExtINT = 0x03, /* vectored interrupt from external PIC */
|
||||
// PCMPiointr and PCMPlintr interrupt type
|
||||
MPINT = 0x00, // vectored interrupt from APIC Rdt
|
||||
MPNMI = 0x01, // non-maskable interrupt
|
||||
MPSMI = 0x02, // system management interrupt
|
||||
MPExtINT = 0x03, // vectored interrupt from external PIC
|
||||
};
|
||||
|
||||
/*
|
||||
* Common bits for
|
||||
* I/O APIC Redirection Table Entry;
|
||||
* Local APIC Local Interrupt Vector Table;
|
||||
* Local APIC Inter-Processor Interrupt;
|
||||
* Local APIC Timer Vector Table.
|
||||
*/
|
||||
// Common bits for
|
||||
// I/O APIC Redirection Table Entry;
|
||||
// Local APIC Local Interrupt Vector Table;
|
||||
// Local APIC Inter-Processor Interrupt;
|
||||
// Local APIC Timer Vector Table.
|
||||
enum {
|
||||
APIC_FIXED = 0x00000000, /* [10:8] Delivery Mode */
|
||||
APIC_LOWEST = 0x00000100, /* Lowest priority */
|
||||
APIC_SMI = 0x00000200, /* System Management Interrupt */
|
||||
APIC_RR = 0x00000300, /* Remote Read */
|
||||
APIC_FIXED = 0x00000000, // [10:8] Delivery Mode
|
||||
APIC_LOWEST = 0x00000100, // Lowest priority
|
||||
APIC_SMI = 0x00000200, // System Management Interrupt
|
||||
APIC_RR = 0x00000300, // Remote Read
|
||||
APIC_NMI = 0x00000400,
|
||||
APIC_INIT = 0x00000500, /* INIT/RESET */
|
||||
APIC_STARTUP = 0x00000600, /* Startup IPI */
|
||||
APIC_INIT = 0x00000500, // INIT/RESET
|
||||
APIC_STARTUP = 0x00000600, // Startup IPI
|
||||
APIC_EXTINT = 0x00000700,
|
||||
|
||||
APIC_PHYSICAL = 0x00000000, /* [11] Destination Mode (RW) */
|
||||
APIC_PHYSICAL = 0x00000000, // [11] Destination Mode (RW)
|
||||
APIC_LOGICAL = 0x00000800,
|
||||
|
||||
APIC_DELIVS = 0x00001000, /* [12] Delivery Status (RO) */
|
||||
APIC_HIGH = 0x00000000, /* [13] Interrupt Input Pin Polarity (RW) */
|
||||
APIC_DELIVS = 0x00001000, // [12] Delivery Status (RO)
|
||||
APIC_HIGH = 0x00000000, // [13] Interrupt Input Pin Polarity (RW)
|
||||
APIC_LOW = 0x00002000,
|
||||
APIC_REMOTEIRR = 0x00004000, /* [14] Remote IRR (RO) */
|
||||
APIC_EDGE = 0x00000000, /* [15] Trigger Mode (RW) */
|
||||
APIC_REMOTEIRR = 0x00004000, // [14] Remote IRR (RO)
|
||||
APIC_EDGE = 0x00000000, // [15] Trigger Mode (RW)
|
||||
APIC_LEVEL = 0x00008000,
|
||||
APIC_IMASK = 0x00010000, /* [16] Interrupt Mask */
|
||||
APIC_IMASK = 0x00010000, // [16] Interrupt Mask
|
||||
};
|
||||
|
|
10
picirq.c
10
picirq.c
|
@ -22,7 +22,7 @@ irq_setmask_8259A(ushort mask)
|
|||
outb(IO_PIC2+1, (char)(mask >> 8));
|
||||
}
|
||||
|
||||
/* Initialize the 8259A interrupt controllers. */
|
||||
// Initialize the 8259A interrupt controllers.
|
||||
void
|
||||
pic_init(void)
|
||||
{
|
||||
|
@ -67,11 +67,11 @@ pic_init(void)
|
|||
// ef: 0x = NOP, 10 = clear specific mask, 11 = set specific mask
|
||||
// p: 0 = no polling, 1 = polling mode
|
||||
// rs: 0x = NOP, 10 = read IRR, 11 = read ISR
|
||||
outb(IO_PIC1, 0x68); /* clear specific mask */
|
||||
outb(IO_PIC1, 0x0a); /* read IRR by default */
|
||||
outb(IO_PIC1, 0x68); // clear specific mask
|
||||
outb(IO_PIC1, 0x0a); // read IRR by default
|
||||
|
||||
outb(IO_PIC2, 0x68); /* OCW3 */
|
||||
outb(IO_PIC2, 0x0a); /* OCW3 */
|
||||
outb(IO_PIC2, 0x68); // OCW3
|
||||
outb(IO_PIC2, 0x0a); // OCW3
|
||||
|
||||
if(irq_mask_8259A != 0xFFFF)
|
||||
irq_setmask_8259A(irq_mask_8259A);
|
||||
|
|
4
printf.c
4
printf.c
|
@ -33,9 +33,7 @@ printint(int fd, int xx, int base, int sgn)
|
|||
putc(fd, buf[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* printf to the stdout. only understands %d, %x, %p, %s.
|
||||
*/
|
||||
// Print to the given fd. Only understands %d, %x, %p, %s.
|
||||
void
|
||||
printf(int fd, char *fmt, ...)
|
||||
{
|
||||
|
|
9
proc.c
9
proc.c
|
@ -21,11 +21,10 @@ pinit(void)
|
|||
initlock(&proc_table_lock, "proc_table");
|
||||
}
|
||||
|
||||
/*
|
||||
* set up CPU's segment descriptors and task state for a
|
||||
* given process. If p==0, set up for "idle" state for
|
||||
* when scheduler() isn't running any process.
|
||||
*/
|
||||
// Set up CPU's segment descriptors and task state for a
|
||||
// given process.
|
||||
// If p==0, set up for "idle" state for when scheduler()
|
||||
// is idling, not running any process.
|
||||
void
|
||||
setupsegs(struct proc *p)
|
||||
{
|
||||
|
|
21
proc.h
21
proc.h
|
@ -1,20 +1,10 @@
|
|||
/*
|
||||
* p->mem:
|
||||
* text
|
||||
* original data and bss
|
||||
* fixed-size stack
|
||||
* expandable heap
|
||||
*/
|
||||
|
||||
/*
|
||||
* segments in proc->gdt
|
||||
*/
|
||||
// segments in proc->gdt
|
||||
#define SEG_KCODE 1 // kernel code
|
||||
#define SEG_KDATA 2 // kernel data+stack
|
||||
#define SEG_UCODE 3
|
||||
#define SEG_UDATA 4
|
||||
#define SEG_TSS 5 // this process's task state
|
||||
#define NSEGS 6
|
||||
#define SEG_TSS 5 // this process's task state
|
||||
#define NSEGS 6
|
||||
|
||||
struct jmpbuf {
|
||||
// saved registers for kernel context switches
|
||||
|
@ -37,6 +27,11 @@ enum proc_state { UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE };
|
|||
|
||||
struct proc{
|
||||
char *mem; // start of process's memory (a kernel address)
|
||||
// process memory is laid out contiguously:
|
||||
// text
|
||||
// original data and bss
|
||||
// fixed-size stack
|
||||
// expandable heap
|
||||
uint sz; // user memory size
|
||||
char *kstack; // kernel stack
|
||||
enum proc_state state;
|
||||
|
|
22
syscall.c
22
syscall.c
|
@ -15,18 +15,14 @@
|
|||
#include "fd.h"
|
||||
#include "fcntl.h"
|
||||
|
||||
/*
|
||||
* User code makes a system call with INT T_SYSCALL.
|
||||
* System call number in %eax.
|
||||
* Arguments on the stack, from the user call to the C
|
||||
* library system call function. The saved user %esp points
|
||||
* to a saved program counter, and then the first argument.
|
||||
*/
|
||||
// User code makes a system call with INT T_SYSCALL.
|
||||
// System call number in %eax.
|
||||
// Arguments on the stack, from the user call to the C
|
||||
// library system call function. The saved user %esp points
|
||||
// to a saved program counter, and then the first argument.
|
||||
|
||||
/*
|
||||
* fetch 32 bits from a user-supplied pointer.
|
||||
* returns 0 if addr was OK, -1 if illegal.
|
||||
*/
|
||||
// Fetch 32 bits from a user-supplied pointer.
|
||||
// Returns 0 if addr was OK, -1 if illegal.
|
||||
int
|
||||
fetchint(struct proc *p, uint addr, int *ip)
|
||||
{
|
||||
|
@ -58,8 +54,8 @@ fetcharg(int argno, void *ip)
|
|||
return fetchint(curproc[cpu()], esp + 4 + 4*argno, ip);
|
||||
}
|
||||
|
||||
// check that an entire string is valid in user space.
|
||||
// returns the length, not including null, or -1.
|
||||
// Check that an entire string is valid in user space.
|
||||
// Returns the length, not including null, or -1.
|
||||
int
|
||||
checkstring(uint s)
|
||||
{
|
||||
|
|
2
trap.c
2
trap.c
|
@ -8,7 +8,7 @@
|
|||
#include "syscall.h"
|
||||
|
||||
struct gatedesc idt[256];
|
||||
extern uint vectors[]; /* vectors.S, array of 256 entry point addresses */
|
||||
extern uint vectors[]; // in vectors.S: array of 256 entry point addresses
|
||||
|
||||
extern void trapenter(void);
|
||||
extern void trapenter1(void);
|
||||
|
|
6
traps.h
6
traps.h
|
@ -8,13 +8,13 @@
|
|||
#define T_ILLOP 6 // illegal opcode
|
||||
#define T_DEVICE 7 // device not available
|
||||
#define T_DBLFLT 8 // double fault
|
||||
/* #define T_COPROC 9 */ // reserved (not generated by recent processors)
|
||||
// #define T_COPROC 9 // reserved (not generated by recent processors)
|
||||
#define T_TSS 10 // invalid task switch segment
|
||||
#define T_SEGNP 11 // segment not present
|
||||
#define T_STACK 12 // stack exception
|
||||
#define T_GPFLT 13 // genernal protection fault
|
||||
#define T_PGFLT 14 // page fault
|
||||
/* #define T_RES 15 */ // reserved
|
||||
// #define T_RES 15 // reserved
|
||||
#define T_FPERR 16 // floating point error
|
||||
#define T_ALIGN 17 // aligment check
|
||||
#define T_MCHK 18 // machine check
|
||||
|
@ -25,7 +25,7 @@
|
|||
#define T_SYSCALL 48 // system call
|
||||
#define T_DEFAULT 500 // catchall
|
||||
|
||||
#define IRQ_OFFSET 32 // IRQ 0 corresponds to int IRQ_OFFSET
|
||||
#define IRQ_OFFSET 32 // IRQ 0 corresponds to int IRQ_OFFSET
|
||||
|
||||
#define IRQ_KBD 1
|
||||
#define IRQ_IDE 14
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
# since otherwise there's no way for trap() to discover
|
||||
# the interrupt number.
|
||||
|
||||
print "/* generated by vectors.pl */\n";
|
||||
print "/* handlers */\n";
|
||||
print "# generated by vectors.pl - do not edit\n";
|
||||
print "# handlers\n";
|
||||
print ".text\n";
|
||||
print ".globl alltraps\n";
|
||||
for(my $i = 0; $i < 256; $i++){
|
||||
|
@ -19,7 +19,7 @@ for(my $i = 0; $i < 256; $i++){
|
|||
print " jmp alltraps\n";
|
||||
}
|
||||
|
||||
print "\n/* vector table */\n";
|
||||
print "\n# vector table\n";
|
||||
print ".data\n";
|
||||
print ".globl vectors\n";
|
||||
print "vectors:\n";
|
||||
|
|
13
x86.h
13
x86.h
|
@ -125,28 +125,31 @@ sti(void)
|
|||
}
|
||||
|
||||
struct trapframe {
|
||||
/* registers as pushed by pusha */
|
||||
// registers as pushed by pusha
|
||||
uint edi;
|
||||
uint esi;
|
||||
uint ebp;
|
||||
uint oesp; /* Useless */
|
||||
uint oesp; // useless & ignored
|
||||
uint ebx;
|
||||
uint edx;
|
||||
uint ecx;
|
||||
uint eax;
|
||||
/* rest of trap frame */
|
||||
|
||||
// rest of trap frame
|
||||
ushort es;
|
||||
ushort padding1;
|
||||
ushort ds;
|
||||
ushort padding2;
|
||||
uint trapno;
|
||||
/* below here defined by x86 hardware */
|
||||
|
||||
// below here defined by x86 hardware
|
||||
uint err;
|
||||
uint eip;
|
||||
ushort cs;
|
||||
ushort padding3;
|
||||
uint eflags;
|
||||
/* below here only when crossing rings, such as from user to kernel */
|
||||
|
||||
// below here only when crossing rings, such as from user to kernel
|
||||
uint esp;
|
||||
ushort ss;
|
||||
ushort padding4;
|
||||
|
|
Loading…
Reference in a new issue