mm: percpu: Add PCPU_FC_FIXED to pcpu_fc for setting fixed pcpu_atom_size.
Subsystems (4)
PATCH 1/1 mm: percpu: Add PCPU_FC_FIXED to pcpu_fc for setting fixed pcpu_atom_size.
From: ShuoX Liu <[email protected]>
We are enabling Android on Medfield. On i386, if the board has more physical memory, it means the vmalloc space is small. If the vmalloc space is big, it means physical memory is small. Dynamic percpu allocation is based on VM space. On i386, by default, the chunk size is 4MB. As vmalloc space is <= 128M, percpu allocation often fails. If using PERCPU_FC_PAGE, system can't go to deep sleep states.
The patch add one more chosen to percpu_alloc kernel parameter. Besides page,embed,auto are available for percpu_alloc, memory size suffixed with %K,%M are supported. It set pcpu_atom_size to fixed wanted size.
--- Documentation/kernel-parameters.txt | 4 +++- arch/x86/kernel/setup_percpu.c | 6 +++++- include/linux/percpu.h | 2 ++ mm/percpu.c | 11 +++++++++-- 4 files changed, 19 insertions(+), 4 deletions(-)
Documentation/kernel-parameters.txt +3 -1
@@ -2196,7 +2196,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted. See arch/parisc/kernel/pdc_chassis.c percpu_alloc= Select which percpu first chunk allocator to use. - Currently supported values are "embed" and "page". + Currently supported values are "embed", "page" and size + suffixed with %K,%M. Fixed size will overwrite + pcpu_atom_size of chunk allocation parameter. Archs may support subset or none of the selections. See comments in mm/percpu.c for details on each allocator. This parameter is primarily for debugging
arch/x86/kernel/setup_percpu.c +5 -1
@@ -185,9 +185,13 @@ void __init setup_per_cpu_areas(void)#endif rc = -EINVAL ;if (pcpu_chosen_fc !=PCPU_FC_PAGE ) { -const size_t atom_size = cpu_has_pse ?PMD_SIZE :PAGE_SIZE ; +size_t atom_size;const size_t dyn_size =PERCPU_MODULE_RESERVE +PERCPU_DYNAMIC_RESERVE -PERCPU_FIRST_CHUNK_RESERVE ; +if (pcpu_chosen_fc ==PCPU_FC_FIXED && pcpu_atom_size) + atom_size = pcpu_atom_size; +else + atom_size = cpu_has_pse ?PMD_SIZE :PAGE_SIZE ; rc = pcpu_embed_first_chunk(PERCPU_FIRST_CHUNK_RESERVE, dyn_size, atom_size,
include/linux/percpu.h +2 -0
@@ -104,12 +104,14 @@ enum pcpu_fc {PCPU_FC_AUTO ,PCPU_FC_EMBED ,PCPU_FC_PAGE , +PCPU_FC_FIXED , PCPU_FC_NR, };extern const char *pcpu_fc_names[PCPU_FC_NR ];extern enum pcpu_fc pcpu_chosen_fc; +extern size_t pcpu_atom_size;typedef void * (*pcpu_fc_alloc_fn_t )(unsigned int cpu,size_t size,size_t align);
mm/percpu.c +9 -2
@@ -113,9 +113,9 @@ struct pcpu_chunk {static int pcpu_unit_pages__read_mostly ;static int pcpu_unit_size__read_mostly ;static int pcpu_nr_units__read_mostly ; -static int pcpu_atom_size__read_mostly ;static int pcpu_nr_slots__read_mostly ;static size_t pcpu_chunk_struct_size__read_mostly ; +size_t pcpu_atom_size__read_mostly ;/* cpus with the lowest and highest unit addresses */ static unsigned int pcpu_low_unit_cpu__read_mostly ;
@@ -1374,12 +1374,14 @@ const char *pcpu_fc_names[PCPU_FC_NR] __initdata = { [PCPU_FC_AUTO] = "auto", [PCPU_FC_EMBED] = "embed", [PCPU_FC_PAGE] = "page", + [PCPU_FC_FIXED] = "fixed", };enum pcpu_fc pcpu_chosen_fc__initdata =PCPU_FC_AUTO ;static int __init percpu_alloc_setup (char *str) { +size_t size =memparse (str,NULL );if (0 )/* nada */ ;#ifdef CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK
@@ -1390,7 +1392,12 @@ static int __init percpu_alloc_setup(char *str) else if (!strcmp(str, "page")) pcpu_chosen_fc =PCPU_FC_PAGE ;#endif - else + else if (!strcmp(str, "auto")) + pcpu_chosen_fc =PCPU_FC_AUTO ; + else if (size > 0) { + pcpu_atom_size = size; + pcpu_chosen_fc =PCPU_FC_FIXED ; + } else pr_warning("PERCPU: unknown allocator %s specified\n", str);return 0 ;
Tejun Heo
maintainerHello, ShouX.
Quoted 7 lines · ShuoX Liu
From: ShuoX Liu <[email protected]>
We are enabling Android on Medfield. On i386, if the board has more physical memory, it means the vmalloc space is small. If the vmalloc space is big, it means physical memory is small. Dynamic percpu allocation is based on VM space. On i386, by default, the chunk size is 4MB. As vmalloc space is <= 128M, percpu allocation often fails.
Can you please provide more details - which kernel/user split was used, how much memory was there and so on? Also, can you please attach boot log and the output of "cat /proc/vmallocinfo"?
Quoted 1 line
If using
PERCPU_FC_PAGE, system can't go to deep sleep states.
Why?
Quoted 9 lines
arch/x86/kernel/setup_percpu.c +0
-1@@ -185,9 +185,13 @@ void __init setup_per_cpu_areas(void)#endif rc = -EINVAL ;if (pcpu_chosen_fc !=PCPU_FC_PAGE ) { -const size_t atom_size = cpu_has_pse ?PMD_SIZE :PAGE_SIZE ;
arch/x86/kernel/setup_percpu.c void __init setup_per_cpu_areas(void) · line 197
Quoted 10 lines
arch/x86/kernel/setup_percpu.c +5
-0+size_t atom_size;const size_t dyn_size =PERCPU_MODULE_RESERVE +PERCPU_DYNAMIC_RESERVE -PERCPU_FIRST_CHUNK_RESERVE ; +if (pcpu_chosen_fc ==PCPU_FC_FIXED && pcpu_atom_size) + atom_size = pcpu_atom_size; +else + atom_size = cpu_has_pse ?PMD_SIZE :PAGE_SIZE ; rc = pcpu_embed_first_chunk(PERCPU_FIRST_CHUNK_RESERVE, dyn_size, atom_size,
Umm... this is way too hacky. atom_size can't be an arbitrary value and the param is meaningful only to x86 yet defined globally. Also, while atom_size has effect on vmalloc area usage, way more important factor is distance between units. What we probably need to do is tighten the rejection criteria of pcpu_embed_first_chunk() and fix whatever problem FC_PAGE is causing.
Thanks.
Signature · 1 line
tejun
Quoted 11 lines · Tejun Heo
Hello, ShouX.
Quoted 7 lines · ShuoX Liu
From: ShuoX Liu <[email protected]>
We are enabling Android on Medfield. On i386, if the board has more physical memory, it means the vmalloc space is small. If the vmalloc space is big, it means physical memory is small. Dynamic percpu allocation is based on VM space. On i386, by default, the chunk size is 4MB. As vmalloc space is <= 128M, percpu allocation often fails.
Quoted 3 lines
Can you please provide more details - which kernel/user split was used, how much memory was there and so on? Also, can you please attach boot log and the output of "cat
/proc/vmallocinfo"?
We are enabling Android on Medfield which is an embedded i386 platform. kernel/user split is 1/3G. Physical memory is 1GB and we turn on HIGHMEM.
The boot log is a little big. I copied the percpu part for your reference.
04-26 09:57:32.987 0 0 W Kernel-Dmesg: <6>[ 0.000000] SMP: Allowing 2 CPUs, 0 hotplug CPUs 04-26 09:57:32.987 0 0 W Kernel-Dmesg: <7>[ 0.000000] nr_irqs_gsi: 85 04-26 09:57:32.987 0 0 W Kernel-Dmesg: <6>[ 0.000000] Allocating PCI resources starting at 40000000 (gap: 40000000:bec00000) 04-26 09:57:32.987 0 0 W Kernel-Dmesg: <6>[ 0.000000] setup_percpu: NR_CPUS:2 nr_cpumask_bits:2 nr_cpu_ids:2 nr_node_ids:1 04-26 09:57:32.987 0 0 W Kernel-Dmesg: <6>[ 0.000000] PERCPU: Embedded 12 pages/cpu @f6400000 s25280 r0 d23872 u2097152 04-26 09:57:32.987 0 0 W Kernel-Dmesg: <7>[ 0.000000] pcpu-alloc: s25280 r0 d23872 u2097152 alloc=1*4194304 04-26 09:57:32.987 0 0 W Kernel-Dmesg: <7>[ 0.000000] pcpu-alloc: [0] 0 1 04-26 09:57:32.987 0 0 W Kernel-Dmesg: <4>[ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 252826 04-26 09:57:32.987 0 0 W Kernel-Dmesg: <5>[ 0.000000] Kernel command line: init=/init pci=noearly console=tty 04-26 09:57:32.988 0 0 W Kernel-Dmesg: MFD3 console=logk0 earlyprintk=nologger loglevel=7 hsu_dma=7 kmemleak=off androidboot.bootmedia=sdcard androidboot.hardware=mfld_pr2 ip=50.0.0.2:50.0.0.1::255.255.255.0::usb0:on g_android.fastboot=1 droidboot.scratch=100 androidboot.wakesrc=05 androidboot.mode=fastboot 04-26 09:57:32.988 0 0 W Kernel-Dmesg: <6>[ 0.000000] PID hash table entries: 4096 (order: 2, 16384 bytes) 04-26 09:57:32.988 0 0 W Kernel-Dmesg: <6>[ 0.000000] Dentry cache hash table entries: 131072 (order: 7, 524288 b
We hit below issue.
03-13 08:22:36.273 11151 11133 I KERNEL : [74395.013328] PERCPU: allocation failed, size=252 align=4, failed to allocate new chunk
03-13 08:22:36.274 11151 11133 I KERNEL : [74395.014062] Pid: 11151, comm: rild Not tainted 3.0.8-137162-g5e405a0 #1
03-13 08:22:36.275 11151 11133 I KERNEL : [74395.014656] Call Trace:
03-13 08:22:36.283 11151 11133 I KERNEL : [74395.022691] [<c1306eaa>] pcpu_alloc+0x12ca/0x1300
03-13 08:22:36.288 11151 11133 I KERNEL : [74395.027998] [<c125c1a9>] ? sysctl_set_parent+0x29/0x40
03-13 08:22:36.293 11151 11133 I KERNEL : [74395.033335] [<c1306f0f>] __alloc_percpu+0xf/0x20
03-13 08:22:36.298 11151 11133 I KERNEL : [74395.038144] [<c180dcad>] snmp_mib_init+0x3d/0x70
03-13 08:22:36.302 11151 11133 I KERNEL : [74395.043221] [<c1846efa>] ipv6_add_dev+0xfa/0x380
We run many stress testing and hit the percpu allocation failure at other places.
We googled the error and found other guys in community also hit the bug. You suggested them to use percpu_alloc=page. We tried it and it hurts power.
vmallocinfo is attached. From the vmallocinfo, we could find the VM space is fragmented. We would write another patch to clean it up.
Quoted 4 lines
Quoted 2 lines
If using
PERCPU_FC_PAGE, system can't go to deep sleep states.Why?
Medfield has 2 cpu threads. Only when all the 2 threads enter deep C states, for example, C6, the core would enter C6. If booting kernel with percpu_alloc=page, cpu core often aborts the C6 entering. We don't know why. C6 is aborted under many conditions. One is when there is pending interrupt. I suspect with page size alloc, it might trigger more cache miss. Just before calls mwait to enter C6, we record some statistics data and that might trigger the cache miss to abort the C6. It's just a _GUESS_.
We tried atom_size with 32k, 128k, 256k. There is no power regression.
Quoted 18 lines
Quoted 18 lines
arch/x86/kernel/setup_percpu.c +5
-1@@ -185,9 +185,13 @@ void __init setup_per_cpu_areas(void)#endif rc = -EINVAL ;if (pcpu_chosen_fc !=PCPU_FC_PAGE ) { -const size_t atom_size = cpu_has_pse ?PMD_SIZE :PAGE_SIZE ; +size_t atom_size;const size_t dyn_size =PERCPU_MODULE_RESERVE +PERCPU_DYNAMIC_RESERVE -PERCPU_FIRST_CHUNK_RESERVE ; +if (pcpu_chosen_fc ==PCPU_FC_FIXED && pcpu_atom_size) + atom_size = pcpu_atom_size; +else + atom_size = cpu_has_pse ?PMD_SIZE :PAGE_SIZE ;
Quoted 4 lines
arch/x86/kernel/setup_percpu.c void __init setup_per_cpu_areas(void) · line 197
Quoted 2 lines
arch/x86/kernel/setup_percpu.c +0
-0rc = pcpu_embed_first_chunk(PERCPU_FIRST_CHUNK_RESERVE, dyn_size, atom_size,Umm... this is way too hacky.
atom_sizecan't be an arbitrary value
The interface is give admin more options. It doesn't mean admin could choose any value.
Quoted 1 line
and the param is meaningful only to x86 yet defined globally.
Right, from real usage requirement point of view. If we googled the failure info dumped from kernel, we could see many other guys also hit it. That's why we send the patch to LKML.
Quoted 3 lines
Also,
whileatom_sizehas effect on vmalloc area usage, way more important factor is distance between units.
Could you elaborate it?
Quoted 2 lines
What we probably need to do is
tighten the rejection criteria ofpcpu_embed_first_chunk()
Could you explain it more?
Quoted 2 lines
and fix
whatever problemFC_PAGEis causing.
We can't fix FC_PAGE power regression. If we do so, we need contact many hardware architects. Current kernel supports FC_PAGE and PMD_SIZE, why not to allow admin to choose other values?
Thanks for the comments.
Yanmin
Tejun Heo
maintainerHello,
Quoted 7 lines · Yanmin Zhang
[ 0.000000] SMP: Allowing 2 CPUs, 0 hotplug CPUs [ 0.000000] nr_irqs_gsi: 85 [ 0.000000] Allocating PCI resources starting at 40000000 (gap: 40000000:bec00000) [ 0.000000] setup_percpu: NR_CPUS:2 nr_cpumask_bits:2 nr_cpu_ids:2 nr_node_ids:1 [ 0.000000] PERCPU: Embedded 12 pages/cpu @f6400000 s25280 r0 d23872 u2097152 [ 0.000000] pcpu-alloc: s25280 r0 d23872 u2097152 alloc=1*4194304 [ 0.000000] pcpu-alloc: [0] 0 1
Heh, I was getting confused, forget the distance thing, so it's single group w/ 4MiB allocation size.
Quoted 1 line
PERCPU: allocation failed, size=252 align=4, failed to allocate new chunk
Which later fails percpu allocation due to vmalloc space exhaustion. How long does that take to happen?
Quoted 2 lines
vmallocinfo is attached. From the vmallocinfo, we could find the VM space is fragmented. We would write another patch to clean it up.
Whee... ah well, 128M isn't that big after all.
Quoted 12 lines
Quoted 3 lines
Quoted 1 line
If using
PERCPU_FC_PAGE, system can't go to deep sleep states.Why?
Medfield has 2 cpu threads. Only when all the 2 threads enter deep C states, for example, C6, the core would enter C6. If booting kernel with percpu_alloc=page, cpu core often aborts the C6 entering. We don't know why. C6 is aborted under many conditions. One is when there is pending interrupt. I suspect with page size alloc, it might trigger more cache miss. Just before calls mwait to enter C6, we record some statistics data and that might trigger the cache miss to abort the C6. It's just a _GUESS_.
Quoted 1 line
We tried
atom_sizewith 32k, 128k, 256k. There is no power regression.
So, the difference between EMBED and PAGE is how the first chunk which contains all the static percpu variables and some dynamic area for optimization is allocated. For EMBED, it's just kmallocd which means that it piggy backs on the default kernel linear mapping thus avoiding adding any extra TLB pressure. For PAGE, all those percpu areas end up getting re-mapped in vmalloc area using 4k pages, so if TLB pressure can affect entering C6, that could be it.
Quoted 3 lines
We can't fix
FC_PAGEpower regression. If we do so, we need contact many hardware architects. Current kernel supportsFC_PAGEandPMD_SIZE, why not to allow admin to choose other values?
If this is something which is met in the field commonly, we need to fix the default behavior rather than introducing some arcane boot param. IIRC, the reasons PMD_SIZE is used for atom_size are so that percpu areas are aligned to PSE mapping, maybe later we can make use of PSE mapping in vmalloc area too, and it didn't seem to hurt anything.
If the large unit size is becoming a problem on i386, we can just use PAGE_SIZE as atom_size. Can you please verify that atom_size of 4k w/ EMBED also resolves the power issue?
Thanks.
Signature · 1 line
tejun
Quoted 11 lines · Tejun Heo
Hello,
Quoted 7 lines · Yanmin Zhang
[ 0.000000] SMP: Allowing 2 CPUs, 0 hotplug CPUs [ 0.000000] nr_irqs_gsi: 85 [ 0.000000] Allocating PCI resources starting at 40000000 (gap: 40000000:bec00000) [ 0.000000] setup_percpu: NR_CPUS:2 nr_cpumask_bits:2 nr_cpu_ids:2 nr_node_ids:1 [ 0.000000] PERCPU: Embedded 12 pages/cpu @f6400000 s25280 r0 d23872 u2097152 [ 0.000000] pcpu-alloc: s25280 r0 d23872 u2097152 alloc=1*4194304 [ 0.000000] pcpu-alloc: [0] 0 1
Quoted 7 lines
Heh, I was getting confused, forget the distance thing, so it's single group w/ 4MiB allocation size.
Quoted 1 line
PERCPU: allocation failed, size=252 align=4, failed to allocate new chunk
Which later fails percpu allocation due to vmalloc space exhaustion. How long does that take to happen?
It depends. Sometimes it fails in 400 seconds after booting. We run MTBF and other stress testing. Sometimes even with other non-stress testing, pecpu allocation fails. Most drivers or upper layers expect the percpu allocation should succeed. If not, although mostly there is no OOPS in kernel, upper applications wouldn't work.
Quoted 5 lines
Quoted 3 lines
vmallocinfo is attached. From the vmallocinfo, we could find the VM space is fragmented. We would write another patch to clean it up.
Whee... ah well, 128M isn't that big after all.
Indeed, so we need tune the memory utilization carefully on i386. We did work out other patches at other places/drivers to fix other OOM issues.
Quoted 15 lines
Quoted 13 lines
Quoted 4 lines
Quoted 2 lines
If using
PERCPU_FC_PAGE, system can't go to deep sleep states.Why?
Medfield has 2 cpu threads. Only when all the 2 threads enter deep C states, for example, C6, the core would enter C6. If booting kernel with percpu_alloc=page, cpu core often aborts the C6 entering. We don't know why. C6 is aborted under many conditions. One is when there is pending interrupt. I suspect with page size alloc, it might trigger more cache miss. Just before calls mwait to enter C6, we record some statistics data and that might trigger the cache miss to abort the C6. It's just a _GUESS_.
Quoted 1 line
We tried
atom_sizewith 32k, 128k, 256k. There is no power regression.
Quoted 7 lines
So, the difference between EMBED and PAGE is how the first chunk which contains all the static percpu variables and some dynamic area for optimization is allocated. For EMBED, it's just kmallocd which means that it piggy backs on the default kernel linear mapping thus avoiding adding any extra TLB pressure. For PAGE, all those percpu areas end up getting re-mapped in vmalloc area using 4k pages, so if TLB pressure can affect entering C6, that could be it.
Thanks for the explanation.
Quoted 8 lines
Quoted 4 lines
We can't fix
FC_PAGEpower regression. If we do so, we need contact many hardware architects. Current kernel supportsFC_PAGEandPMD_SIZE, why not to allow admin to choose other values?If this is something which is met in the field commonly, we need to fix the default behavior rather than introducing some arcane boot param.
We just add a new value input method instead of introducing new parameter.
Quoted 4 lines
IIRC, the reasons
PMD_SIZEis used foratom_sizeare so that
percpu areas are aligned to PSE mapping, maybe later we can make use of PSE mapping in vmalloc area too, and it didn't seem to hurt anything.
Well, vmalloc area might use different prot to map physical pages. So sharing one PMD huge page by many vmalloc areas might be not good.
Quoted 4 lines
If the large unit size is becoming a problem on i386, we can just use
PAGE_SIZEasatom_size. Can you please verify thatatom_sizeof 4k w/ EMBED also resolves the power issue?
We are enable Android ICS which is based on kernel 3.0.8. It seems there is no much change between 3.0.8 and the latest kernel.
With 3.0.8, although we could set percpualloc=embed, atom_size would becomes PMD_SIZE.
With our patch, we could do the experiment as we could configure percpu_alloc=4K easily. We would let you know the testing result of atom_size=4K && first_chunk_embedded.
Yanmin
Quoted 77 lines · Yanmin Zhang
Quoted 11 lines · Tejun Heo
Hello,
Quoted 7 lines · Yanmin Zhang
[ 0.000000] SMP: Allowing 2 CPUs, 0 hotplug CPUs [ 0.000000] nr_irqs_gsi: 85 [ 0.000000] Allocating PCI resources starting at 40000000 (gap: 40000000:bec00000) [ 0.000000] setup_percpu: NR_CPUS:2 nr_cpumask_bits:2 nr_cpu_ids:2 nr_node_ids:1 [ 0.000000] PERCPU: Embedded 12 pages/cpu @f6400000 s25280 r0 d23872 u2097152 [ 0.000000] pcpu-alloc: s25280 r0 d23872 u2097152 alloc=1*4194304 [ 0.000000] pcpu-alloc: [0] 0 1Quoted 7 lines
Heh, I was getting confused, forget the distance thing, so it's single group w/ 4MiB allocation size.
Quoted 1 line
PERCPU: allocation failed, size=252 align=4, failed to allocate new chunk
Which later fails percpu allocation due to vmalloc space exhaustion. How long does that take to happen?
It depends. Sometimes it fails in 400 seconds after booting. We run MTBF and other stress testing. Sometimes even with other non-stress testing, pecpu allocation fails. Most drivers or upper layers expect the percpu allocation should succeed. If not, although mostly there is no OOPS in kernel, upper applications wouldn't work.
Quoted 5 lines
Quoted 3 lines
vmallocinfo is attached. From the vmallocinfo, we could find the VM space is fragmented. We would write another patch to clean it up.
Whee... ah well, 128M isn't that big after all.
Indeed, so we need tune the memory utilization carefully on i386. We did work out other patches at other places/drivers to fix other OOM issues.
Quoted 15 lines
Quoted 13 lines
Quoted 4 lines
Quoted 2 lines
If using
PERCPU_FC_PAGE, system can't go to deep sleep states.Why?
Medfield has 2 cpu threads. Only when all the 2 threads enter deep C states, for example, C6, the core would enter C6. If booting kernel with percpu_alloc=page, cpu core often aborts the C6 entering. We don't know why. C6 is aborted under many conditions. One is when there is pending interrupt. I suspect with page size alloc, it might trigger more cache miss. Just before calls mwait to enter C6, we record some statistics data and that might trigger the cache miss to abort the C6. It's just a _GUESS_.
Quoted 1 line
We tried
atom_sizewith 32k, 128k, 256k. There is no power regression.Quoted 7 lines
So, the difference between EMBED and PAGE is how the first chunk which contains all the static percpu variables and some dynamic area for optimization is allocated. For EMBED, it's just kmallocd which means that it piggy backs on the default kernel linear mapping thus avoiding adding any extra TLB pressure. For PAGE, all those percpu areas end up getting re-mapped in vmalloc area using 4k pages, so if TLB pressure can affect entering C6, that could be it.
Thanks for the explanation.
Quoted 8 lines
Quoted 4 lines
We can't fix
FC_PAGEpower regression. If we do so, we need contact many hardware architects. Current kernel supportsFC_PAGEandPMD_SIZE, why not to allow admin to choose other values?If this is something which is met in the field commonly, we need to fix the default behavior rather than introducing some arcane boot param.
We just add a new value input method instead of introducing new parameter.
Quoted 4 lines
IIRC, the reasons
PMD_SIZEis used foratom_sizeare so that
percpu areas are aligned to PSE mapping, maybe later we can make use of PSE mapping in vmalloc area too, and it didn't seem to hurt anything.Well, vmalloc area might use different prot to map physical pages. So sharing one PMD huge page by many vmalloc areas might be not good.
Quoted 4 lines
If the large unit size is becoming a problem on i386, we can just use
PAGE_SIZEasatom_size. Can you please verify thatatom_sizeof 4k w/ EMBED also resolves the power issue?
Quoted 6 lines
We are enable Android ICS which is based on kernel 3.0.8. It seems there is no much change between 3.0.8 and the latest kernel.
With 3.0.8, although we could set percpualloc=embed,atom_sizewould becomesPMD_SIZE.
With our patch, we could do the experiment as we could configure percpu_alloc=4K easily. We would let you know the testing result of atom_size=4K &&first_chunk_embedded.
Liu Shuo did initial testing about this scenario and there is no power regression.
Yanmin
Tejun Heo
maintainerPATCH 1/1 percpu, x86: don't use PMD_SIZE as embedded atom_size on 32bit
With the embed percpu first chunk allocator, x86 uses either PAGE_SIZE or PMD_SIZE for atom_size. PMD_SIZE is used when CPU supports PSE so that percpu areas are aligned to PMD mappings and possibly allow using PMD mappings in vmalloc areas in the future. Using larger atom_size doesn't waste actual memory; however, it does require larger vmalloc space allocation later on for !first chunks.
With reasonably sized vmalloc area, PMD_SIZE shouldn't be a problem but x86_32 at this point is anything but reasonable in terms of address space and using later atom_size reportedly leads to frequent percpu allocation failures on certain setups.
This patch makes x86_32 always use PAGE_SIZE as atom_size for embed first chunk allocator.
LKML-Reference: <[email protected]>
Cc: [email protected]
---
Can you please verify this resolves the issue you guys are seeing? Once verified, I'll push it through percpu/for-3.5-fixes.
Thanks.
arch/x86/kernel/setup_percpu.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
arch/x86/kernel/setup_percpu.c +13 -1
@@ -185,10 +185,22 @@ void __init setup_per_cpu_areas(void)#endif rc = -EINVAL ;if (pcpu_chosen_fc !=PCPU_FC_PAGE ) { -const size_t atom_size = cpu_has_pse ?PMD_SIZE :PAGE_SIZE ;const size_t dyn_size =PERCPU_MODULE_RESERVE +PERCPU_DYNAMIC_RESERVE -PERCPU_FIRST_CHUNK_RESERVE ; +size_t atom_size; +/* +* If PSE is available, use PMD_SIZE for atom_size so that +* embedded percpu areas are aligned to PMD. This, in the +* future, can also allow using PMD mappings in vmalloc +* area. Use PAGE_SIZE on 32bit as vmalloc space is highly +* contended and large vmalloc area alloc can easily fail. +*/ + atom_size =PAGE_SIZE ; +#ifdef CONFIG_X86_64 +if (cpu_has_pse) + atom_size =PMD_SIZE ; +#endif rc = pcpu_embed_first_chunk(PERCPU_FIRST_CHUNK_RESERVE, dyn_size, atom_size, pcpu_cpu_distance,
Re: [PATCH] percpu, x86: don't use PMD_SIZE as embedded atom_size on 32bit
arch/x86/kernel/setup_percpu.c void __init setup_per_cpu_areas(void) · line 203
Quoted 13 lines · Tejun Heo
arch/x86/kernel/setup_percpu.c +12
-0+/* +* If PSE is available, use PMD_SIZE for atom_size so that +* embedded percpu areas are aligned to PMD. This, in the +* future, can also allow using PMD mappings in vmalloc +* area. Use PAGE_SIZE on 32bit as vmalloc space is highly +* contended and large vmalloc area alloc can easily fail. +*/ + atom_size =PAGE_SIZE ; +#ifdef CONFIG_X86_64 +if (cpu_has_pse) + atom_size =PMD_SIZE ; +#endif
Just make it PAGE_SIZE on i386 and PMD_SIZE on x86-64; keep the behavior consistent. !cpu_has_pse on x86-64 is an abnormal situation (I think it applies to Xen, pretty much.)
Other than that,
-hpa
Signature · 2 lines
H. Peter Anvin, Intel Open Source Technology Center I work for Intel. I don't speak on their behalf.
Tejun Heo
maintainerRe: [PATCH] percpu, x86: don't use PMD_SIZE as embedded atom_size on 32bit
Quoted 19 lines · H. Peter Anvin
arch/x86/kernel/setup_percpu.c void __init setup_per_cpu_areas(void) · line 203
Quoted 13 lines · Tejun Heo
arch/x86/kernel/setup_percpu.c +12
-0+/* +* If PSE is available, use PMD_SIZE for atom_size so that +* embedded percpu areas are aligned to PMD. This, in the +* future, can also allow using PMD mappings in vmalloc +* area. Use PAGE_SIZE on 32bit as vmalloc space is highly +* contended and large vmalloc area alloc can easily fail. +*/ + atom_size =PAGE_SIZE ; +#ifdef CONFIG_X86_64 +if (cpu_has_pse) + atom_size =PMD_SIZE ; +#endif Just make it
PAGE_SIZEon i386 andPMD_SIZEon x86-64; keep the behavior consistent. !cpu_has_pse on x86-64 is an abnormal situation (I think it applies to Xen, pretty much.)
Quoted 3 lines
Other than that,
Acked-by H. Peter Anvin <[email protected]>
Yeah, that's simpler. Will update.
Thanks.
Signature · 1 line
tejun
Re: [PATCH] percpu, x86: don't use PMD_SIZE as embedded atom_size on 32bit
In reply to Tejun HeoQuoted 2 lines · Tejun Heo
This patch makes
x86_32always usePAGE_SIZEasatom_sizefor embed first chunk allocator.
Would it not be easier to use the first #ifdef in the function to set pcpu_chosen_fc = PCPU_FC_PAGE?
You could just skip the whole PCPU_FC_PAGE block in the CONFIG_X86_32 case.
Tejun Heo
maintainerRe: [PATCH] percpu, x86: don't use PMD_SIZE as embedded atom_size on 32bit
Quoted 10 lines · Christoph Lameter
Quoted 2 lines · Tejun Heo
This patch makes
x86_32always usePAGE_SIZEasatom_sizefor embed first chunk allocator.Would it not be easier to use the first #ifdef in the function to set
pcpu_chosen_fc=PCPU_FC_PAGE?You could just skip the whole
PCPU_FC_PAGEblock in theCONFIG_X86_32case.
PCPU_FC_PAGE != PCPU_FC_EMBED w/ PAGE_SIZE atom_size. EMBED still gets to piggy back on the kernel linear mapping for the first chunk unlike PAGE. It apparently created noticeable difference (I'm guessing due to extra TLB pressure) for intel android folks.
Thanks.
Signature · 1 line
tejun
Tejun Heo
maintainerPATCH v2 1/1 percpu, x86: don't use PMD_SIZE as embedded atom_size on 32bit
In reply to Tejun HeoWith the embed percpu first chunk allocator, x86 uses either PAGE_SIZE or PMD_SIZE for atom_size. PMD_SIZE is used when CPU supports PSE so that percpu areas are aligned to PMD mappings and possibly allow using PMD mappings in vmalloc areas in the future. Using larger atom_size doesn't waste actual memory; however, it does require larger vmalloc space allocation later on for !first chunks.
With reasonably sized vmalloc area, PMD_SIZE shouldn't be a problem but x86_32 at this point is anything but reasonable in terms of address space and using larger atom_size reportedly leads to frequent percpu allocation failures on certain setups.
As there is no reason to not use PMD_SIZE on x86_64 as vmalloc space is aplenty and most x86_64 configurations support PSE, fix the issue by always using PMD_SIZE on x86_64 and PAGE_SIZE on x86_32.
v2: drop cpu_has_pse test and make x86_64 always use PMD_SIZE and
x86_32 PAGE_SIZE as suggested by hpa.
LKML-Reference: <[email protected]>
Cc: [email protected]
--- arch/x86/kernel/setup_percpu.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
arch/x86/kernel/setup_percpu.c +13 -1
@@ -185,10 +185,22 @@ void __init setup_per_cpu_areas(void)#endif rc = -EINVAL ;if (pcpu_chosen_fc !=PCPU_FC_PAGE ) { -const size_t atom_size = cpu_has_pse ?PMD_SIZE :PAGE_SIZE ;const size_t dyn_size =PERCPU_MODULE_RESERVE +PERCPU_DYNAMIC_RESERVE -PERCPU_FIRST_CHUNK_RESERVE ; +size_t atom_size; +/* +* On 64bit, use PMD_SIZE for atom_size so that embedded +* percpu areas are aligned to PMD. This, in the future, +* can also allow using PMD mappings in vmalloc area. Use +* PAGE_SIZE on 32bit as vmalloc space is highly contended +* and large vmalloc area allocs can easily fail. +*/ +#ifdef CONFIG_X86_64 + atom_size =PMD_SIZE ; +#else + atom_size =PAGE_SIZE ; +#endif rc = pcpu_embed_first_chunk(PERCPU_FIRST_CHUNK_RESERVE, dyn_size, atom_size, pcpu_cpu_distance,
H. Peter Anvin
reviewerRe: [PATCH v2] percpu, x86: don't use PMD_SIZE as embedded atom_size on 32bit
Quoted 19 lines · Tejun Heo
With the embed percpu first chunk allocator, x86 uses either
PAGE_SIZEorPMD_SIZEforatom_size.PMD_SIZEis used when CPU supports PSE so that percpu areas are aligned to PMD mappings and possibly allow using PMD mappings in vmalloc areas in the future. Using largeratom_sizedoesn't waste actual memory; however, it does require larger vmalloc space allocation later on for !first chunks.With reasonably sized vmalloc area,
PMD_SIZEshouldn't be a problem butx86_32at this point is anything but reasonable in terms of address space and using largeratom_sizereportedly leads to frequent percpu allocation failures on certain setups.As there is no reason to not use
PMD_SIZEonx86_64as vmalloc space is aplenty and mostx86_64configurations support PSE, fix the issue by always usingPMD_SIZEonx86_64andPAGE_SIZEonx86_32.v2: drop
cpu_has_psetest and makex86_64always usePMD_SIZEand
x86_32PAGE_SIZEas suggested by hpa.
Quoted 6 lines
Signed-off-by Tejun Heo <[email protected]>Reported-by Yanmin Zhang <[email protected]>Reported-by ShuoX Liu <[email protected]>Acked-by H. Peter Anvin <[email protected]>LKML-Reference: <[email protected]>
Cc: [email protected]
You're carrying this, or should I?
-hpa
Tejun Heo
maintainerRe: [PATCH v2] percpu, x86: don't use PMD_SIZE as embedded atom_size on 32bit
Quoted 20 lines · H. Peter Anvin
Quoted 19 lines · Tejun Heo
With the embed percpu first chunk allocator, x86 uses either
PAGE_SIZEorPMD_SIZEforatom_size.PMD_SIZEis used when CPU supports PSE so that percpu areas are aligned to PMD mappings and possibly allow using PMD mappings in vmalloc areas in the future. Using largeratom_sizedoesn't waste actual memory; however, it does require larger vmalloc space allocation later on for !first chunks.With reasonably sized vmalloc area,
PMD_SIZEshouldn't be a problem butx86_32at this point is anything but reasonable in terms of address space and using largeratom_sizereportedly leads to frequent percpu allocation failures on certain setups.As there is no reason to not use
PMD_SIZEonx86_64as vmalloc space is aplenty and mostx86_64configurations support PSE, fix the issue by always usingPMD_SIZEonx86_64andPAGE_SIZEonx86_32.v2: drop
cpu_has_psetest and makex86_64always usePMD_SIZEand
x86_32PAGE_SIZEas suggested by hpa.
Quoted 8 lines
Quoted 6 lines
Signed-off-by Tejun Heo <[email protected]>Reported-by Yanmin Zhang <[email protected]>Reported-by ShuoX Liu <[email protected]>Acked-by H. Peter Anvin <[email protected]>LKML-Reference: <[email protected]>
Cc: [email protected]You're carrying this, or should I?
I have another percpu fix to push so I can carry it.
Thanks.
Signature · 1 line
tejun
Re: [PATCH] percpu, x86: don't use PMD_SIZE as embedded atom_size on 32bit
In reply to Tejun HeoQuoted 15 lines · Tejun Heo
With the embed percpu first chunk allocator, x86 uses either
PAGE_SIZEorPMD_SIZEforatom_size.PMD_SIZEis used when CPU supports PSE so that percpu areas are aligned to PMD mappings and possibly allow using PMD mappings in vmalloc areas in the future. Using largeratom_sizedoesn't waste actual memory; however, it does require larger vmalloc space allocation later on for !first chunks.With reasonably sized vmalloc area,
PMD_SIZEshouldn't be a problem butx86_32at this point is anything but reasonable in terms of address space and using lateratom_sizereportedly leads to frequent percpu allocation failures on certain setups.This patch makes
x86_32always usePAGE_SIZEasatom_sizefor embed first chunk allocator.
Quoted 9 lines
Signed-off-by Tejun Heo <[email protected]>Reported-by Yanmin Zhang <[email protected]>Reported-by ShuoX Liu <[email protected]>LKML-Reference: <[email protected]>
Cc: [email protected]
---
Can you please verify this resolves the issue you guys are seeing? Once verified, I'll push it through percpu/for-3.5-fixes.
Verify OK.
Quoted 33 lines
Thanks.
arch/x86/kernel/setup_percpu.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)arch/x86/kernel/setup_percpu.c +13
-1@@ -185,10 +185,22 @@ void __init setup_per_cpu_areas(void)#endif rc = -EINVAL ;if (pcpu_chosen_fc !=PCPU_FC_PAGE ) { -const size_t atom_size = cpu_has_pse ?PMD_SIZE :PAGE_SIZE ;const size_t dyn_size =PERCPU_MODULE_RESERVE +PERCPU_DYNAMIC_RESERVE -PERCPU_FIRST_CHUNK_RESERVE ; +size_t atom_size; +/* +* If PSE is available, use PMD_SIZE for atom_size so that +* embedded percpu areas are aligned to PMD. This, in the +* future, can also allow using PMD mappings in vmalloc +* area. Use PAGE_SIZE on 32bit as vmalloc space is highly +* contended and large vmalloc area alloc can easily fail. +*/ + atom_size =PAGE_SIZE ; +#ifdef CONFIG_X86_64 +if (cpu_has_pse) + atom_size =PMD_SIZE ; +#endif rc = pcpu_embed_first_chunk(PERCPU_FIRST_CHUNK_RESERVE, dyn_size, atom_size, pcpu_cpu_distance,
Tejun Heo
maintainerHello,
Quoted 9 lines · Yanmin Zhang
Quoted 7 lines
Quoted 3 lines
We can't fix
FC_PAGEpower regression. If we do so, we need contact many hardware architects. Current kernel supportsFC_PAGEandPMD_SIZE, why not to allow admin to choose other values?If this is something which is met in the field commonly, we need to fix the default behavior rather than introducing some arcane boot param.
We just add a new value input method instead of introducing new parameter.
Ummm... I don't know what you meant by the above sentence but adding a new magic kernel param whether it's part of an existing one or not, is not a good solution. They're difficult to discover and not many actually understand what they do. If you *have* to add some, then you better make it clear where it's being applied for what. ie. in this case, add something like x86_percpu_embed_unit_size.
Quoted 7 lines
Quoted 4 lines
IIRC, the reasons
PMD_SIZEis used foratom_sizeare so that
percpu areas are aligned to PSE mapping, maybe later we can make use of PSE mapping in vmalloc area too, and it didn't seem to hurt anything.Well, vmalloc area might use different prot to map physical pages. So sharing one PMD huge page by many vmalloc areas might be not good.
Percpu allocator uses the whole vmalloc chunk, so there's no prot problem. They're all percpu memory.
Thanks.
Signature · 1 line
tejun