Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
42d5f99b
K
Kernel
项目概览
openeuler
/
Kernel
大约 1 年 前同步成功
通知
5
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
42d5f99b
编写于
10月 13, 2007
作者:
D
David S. Miller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[SPARC64]: Only use bypass accesses to INO buckets.
Signed-off-by:
N
David S. Miller
<
davem@davemloft.net
>
上级
f14356de
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
91 addition
and
33 deletion
+91
-33
arch/sparc64/kernel/irq.c
arch/sparc64/kernel/irq.c
+91
-31
arch/sparc64/mm/init.c
arch/sparc64/mm/init.c
+0
-2
未找到文件。
arch/sparc64/kernel/irq.c
浏览文件 @
42d5f99b
...
@@ -42,6 +42,7 @@
...
@@ -42,6 +42,7 @@
#include <asm/auxio.h>
#include <asm/auxio.h>
#include <asm/head.h>
#include <asm/head.h>
#include <asm/hypervisor.h>
#include <asm/hypervisor.h>
#include <asm/cacheflush.h>
/* UPA nodes send interrupt packet to UltraSparc with first data reg
/* UPA nodes send interrupt packet to UltraSparc with first data reg
* value low 5 (7 on Starfire) bits holding the IRQ identifier being
* value low 5 (7 on Starfire) bits holding the IRQ identifier being
...
@@ -56,10 +57,10 @@
...
@@ -56,10 +57,10 @@
* of the vectored interrupt trap handler(s) in entry.S and sun4v_ivec.S
* of the vectored interrupt trap handler(s) in entry.S and sun4v_ivec.S
*/
*/
struct
ino_bucket
{
struct
ino_bucket
{
/*0x00*/
unsigned
long
irq_chain_pa
;
/*0x00*/
unsigned
long
__
irq_chain_pa
;
/* Virtual interrupt number assigned to this INO. */
/* Virtual interrupt number assigned to this INO. */
/*0x08*/
unsigned
int
virt_irq
;
/*0x08*/
unsigned
int
__
virt_irq
;
/*0x0c*/
unsigned
int
__pad
;
/*0x0c*/
unsigned
int
__pad
;
};
};
...
@@ -67,6 +68,60 @@ struct ino_bucket {
...
@@ -67,6 +68,60 @@ struct ino_bucket {
struct
ino_bucket
*
ivector_table
;
struct
ino_bucket
*
ivector_table
;
unsigned
long
ivector_table_pa
;
unsigned
long
ivector_table_pa
;
/* On several sun4u processors, it is illegal to mix bypass and
* non-bypass accesses. Therefore we access all INO buckets
* using bypass accesses only.
*/
static
unsigned
long
bucket_get_chain_pa
(
unsigned
long
bucket_pa
)
{
unsigned
long
ret
;
__asm__
__volatile__
(
"ldxa [%1] %2, %0"
:
"=&r"
(
ret
)
:
"r"
(
bucket_pa
+
offsetof
(
struct
ino_bucket
,
__irq_chain_pa
)),
"i"
(
ASI_PHYS_USE_EC
));
return
ret
;
}
static
void
bucket_clear_chain_pa
(
unsigned
long
bucket_pa
)
{
__asm__
__volatile__
(
"stxa %%g0, [%0] %1"
:
/* no outputs */
:
"r"
(
bucket_pa
+
offsetof
(
struct
ino_bucket
,
__irq_chain_pa
)),
"i"
(
ASI_PHYS_USE_EC
));
}
static
unsigned
int
bucket_get_virt_irq
(
unsigned
long
bucket_pa
)
{
unsigned
int
ret
;
__asm__
__volatile__
(
"lduwa [%1] %2, %0"
:
"=&r"
(
ret
)
:
"r"
(
bucket_pa
+
offsetof
(
struct
ino_bucket
,
__virt_irq
)),
"i"
(
ASI_PHYS_USE_EC
));
return
ret
;
}
static
void
bucket_set_virt_irq
(
unsigned
long
bucket_pa
,
unsigned
int
virt_irq
)
{
__asm__
__volatile__
(
"stwa %0, [%1] %2"
:
/* no outputs */
:
"r"
(
virt_irq
),
"r"
(
bucket_pa
+
offsetof
(
struct
ino_bucket
,
__virt_irq
)),
"i"
(
ASI_PHYS_USE_EC
));
}
#define __irq_ino(irq) \
#define __irq_ino(irq) \
(((struct ino_bucket *)(irq)) - &ivector_table[0])
(((struct ino_bucket *)(irq)) - &ivector_table[0])
#define __bucket(irq) ((struct ino_bucket *)(irq))
#define __bucket(irq) ((struct ino_bucket *)(irq))
...
@@ -569,18 +624,21 @@ unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap)
...
@@ -569,18 +624,21 @@ unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap)
{
{
struct
ino_bucket
*
bucket
;
struct
ino_bucket
*
bucket
;
struct
irq_handler_data
*
data
;
struct
irq_handler_data
*
data
;
unsigned
int
virt_irq
;
int
ino
;
int
ino
;
BUG_ON
(
tlb_type
==
hypervisor
);
BUG_ON
(
tlb_type
==
hypervisor
);
ino
=
(
upa_readq
(
imap
)
&
(
IMAP_IGN
|
IMAP_INO
))
+
inofixup
;
ino
=
(
upa_readq
(
imap
)
&
(
IMAP_IGN
|
IMAP_INO
))
+
inofixup
;
bucket
=
&
ivector_table
[
ino
];
bucket
=
&
ivector_table
[
ino
];
if
(
!
bucket
->
virt_irq
)
{
virt_irq
=
bucket_get_virt_irq
(
__pa
(
bucket
));
bucket
->
virt_irq
=
virt_irq_alloc
(
__irq
(
bucket
));
if
(
!
virt_irq
)
{
set_irq_chip
(
bucket
->
virt_irq
,
&
sun4u_irq
);
virt_irq
=
virt_irq_alloc
(
__irq
(
bucket
));
bucket_set_virt_irq
(
__pa
(
bucket
),
virt_irq
);
set_irq_chip
(
virt_irq
,
&
sun4u_irq
);
}
}
data
=
get_irq_chip_data
(
bucket
->
virt_irq
);
data
=
get_irq_chip_data
(
virt_irq
);
if
(
unlikely
(
data
))
if
(
unlikely
(
data
))
goto
out
;
goto
out
;
...
@@ -589,13 +647,13 @@ unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap)
...
@@ -589,13 +647,13 @@ unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap)
prom_printf
(
"IRQ: kzalloc(irq_handler_data) failed.
\n
"
);
prom_printf
(
"IRQ: kzalloc(irq_handler_data) failed.
\n
"
);
prom_halt
();
prom_halt
();
}
}
set_irq_chip_data
(
bucket
->
virt_irq
,
data
);
set_irq_chip_data
(
virt_irq
,
data
);
data
->
imap
=
imap
;
data
->
imap
=
imap
;
data
->
iclr
=
iclr
;
data
->
iclr
=
iclr
;
out:
out:
return
bucket
->
virt_irq
;
return
virt_irq
;
}
}
static
unsigned
int
sun4v_build_common
(
unsigned
long
sysino
,
static
unsigned
int
sun4v_build_common
(
unsigned
long
sysino
,
...
@@ -603,16 +661,19 @@ static unsigned int sun4v_build_common(unsigned long sysino,
...
@@ -603,16 +661,19 @@ static unsigned int sun4v_build_common(unsigned long sysino,
{
{
struct
ino_bucket
*
bucket
;
struct
ino_bucket
*
bucket
;
struct
irq_handler_data
*
data
;
struct
irq_handler_data
*
data
;
unsigned
int
virt_irq
;
BUG_ON
(
tlb_type
!=
hypervisor
);
BUG_ON
(
tlb_type
!=
hypervisor
);
bucket
=
&
ivector_table
[
sysino
];
bucket
=
&
ivector_table
[
sysino
];
if
(
!
bucket
->
virt_irq
)
{
virt_irq
=
bucket_get_virt_irq
(
__pa
(
bucket
));
bucket
->
virt_irq
=
virt_irq_alloc
(
__irq
(
bucket
));
if
(
!
virt_irq
)
{
set_irq_chip
(
bucket
->
virt_irq
,
chip
);
virt_irq
=
virt_irq_alloc
(
__irq
(
bucket
));
bucket_set_virt_irq
(
__pa
(
bucket
),
virt_irq
);
set_irq_chip
(
virt_irq
,
chip
);
}
}
data
=
get_irq_chip_data
(
bucket
->
virt_irq
);
data
=
get_irq_chip_data
(
virt_irq
);
if
(
unlikely
(
data
))
if
(
unlikely
(
data
))
goto
out
;
goto
out
;
...
@@ -621,7 +682,7 @@ static unsigned int sun4v_build_common(unsigned long sysino,
...
@@ -621,7 +682,7 @@ static unsigned int sun4v_build_common(unsigned long sysino,
prom_printf
(
"IRQ: kzalloc(irq_handler_data) failed.
\n
"
);
prom_printf
(
"IRQ: kzalloc(irq_handler_data) failed.
\n
"
);
prom_halt
();
prom_halt
();
}
}
set_irq_chip_data
(
bucket
->
virt_irq
,
data
);
set_irq_chip_data
(
virt_irq
,
data
);
/* Catch accidental accesses to these things. IMAP/ICLR handling
/* Catch accidental accesses to these things. IMAP/ICLR handling
* is done by hypervisor calls on sun4v platforms, not by direct
* is done by hypervisor calls on sun4v platforms, not by direct
...
@@ -631,7 +692,7 @@ static unsigned int sun4v_build_common(unsigned long sysino,
...
@@ -631,7 +692,7 @@ static unsigned int sun4v_build_common(unsigned long sysino,
data
->
iclr
=
~
0UL
;
data
->
iclr
=
~
0UL
;
out:
out:
return
bucket
->
virt_irq
;
return
virt_irq
;
}
}
unsigned
int
sun4v_build_irq
(
u32
devhandle
,
unsigned
int
devino
)
unsigned
int
sun4v_build_irq
(
u32
devhandle
,
unsigned
int
devino
)
...
@@ -646,19 +707,24 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
...
@@ -646,19 +707,24 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
struct
irq_handler_data
*
data
;
struct
irq_handler_data
*
data
;
struct
ino_bucket
*
bucket
;
struct
ino_bucket
*
bucket
;
unsigned
long
hv_err
,
cookie
;
unsigned
long
hv_err
,
cookie
;
unsigned
int
virt_irq
;
bucket
=
kzalloc
(
sizeof
(
struct
ino_bucket
),
GFP_ATOMIC
);
bucket
=
kzalloc
(
sizeof
(
struct
ino_bucket
),
GFP_ATOMIC
);
if
(
unlikely
(
!
bucket
))
if
(
unlikely
(
!
bucket
))
return
0
;
return
0
;
__flush_dcache_range
((
unsigned
long
)
bucket
,
((
unsigned
long
)
bucket
+
sizeof
(
struct
ino_bucket
)));
bucket
->
virt_irq
=
virt_irq_alloc
(
__irq
(
bucket
));
virt_irq
=
virt_irq_alloc
(
__irq
(
bucket
));
set_irq_chip
(
bucket
->
virt_irq
,
&
sun4v_virq
);
bucket_set_virt_irq
(
__pa
(
bucket
),
virt_irq
);
set_irq_chip
(
virt_irq
,
&
sun4v_virq
);
data
=
kzalloc
(
sizeof
(
struct
irq_handler_data
),
GFP_ATOMIC
);
data
=
kzalloc
(
sizeof
(
struct
irq_handler_data
),
GFP_ATOMIC
);
if
(
unlikely
(
!
data
))
if
(
unlikely
(
!
data
))
return
0
;
return
0
;
set_irq_chip_data
(
bucket
->
virt_irq
,
data
);
set_irq_chip_data
(
virt_irq
,
data
);
/* Catch accidental accesses to these things. IMAP/ICLR handling
/* Catch accidental accesses to these things. IMAP/ICLR handling
* is done by hypervisor calls on sun4v platforms, not by direct
* is done by hypervisor calls on sun4v platforms, not by direct
...
@@ -675,10 +741,10 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
...
@@ -675,10 +741,10 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
prom_halt
();
prom_halt
();
}
}
virt_to_real_irq_table
[
bucket
->
virt_irq
].
dev_handle
=
devhandle
;
virt_to_real_irq_table
[
virt_irq
].
dev_handle
=
devhandle
;
virt_to_real_irq_table
[
bucket
->
virt_irq
].
dev_ino
=
devino
;
virt_to_real_irq_table
[
virt_irq
].
dev_ino
=
devino
;
return
bucket
->
virt_irq
;
return
virt_irq
;
}
}
void
ack_bad_irq
(
unsigned
int
virt_irq
)
void
ack_bad_irq
(
unsigned
int
virt_irq
)
...
@@ -718,17 +784,9 @@ void handler_irq(int irq, struct pt_regs *regs)
...
@@ -718,17 +784,9 @@ void handler_irq(int irq, struct pt_regs *regs)
unsigned
long
next_pa
;
unsigned
long
next_pa
;
unsigned
int
virt_irq
;
unsigned
int
virt_irq
;
__asm__
__volatile__
(
"ldxa [%2] %4, %0
\n\t
"
next_pa
=
bucket_get_chain_pa
(
bucket_pa
);
"lduwa [%3] %4, %1
\n\t
"
virt_irq
=
bucket_get_virt_irq
(
bucket_pa
);
"stxa %%g0, [%2] %4"
bucket_clear_chain_pa
(
bucket_pa
);
:
"=&r"
(
next_pa
),
"=&r"
(
virt_irq
)
:
"r"
(
bucket_pa
+
offsetof
(
struct
ino_bucket
,
irq_chain_pa
)),
"r"
(
bucket_pa
+
offsetof
(
struct
ino_bucket
,
virt_irq
)),
"i"
(
ASI_PHYS_USE_EC
));
__do_IRQ
(
virt_irq
);
__do_IRQ
(
virt_irq
);
...
@@ -957,6 +1015,8 @@ void __init init_IRQ(void)
...
@@ -957,6 +1015,8 @@ void __init init_IRQ(void)
prom_printf
(
"Fatal error, cannot allocate ivector_table
\n
"
);
prom_printf
(
"Fatal error, cannot allocate ivector_table
\n
"
);
prom_halt
();
prom_halt
();
}
}
__flush_dcache_range
((
unsigned
long
)
ivector_table
,
((
unsigned
long
)
ivector_table
)
+
size
);
ivector_table_pa
=
__pa
(
ivector_table
);
ivector_table_pa
=
__pa
(
ivector_table
);
...
...
arch/sparc64/mm/init.c
浏览文件 @
42d5f99b
...
@@ -631,7 +631,6 @@ void prom_world(int enter)
...
@@ -631,7 +631,6 @@ void prom_world(int enter)
__asm__
__volatile__
(
"flushw"
);
__asm__
__volatile__
(
"flushw"
);
}
}
#ifdef DCACHE_ALIASING_POSSIBLE
void
__flush_dcache_range
(
unsigned
long
start
,
unsigned
long
end
)
void
__flush_dcache_range
(
unsigned
long
start
,
unsigned
long
end
)
{
{
unsigned
long
va
;
unsigned
long
va
;
...
@@ -655,7 +654,6 @@ void __flush_dcache_range(unsigned long start, unsigned long end)
...
@@ -655,7 +654,6 @@ void __flush_dcache_range(unsigned long start, unsigned long end)
"i"
(
ASI_DCACHE_INVALIDATE
));
"i"
(
ASI_DCACHE_INVALIDATE
));
}
}
}
}
#endif
/* DCACHE_ALIASING_POSSIBLE */
/* get_new_mmu_context() uses "cache + 1". */
/* get_new_mmu_context() uses "cache + 1". */
DEFINE_SPINLOCK
(
ctx_alloc_lock
);
DEFINE_SPINLOCK
(
ctx_alloc_lock
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录