提交 21a88fd4 创建 作者: kaashoek's avatar kaashoek

checkpoint. booting second processor. stack is messed up, but thanks to cliff

and plan 9 code, at least boots and gets into C code.
上级 7baa34a4
OBJS = main.o console.o string.o kalloc.o proc.o trapasm.o trap.o vectors.o \ OBJS = main.o console.o string.o kalloc.o proc.o trapasm.o trap.o vectors.o \
syscall.o ide.o picirq.o mp.o syscall.o ide.o picirq.o mp.o spinlock.o
CC = i386-jos-elf-gcc CC = i386-jos-elf-gcc
LD = i386-jos-elf-ld LD = i386-jos-elf-ld
...@@ -20,8 +20,12 @@ bootblock : bootasm.S bootmain.c ...@@ -20,8 +20,12 @@ bootblock : bootasm.S bootmain.c
$(OBJCOPY) -S -O binary bootblock.o bootblock $(OBJCOPY) -S -O binary bootblock.o bootblock
./sign.pl bootblock ./sign.pl bootblock
kernel : $(OBJS) kernel : $(OBJS) bootother.S
$(LD) -Ttext 0x100000 -e main -o kernel $(OBJS) $(CC) -nostdinc -I. -c bootother.S
$(LD) -N -e start -Ttext 0x7000 -o bootother.out bootother.o
$(OBJCOPY) -S -O binary bootother.out bootother
$(OBJDUMP) -S bootother.o > bootother.asm
$(LD) -Ttext 0x100000 -e main -o kernel $(OBJS) -b binary bootother
$(OBJDUMP) -S kernel > kernel.asm $(OBJDUMP) -S kernel > kernel.asm
vectors.S : vectors.pl vectors.S : vectors.pl
......
#define SEG_NULL \ #include "asm.h"
.word 0, 0; \
.byte 0, 0, 0, 0
#define SEG(type,base,lim) \
.word (((lim) >> 12) & 0xffff), ((base) & 0xffff); \
.byte (((base) >> 16) & 0xff), (0x90 | (type)), \
(0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff)
#define STA_X 0x8 // Executable segment
#define STA_E 0x4 // Expand down (non-executable segments)
#define STA_C 0x4 // Conforming code segment (executable only)
#define STA_W 0x2 // Writeable (non-executable segments)
#define STA_R 0x2 // Readable (executable segments)
#define STA_A 0x1 // Accessed
.set PROT_MODE_CSEG,0x8 # code segment selector .set PROT_MODE_CSEG,0x8 # code segment selector
.set PROT_MODE_DSEG,0x10 # data segment selector .set PROT_MODE_DSEG,0x10 # data segment selector
......
#include "asm.h"
/*
* Start an Application Processor. This must be placed on a 4KB boundary
* somewhere in the 1st MB of conventional memory (APBOOTSTRAP). However,
* due to some shortcuts below it's restricted further to within the 1st
* 64KB. The AP starts in real-mode, with
* CS selector set to the startup memory address/16;
* CS base set to startup memory address;
* CS limit set to 64KB;
* CPL and IP set to 0.
*
* Credit: Cliff Frey
*/
.set PROT_MODE_CSEG,0x8 # code segment selector
.set PROT_MODE_DSEG,0x10 # data segment selector
.set CR0_PE_ON,0x1 # protected mode enable flag
.globl start
start: .code16 # This runs in real mode
cli # Disable interrupts
cld # String operations increment
# Set up the important data segment registers (DS, ES, SS).
xorw %ax,%ax # Segment number zero
movw %ax,%ds # -> Data Segment
movw %ax,%es # -> Extra Segment
movw %ax,%ss # -> Stack Segment
# Set up the stack pointer, growing downward from 0x7000.
movw $start,%sp # Stack Pointer
#### Switch from real to protected mode
#### The descriptors in our GDT allow all physical memory to be accessed.
#### Furthermore, the descriptors have base addresses of 0, so that the
#### segment translation is a NOP, ie. virtual addresses are identical to
#### their physical addresses. With this setup, immediately after
#### enabling protected mode it will still appear to this code
#### that it is running directly on physical memory with no translation.
#### This initial NOP-translation setup is required by the processor
#### to ensure that the transition to protected mode occurs smoothly.
lgdt gdtdesc # load GDT -- mandatory in protected mode
movl %cr0, %eax # turn on protected mode
orl $CR0_PE_ON, %eax #
movl %eax, %cr0 #
### CPU magic: jump to relocation, flush prefetch queue, and reload %cs
### Has the effect of just jmp to the next instruction, but simultaneous
### loads CS with $PROT_MODE_CSEG.
ljmp $PROT_MODE_CSEG, $protcseg
#### we are in 32-bit protected mode (hence the .code32)
.code32
protcseg:
# Set up the protected-mode data segment registers
movw $PROT_MODE_DSEG, %ax # Our data segment selector
movw %ax, %ds # -> DS: Data Segment
movw %ax, %es # -> ES: Extra Segment
movw %ax, %fs # -> FS
movw %ax, %gs # -> GS
movw %ax, %ss # -> SS: Stack Segment
# XXX hack
movl 0x10018, %eax # elfhdr->entry (left over in scratch space)
# subl $KERNBASE, %eax
jmp *%eax # this jumps to _start in kern/entry.S
.p2align 2 # force 4 byte alignment
gdt:
SEG_NULL # null seg
SEG(STA_X|STA_R, 0x0, 0xffffffff) # code seg
SEG(STA_W, 0x0, 0xffffffff) # data seg
gdtdesc:
.word 0x17 # sizeof(gdt) - 1
.long gdt # address gdt
...@@ -22,6 +22,7 @@ void tinit(void); ...@@ -22,6 +22,7 @@ void tinit(void);
void * memcpy(void *dst, void *src, unsigned n); void * memcpy(void *dst, void *src, unsigned n);
void * memset(void *dst, int c, unsigned n); void * memset(void *dst, int c, unsigned n);
int memcmp(const void *v1, const void *v2, unsigned n); int memcmp(const void *v1, const void *v2, unsigned n);
void *memmove(void *dst, const void *src, unsigned n);
// syscall.c // syscall.c
void syscall(void); void syscall(void);
...@@ -31,5 +32,13 @@ void irq_setmask_8259A(uint16_t mask); ...@@ -31,5 +32,13 @@ void irq_setmask_8259A(uint16_t mask);
void pic_init(void); void pic_init(void);
// mp.c // mp.c
void mpinit(void); void mp_init(void);
int lapic_cpu_number(void);
int mp_isbcpu(void);
// spinlock.c
extern uint32_t kernel_lock;
void acquire_spinlock(uint32_t* lock);
void release_spinlock(uint32_t* lock);
void release_grant_spinlock(uint32_t* lock, int cpu);
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "syscall.h" #include "syscall.h"
extern char edata[], end[]; extern char edata[], end[];
extern int acpu;
char buf[512]; char buf[512];
...@@ -16,13 +17,19 @@ main() ...@@ -16,13 +17,19 @@ main()
{ {
struct proc *p; struct proc *p;
int i; int i;
if (acpu) {
cprintf("an application processor\n");
release_spinlock(&kernel_lock);
while (1) ;
}
acpu = 1;
// clear BSS // clear BSS
memset(edata, 0, end - edata); memset(edata, 0, end - edata);
cprintf("\nxV6\n\n"); cprintf("\nxV6\n\n");
mpinit(); // multiprocessor mp_init(); // multiprocessor
kinit(); // physical memory allocator kinit(); // physical memory allocator
tinit(); // traps and interrupts tinit(); // traps and interrupts
pic_init(); pic_init();
......
差异被折叠。
/* /*
* MultiProcessor Specification Version 1.[14]. * MultiProcessor Specification Version 1.[14].
*
* Credit: Plan 9 sources
*/ */
struct _MP_ { /* floating pointer */
struct MP { /* floating pointer */
uint8_t signature[4]; /* "_MP_" */ uint8_t signature[4]; /* "_MP_" */
physaddr_t physaddr; /* physical address of MP configuration table */ physaddr_t physaddr; /* physical address of MP configuration table */
uint8_t length; /* 1 */ uint8_t length; /* 1 */
...@@ -12,7 +15,7 @@ struct _MP_ { /* floating pointer */ ...@@ -12,7 +15,7 @@ struct _MP_ { /* floating pointer */
uint8_t reserved[3]; uint8_t reserved[3];
}; };
struct PCMP { /* configuration table header */ struct MPCTB { /* configuration table header */
uint8_t signature[4]; /* "PCMP" */ uint8_t signature[4]; /* "PCMP" */
uint16_t length; /* total table length */ uint16_t length; /* total table length */
uint8_t version; /* [14] */ uint8_t version; /* [14] */
...@@ -21,15 +24,15 @@ struct PCMP { /* configuration table header */ ...@@ -21,15 +24,15 @@ struct PCMP { /* configuration table header */
uintptr_t oemtable; /* OEM table pointer */ uintptr_t oemtable; /* OEM table pointer */
uint16_t oemlength; /* OEM table length */ uint16_t oemlength; /* OEM table length */
uint16_t entry; /* entry count */ uint16_t entry; /* entry count */
uintptr_t lapicbase; /* address of local APIC */ uintptr_t lapicaddr; /* address of local APIC */
uint16_t xlength; /* extended table length */ uint16_t xlength; /* extended table length */
uint8_t xchecksum; /* extended table checksum */ uint8_t xchecksum; /* extended table checksum */
uint8_t reserved; uint8_t reserved;
}; };
struct PCMPprocessor { /* processor table entry */ struct MPPE { /* processor table entry */
uint8_t type; /* entry type (0) */ uint8_t type; /* entry type (0) */
uint8_t apicno; /* local APIC id */ uint8_t apicid; /* local APIC id */
uint8_t version; /* local APIC verison */ uint8_t version; /* local APIC verison */
uint8_t flags; /* CPU flags */ uint8_t flags; /* CPU flags */
uint8_t signature[4]; /* CPU signature */ uint8_t signature[4]; /* CPU signature */
...@@ -37,13 +40,13 @@ struct PCMPprocessor { /* processor table entry */ ...@@ -37,13 +40,13 @@ struct PCMPprocessor { /* processor table entry */
uint8_t reserved[8]; uint8_t reserved[8];
}; };
struct PCMPbus { /* bus table entry */ struct MPBE { /* bus table entry */
uint8_t type; /* entry type (1) */ uint8_t type; /* entry type (1) */
uint8_t busno; /* bus id */ uint8_t busno; /* bus id */
char string[6]; /* bus type string */ char string[6]; /* bus type string */
}; };
struct PCMPioapic { /* I/O APIC table entry */ struct MPIOAPIC { /* I/O APIC table entry */
uint8_t type; /* entry type (2) */ uint8_t type; /* entry type (2) */
uint8_t apicno; /* I/O APIC id */ uint8_t apicno; /* I/O APIC id */
uint8_t version; /* I/O APIC version */ uint8_t version; /* I/O APIC version */
...@@ -51,7 +54,7 @@ struct PCMPioapic { /* I/O APIC table entry */ ...@@ -51,7 +54,7 @@ struct PCMPioapic { /* I/O APIC table entry */
uintptr_t addr; /* I/O APIC address */ uintptr_t addr; /* I/O APIC address */
}; };
struct PCMPintr { /* interrupt table entry */ struct MPIE { /* interrupt table entry */
uint8_t type; /* entry type ([34]) */ uint8_t type; /* entry type ([34]) */
uint8_t intr; /* interrupt type */ uint8_t intr; /* interrupt type */
uint16_t flags; /* interrupt flag */ uint16_t flags; /* interrupt flag */
...@@ -61,71 +64,34 @@ struct PCMPintr { /* interrupt table entry */ ...@@ -61,71 +64,34 @@ struct PCMPintr { /* interrupt table entry */
uint8_t intin; /* destination APIC [L]INTIN# */ uint8_t intin; /* destination APIC [L]INTIN# */
}; };
struct PCMPsasm { /* system address space mapping entry */ enum { /* table entry types */
uint8_t type; /* entry type (128) */ MPPROCESSOR = 0x00, /* one entry per processor */
uint8_t length; /* of this entry (20) */ MPBUS = 0x01, /* one entry per bus */
uint8_t busno; /* bus id */ MPIOAPIC = 0x02, /* one entry per I/O APIC */
uint8_t addrtype; MPIOINTR = 0x03, /* one entry per bus interrupt source */
uintptr_t addrbase[2]; MPLINTR = 0x04, /* one entry per system interrupt source */
uint32_t addrlength[2];
}; MPSASM = 0x80,
MPHIERARCHY = 0x81,
struct PCMPhierarchy { /* bus hierarchy descriptor entry */ MPCBASM = 0x82,
uint8_t type; /* entry type (129) */
uint8_t length; /* of this entry (8) */ /* PCMPprocessor and PCMPioapic flags */
uint8_t busno; /* bus id */ MPEN = 0x01, /* enabled */
uint8_t info; /* bus info */ MPBP = 0x02, /* bootstrap processor */
uint8_t parent; /* parent bus */
uint8_t reserved[3]; /* PCMPiointr and PCMPlintr flags */
}; MPPOMASK = 0x03, /* polarity conforms to specifications of bus */
MPHIGH = 0x01, /* active high */
struct PCMPcbasm { /* compatibility bus address space modifier entry */ MPLOW = 0x03, /* active low */
uint8_t type; /* entry type (130) */ MPELMASK = 0x0C, /* trigger mode of APIC input signals */
uint8_t length; /* of this entry (8) */ MPEDGE = 0x04, /* edge-triggered */
uint8_t busno; /* bus id */ MPLEVEL = 0x0C, /* level-triggered */
uint8_t modifier; /* address modifier */
uint32_t range; /* predefined range list */ /* PCMPiointr and PCMPlintr interrupt type */
}; MPINT = 0x00, /* vectored interrupt from APIC Rdt */
MPNMI = 0x01, /* non-maskable interrupt */
enum { /* table entry types */ MPSMI = 0x02, /* system management interrupt */
PcmpPROCESSOR = 0x00, /* one entry per processor */ MPExtINT = 0x03, /* vectored interrupt from external PIC */
PcmpBUS = 0x01, /* one entry per bus */
PcmpIOAPIC = 0x02, /* one entry per I/O APIC */
PcmpIOINTR = 0x03, /* one entry per bus interrupt source */
PcmpLINTR = 0x04, /* one entry per system interrupt source */
PcmpSASM = 0x80,
PcmpHIERARCHY = 0x81,
PcmpCBASM = 0x82,
/* PCMPprocessor and PCMPioapic flags */
PcmpEN = 0x01, /* enabled */
PcmpBP = 0x02, /* bootstrap processor */
/* PCMPiointr and PCMPlintr flags */
PcmpPOMASK = 0x03, /* polarity conforms to specifications of bus */
PcmpHIGH = 0x01, /* active high */
PcmpLOW = 0x03, /* active low */
PcmpELMASK = 0x0C, /* trigger mode of APIC input signals */
PcmpEDGE = 0x04, /* edge-triggered */
PcmpLEVEL = 0x0C, /* level-triggered */
/* PCMPiointr and PCMPlintr interrupt type */
PcmpINT = 0x00, /* vectored interrupt from APIC Rdt */
PcmpNMI = 0x01, /* non-maskable interrupt */
PcmpSMI = 0x02, /* system management interrupt */
PcmpExtINT = 0x03, /* vectored interrupt from external PIC */
/* PCMPsasm addrtype */
PcmpIOADDR = 0x00, /* I/O address */
PcmpMADDR = 0x01, /* memory address */
PcmpPADDR = 0x02, /* prefetch address */
/* PCMPhierarchy info */
PcmpSD = 0x01, /* subtractive decode bus */
/* PCMPcbasm modifier */
PcmpPR = 0x01, /* predefined range list */
}; };
/* /*
...@@ -136,23 +102,23 @@ enum { /* table entry types */ ...@@ -136,23 +102,23 @@ enum { /* table entry types */
* Local APIC Timer Vector Table. * Local APIC Timer Vector Table.
*/ */
enum { enum {
ApicFIXED = 0x00000000, /* [10:8] Delivery Mode */ APIC_FIXED = 0x00000000, /* [10:8] Delivery Mode */
ApicLOWEST = 0x00000100, /* Lowest priority */ APIC_LOWEST = 0x00000100, /* Lowest priority */
ApicSMI = 0x00000200, /* System Management Interrupt */ APIC_SMI = 0x00000200, /* System Management Interrupt */
ApicRR = 0x00000300, /* Remote Read */ APIC_RR = 0x00000300, /* Remote Read */
ApicNMI = 0x00000400, APIC_NMI = 0x00000400,
ApicINIT = 0x00000500, /* INIT/RESET */ APIC_INIT = 0x00000500, /* INIT/RESET */
ApicSTARTUP = 0x00000600, /* Startup IPI */ APIC_STARTUP = 0x00000600, /* Startup IPI */
ApicExtINT = 0x00000700, APIC_ExtINT = 0x00000700,
ApicPHYSICAL = 0x00000000, /* [11] Destination Mode (RW) */ APIC_PHYSICAL = 0x00000000, /* [11] Destination Mode (RW) */
ApicLOGICAL = 0x00000800, APIC_LOGICAL = 0x00000800,
ApicDELIVS = 0x00001000, /* [12] Delivery Status (RO) */ APIC_DELIVS = 0x00001000, /* [12] Delivery Status (RO) */
ApicHIGH = 0x00000000, /* [13] Interrupt Input Pin Polarity (RW) */ APIC_HIGH = 0x00000000, /* [13] Interrupt Input Pin Polarity (RW) */
ApicLOW = 0x00002000, APIC_LOW = 0x00002000,
ApicRemoteIRR = 0x00004000, /* [14] Remote IRR (RO) */ APIC_RemoteIRR = 0x00004000, /* [14] Remote IRR (RO) */
ApicEDGE = 0x00000000, /* [15] Trigger Mode (RW) */ APIC_EDGE = 0x00000000, /* [15] Trigger Mode (RW) */
ApicLEVEL = 0x00008000, APIC_LEVEL = 0x00008000,
ApicIMASK = 0x00010000, /* [16] Interrupt Mask */ APIC_IMASK = 0x00010000, /* [16] Interrupt Mask */
}; };
#define NPROC 64 #define NPROC 64
#define PAGE 4096 #define PAGE 4096
#define KSTACKSIZE PAGE #define KSTACKSIZE PAGE
#define NCPU 8
...@@ -4,15 +4,6 @@ ...@@ -4,15 +4,6 @@
#include "x86.h" #include "x86.h"
#include "defs.h" #include "defs.h"
#define MAX_IRQS 16 // Number of IRQs
// I/O Addresses of the two 8259A programmable interrupt controllers
#define IO_PIC1 0x20 // Master (IRQs 0-7)
#define IO_PIC2 0xA0 // Slave (IRQs 8-15)
#define IRQ_SLAVE 2 // IRQ at which slave connects to master
#define IRQ_OFFSET 32 // IRQ 0 corresponds to int IRQ_OFFSET
// Current IRQ mask. // Current IRQ mask.
// Initial IRQ mask has interrupt 2 enabled (for slave 8259A). // Initial IRQ mask has interrupt 2 enabled (for slave 8259A).
uint16_t irq_mask_8259A = 0xFFFF & ~(1<<IRQ_SLAVE); uint16_t irq_mask_8259A = 0xFFFF & ~(1<<IRQ_SLAVE);
......
#include "types.h"
#include "defs.h"
#include "x86.h"
#define LOCK_FREE -1
uint32_t kernel_lock = LOCK_FREE;
// lock = LOCK_FREE if free, else = cpu_id of owner CPU
void
acquire_spinlock(uint32_t* lock)
{
int cpu_id = lapic_cpu_number();
cprintf ("acquire: %d\n", cpu_id);
if (*lock == cpu_id)
return;
while ( cmpxchg(LOCK_FREE, cpu_id, lock) != cpu_id ) { ; }
}
void
release_spinlock(uint32_t* lock)
{
int cpu_id = lapic_cpu_number();
cprintf ("release: %d\n", cpu_id);
if (*lock != cpu_id)
panic("release_spinlock: releasing a lock that i don't own\n");
*lock = LOCK_FREE;
}
void
release_grant_spinlock(uint32_t* lock, int c)
{
int cpu_id = lapic_cpu_number();
cprintf ("release_grant: %d -> %d\n", cpu_id, c);
if (*lock != cpu_id)
panic("release_spinlock: releasing a lock that i don't own\n");
*lock = c;
}
...@@ -38,3 +38,23 @@ memcmp(const void *v1, const void *v2, unsigned n) ...@@ -38,3 +38,23 @@ memcmp(const void *v1, const void *v2, unsigned n)
return 0; return 0;
} }
void *
memmove(void *dst, const void *src, unsigned n)
{
const char *s;
char *d;
s = src;
d = dst;
if (s < d && s + n > d) {
s += n;
d += n;
while (n-- > 0)
*--d = *--s;
} else
while (n-- > 0)
*d++ = *s++;
return dst;
}
...@@ -27,3 +27,8 @@ trapret: ...@@ -27,3 +27,8 @@ trapret:
popl %ds popl %ds
addl $0x8, %esp /* trapno and errcode */ addl $0x8, %esp /* trapno and errcode */
iret iret
.globl acpu
acpu:
.long 0
...@@ -261,6 +261,17 @@ cpuid(uint32_t info, uint32_t *eaxp, uint32_t *ebxp, uint32_t *ecxp, uint32_t *e ...@@ -261,6 +261,17 @@ cpuid(uint32_t info, uint32_t *eaxp, uint32_t *ebxp, uint32_t *ecxp, uint32_t *e
*edxp = edx; *edxp = edx;
} }
static __inline uint32_t
cmpxchg(uint32_t oldval, uint32_t newval, volatile uint32_t* lock_addr)
{
uint32_t result;
__asm__ __volatile__(
"lock; cmpxchgl %2, %0"
:"+m" (*lock_addr), "=a" (result) : "r"(newval), "1"(oldval) : "cc"
);
return result;
}
static __inline uint64_t static __inline uint64_t
read_tsc(void) read_tsc(void)
{ {
...@@ -299,3 +310,16 @@ struct Trapframe { ...@@ -299,3 +310,16 @@ struct Trapframe {
uint16_t tf_ss; uint16_t tf_ss;
uint16_t tf_padding4; uint16_t tf_padding4;
}; };
#define MAX_IRQS 16 // Number of IRQs
// I/O Addresses of the two 8259A programmable interrupt controllers
#define IO_PIC1 0x20 // Master (IRQs 0-7)
#define IO_PIC2 0xA0 // Slave (IRQs 8-15)
#define IRQ_SLAVE 2 // IRQ at which slave connects to master
#define IRQ_OFFSET 32 // IRQ 0 corresponds to int IRQ_OFFSET
#define IRQ_ERROR 19
#define IRQ_SPURIOUS 31
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论