Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
X
xv6-public
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
问题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
银宸时代
OS Lab Group
奖励实验
xv6-public
提交
21a88fd4
提交
21a88fd4
6月 22, 2006
创建
作者:
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
隐藏空白字符变更
内嵌
并排
正在显示
13 个修改的文件
包含
505 行增加
和
151 行删除
+505
-151
Makefile
Makefile
+7
-3
bootasm.S
bootasm.S
+1
-14
bootother.S
bootother.S
+77
-0
defs.h
defs.h
+10
-1
main.c
main.c
+9
-2
mp.c
mp.c
+254
-30
mp.h
mp.h
+58
-92
param.h
param.h
+1
-0
picirq.c
picirq.c
+0
-9
spinlock.c
spinlock.c
+39
-0
string.c
string.c
+20
-0
trapasm.S
trapasm.S
+5
-0
x86.h
x86.h
+24
-0
没有找到文件。
Makefile
浏览文件 @
21a88fd4
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
LD
=
i386-jos-elf-ld
...
...
@@ -20,8 +20,12 @@ bootblock : bootasm.S bootmain.c
$(OBJCOPY)
-S
-O
binary bootblock.o bootblock
./sign.pl bootblock
kernel
:
$(OBJS)
$(LD)
-Ttext
0x100000
-e
main
-o
kernel
$(OBJS)
kernel
:
$(OBJS) bootother.S
$(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
vectors.S
:
vectors.pl
...
...
bootasm.S
浏览文件 @
21a88fd4
#define SEG_NULL \
.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
#include "asm.h"
.set PROT_MODE_CSEG,0x8 # code segment selector
.set PROT_MODE_DSEG,0x10 # data segment selector
...
...
bootother.S
0 → 100644
浏览文件 @
21a88fd4
#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
defs.h
浏览文件 @
21a88fd4
...
...
@@ -22,6 +22,7 @@ void tinit(void);
void
*
memcpy
(
void
*
dst
,
void
*
src
,
unsigned
n
);
void
*
memset
(
void
*
dst
,
int
c
,
unsigned
n
);
int
memcmp
(
const
void
*
v1
,
const
void
*
v2
,
unsigned
n
);
void
*
memmove
(
void
*
dst
,
const
void
*
src
,
unsigned
n
);
// syscall.c
void
syscall
(
void
);
...
...
@@ -31,5 +32,13 @@ void irq_setmask_8259A(uint16_t mask);
void
pic_init
(
void
);
// 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
);
main.c
浏览文件 @
21a88fd4
...
...
@@ -8,6 +8,7 @@
#include "syscall.h"
extern
char
edata
[],
end
[];
extern
int
acpu
;
char
buf
[
512
];
...
...
@@ -16,13 +17,19 @@ main()
{
struct
proc
*
p
;
int
i
;
if
(
acpu
)
{
cprintf
(
"an application processor
\n
"
);
release_spinlock
(
&
kernel_lock
);
while
(
1
)
;
}
acpu
=
1
;
// clear BSS
memset
(
edata
,
0
,
end
-
edata
);
cprintf
(
"
\n
xV6
\n\n
"
);
mpinit
();
// multiprocessor
mp
_
init
();
// multiprocessor
kinit
();
// physical memory allocator
tinit
();
// traps and interrupts
pic_init
();
...
...
mp.c
浏览文件 @
21a88fd4
...
...
@@ -2,11 +2,201 @@
#include "mp.h"
#include "defs.h"
#include "memlayout.h"
#include "param.h"
#include "x86.h"
#include "mmu.h"
static
struct
_MP_
*
_mp_
;
/* The MP floating point structure */
/*
* Credit: Plan 9 sources, Intel MP spec, and Cliff Frey
*/
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_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 */
/* [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_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 */
};
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 */
};
#define APBOOTCODE 0x7000 // XXX hack
static
struct
MP
*
mp
;
/* The MP floating point structure */
static
uint32_t
*
lapicaddr
;
static
struct
cpu
{
uint8_t
apicid
;
/* Local APIC ID */
int
lintr
[
2
];
/* Local APIC */
}
cpu
[
NCPU
];
static
int
ncpu
;
static
struct
cpu
*
bcpu
;
static
int
lapic_read
(
int
r
)
{
return
*
(
lapicaddr
+
(
r
/
sizeof
(
*
lapicaddr
)));
}
static
void
lapic_write
(
int
r
,
int
data
)
{
*
(
lapicaddr
+
(
r
/
sizeof
(
*
lapicaddr
)))
=
data
;
}
static
void
lapic_init
(
int
c
)
{
uint32_t
r
,
lvt
;
cprintf
(
"lapic_init %d
\n
"
,
c
);
lapic_write
(
LAPIC_DFR
,
0xFFFFFFFF
);
r
=
(
lapic_read
(
LAPIC_ID
)
>>
24
)
&
0xFF
;
lapic_write
(
LAPIC_LDR
,
(
1
<<
r
)
<<
24
);
lapic_write
(
LAPIC_TPR
,
0xFF
);
lapic_write
(
LAPIC_SVR
,
LAPIC_ENABLE
|
(
IRQ_OFFSET
+
IRQ_SPURIOUS
));
/*
* Set the local interrupts. It's likely these should just be
* masked off for SMP mode as some Pentium Pros have problems if
* LINT[01] are set to ExtINT.
* Acknowledge any outstanding interrupts.
*/
lapic_write
(
LAPIC_LINT0
,
cpu
[
c
].
lintr
[
0
]);
lapic_write
(
LAPIC_LINT1
,
cpu
[
c
].
lintr
[
1
]);
lapic_write
(
LAPIC_EOI
,
0
);
lvt
=
(
lapic_read
(
LAPIC_VER
)
>>
16
)
&
0xFF
;
if
(
lvt
>=
4
)
lapic_write
(
LAPIC_PCINT
,
APIC_IMASK
);
lapic_write
(
LAPIC_ERROR
,
IRQ_OFFSET
+
IRQ_ERROR
);
lapic_write
(
LAPIC_ESR
,
0
);
lapic_read
(
LAPIC_ESR
);
/*
* 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
)
;
static
struct
_MP_
*
/*
* Do not allow acceptance of interrupts until all initialisation
* for this processor is done. For the bootstrap processor this can be
* early duing initialisation. For the application processors this should
* be after the bootstrap processor has lowered priority and is accepting
* interrupts.
*/
lapic_write
(
LAPIC_TPR
,
0
);
cprintf
(
"Done init of an apic
\n
"
);
}
static
void
lapic_online
(
void
)
{
lapic_write
(
LAPIC_TPR
,
0
);
}
int
lapic_cpu_number
(
void
)
{
return
(
lapic_read
(
LAPIC_ID
)
>>
24
)
&
0xFF
;
}
static
void
lapic_startap
(
struct
cpu
*
c
,
int
v
)
{
int
crhi
,
i
;
volatile
int
j
=
0
;
crhi
=
c
->
apicid
<<
24
;
lapic_write
(
LAPIC_ICRHI
,
crhi
);
lapic_write
(
LAPIC_ICRLO
,
LAPIC_FIELD
|
APIC_LEVEL
|
LAPIC_ASSERT
|
APIC_INIT
);
while
(
j
++
<
10000
)
{;}
lapic_write
(
LAPIC_ICRLO
,
LAPIC_FIELD
|
APIC_LEVEL
|
LAPIC_DEASSERT
|
APIC_INIT
);
while
(
j
++
<
1000000
)
{;}
// in p9 code, this was i < 2, which is what the spec says on page B-3
for
(
i
=
0
;
i
<
1
;
i
++
){
lapic_write
(
LAPIC_ICRHI
,
crhi
);
lapic_write
(
LAPIC_ICRLO
,
LAPIC_FIELD
|
APIC_EDGE
|
APIC_STARTUP
|
(
v
/
PGSIZE
));
while
(
j
++
<
100000
)
{;}
}
}
static
struct
MP
*
mp_scan
(
uint8_t
*
addr
,
int
len
)
{
uint8_t
*
e
,
*
p
,
sum
;
...
...
@@ -14,24 +204,24 @@ mp_scan(uint8_t *addr, int len)
cprintf
(
"scanning: 0x%x
\n
"
,
(
uint32_t
)
addr
);
e
=
addr
+
len
;
for
(
p
=
addr
;
p
<
e
;
p
+=
sizeof
(
struct
_MP_
)){
for
(
p
=
addr
;
p
<
e
;
p
+=
sizeof
(
struct
MP
)){
if
(
memcmp
(
p
,
"_MP_"
,
4
))
continue
;
sum
=
0
;
for
(
i
=
0
;
i
<
sizeof
(
struct
_MP_
);
i
++
)
for
(
i
=
0
;
i
<
sizeof
(
struct
MP
);
i
++
)
sum
+=
p
[
i
];
if
(
sum
==
0
)
return
(
struct
_MP_
*
)
p
;
return
(
struct
MP
*
)
p
;
}
return
0
;
}
static
struct
_MP_
*
static
struct
MP
*
mp_search
(
void
)
{
uint8_t
*
bda
;
uint32_t
p
;
struct
_MP_
*
mp
;
struct
MP
*
mp
;
/*
* Search for the MP Floating Pointer Structure, which according to the
...
...
@@ -56,7 +246,7 @@ mp_search(void)
static
int
mp_detect
(
void
)
{
struct
PCMP
*
pcmp
;
struct
MPCTB
*
pcmp
;
uint8_t
*
p
,
sum
;
uint32_t
length
;
...
...
@@ -67,10 +257,10 @@ mp_detect(void)
* if correct, check the version.
* To do: check extended table checksum.
*/
if
((
_mp_
=
mp_search
())
==
0
||
_mp_
->
physaddr
==
0
)
if
((
mp
=
mp_search
())
==
0
||
mp
->
physaddr
==
0
)
return
1
;
pcmp
=
KADDR
(
_mp_
->
physaddr
);
pcmp
=
KADDR
(
mp
->
physaddr
);
if
(
memcmp
(
pcmp
,
"PCMP"
,
4
))
return
2
;
...
...
@@ -82,48 +272,65 @@ mp_detect(void)
if
(
sum
||
(
pcmp
->
version
!=
1
&&
pcmp
->
version
!=
4
))
return
3
;
cprintf
(
"MP spec rev #: %x
\n
"
,
_mp_
->
specrev
);
cprintf
(
"MP spec rev #: %x
\n
"
,
mp
->
specrev
);
return
0
;
}
int
mp_isbcpu
()
{
if
(
bcpu
==
0
)
return
1
;
else
return
0
;
}
void
mpinit
()
mp
_
init
()
{
int
r
;
uint8_t
*
p
,
*
e
;
struct
PCMP
*
pcmp
;
struct
MPCTB
*
mpctb
;
struct
MPPE
*
proc
;
struct
cpu
*
c
;
ncpu
=
0
;
if
((
r
=
mp_detect
())
!=
0
)
return
;
cprintf
(
"This computer is multiprocessor!
\n
"
);
cprintf
(
"This computer is a multiprocessor!
\n
"
);
/*
* 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.
*/
pcmp
=
KADDR
(
_mp_
->
physaddr
);
p
=
((
uint8_t
*
)
pcmp
)
+
sizeof
(
struct
PCMP
);
e
=
((
uint8_t
*
)
pcmp
)
+
pcmp
->
length
;
mpctb
=
KADDR
(
mp
->
physaddr
);
lapicaddr
=
KADDR
(
mpctb
->
lapicaddr
);
cprintf
(
"apicaddr: %x
\n
"
,
lapicaddr
);
p
=
((
uint8_t
*
)
mpctb
)
+
sizeof
(
struct
MPCTB
);
e
=
((
uint8_t
*
)
mpctb
)
+
mpctb
->
length
;
while
(
p
<
e
)
{
switch
(
*
p
){
case
PcmpPROCESSOR
:
cprintf
(
"a processor
\n
"
);
case
MPPROCESSOR
:
proc
=
(
struct
MPPE
*
)
p
;
cpu
[
ncpu
].
apicid
=
proc
->
apicid
;
cpu
[
ncpu
].
lintr
[
0
]
=
APIC_IMASK
;
cpu
[
ncpu
].
lintr
[
1
]
=
APIC_IMASK
;
cprintf
(
"a processor %x
\n
"
,
cpu
[
ncpu
].
apicid
);
if
(
proc
->
flags
&
MPBP
)
{
bcpu
=
&
cpu
[
ncpu
];
}
ncpu
++
;
p
+=
sizeof
(
struct
PCMPprocessor
);
p
+=
sizeof
(
struct
MPPE
);
continue
;
case
PcmpBUS
:
cprintf
(
"a bus
\n
"
);
p
+=
sizeof
(
struct
PCMPbus
);
case
MPBUS
:
p
+=
sizeof
(
struct
MPBE
);
continue
;
case
Pcmp
IOAPIC
:
cprintf
(
"an IO APIC
\n
"
);
p
+=
sizeof
(
struct
PCMPioapic
);
case
MP
IOAPIC
:
cprintf
(
"an I
/
O APIC
\n
"
);
p
+=
sizeof
(
struct
MPIOAPIC
);
continue
;
case
PcmpIOINTR
:
cprintf
(
"an IO interrupt assignment
\n
"
);
p
+=
sizeof
(
struct
PCMPintr
);
case
MPIOINTR
:
p
+=
sizeof
(
struct
MPIE
);
continue
;
default:
cprintf
(
"mpinit: unknown PCMP type 0x%x (e-p 0x%x)
\n
"
,
*
p
,
e
-
p
);
...
...
@@ -134,6 +341,23 @@ mpinit()
break
;
}
}
lapic_init
(
cpu
-
bcpu
);
cprintf
(
"ncpu: %d boot %d
\n
"
,
ncpu
,
cpu
-
bcpu
);
cprintf
(
"ncpu: %d
\n
"
,
ncpu
);
lapic_online
();
extern
uint8_t
_binary_bootother_start
[],
_binary_bootother_size
[];
memmove
(
KADDR
(
APBOOTCODE
),
_binary_bootother_start
,
(
uint32_t
)
_binary_bootother_size
);
acquire_spinlock
(
&
kernel_lock
);
for
(
c
=
cpu
;
c
<
&
cpu
[
ncpu
];
c
++
)
{
if
(
c
==
bcpu
)
continue
;
cprintf
(
"starting processor %d
\n
"
,
c
-
cpu
);
release_grant_spinlock
(
&
kernel_lock
,
c
-
cpu
);
lapic_startap
(
c
,
(
uint32_t
)
KADDR
(
APBOOTCODE
));
acquire_spinlock
(
&
kernel_lock
);
cprintf
(
"done starting processor %d
\n
"
,
c
-
cpu
);
}
}
mp.h
浏览文件 @
21a88fd4
/*
* MultiProcessor Specification Version 1.[14].
*
* Credit: Plan 9 sources
*/
struct
_MP_
{
/* floating pointer */
struct
MP
{
/* floating pointer */
uint8_t
signature
[
4
];
/* "_MP_" */
physaddr_t
physaddr
;
/* physical address of MP configuration table */
uint8_t
length
;
/* 1 */
...
...
@@ -12,7 +15,7 @@ struct _MP_ { /* floating pointer */
uint8_t
reserved
[
3
];
};
struct
PCMP
{
/* configuration table header */
struct
MPCTB
{
/* configuration table header */
uint8_t
signature
[
4
];
/* "PCMP" */
uint16_t
length
;
/* total table length */
uint8_t
version
;
/* [14] */
...
...
@@ -21,15 +24,15 @@ struct PCMP { /* configuration table header */
uintptr_t
oemtable
;
/* OEM table pointer */
uint16_t
oemlength
;
/* OEM table length */
uint16_t
entry
;
/* entry count */
uintptr_t
lapic
base
;
/* address of local APIC */
uintptr_t
lapic
addr
;
/* address of local APIC */
uint16_t
xlength
;
/* extended table length */
uint8_t
xchecksum
;
/* extended table checksum */
uint8_t
reserved
;
};
struct
PCMPprocessor
{
/* processor table entry */
struct
MPPE
{
/* processor table entry */
uint8_t
type
;
/* entry type (0) */
uint8_t
apic
no
;
/* local APIC id */
uint8_t
apic
id
;
/* local APIC id */
uint8_t
version
;
/* local APIC verison */
uint8_t
flags
;
/* CPU flags */
uint8_t
signature
[
4
];
/* CPU signature */
...
...
@@ -37,13 +40,13 @@ struct PCMPprocessor { /* processor table entry */
uint8_t
reserved
[
8
];
};
struct
PCMPbus
{
/* bus table entry */
struct
MPBE
{
/* bus table entry */
uint8_t
type
;
/* entry type (1) */
uint8_t
busno
;
/* bus id */
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
apicno
;
/* I/O APIC id */
uint8_t
version
;
/* I/O APIC version */
...
...
@@ -51,7 +54,7 @@ struct PCMPioapic { /* I/O APIC table entry */
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
intr
;
/* interrupt type */
uint16_t
flags
;
/* interrupt flag */
...
...
@@ -61,71 +64,34 @@ struct PCMPintr { /* interrupt table entry */
uint8_t
intin
;
/* destination APIC [L]INTIN# */
};
struct
PCMPsasm
{
/* system address space mapping entry */
uint8_t
type
;
/* entry type (128) */
uint8_t
length
;
/* of this entry (20) */
uint8_t
busno
;
/* bus id */
uint8_t
addrtype
;
uintptr_t
addrbase
[
2
];
uint32_t
addrlength
[
2
];
};
struct
PCMPhierarchy
{
/* bus hierarchy descriptor entry */
uint8_t
type
;
/* entry type (129) */
uint8_t
length
;
/* of this entry (8) */
uint8_t
busno
;
/* bus id */
uint8_t
info
;
/* bus info */
uint8_t
parent
;
/* parent bus */
uint8_t
reserved
[
3
];
};
struct
PCMPcbasm
{
/* compatibility bus address space modifier entry */
uint8_t
type
;
/* entry type (130) */
uint8_t
length
;
/* of this entry (8) */
uint8_t
busno
;
/* bus id */
uint8_t
modifier
;
/* address modifier */
uint32_t
range
;
/* predefined range list */
};
enum
{
/* table entry types */
PcmpPROCESSOR
=
0x00
,
/* one entry per processor */
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 */
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 */
/* 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 */
};
/*
...
...
@@ -136,23 +102,23 @@ enum { /* table entry types */
* Local APIC Timer Vector Table.
*/
enum
{
A
pic
FIXED
=
0x00000000
,
/* [10:8] Delivery Mode */
A
pic
LOWEST
=
0x00000100
,
/* Lowest priority */
A
pic
SMI
=
0x00000200
,
/* System Management Interrupt */
A
pic
RR
=
0x00000300
,
/* Remote Read */
A
pic
NMI
=
0x00000400
,
A
pic
INIT
=
0x00000500
,
/* INIT/RESET */
A
pic
STARTUP
=
0x00000600
,
/* Startup IPI */
A
pic
ExtINT
=
0x00000700
,
A
pic
PHYSICAL
=
0x00000000
,
/* [11] Destination Mode (RW) */
A
pic
LOGICAL
=
0x00000800
,
A
pic
DELIVS
=
0x00001000
,
/* [12] Delivery Status (RO) */
A
pic
HIGH
=
0x00000000
,
/* [13] Interrupt Input Pin Polarity (RW) */
A
pic
LOW
=
0x00002000
,
A
pic
RemoteIRR
=
0x00004000
,
/* [14] Remote IRR (RO) */
A
pic
EDGE
=
0x00000000
,
/* [15] Trigger Mode (RW) */
A
pic
LEVEL
=
0x00008000
,
A
pic
IMASK
=
0x00010000
,
/* [16] Interrupt Mask */
A
PIC_
FIXED
=
0x00000000
,
/* [10:8] Delivery Mode */
A
PIC_
LOWEST
=
0x00000100
,
/* Lowest priority */
A
PIC_
SMI
=
0x00000200
,
/* System Management Interrupt */
A
PIC_
RR
=
0x00000300
,
/* Remote Read */
A
PIC_
NMI
=
0x00000400
,
A
PIC_
INIT
=
0x00000500
,
/* INIT/RESET */
A
PIC_
STARTUP
=
0x00000600
,
/* Startup IPI */
A
PIC_
ExtINT
=
0x00000700
,
A
PIC_
PHYSICAL
=
0x00000000
,
/* [11] Destination Mode (RW) */
A
PIC_
LOGICAL
=
0x00000800
,
A
PIC_
DELIVS
=
0x00001000
,
/* [12] Delivery Status (RO) */
A
PIC_
HIGH
=
0x00000000
,
/* [13] Interrupt Input Pin Polarity (RW) */
A
PIC_
LOW
=
0x00002000
,
A
PIC_
RemoteIRR
=
0x00004000
,
/* [14] Remote IRR (RO) */
A
PIC_
EDGE
=
0x00000000
,
/* [15] Trigger Mode (RW) */
A
PIC_
LEVEL
=
0x00008000
,
A
PIC_
IMASK
=
0x00010000
,
/* [16] Interrupt Mask */
};
param.h
浏览文件 @
21a88fd4
#define NPROC 64
#define PAGE 4096
#define KSTACKSIZE PAGE
#define NCPU 8
picirq.c
浏览文件 @
21a88fd4
...
...
@@ -4,15 +4,6 @@
#include "x86.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.
// Initial IRQ mask has interrupt 2 enabled (for slave 8259A).
uint16_t
irq_mask_8259A
=
0xFFFF
&
~
(
1
<<
IRQ_SLAVE
);
...
...
spinlock.c
0 → 100644
浏览文件 @
21a88fd4
#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
;
}
string.c
浏览文件 @
21a88fd4
...
...
@@ -38,3 +38,23 @@ memcmp(const void *v1, const void *v2, unsigned n)
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
;
}
trapasm.S
浏览文件 @
21a88fd4
...
...
@@ -27,3 +27,8 @@ trapret:
popl %ds
addl $0x8, %esp /* trapno and errcode */
iret
.globl acpu
acpu:
.long 0
x86.h
浏览文件 @
21a88fd4
...
...
@@ -261,6 +261,17 @@ cpuid(uint32_t info, uint32_t *eaxp, uint32_t *ebxp, uint32_t *ecxp, uint32_t *e
*
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
read_tsc
(
void
)
{
...
...
@@ -299,3 +310,16 @@ struct Trapframe {
uint16_t
tf_ss
;
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
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论