Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
X
xv6-public
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
问题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
银宸时代
OS Lab Group
奖励实验
xv6-public
提交
a8efbd38
提交
a8efbd38
4月 19, 2012
创建
作者:
Silas Boyd-Wickizer
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Some x2apic code. Once it works we can merge with the xapic code
上级
30e53e7a
显示空白字符变更
内嵌
并排
正在显示
1 个修改的文件
包含
126 行增加
和
6 行删除
+126
-6
x2apic.cc
kernel/x2apic.cc
+126
-6
没有找到文件。
kernel/x2apic.cc
浏览文件 @
a8efbd38
...
@@ -2,17 +2,85 @@
...
@@ -2,17 +2,85 @@
#include "amd64.h"
#include "amd64.h"
#include "bits.hh"
#include "bits.hh"
#include "kernel.hh"
#include "kernel.hh"
#include "traps.h"
#define ID 0x802 // ID
#define VER 0x803 // Version
#define TPR 0x808 // Task Priority
#define EOI 0x80b // EOI
#define SVR 0x80f // Spurious Interrupt Vector
#define ENABLE 0x00000100 // Unit Enable
#define ESR 0x828 // Error Status
#define ICR 0x830 // Interrupt Command
#define INIT 0x00000500 // INIT/RESET
#define STARTUP 0x00000600 // Startup IPI
#define BCAST 0x00080000 // Send to all APICs, including self.
#define LEVEL 0x00008000 // Level triggered
// #define DELIVS 0x00001000 // Delivery status
#define ASSERT 0x00004000 // Assert interrupt (vs deassert)
#define TIMER 0x832 // Local Vector Table 0 (TIMER)
#define X1 0x0000000B // divide counts by 1
#define PERIODIC 0x00020000 // Periodic
#define PCINT 0x834 // Performance Counter LVT
#define LINT0 0x835 // Local Vector Table 1 (LINT0)
#define LINT1 0x836 // Local Vector Table 2 (LINT1)
#define ERROR 0x837 // Local Vector Table 3 (ERROR)
#define MASKED 0x00010000 // Interrupt masked
#define MT_NMI 0x00000400 // NMI message type
#define MT_FIX 0x00000000 // Fixed message type
#define TICR 0x838 // Timer Initial Count
#define TCCR 0x839 // Timer Current Count
#define TDCR 0x83e // Timer Divide Configuration
#define IO_RTC 0x70
static
u64
x2apichz
;
void
void
x2apicstartap
(
hwid_t
id
,
u32
addr
)
x2apicstartap
(
hwid_t
id
,
u32
addr
)
{
{
panic
(
"x2apicstartap"
);
int
i
;
volatile
u16
*
wrv
;
// "The BSP must initialize CMOS shutdown code to 0AH
// and the warm reset vector (DWORD based at 40:67) to point at
// the AP startup code prior to the [universal startup algorithm]."
outb
(
IO_RTC
,
0xF
);
// offset 0xF is shutdown code
outb
(
IO_RTC
+
1
,
0x0A
);
wrv
=
(
u16
*
)(
0x40
<<
4
|
0x67
);
// Warm reset vector
wrv
[
0
]
=
0
;
wrv
[
1
]
=
addr
>>
4
;
// "Universal startup algorithm."
// Send INIT (level-triggered) interrupt to reset other CPU.
writemsr
(
ICR
,
(((
u64
)
id
.
num
)
<<
32
)
|
INIT
|
LEVEL
|
ASSERT
);
//xapicwait();
microdelay
(
10000
);
writemsr
(
ICR
,
(((
u64
)
id
.
num
)
<<
32
)
|
INIT
|
LEVEL
);
//xapicw(ICRLO, hwid.num |INIT | LEVEL);
//xapicwait();
microdelay
(
10000
);
// should be 10ms, but too slow in Bochs!
// Send startup IPI (twice!) to enter bootstrap code.
// Regular hardware is supposed to only accept a STARTUP
// when it is in the halted state due to an INIT. So the second
// should be ignored, but it is part of the official Intel algorithm.
// Bochs complains about the second one. Too bad for Bochs.
for
(
i
=
0
;
i
<
2
;
i
++
){
//xapicw(ICRHI, hwid.num<<24);
//xapicw(ICRLO, STARTUP | (addr>>12));
writemsr
(
ICR
,
(((
u64
)
id
.
num
)
<<
32
)
|
STARTUP
|
(
addr
>>
12
));
microdelay
(
200
);
}
}
}
void
void
x2apiceoi
(
void
)
x2apiceoi
(
void
)
{
{
panic
(
"x2apiceoi"
);
writemsr
(
EOI
,
0
);
}
}
void
void
...
@@ -30,18 +98,70 @@ x2apic_sampconf(hwid_t id)
...
@@ -30,18 +98,70 @@ x2apic_sampconf(hwid_t id)
void
void
x2apicpc
(
char
mask
)
x2apicpc
(
char
mask
)
{
{
panic
(
"x2apicpc"
);
writemsr
(
PCINT
,
mask
?
MASKED
:
MT_NMI
);
}
}
hwid_t
hwid_t
x2apicid
(
void
)
x2apicid
(
void
)
{
{
panic
(
"x2apicid"
);
u64
id
=
readmsr
(
ID
);
return
HWID
(
0
);
return
HWID
(
(
u32
)
id
);
}
}
void
void
initx2apic
(
void
)
initx2apic
(
void
)
{
{
panic
(
"initx2apic"
);
u64
count
;
// Enable local APIC; set spurious interrupt vector.
writemsr
(
SVR
,
ENABLE
|
(
T_IRQ0
+
IRQ_SPURIOUS
));
if
(
x2apichz
==
0
)
{
// Measure the TICR frequency
writemsr
(
TDCR
,
X1
);
writemsr
(
TICR
,
0xffffffff
);
u64
ccr0
=
readmsr
(
TCCR
);
microdelay
(
10
*
1000
);
// 1/100th of a second
u64
ccr1
=
readmsr
(
TCCR
);
x2apichz
=
100
*
(
ccr0
-
ccr1
);
}
count
=
(
QUANTUM
*
x2apichz
)
/
1000
;
if
(
count
>
0xffffffff
)
panic
(
"initxapic: QUANTUM too large"
);
// The timer repeatedly counts down at bus frequency
// from xapic[TICR] and then issues an interrupt.
writemsr
(
TDCR
,
X1
);
writemsr
(
TIMER
,
PERIODIC
|
(
T_IRQ0
+
IRQ_TIMER
));
writemsr
(
TICR
,
count
);
// Disable logical interrupt lines.
writemsr
(
LINT0
,
MASKED
);
writemsr
(
LINT1
,
MASKED
);
// Disable performance counter overflow interrupts
// on machines that provide that interrupt entry.
if
(((
readmsr
(
VER
)
>>
16
)
&
0xFF
)
>=
4
)
x2apicpc
(
0
);
// Map error interrupt to IRQ_ERROR.
writemsr
(
ERROR
,
T_IRQ0
+
IRQ_ERROR
);
// Clear error status register (requires back-to-back writes).
writemsr
(
ESR
,
0
);
writemsr
(
ESR
,
0
);
// Ack any outstanding interrupts.
writemsr
(
EOI
,
0
);
// Send an Init Level De-Assert to synchronise arbitration ID's.
writemsr
(
ICR
,
BCAST
|
INIT
|
LEVEL
);
#if 0 // XXX(sbw) now need to poll anymore
while (readmsr(ICR) & DELIVS)
;
#endif
// Enable interrupts on the APIC (but not on the processor).
writemsr
(
TPR
,
0
);
}
}
编写
预览
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论