Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
cd774b90
K
Kernel
项目概览
openeuler
/
Kernel
1 年多 前同步成功
通知
8
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看板
提交
cd774b90
编写于
7月 26, 2016
作者:
M
Martin Schwidefsky
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
s390/mm,kvm: use nodat PGSTE tag to optimize TLB flushing
Signed-off-by:
N
Martin Schwidefsky
<
schwidefsky@de.ibm.com
>
上级
28c807e5
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
31 addition
and
17 deletion
+31
-17
arch/s390/include/asm/pgtable.h
arch/s390/include/asm/pgtable.h
+1
-0
arch/s390/mm/pgtable.c
arch/s390/mm/pgtable.c
+30
-17
未找到文件。
arch/s390/include/asm/pgtable.h
浏览文件 @
cd774b90
...
...
@@ -376,6 +376,7 @@ static inline int is_module_addr(void *addr)
/* Guest Page State used for virtualization */
#define _PGSTE_GPS_ZERO 0x0000000080000000UL
#define _PGSTE_GPS_NODAT 0x0000000040000000UL
#define _PGSTE_GPS_USAGE_MASK 0x0000000003000000UL
#define _PGSTE_GPS_USAGE_STABLE 0x0000000000000000UL
#define _PGSTE_GPS_USAGE_UNUSED 0x0000000001000000UL
...
...
arch/s390/mm/pgtable.c
浏览文件 @
cd774b90
...
...
@@ -26,14 +26,14 @@
#include <asm/page-states.h>
static
inline
void
ptep_ipte_local
(
struct
mm_struct
*
mm
,
unsigned
long
addr
,
pte_t
*
ptep
)
pte_t
*
ptep
,
int
nodat
)
{
unsigned
long
opt
,
asce
;
if
(
MACHINE_HAS_TLB_GUEST
)
{
opt
=
0
;
asce
=
READ_ONCE
(
mm
->
context
.
gmap_asce
);
if
(
asce
==
0UL
)
if
(
asce
==
0UL
||
nodat
)
opt
|=
IPTE_NODAT
;
if
(
asce
!=
-
1UL
)
{
asce
=
asce
?
:
mm
->
context
.
asce
;
...
...
@@ -46,14 +46,14 @@ static inline void ptep_ipte_local(struct mm_struct *mm, unsigned long addr,
}
static
inline
void
ptep_ipte_global
(
struct
mm_struct
*
mm
,
unsigned
long
addr
,
pte_t
*
ptep
)
pte_t
*
ptep
,
int
nodat
)
{
unsigned
long
opt
,
asce
;
if
(
MACHINE_HAS_TLB_GUEST
)
{
opt
=
0
;
asce
=
READ_ONCE
(
mm
->
context
.
gmap_asce
);
if
(
asce
==
0UL
)
if
(
asce
==
0UL
||
nodat
)
opt
|=
IPTE_NODAT
;
if
(
asce
!=
-
1UL
)
{
asce
=
asce
?
:
mm
->
context
.
asce
;
...
...
@@ -66,7 +66,8 @@ static inline void ptep_ipte_global(struct mm_struct *mm, unsigned long addr,
}
static
inline
pte_t
ptep_flush_direct
(
struct
mm_struct
*
mm
,
unsigned
long
addr
,
pte_t
*
ptep
)
unsigned
long
addr
,
pte_t
*
ptep
,
int
nodat
)
{
pte_t
old
;
...
...
@@ -76,15 +77,16 @@ static inline pte_t ptep_flush_direct(struct mm_struct *mm,
atomic_inc
(
&
mm
->
context
.
flush_count
);
if
(
MACHINE_HAS_TLB_LC
&&
cpumask_equal
(
mm_cpumask
(
mm
),
cpumask_of
(
smp_processor_id
())))
ptep_ipte_local
(
mm
,
addr
,
ptep
);
ptep_ipte_local
(
mm
,
addr
,
ptep
,
nodat
);
else
ptep_ipte_global
(
mm
,
addr
,
ptep
);
ptep_ipte_global
(
mm
,
addr
,
ptep
,
nodat
);
atomic_dec
(
&
mm
->
context
.
flush_count
);
return
old
;
}
static
inline
pte_t
ptep_flush_lazy
(
struct
mm_struct
*
mm
,
unsigned
long
addr
,
pte_t
*
ptep
)
unsigned
long
addr
,
pte_t
*
ptep
,
int
nodat
)
{
pte_t
old
;
...
...
@@ -97,7 +99,7 @@ static inline pte_t ptep_flush_lazy(struct mm_struct *mm,
pte_val
(
*
ptep
)
|=
_PAGE_INVALID
;
mm
->
context
.
flush_mm
=
1
;
}
else
ptep_ipte_global
(
mm
,
addr
,
ptep
);
ptep_ipte_global
(
mm
,
addr
,
ptep
,
nodat
);
atomic_dec
(
&
mm
->
context
.
flush_count
);
return
old
;
}
...
...
@@ -269,10 +271,12 @@ pte_t ptep_xchg_direct(struct mm_struct *mm, unsigned long addr,
{
pgste_t
pgste
;
pte_t
old
;
int
nodat
;
preempt_disable
();
pgste
=
ptep_xchg_start
(
mm
,
addr
,
ptep
);
old
=
ptep_flush_direct
(
mm
,
addr
,
ptep
);
nodat
=
!!
(
pgste_val
(
pgste
)
&
_PGSTE_GPS_NODAT
);
old
=
ptep_flush_direct
(
mm
,
addr
,
ptep
,
nodat
);
old
=
ptep_xchg_commit
(
mm
,
addr
,
ptep
,
pgste
,
old
,
new
);
preempt_enable
();
return
old
;
...
...
@@ -284,10 +288,12 @@ pte_t ptep_xchg_lazy(struct mm_struct *mm, unsigned long addr,
{
pgste_t
pgste
;
pte_t
old
;
int
nodat
;
preempt_disable
();
pgste
=
ptep_xchg_start
(
mm
,
addr
,
ptep
);
old
=
ptep_flush_lazy
(
mm
,
addr
,
ptep
);
nodat
=
!!
(
pgste_val
(
pgste
)
&
_PGSTE_GPS_NODAT
);
old
=
ptep_flush_lazy
(
mm
,
addr
,
ptep
,
nodat
);
old
=
ptep_xchg_commit
(
mm
,
addr
,
ptep
,
pgste
,
old
,
new
);
preempt_enable
();
return
old
;
...
...
@@ -299,10 +305,12 @@ pte_t ptep_modify_prot_start(struct mm_struct *mm, unsigned long addr,
{
pgste_t
pgste
;
pte_t
old
;
int
nodat
;
preempt_disable
();
pgste
=
ptep_xchg_start
(
mm
,
addr
,
ptep
);
old
=
ptep_flush_lazy
(
mm
,
addr
,
ptep
);
nodat
=
!!
(
pgste_val
(
pgste
)
&
_PGSTE_GPS_NODAT
);
old
=
ptep_flush_lazy
(
mm
,
addr
,
ptep
,
nodat
);
if
(
mm_has_pgste
(
mm
))
{
pgste
=
pgste_update_all
(
old
,
pgste
,
mm
);
pgste_set
(
ptep
,
pgste
);
...
...
@@ -557,7 +565,7 @@ int ptep_force_prot(struct mm_struct *mm, unsigned long addr,
{
pte_t
entry
;
pgste_t
pgste
;
int
pte_i
,
pte_p
;
int
pte_i
,
pte_p
,
nodat
;
pgste
=
pgste_get_lock
(
ptep
);
entry
=
*
ptep
;
...
...
@@ -570,13 +578,14 @@ int ptep_force_prot(struct mm_struct *mm, unsigned long addr,
return
-
EAGAIN
;
}
/* Change access rights and set pgste bit */
nodat
=
!!
(
pgste_val
(
pgste
)
&
_PGSTE_GPS_NODAT
);
if
(
prot
==
PROT_NONE
&&
!
pte_i
)
{
ptep_flush_direct
(
mm
,
addr
,
ptep
);
ptep_flush_direct
(
mm
,
addr
,
ptep
,
nodat
);
pgste
=
pgste_update_all
(
entry
,
pgste
,
mm
);
pte_val
(
entry
)
|=
_PAGE_INVALID
;
}
if
(
prot
==
PROT_READ
&&
!
pte_p
)
{
ptep_flush_direct
(
mm
,
addr
,
ptep
);
ptep_flush_direct
(
mm
,
addr
,
ptep
,
nodat
);
pte_val
(
entry
)
&=
~
_PAGE_INVALID
;
pte_val
(
entry
)
|=
_PAGE_PROTECT
;
}
...
...
@@ -616,10 +625,12 @@ int ptep_shadow_pte(struct mm_struct *mm, unsigned long saddr,
void
ptep_unshadow_pte
(
struct
mm_struct
*
mm
,
unsigned
long
saddr
,
pte_t
*
ptep
)
{
pgste_t
pgste
;
int
nodat
;
pgste
=
pgste_get_lock
(
ptep
);
/* notifier is called by the caller */
ptep_flush_direct
(
mm
,
saddr
,
ptep
);
nodat
=
!!
(
pgste_val
(
pgste
)
&
_PGSTE_GPS_NODAT
);
ptep_flush_direct
(
mm
,
saddr
,
ptep
,
nodat
);
/* don't touch the storage key - it belongs to parent pgste */
pgste
=
pgste_set_pte
(
ptep
,
pgste
,
__pte
(
_PAGE_INVALID
));
pgste_set_unlock
(
ptep
,
pgste
);
...
...
@@ -692,6 +703,7 @@ bool test_and_clear_guest_dirty(struct mm_struct *mm, unsigned long addr)
pte_t
*
ptep
;
pte_t
pte
;
bool
dirty
;
int
nodat
;
pgd
=
pgd_offset
(
mm
,
addr
);
p4d
=
p4d_alloc
(
mm
,
pgd
,
addr
);
...
...
@@ -720,7 +732,8 @@ bool test_and_clear_guest_dirty(struct mm_struct *mm, unsigned long addr)
pte
=
*
ptep
;
if
(
dirty
&&
(
pte_val
(
pte
)
&
_PAGE_PRESENT
))
{
pgste
=
pgste_pte_notify
(
mm
,
addr
,
ptep
,
pgste
);
ptep_ipte_global
(
mm
,
addr
,
ptep
);
nodat
=
!!
(
pgste_val
(
pgste
)
&
_PGSTE_GPS_NODAT
);
ptep_ipte_global
(
mm
,
addr
,
ptep
,
nodat
);
if
(
MACHINE_HAS_ESOP
||
!
(
pte_val
(
pte
)
&
_PAGE_WRITE
))
pte_val
(
pte
)
|=
_PAGE_PROTECT
;
else
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录