Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
X
xv6-public
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
问题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
银宸时代
OS Lab Group
奖励实验
xv6-public
提交
d9872ffa
提交
d9872ffa
7月 12, 2006
创建
作者:
kaashoek
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
and the file
上级
f27a68a2
隐藏空白字符变更
内嵌
并排
正在显示
1 个修改的文件
包含
204 行增加
和
0 行删除
+204
-0
lapic.c
lapic.c
+204
-0
没有找到文件。
lapic.c
0 → 100644
浏览文件 @
d9872ffa
#include "types.h"
#include "mp.h"
#include "defs.h"
#include "memlayout.h"
#include "param.h"
#include "x86.h"
#include "traps.h"
#include "mmu.h"
#include "proc.h"
/*
* 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 */
};
uint32_t
*
lapicaddr
;
static
int
lapic_read
(
int
r
)
{
return
*
(
lapicaddr
+
(
r
/
sizeof
(
*
lapicaddr
)));
}
static
void
lapic_write
(
int
r
,
int
data
)
{
*
(
lapicaddr
+
(
r
/
sizeof
(
*
lapicaddr
)))
=
data
;
}
void
lapic_timerinit
()
{
cprintf
(
"%d: init timer
\n
"
,
cpu
());
lapic_write
(
LAPIC_TDCR
,
LAPIC_X1
);
lapic_write
(
LAPIC_TIMER
,
LAPIC_CLKIN
|
LAPIC_PERIODIC
|
(
IRQ_OFFSET
+
IRQ_TIMER
));
lapic_write
(
LAPIC_TCCR
,
10000000
);
lapic_write
(
LAPIC_TICR
,
10000000
);
}
void
lapic_timerintr
()
{
cprintf
(
"%d: timer interrupt!
\n
"
,
cpu
());
lapic_write
(
LAPIC_EOI
,
0
);
}
void
lapic_init
(
int
c
)
{
uint32_t
r
,
lvt
;
cprintf
(
"lapic_init %d
\n
"
,
c
);
lapic_write
(
LAPIC_DFR
,
0xFFFFFFFF
);
// set destination format register
r
=
(
lapic_read
(
LAPIC_ID
)
>>
24
)
&
0xFF
;
// read APIC ID
lapic_write
(
LAPIC_LDR
,
(
1
<<
r
)
<<
24
);
// set logical destination register to r
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:
lapic_write
(
LAPIC_LINT0
,
APIC_IMASK
|
APIC_EXTINT
);
lapic_write
(
LAPIC_LINT1
,
APIC_IMASK
|
APIC_NMI
);
lapic_write
(
LAPIC_EOI
,
0
);
// acknowledge any outstanding interrupts.
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
)
;
cprintf
(
"Done init of an apic
\n
"
);
}
void
lapic_enableintr
(
void
)
{
lapic_write
(
LAPIC_TPR
,
0
);
}
void
lapic_disableintr
(
void
)
{
lapic_write
(
LAPIC_TPR
,
0xFF
);
}
int
cpu
(
void
)
{
return
(
lapic_read
(
LAPIC_ID
)
>>
24
)
&
0xFF
;
}
void
lapic_startap
(
uint8_t
apicid
,
int
v
)
{
int
crhi
,
i
;
volatile
int
j
=
0
;
crhi
=
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
)
{;}
}
}
编写
预览
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论