Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
4fd78a5f
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看板
提交
4fd78a5f
编写于
4月 08, 2009
作者:
D
David S. Miller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
sparc64: Use new dynamic per-cpu allocator.
Signed-off-by:
N
David S. Miller
<
davem@davemloft.net
>
上级
0c243ad8
变更
2
显示空白变更内容
内联
并排
Showing
2 changed file
with
159 addition
and
9 deletion
+159
-9
arch/sparc/Kconfig
arch/sparc/Kconfig
+3
-0
arch/sparc/kernel/smp_64.c
arch/sparc/kernel/smp_64.c
+156
-9
未找到文件。
arch/sparc/Kconfig
浏览文件 @
4fd78a5f
...
@@ -93,6 +93,9 @@ config AUDIT_ARCH
...
@@ -93,6 +93,9 @@ config AUDIT_ARCH
config HAVE_SETUP_PER_CPU_AREA
config HAVE_SETUP_PER_CPU_AREA
def_bool y if SPARC64
def_bool y if SPARC64
config HAVE_DYNAMIC_PER_CPU_AREA
def_bool y if SPARC64
config GENERIC_HARDIRQS_NO__DO_IRQ
config GENERIC_HARDIRQS_NO__DO_IRQ
bool
bool
def_bool y if SPARC64
def_bool y if SPARC64
...
...
arch/sparc/kernel/smp_64.c
浏览文件 @
4fd78a5f
...
@@ -21,6 +21,7 @@
...
@@ -21,6 +21,7 @@
#include <linux/jiffies.h>
#include <linux/jiffies.h>
#include <linux/profile.h>
#include <linux/profile.h>
#include <linux/bootmem.h>
#include <linux/bootmem.h>
#include <linux/vmalloc.h>
#include <linux/cpu.h>
#include <linux/cpu.h>
#include <asm/head.h>
#include <asm/head.h>
...
@@ -1371,19 +1372,165 @@ void smp_send_stop(void)
...
@@ -1371,19 +1372,165 @@ void smp_send_stop(void)
{
{
}
}
/**
* pcpu_alloc_bootmem - NUMA friendly alloc_bootmem wrapper for percpu
* @cpu: cpu to allocate for
* @size: size allocation in bytes
* @align: alignment
*
* Allocate @size bytes aligned at @align for cpu @cpu. This wrapper
* does the right thing for NUMA regardless of the current
* configuration.
*
* RETURNS:
* Pointer to the allocated area on success, NULL on failure.
*/
static
void
*
__init
pcpu_alloc_bootmem
(
unsigned
int
cpu
,
unsigned
long
size
,
unsigned
long
align
)
{
const
unsigned
long
goal
=
__pa
(
MAX_DMA_ADDRESS
);
#ifdef CONFIG_NEED_MULTIPLE_NODES
int
node
=
cpu_to_node
(
cpu
);
void
*
ptr
;
if
(
!
node_online
(
node
)
||
!
NODE_DATA
(
node
))
{
ptr
=
__alloc_bootmem
(
size
,
align
,
goal
);
pr_info
(
"cpu %d has no node %d or node-local memory
\n
"
,
cpu
,
node
);
pr_debug
(
"per cpu data for cpu%d %lu bytes at %016lx
\n
"
,
cpu
,
size
,
__pa
(
ptr
));
}
else
{
ptr
=
__alloc_bootmem_node
(
NODE_DATA
(
node
),
size
,
align
,
goal
);
pr_debug
(
"per cpu data for cpu%d %lu bytes on node%d at "
"%016lx
\n
"
,
cpu
,
size
,
node
,
__pa
(
ptr
));
}
return
ptr
;
#else
return
__alloc_bootmem
(
size
,
align
,
goal
);
#endif
}
static
size_t
pcpur_size
__initdata
;
static
void
**
pcpur_ptrs
__initdata
;
static
struct
page
*
__init
pcpur_get_page
(
unsigned
int
cpu
,
int
pageno
)
{
size_t
off
=
(
size_t
)
pageno
<<
PAGE_SHIFT
;
if
(
off
>=
pcpur_size
)
return
NULL
;
return
virt_to_page
(
pcpur_ptrs
[
cpu
]
+
off
);
}
#define PCPU_CHUNK_SIZE (4UL * 1024UL * 1024UL)
static
void
__init
pcpu_map_range
(
unsigned
long
start
,
unsigned
long
end
,
struct
page
*
page
)
{
unsigned
long
pfn
=
page_to_pfn
(
page
);
unsigned
long
pte_base
;
BUG_ON
((
pfn
<<
PAGE_SHIFT
)
&
(
PCPU_CHUNK_SIZE
-
1UL
));
pte_base
=
(
_PAGE_VALID
|
_PAGE_SZ4MB_4U
|
_PAGE_CP_4U
|
_PAGE_CV_4U
|
_PAGE_P_4U
|
_PAGE_W_4U
);
if
(
tlb_type
==
hypervisor
)
pte_base
=
(
_PAGE_VALID
|
_PAGE_SZ4MB_4V
|
_PAGE_CP_4V
|
_PAGE_CV_4V
|
_PAGE_P_4V
|
_PAGE_W_4V
);
while
(
start
<
end
)
{
pgd_t
*
pgd
=
pgd_offset_k
(
start
);
unsigned
long
this_end
;
pud_t
*
pud
;
pmd_t
*
pmd
;
pte_t
*
pte
;
pud
=
pud_offset
(
pgd
,
start
);
if
(
pud_none
(
*
pud
))
{
pmd_t
*
new
;
new
=
__alloc_bootmem
(
PAGE_SIZE
,
PAGE_SIZE
,
PAGE_SIZE
);
pud_populate
(
&
init_mm
,
pud
,
new
);
}
pmd
=
pmd_offset
(
pud
,
start
);
if
(
!
pmd_present
(
*
pmd
))
{
pte_t
*
new
;
new
=
__alloc_bootmem
(
PAGE_SIZE
,
PAGE_SIZE
,
PAGE_SIZE
);
pmd_populate_kernel
(
&
init_mm
,
pmd
,
new
);
}
pte
=
pte_offset_kernel
(
pmd
,
start
);
this_end
=
(
start
+
PMD_SIZE
)
&
PMD_MASK
;
if
(
this_end
>
end
)
this_end
=
end
;
while
(
start
<
this_end
)
{
unsigned
long
paddr
=
pfn
<<
PAGE_SHIFT
;
pte_val
(
*
pte
)
=
(
paddr
|
pte_base
);
start
+=
PAGE_SIZE
;
pte
++
;
pfn
++
;
}
}
}
void
__init
setup_per_cpu_areas
(
void
)
void
__init
setup_per_cpu_areas
(
void
)
{
{
unsigned
long
size
,
i
,
nr_possible_cpus
=
num_possible_cpus
();
size_t
dyn_size
,
static_size
=
__per_cpu_end
-
__per_cpu_start
;
char
*
ptr
;
static
struct
vm_struct
vm
;
unsigned
long
delta
,
cpu
;
size_t
pcpu_unit_size
;
size_t
ptrs_size
;
pcpur_size
=
PFN_ALIGN
(
static_size
+
PERCPU_MODULE_RESERVE
+
PERCPU_DYNAMIC_RESERVE
);
dyn_size
=
pcpur_size
-
static_size
-
PERCPU_MODULE_RESERVE
;
ptrs_size
=
PFN_ALIGN
(
num_possible_cpus
()
*
sizeof
(
pcpur_ptrs
[
0
]));
pcpur_ptrs
=
alloc_bootmem
(
ptrs_size
);
for_each_possible_cpu
(
cpu
)
{
pcpur_ptrs
[
cpu
]
=
pcpu_alloc_bootmem
(
cpu
,
PCPU_CHUNK_SIZE
,
PCPU_CHUNK_SIZE
);
free_bootmem
(
__pa
(
pcpur_ptrs
[
cpu
]
+
pcpur_size
),
PCPU_CHUNK_SIZE
-
pcpur_size
);
memcpy
(
pcpur_ptrs
[
cpu
],
__per_cpu_load
,
static_size
);
}
/* allocate address and map */
vm
.
flags
=
VM_ALLOC
;
vm
.
size
=
num_possible_cpus
()
*
PCPU_CHUNK_SIZE
;
vm_area_register_early
(
&
vm
,
PCPU_CHUNK_SIZE
);
for_each_possible_cpu
(
cpu
)
{
unsigned
long
start
=
(
unsigned
long
)
vm
.
addr
;
unsigned
long
end
;
start
+=
cpu
*
PCPU_CHUNK_SIZE
;
end
=
start
+
PCPU_CHUNK_SIZE
;
pcpu_map_range
(
start
,
end
,
virt_to_page
(
pcpur_ptrs
[
cpu
]));
}
pcpu_unit_size
=
pcpu_setup_first_chunk
(
pcpur_get_page
,
static_size
,
PERCPU_MODULE_RESERVE
,
dyn_size
,
PCPU_CHUNK_SIZE
,
vm
.
addr
,
NULL
);
/* Copy section for each CPU (we discard the original) */
free_bootmem
(
__pa
(
pcpur_ptrs
),
ptrs_size
);
size
=
ALIGN
(
PERCPU_ENOUGH_ROOM
,
PAGE_SIZE
);
ptr
=
alloc_bootmem_pages
(
size
*
nr_possible_cpus
);
for_each_possible_cpu
(
i
)
{
delta
=
(
unsigned
long
)
pcpu_base_addr
-
(
unsigned
long
)
__per_cpu_start
;
__per_cpu_offset
(
i
)
=
ptr
-
__per_cpu_start
;
for_each_possible_cpu
(
cpu
)
{
memcpy
(
ptr
,
__per_cpu_start
,
__per_cpu_end
-
__per_cpu_start
);
__per_cpu_offset
(
cpu
)
=
delta
+
cpu
*
pcpu_unit_size
;
ptr
+=
size
;
}
}
/* Setup %g5 for the boot cpu. */
/* Setup %g5 for the boot cpu. */
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录