Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
X
xv6-public
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
问题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
银宸时代
OS Lab Group
奖励实验
xv6-public
提交
532dd8db
提交
532dd8db
4月 24, 2012
创建
作者:
Silas Boyd-Wickizer
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
More Linux x2apic code
上级
f3f8c351
隐藏空白字符变更
内嵌
并排
正在显示
1 个修改的文件
包含
91 行增加
和
27 行删除
+91
-27
x2apic.cc
kernel/x2apic.cc
+91
-27
没有找到文件。
kernel/x2apic.cc
浏览文件 @
532dd8db
...
...
@@ -3,6 +3,7 @@
#include "bits.hh"
#include "kernel.hh"
#include "traps.h"
#include "cpu.hh"
#define ID 0x802 // ID
#define VER 0x803 // Version
...
...
@@ -10,13 +11,15 @@
#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 IRR 0x820
#define ISR 0x810
#define ISR_NR 0x8
#define ESR 0x828ull // Error Status
#define ICR 0x830ull // Interrupt Command
#define INIT 0x00000500ull // 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 LEVEL 0x00008000ull // Level triggered
#define ASSERT 0x00004000 // Assert interrupt (vs deassert)
#define TIMER 0x832 // Local Vector Table 0 (TIMER)
#define X1 0x0000000B // divide counts by 1
...
...
@@ -67,7 +70,7 @@ x2apicstartap(hwid_t id, u32 addr)
// Be paranoid about clearing APIC errors
writemsr
(
ESR
,
0
);
readmsr
(
ESR
);
unsigned
long
accept_status
;
int
maxlvt
=
x2apicmaxlvt
();
...
...
@@ -77,7 +80,6 @@ x2apicstartap(hwid_t id, u32 addr)
// "Universal startup algorithm."
// Send INIT (level-triggered) interrupt to reset other CPU.
// Asserting INIT
writemsr
(
ICR
,
(((
u64
)
id
.
num
)
<<
32
)
|
INIT
|
LEVEL
|
ASSERT
);
microdelay
(
10000
);
...
...
@@ -89,10 +91,8 @@ x2apicstartap(hwid_t id, u32 addr)
// 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
++
){
if
(
maxlvt
>
3
)
writemsr
(
ESR
,
0
);
writemsr
(
ESR
,
0
);
readmsr
(
ESR
);
// Kick the target chip
...
...
@@ -137,13 +137,92 @@ x2apicid(void)
return
HWID
((
u32
)
id
);
}
static
void
clearintr
(
void
)
{
// Clear any pending interrupts. Linux does this.
unsigned
int
value
,
queued
;
int
i
,
j
,
acked
=
0
;
unsigned
long
long
tsc
=
0
,
ntsc
;
long
long
max_loops
=
2400000
;
tsc
=
rdtsc
();
do
{
queued
=
0
;
for
(
i
=
ISR_NR
-
1
;
i
>=
0
;
i
--
)
queued
|=
readmsr
(
IRR
+
i
*
0x1
);
for
(
i
=
ISR_NR
-
1
;
i
>=
0
;
i
--
)
{
value
=
readmsr
(
ISR
+
i
*
0x1
);
for
(
j
=
31
;
j
>=
0
;
j
--
)
{
if
(
value
&
(
1
<<
j
))
{
x2apiceoi
();
acked
++
;
}
}
}
if
(
acked
>
256
)
{
cprintf
(
"x2apic pending interrupts after %d EOI
\n
"
,
acked
);
break
;
}
ntsc
=
rdtsc
();
max_loops
=
(
2400000
<<
10
)
-
(
ntsc
-
tsc
);
}
while
(
queued
&&
max_loops
>
0
);
}
// Code closely follows setup_local_APIC in Linux v3.3
void
initx2apic
(
void
)
{
u64
count
;
u32
value
;
int
maxlvt
;
// BIOS sanity checking
if
(
!
(
readmsr
(
MSR_APIC_BAR
)
&
APIC_BAR_X2APIC_EN
)
||
!
(
readmsr
(
MSR_APIC_BAR
)
&
APIC_BAR_XAPIC_EN
))
{
panic
(
"initx2apic: not enabled"
);
}
// Enable performance counter overflow interrupts for sampler.cc
x2apicpc
(
0
);
// Enable interrupts on the APIC (but not on the processor).
value
=
readmsr
(
TPR
);
value
&=
~
0xffU
;
writemsr
(
TPR
,
value
);
clearintr
();
// Enable local APIC; set spurious interrupt vector.
writemsr
(
SVR
,
ENABLE
|
(
T_IRQ0
+
IRQ_SPURIOUS
));
value
=
readmsr
(
SVR
);
value
&=
~
0x000FF
;
value
|=
ENABLE
;
value
|=
T_IRQ0
+
IRQ_SPURIOUS
;
writemsr
(
SVR
,
value
);
writemsr
(
LINT0
,
MT_EXTINT
|
MASKED
);
if
(
readmsr
(
ID
)
==
0
)
writemsr
(
LINT1
,
MT_NMI
);
else
writemsr
(
LINT1
,
MT_NMI
|
MASKED
);
maxlvt
=
x2apicmaxlvt
();
if
(
maxlvt
>
3
)
writemsr
(
ESR
,
0
);
// enables sending errors
value
=
T_IRQ0
+
IRQ_ERROR
;
writemsr
(
ERROR
,
value
);
if
(
maxlvt
>
3
)
writemsr
(
ESR
,
0
);
readmsr
(
ESR
);
// Send an Init Level De-Assert to synchronise arbitration ID's.
writemsr
(
ICR
,
BCAST
|
INIT
|
LEVEL
);
if
(
x2apichz
==
0
)
{
// Measure the TICR frequency
...
...
@@ -165,17 +244,6 @@ initx2apic(void)
writemsr
(
TIMER
,
PERIODIC
|
(
T_IRQ0
+
IRQ_TIMER
));
writemsr
(
TICR
,
count
);
// Disable logical interrupt lines.
writemsr
(
LINT0
,
MASKED
);
writemsr
(
LINT1
,
MASKED
);
// Enable performance counter overflow interrupts for sampler.cc
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
);
...
...
@@ -183,9 +251,5 @@ initx2apic(void)
// Ack any outstanding interrupts.
writemsr
(
EOI
,
0
);
// Send an Init Level De-Assert to synchronise arbitration ID's.
writemsr
(
ICR
,
BCAST
|
INIT
|
LEVEL
);
// Enable interrupts on the APIC (but not on the processor).
writemsr
(
TPR
,
0
);
return
;
}
编写
预览
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论