x86: not use bootmem for x86
Subsystems (10)
cover x86: not use bootmem for x86
please check the patches regarding with early_res and bootmem
and at last it will use early_res instead of bootmem with x86 64bits
-v2: allocate vmemmap on one node together, and also seperate early_res -v3: make x86 32 bit support early_res to use bootmem too
move related early_res to kernel/
sparse vmemmap together: address Ingo.
-v4: some patches could go with tip with acked-by Jesse
radix and logical flat etc
http://lkml.indiana.edu/hypermail/linux/kernel/0910.3/01432.html
Ingo said:
------------------------
I think we could remove the bootmem allocator middle man altogether.
This can be done by initializing the page allocator sooner and by extending (already existing) 'reserve memory early on' mechanisms in architecture code. (the reserve_early*() APIs in x86 for example)
Right now we have 5 memory allocation models on x86, initialized gradually:
- allocator (buddy) [generic]
- early allocator (bootmem) [generic]
- very early allocator (reserve_early*()) [x86]
- very very early allocator (early brk model) [x86]
- very very very early allocator (build time .data/.bss) [generic]
Seems excessive.
The reserve_early() method is list/range based and can handle vast amounts of not very fragmented memory - perfect for basically all the real bootmem purposes (which is to bootstrap the buddy).
reserve_early() allocated memory could be freed into the buddy later on as well. The main reason why bootmem is 'destroyed' during free-to-buddy is because it has excessive internal bitmaps we want to free. With a list/range based reserve_early() mechanism there's no such problem - they can linger indefinitely and there's near zero allocation management overhead.
reserve_early() might need some small amount of extra work before it can be used as a generic early allocator - like adding a node field to it (so that the buddy can then pick those ranges up in a NUMA aware fashion) - but nothing very complex.
--------x86 early_res related-------------
277f661: x86: move range related operation to one file
77f283c: x86: check range in update range
897f4ba: x86/pci: use u64 instead of size_t in amd_bus.c
84431bb: x86/pci: add cap_resource
48d49e8: x86/pci: enable pci root res read out for 32bit too
5255621: x86: call early_res_to_bootmem one time
0925f47: x86: introduce max_early_res and early_res_count
0c97b47: x86: dynamic increase early_res array size
f910ca6: x86: print bootmem free before pci_iommu_alloc and free_all_bootmem -v2
cfe85c0: x86: make early_node_mem get mem > 4g if possible
1d61d6c: x86: only call dma32_reserve_bootmem 64bit !CONFIG_NUMA 311f90d: x86: make 64 bit use early_res instead of bootmem before slab 788c828: sparsemem: put usemap for one node together
c1bb314: sparsemem: put mem map for one node together.
6e61ad7: x86: change range end to start+size
2a25d29: x86: move bios page reserve early to head32/64.c
36f0ad3: x86: seperate early_res related code from e820.c
ef1540b: x86: add find_early_area_size
fdd6fc1: x86: move back find_e820_area to e820.c
bedba96: early_res: enhance check_and_double_early_res
5c40d2d: x86: make 32bit support NO_BOOTMEM
c7987c9: move round_up/down to kernel.h
b047971: x86: add find_fw_memmap_area
a7ea42c: core: move early_res
5c972f9: x86: print out for RAM buffer
1267c07: x86: remove bios data range from e820
4826805: x86/pci: add mmconf range into e820 for when it is from MSR with amd faml0h
---------spareirq radix tree related ----------------
eba3887: irq: remove not need bootmem code 4c0d053: radix: move radix init early
5026493: sparseirq: change irq_desc_ptrs to static
e74a8ce: sparseirq: use radix_tree instead of ptrs array
---------------x86 logical flat related -----------
fa2bb9e: x86: remove arch_probe_nr_irqs
50f2e29: use nr_cpus= to set nr_cpu_ids early
2792a41: x86: according to nr_cpu_ids to decide if need to leave logical flat
c36a2f3: x86: make 32bit apic flat to physflat switch like 64bit 3f2e18b: x86: use num_processors for possible cpus
Thanks
Yinghai
PATCH 1/36 x86: move range related operation to one file
we have almost same copies for mtrr cleanup and amd_bus checkup.
and will also use it in replacing bootmem with early_res
so try to move them together and reuse it from different parts.
also rename update_range to subtract_range as the function acctuallu doing
-v2: update comments as Christoph requested
--- arch/x86/kernel/cpu/mtrr/cleanup.c | 180 +++--------------------------------- arch/x86/kernel/mmconf-fam10h_64.c | 7 +- arch/x86/pci/amd_bus.c | 70 ++------------ include/linux/range.h | 22 +++++ kernel/Makefile | 2 +- kernel/range.c | 154 ++++++++++++++++++++++++++++++ 6 files changed, 205 insertions(+), 230 deletions(-) create mode 100644 include/linux/range.h create mode 100644 kernel/range.c
arch/x86/kernel/cpu/mtrr/cleanup.c +15 -165
@@ -22,10 +22,10 @@#include <linux/pci.h> #include <linux/smp.h> #include <linux/cpu.h> -#include <linux/sort.h> #include <linux/mutex.h> #include <linux/uaccess.h> #include <linux/kvm_para.h> +#include <linux/range.h> #include <asm/processor.h> #include <asm/e820.h>
@@ -34,11 +34,6 @@#include "mtrr.h" -struct res_range { -unsigned long start; -unsigned long end; -}; -struct var_mtrr_range_state {unsigned long base_pfn;unsigned long size_pfn;
@@ -56,7 +51,7 @@ struct var_mtrr_state {/* Should be related to MTRR_VAR_RANGES nums */ #define RANGE_NUM 256 -static struct res_range __initdata range[RANGE_NUM ]; +static struct range __initdata range[RANGE_NUM ];static int __initdata nr_range;static struct var_mtrr_range_state __initdata range_state[RANGE_NUM ];
@@ -64,152 +59,11 @@ static struct var_mtrr_range_state __initdata range_state[RANGE_NUM];static int __initdata debug_print; #define Dprintk(x...) do { if (debug_print) printk(KERN_DEBUG x); } while (0) - -static int __init -add_range (struct res_range *range,int nr_range, -unsigned long start,unsigned long end) -{ -/* Out of slots: */ -if (nr_range >=RANGE_NUM ) -return nr_range; - - range[nr_range].start = start; - range[nr_range].end = end; - - nr_range++; - -return nr_range; -} - -static int __init -add_range_with_merge (struct res_range *range,int nr_range, -unsigned long start,unsigned long end) -{ -int i; - -/* Try to merge it with old one: */ -for (i =0 ; i < nr_range; i++) { -unsigned long final_start, final_end; -unsigned long common_start, common_end; - -if (!range[i].end) -continue ; - - common_start =max (range[i].start, start); - common_end =min (range[i].end, end); -if (common_start > common_end +1 ) -continue ; - - final_start =min (range[i].start, start); - final_end =max (range[i].end, end); - - range[i].start = final_start; - range[i].end = final_end; -return nr_range; - } - -/* Need to add it: */ -return add_range (range, nr_range, start, end); -} - -static void __init -subtract_range (struct res_range *range,unsigned long start,unsigned long end) -{ -int i, j; - -for (j =0 ; j <RANGE_NUM ; j++) { -if (!range[j].end) -continue ; - -if (start <= range[j].start && end >= range[j].end) { - range[j].start =0 ; - range[j].end =0 ; -continue ; - } - -if (start <= range[j].start && end < range[j].end && - range[j].start < end +1 ) { - range[j].start = end +1 ; -continue ; - } - - -if (start > range[j].start && end >= range[j].end && - range[j].end > start -1 ) { - range[j].end = start -1 ; -continue ; - } - -if (start > range[j].start && end < range[j].end) { -/* Find the new spare: */ -for (i =0 ; i <RANGE_NUM ; i++) { -if (range[i].end ==0 ) -break ; - } -if (i <RANGE_NUM ) { - range[i].end = range[j].end; - range[i].start = end +1 ; - }else { -printk (KERN_ERR "run of slot in ranges\n" ); - } - range[j].end = start -1 ; -continue ; - } - } -} - -static int __init cmp_range (const void *x1,const void *x2) -{ -const struct res_range *r1 = x1; -const struct res_range *r2 = x2; -long start1, start2; - - start1 = r1->start; - start2 = r2->start; - -return start1 - start2; -} - -static int __init clean_sort_range (struct res_range *range,int az) -{ -int i, j, k = az -1 , nr_range =0 ; - -for (i =0 ; i < k; i++) { -if (range[i].end) -continue ; -for (j = k; j > i; j--) { -if (range[j].end) { - k = j; -break ; - } - } -if (j == i) -break ; - range[i].start = range[k].start; - range[i].end = range[k].end; - range[k].start =0 ; - range[k].end =0 ; - k--; - } -/* count it */ -for (i =0 ; i < az; i++) { -if (!range[i].end) { - nr_range = i; -break ; - } - } - -/* sort them */ -sort (range, nr_range,sizeof (struct res_range ), cmp_range,NULL ); - -return nr_range; -} -#define BIOS_BUG_MSG KERN_WARNING \ "WARNING: BIOS bug: VAR MTRR %d contains strange UC entry under 1M, check with your system vendor!\n"static int __init -x86_get_mtrr_mem_range (struct res_range *range,int nr_range, +x86_get_mtrr_mem_range (struct range *range,int nr_range,unsigned long extra_remove_base,unsigned long extra_remove_size) {
@@ -223,13 +77,13 @@ x86_get_mtrr_mem_range(struct res_range *range, int nr_range,continue ; base = range_state[i].base_pfn; size = range_state[i].size_pfn; - nr_range =add_range_with_merge (range, nr_range, base, - base + size -1 ); + nr_range =add_range_with_merge (range,RANGE_NUM , nr_range, + base, base + size -1 ); }if (debug_print) {printk (KERN_DEBUG "After WB checking\n" );for (i =0 ; i < nr_range; i++) -printk (KERN_DEBUG "MTRR MAP PFN: %016lx - %016lx\n" , +printk (KERN_DEBUG "MTRR MAP PFN: %016llx - %016llx\n" , range[i].start, range[i].end +1 ); }
@@ -252,10 +106,10 @@ x86_get_mtrr_mem_range(struct res_range *range, int nr_range, size -= (1 <<(20 -PAGE_SHIFT )) - base; base =1 <<(20 -PAGE_SHIFT ); } -subtract_range (range, base, base + size -1 ); +subtract_range (range,RANGE_NUM , base, base + size -1 ); }if (extra_remove_size) -subtract_range (range, extra_remove_base, +subtract_range (range,RANGE_NUM , extra_remove_base, extra_remove_base + extra_remove_size -1 );if (debug_print) {
@@ -263,7 +117,7 @@ x86_get_mtrr_mem_range(struct res_range *range, int nr_range,for (i =0 ; i <RANGE_NUM ; i++) {if (!range[i].end)continue ; -printk (KERN_DEBUG "MTRR MAP PFN: %016lx - %016lx\n" , +printk (KERN_DEBUG "MTRR MAP PFN: %016llx - %016llx\n" , range[i].start, range[i].end +1 ); } }
@@ -273,20 +127,16 @@ x86_get_mtrr_mem_range(struct res_range *range, int nr_range,if (debug_print) {printk (KERN_DEBUG "After sorting\n" );for (i =0 ; i < nr_range; i++) -printk (KERN_DEBUG "MTRR MAP PFN: %016lx - %016lx\n" , +printk (KERN_DEBUG "MTRR MAP PFN: %016llx - %016llx\n" , range[i].start, range[i].end +1 ); } -/* clear those is not used */ -for (i = nr_range; i <RANGE_NUM ; i++) -memset (&range[i],0 ,sizeof (range[i])); -return nr_range; }#ifdef CONFIG_MTRR_SANITIZER -static unsigned long __init sum_ranges (struct res_range *range,int nr_range) +static unsigned long __init sum_ranges (struct range *range,int nr_range) {unsigned long sum =0 ;int i;
@@ -621,7 +471,7 @@ static int __init parse_mtrr_spare_reg(char *arg)early_param ("mtrr_spare_reg_nr" , parse_mtrr_spare_reg);static int __init -x86_setup_var_mtrrs (struct res_range *range,int nr_range, +x86_setup_var_mtrrs (struct range *range,int nr_range,u64 chunk_size,u64 gran_size) {struct var_mtrr_state var_state;
@@ -742,7 +592,7 @@ mtrr_calc_range_state(u64 chunk_size, u64 gran_size,unsigned long x_remove_base, unsigned long x_remove_size, int i) { - static struct res_range range_new[RANGE_NUM]; + static struct range range_new[RANGE_NUM];unsigned long range_sums_new;static int nr_range_new;int num_reg;
@@ -869,10 +719,10 @@ int __init mtrr_cleanup(unsigned address_bits)* [0, 1M) should always be covered by var mtrr with WB * and fixed mtrrs should take effect before var mtrr for it: */ - nr_range =add_range_with_merge (range, nr_range,0 , + nr_range =add_range_with_merge (range,RANGE_NUM , nr_range,0 , (1ULL <<(20 -PAGE_SHIFT )) -1 );/* Sort the ranges: */ -sort (range, nr_range,sizeof (struct res_range ), cmp_range,NULL ); +sort_range (range, nr_range); range_sums =sum_ranges (range, nr_range); printk(KERN_INFO "total RAM covered: %ldM\n",
arch/x86/kernel/mmconf-fam10h_64.c +2 -5
@@ -7,6 +7,8 @@#include <linux/string.h> #include <linux/pci.h> #include <linux/dmi.h> +#include <linux/range.h> +#include <asm/pci-direct.h> #include <linux/sort.h> #include <asm/io.h>
@@ -30,11 +32,6 @@ static struct pci_hostbridge_probe pci_probes[] __cpuinitdata = { { 0xff, 0, PCI_VENDOR_ID_AMD, 0x1200 }, }; -struct range { -u64 start; -u64 end; -}; -static int __cpuinit cmp_range (const void *x1,const void *x2) {const struct range *r1 = x1;
arch/x86/pci/amd_bus.c +11 -59
130 lines not on this page · raw message
include/linux/range.h new file +22 -0
@@ -0,0 +1,22 @@ +#ifndef _LINUX_RANGE_H +#define _LINUX_RANGE_H + +struct range { +u64 start; +u64 end; +}; + +int add_range (struct range *range,int az,int nr_range, +u64 start,u64 end); + + +int add_range_with_merge (struct range *range,int az,int nr_range, +u64 start,u64 end); + +void subtract_range (struct range *range,int az,u64 start,u64 end); + +int clean_sort_range (struct range *range,int az); + +void sort_range (struct range *range,int nr_range); + +#endif
kernel/Makefile +1 -1
@@ -10,7 +10,7 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o \ kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \ notifier.o ksysfs.o pm_qos_params.o sched_clock.o cred.o \ - async.o + async.o range.o obj-y += groups.o ifdef CONFIG_FUNCTION_TRACER
kernel/range.c new file +154 -0
154 lines not on this page · raw message
Signature · 1 line
1.6.4.2
PATCH 2/36 x86: check range in update range
In reply to Yinghai Lufend off wrong range
so later could use it with 32bit amd_bus/intel_bus, and it could have cap_resource.
-v2: update comments
--- kernel/range.c | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-)
kernel/range.c +9 -0
@@ -13,6 +13,9 @@int add_range (struct range *range,int az,int nr_range,u64 start,u64 end) { +if (start > end) +return nr_range; +/* Out of slots: */ if (nr_range >= az)return nr_range;
@@ -30,6 +33,9 @@ int add_range_with_merge(struct range *range, int az, int nr_range, {int i; +if (start > end) +return nr_range; +/* Try to merge it with old one: */ for (i =0 ; i < nr_range; i++) {u64 final_start, final_end;
@@ -59,6 +65,9 @@ void subtract_range(struct range *range, int az, u64 start, u64 end) {int i, j; +if (start > end) +return ; +for (j =0 ; j < az; j++) {if (!range[j].end)continue ;
Signature · 1 line
1.6.4.2
Re: [PATCH 02/36] x86: check range in update range
Quoted 1 line · Yinghai Lu
-v2: update comments
Dont see any comments being added.
Re: [PATCH 02/36] x86: check range in update range
Quoted 5 lines · Christoph Lameter
Quoted 1 line · Yinghai Lu
-v2: update comments
Dont see any comments being added.
----------------------------
so later could use it with 32bit amd_bus/intel_bus, and it could have cap_resource.
----------------------------
Re: [PATCH 02/36] x86: check range in update range
Quoted 9 lines · Yinghai Lu
Quoted 5 lines · Christoph Lameter
Quoted 1 line · Yinghai Lu
-v2: update comments
Dont see any comments being added.
----------------------------
so later could use it with 32bit amd_bus/intel_bus, and it could havecap_resource.
----------------------------
Ah the description.
PATCH 3/36 x86/pci: use u64 instead of size_t in amd_bus.c
In reply to Yinghai Luprepare to enable it for 32bit
-v2: remove not needed cast
--- arch/x86/pci/amd_bus.c | 16 ++++++++-------- 1 files changed, 8 insertions(+), 8 deletions(-)
arch/x86/pci/amd_bus.c +8 -8
@@ -82,8 +82,8 @@ static int __init early_fill_mp_bus_info(void)struct pci_root_info *info;u32 reg;struct resource *res; -size_t start; -size_t end; +u64 start; +u64 end;struct range range[RANGE_NUM ];u64 val;u32 address;
@@ -172,7 +172,7 @@ static int __init early_fill_mp_bus_info(void) info = &pci_root_info[j];printk (KERN_DEBUG "node %d link %d: io port [%llx, %llx]\n" , - node, link, (u64 )start, (u64 )end); + node, link, start, end);/* kernel only handle 16 bit only */ if (end >0xffff )
@@ -206,7 +206,7 @@ static int __init early_fill_mp_bus_info(void) address =MSR_K8_TOP_MEM1 ;rdmsrl (address, val); end = (val &0xffffff800000ULL ); -printk (KERN_INFO "TOM: %016lx aka %ldM\n" , end, end>>20 ); +printk (KERN_INFO "TOM: %016llx aka %lldM\n" , end, end>>20 );if (end < (1ULL <<32 ))subtract_range (range,RANGE_NUM ,0 , end -1 );
@@ -245,7 +245,7 @@ static int __init early_fill_mp_bus_info(void) info = &pci_root_info[j];printk (KERN_DEBUG "node %d link %d: mmio [%llx, %llx]" , - node, link, (u64 )start, (u64 )end); + node, link, start, end);/* * some sick allocation would have range overlap with fam10h * mmconf range, so need to update start and end.
@@ -271,13 +271,13 @@ static int __init early_fill_mp_bus_info(void) endx = fam10h_mmconf_start -1 ;update_res (info, start, endx,IORESOURCE_MEM ,0 );subtract_range (range,RANGE_NUM , start, endx); -printk (KERN_CONT " ==> [%llx, %llx]" , (u64 )start, endx); +printk (KERN_CONT " ==> [%llx, %llx]" , start, endx); start = fam10h_mmconf_end +1 ; changed =1 ; }if (changed) {if (start <= end) { -printk (KERN_CONT " %s [%llx, %llx]" , endx?"and" :"==>" , (u64 )start, (u64 )end); +printk (KERN_CONT " %s [%llx, %llx]" , endx?"and" :"==>" , start, end); }else {printk (KERN_CONT "%s\n" , endx?"" :" ==> none" );continue ;
@@ -300,7 +300,7 @@ static int __init early_fill_mp_bus_info(void) address =MSR_K8_TOP_MEM2 ;rdmsrl (address, val); end = (val &0xffffff800000ULL ); -printk (KERN_INFO "TOM2: %016lx aka %ldM\n" , end, end>>20 ); +printk (KERN_INFO "TOM2: %016llx aka %lldM\n" , end, end>>20 );subtract_range (range,RANGE_NUM ,1ULL <<32 , end -1 ); }
Signature · 1 line
1.6.4.2
PATCH 4/36 x86/pci: add cap_resource
In reply to Yinghai Luprepare for 32bit pci root bus
-v2: hpa said we should compare with (resource_size_t)~0
--- arch/x86/pci/amd_bus.c | 8 +++++--- arch/x86/pci/bus_numa.c | 3 +++ arch/x86/pci/intel_bus.c | 5 ++++- include/linux/range.h | 8 ++++++++ 4 files changed, 20 insertions(+), 4 deletions(-)
arch/x86/pci/amd_bus.c +5 -3
@@ -200,7 +200,7 @@ static int __init early_fill_mp_bus_info(void)memset (range,0 ,sizeof (range));/* 0xfd00000000-0xffffffffff for HT */ - range[0 ].end = (0xfdULL <<32 ) -1 ; + range[0 ].end =cap_resource ((0xfdULL <<32 ) -1 );/* need to take out [0, TOM) for RAM*/ address =MSR_K8_TOP_MEM1 ;
@@ -285,7 +285,8 @@ static int __init early_fill_mp_bus_info(void) } } -update_res (info, start, end,IORESOURCE_MEM ,1 ); +update_res (info,cap_resource (start),cap_resource (end), +IORESOURCE_MEM ,1 );subtract_range (range,RANGE_NUM , start, end);printk (KERN_CONT "\n" ); }
@@ -320,7 +321,8 @@ static int __init early_fill_mp_bus_info(void)if (!range[i].end)continue ; -update_res (info, range[i].start, range[i].end, +update_res (info,cap_resource (range[i].start), +cap_resource (range[i].end),IORESOURCE_MEM ,1 ); } }
arch/x86/pci/bus_numa.c +3 -0
@@ -60,6 +60,9 @@ void __devinit update_res(struct pci_root_info *info, size_t start,if (start > end)return ; +if (start == (resource_size_t )~0 ) +return ; +if (!merge) goto addit;
arch/x86/pci/intel_bus.c +4 -1
@@ -6,6 +6,8 @@#include <linux/dmi.h> #include <linux/pci.h> #include <linux/init.h> +#include <linux/range.h> +#include <asm/pci_x86.h> #include "bus_numa.h"
@@ -85,7 +87,8 @@ static void __devinit pci_root_bus_res(struct pci_dev *dev) mmioh_base |= ((u64)(dword &0x7ffff )) <<32 ;pci_read_config_dword (dev,IOH_LMMIOH_LIMITU , &dword); mmioh_end |= ((u64)(dword &0x7ffff )) <<32 ; -update_res (info, mmioh_base, mmioh_end,IORESOURCE_MEM ,0 ); +update_res (info,cap_resource (mmioh_base),cap_resource (mmioh_end), +IORESOURCE_MEM ,0 );print_ioh_resources (info); }
include/linux/range.h +8 -0
@@ -19,4 +19,12 @@ int clean_sort_range(struct range *range, int az);void sort_range (struct range *range,int nr_range); + +static inline resource_size_t cap_resource (u64 val) +{ +if (val > (resource_size_t )~0 ) +return (resource_size_t )~0 ; +else +return val; +}#endif
Signature · 1 line
1.6.4.2
Re: [PATCH 04/36] x86/pci: add cap_resource
Quoted 2 lines · Yinghai Lu
-v2: hpa said we should compare with (resource_size_t)~0
Hmm. Some of these look dubious.
arch/x86/pci/bus_numa.c void __devinit update_res(struct pci_root_info *info, size_t start, · line 64
Quoted 10 lines
arch/x86/pci/bus_numa.c +2
-0@@ -60,6 +60,9 @@ void __devinit update_res(struct pci_root_info *info, size_t start,if (start > end)return ; +if (start == (resource_size_t )~0 ) +return ;
Here, 'start' isn't a resource_size_t. It's a regular size_t. And if resource_size_t is u64, and size_t is u32, this test can never be true.
Maybe that is intentional, but if looks odd/wrong. Needs a comment if right, needs fixing if wrong.
arch/x86/pci/bus_numa.c void __devinit update_res(struct pci_root_info *info, size_t start,
Quoted 8 lines
arch/x86/pci/bus_numa.c +7
-0+static inline resource_size_t cap_resource (u64 val) +{ +if (val > (resource_size_t )~0 ) +return (resource_size_t )~0 ; +else +return val; +}#endif
And this just looks odd. I'd suggest just doing
#define MAX_RESOURCE ((resource_size_t)~0)
static inline resource_size_t cap_resource(u64 val)
{
if (val > MAX_RESOURCE)
val = MAX_RESOURCE;
return val;
}instead, which looks a whole lot more natural. No?
Linus
Re: [PATCH 04/36] x86/pci: add cap_resource
Quoted 16 lines · Linus Torvalds
Quoted 2 lines · Yinghai Lu
-v2: hpa said we should compare with (resource_size_t)~0
Hmm. Some of these look dubious.
Quoted 8 lines
arch/x86/pci/bus_numa.c +0
-0@@ -60,6 +60,9 @@ void __devinit update_res(struct pci_root_info *info, size_t start,if (start > end)return ;
Quoted 8 lines
arch/x86/pci/bus_numa.c void __devinit update_res(struct pci_root_info *info, size_t start, · line 64
Quoted 2 lines
arch/x86/pci/bus_numa.c +2
-0+if (start == (resource_size_t )~0 ) +return ;Here, 'start' isn't a
resource_size_t. It's a regularsize_t. And ifresource_size_tis u64, andsize_tis u32, this test can never be true.Maybe that is intentional, but if looks odd/wrong. Needs a comment if right, needs fixing if wrong.
you are right, there are two patches about that already went into pci/linux-next
will ask Jesse to drop them from pci tree.
so could make them go via tip/x86
http://git.kernel.org/?p=linux/kernel/git/jbarnes/pci-2.6.git;a=commitdiff;h=f84fe8aef6e4b23ab58175a15dd12c197c993f81
http://git.kernel.org/?p=linux/kernel/git/jbarnes/pci-2.6.git;a=commitdiff;h=693f084f82a38fc1b01e3b05664a6fe014a3488a
or later may have merge problem.
Quoted 21 lines
arch/x86/pci/bus_numa.c void __devinit update_res(struct pci_root_info *info, size_t start,
Quoted 9 lines
arch/x86/pci/bus_numa.c +7
-0+static inline resource_size_t cap_resource (u64 val) +{ +if (val > (resource_size_t )~0 ) +return (resource_size_t )~0 ; +else +return val; +}#endif And this just looks odd. I'd suggest just doing
#define MAX_RESOURCE ((resource_size_t)~0) static inline resource_size_t cap_resource(u64 val) { if (val > MAX_RESOURCE) val = MAX_RESOURCE; return val; }
Quoted 1 line
instead, which looks a whole lot more natural. No?
OK
Yinghai
PATCH 5/36 x86/pci: enable pci root res read out for 32bit too
In reply to Yinghai Lushould be good for 32bit too.
-v3: cast res->start
--- arch/x86/pci/Makefile | 3 +-- arch/x86/pci/amd_bus.c | 14 +------------- arch/x86/pci/bus_numa.h | 4 ++-- arch/x86/pci/i386.c | 4 ---- arch/x86/pci/intel_bus.c | 2 +- 5 files changed, 5 insertions(+), 22 deletions(-)
arch/x86/pci/Makefile +1 -2
@@ -14,8 +14,7 @@ obj-$(CONFIG_X86_VISWS) += visws.o obj-$(CONFIG_X86_NUMAQ) += numaq_32.o obj-y += common.o early.o -obj-y += amd_bus.o -obj-$(CONFIG_X86_64) += bus_numa.o intel_bus.o +obj-y += amd_bus.o bus_numa.o intel_bus.o ifeq ($(CONFIG_PCI_DEBUG),y) EXTRA_CFLAGS += -DDEBUG
arch/x86/pci/amd_bus.c +1 -13
@@ -6,9 +6,7 @@#include <asm/pci_x86.h> -#ifdef CONFIG_X86_64 #include <asm/pci-direct.h> -#endif #include "bus_numa.h"
@@ -17,8 +15,6 @@* also get peer root bus resource for io,mmio */ -#ifdef CONFIG_X86_64 -struct pci_hostbridge_probe {u32 bus;u32 slot;
@@ -341,21 +337,13 @@ static int __init early_fill_mp_bus_info(void)printk (KERN_DEBUG "bus: %02x index %x %s: [%llx, %llx]\n" , busnum, j, (res->flags &IORESOURCE_IO )?"io port" :"mmio" , - res->start, res->end); + (u64 )res->start, (u64 )res->end); } }return 0 ; } -#else /* !CONFIG_X86_64 */ - -static int __init early_fill_mp_bus_info (void ) {return 0 ; } - -#endif /* !CONFIG_X86_64 */ - -/* common 32/64 bit code */ -#define ENABLE_CF8_EXT_CFG (1ULL << 46)static void enable_pci_io_ecs (void *unused)
arch/x86/pci/bus_numa.h +2 -2
@@ -1,5 +1,5 @@ -#ifdef CONFIG_X86_64 - +#ifndef __BUS_NUMA_H +#define __BUS_NUMA_H/* * sub bus (transparent) will use entres from 3 to store extra from * root, so need to make sure we have enough slot there, Should we
arch/x86/pci/i386.c +0 -4
@@ -257,10 +257,6 @@ void __init pcibios_resource_survey(void)*/ fs_initcall (pcibios_assign_resources); -void __weak x86_pci_root_bus_res_quirks (struct pci_bus *b) -{ -} -/* * If we set up a device for bus mastering, we need to check the latency * timer as certain crappy BIOSes forget to set it properly.
arch/x86/pci/intel_bus.c +1 -1
@@ -30,7 +30,7 @@ static inline void print_ioh_resources(struct pci_root_info *info) busnum, i, (res->flags &IORESOURCE_IO ) ?"io port" :"mmio" , - res->start, res->end); + (u64)res->start, (u64)res->end); } }
Signature · 1 line
1.6.4.2
Re: [PATCH 05/36] x86/pci: enable pci root res read out for 32bit too
arch/x86/pci/amd_bus.c static int __init early_fill_mp_bus_info(void) · line 340
Quoted 6 lines · Yinghai Lu
arch/x86/pci/amd_bus.c +1
-1printk (KERN_DEBUG "bus: %02x index %x %s: [%llx, %llx]\n" , busnum, j, (res->flags &IORESOURCE_IO )?"io port" :"mmio" , - res->start, res->end); + (u64 )res->start, (u64 )res->end);
When fixing these kinds of things, please just make it use '%pR' instead.
A simple
printk(KERN_DEBUG "bus: %02x index %x %pR\n", busnum, j, res);
should do the right thing, printing the resource with nice human-readable flags. Including things like 64-bit/prefetching information for memory resources etc that the current manual resource printout doesn't do.
Linus
Re: [PATCH 05/36] x86/pci: enable pci root res read out for 32bit too
Quoted 12 lines · Linus Torvalds
arch/x86/pci/amd_bus.c static int __init early_fill_mp_bus_info(void) · line 340
Quoted 6 lines · Yinghai Lu
arch/x86/pci/amd_bus.c +1
-1printk (KERN_DEBUG "bus: %02x index %x %s: [%llx, %llx]\n" , busnum, j, (res->flags &IORESOURCE_IO )?"io port" :"mmio" , - res->start, res->end); + (u64 )res->start, (u64 )res->end);When fixing these kinds of things, please just make it use '%pR' instead.
Quoted 7 lines
A simple
printk(KERN_DEBUG "bus: %02x index %x %pR\n", busnum, j, res);should do the right thing, printing the resource with nice human-readable flags. Including things like 64-bit/prefetching information for memory resources etc that the current manual resource printout doesn't do.
ok.
YH
PATCH 6/36 x86: call early_res_to_bootmem one time
In reply to Yinghai Lusimplify setup_node_mem, do use bootmem from other node. instead just find_e820_area in early_node_mem.
so we can keep the boundary between early_res and boot mem more clear. and only call civertion one time instead of for all nodes.
--- arch/x86/kernel/setup.c | 1 + arch/x86/mm/init_32.c | 1 - arch/x86/mm/init_64.c | 3 +- arch/x86/mm/numa_64.c | 62 +++++++++++++++------------------------------- 4 files changed, 22 insertions(+), 45 deletions(-)
arch/x86/kernel/setup.c +1 -0
@@ -942,6 +942,7 @@ void __init setup_arch(char **cmdline_p)#endif initmem_init (0 , max_pfn, acpi, k8); +early_res_to_bootmem (0 , max_low_pfn<<PAGE_SHIFT );#ifdef CONFIG_X86_64 /*
arch/x86/mm/init_32.c +0 -1
@@ -764,7 +764,6 @@ static unsigned long __init setup_node_bootmem(int nodeid,printk (KERN_INFO " node %d bootmap %08lx - %08lx\n" , nodeid, bootmap, bootmap + bootmap_size);free_bootmem_with_active_regions (nodeid, end_pfn); -early_res_to_bootmem (start_pfn<<PAGE_SHIFT , end_pfn<<PAGE_SHIFT );return bootmap + bootmap_size; }
arch/x86/mm/init_64.c +1 -2
@@ -578,13 +578,12 @@ void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn, PAGE_SIZE);if (bootmap ==-1L )panic ("Cannot find bootmem map of size %ld\n" , bootmap_size); +reserve_early (bootmap, bootmap + bootmap_size,"BOOTMAP" );/* don't touch min_low_pfn */ bootmap_size =init_bootmem_node (NODE_DATA (0 ), bootmap >>PAGE_SHIFT ,0 , end_pfn);e820_register_active_regions (0 , start_pfn, end_pfn); free_bootmem_with_active_regions(0, end_pfn); -early_res_to_bootmem (0 , end_pfn<<PAGE_SHIFT ); - reserve_bootmem(bootmap, bootmap_size, BOOTMEM_DEFAULT); }#endif
arch/x86/mm/numa_64.c +20 -42
106 lines not on this page · raw message
Signature · 1 line
1.6.4.2
PATCH 7/36 x86: introduce max_early_res and early_res_count
In reply to Yinghai Luto prepare allocate early res array from fine_e820_area
--- arch/x86/kernel/e820.c | 47 ++++++++++++++++++++++++++++++++--------------- 1 files changed, 32 insertions(+), 15 deletions(-)
arch/x86/kernel/e820.c +32 -15
@@ -724,14 +724,18 @@ core_initcall(e820_mark_nvs_memory);/* * Early reserved memory areas. */ -#define MAX_EARLY_RES 32 +/* +* need to make sure this one is bigger enough before +* find_e820_area could be used +*/ +#define MAX_EARLY_RES_X 32struct early_res {u64 start, end; -char name[16 ]; +char name[15 ];char overlap_ok; }; -static struct early_res early_res[MAX_EARLY_RES ]__initdata = { +static struct early_res early_res_x[MAX_EARLY_RES_X ]__initdata = { {0 ,PAGE_SIZE ,"BIOS data page" ,1 },/* BIOS data page */ #if defined(CONFIG_X86_32) && defined(CONFIG_X86_TRAMPOLINE)/*
@@ -745,12 +749,22 @@ static struct early_res early_res[MAX_EARLY_RES] __initdata = { {} }; +static int max_early_res__initdata =MAX_EARLY_RES_X ; +static struct early_res *early_res__initdata = &early_res_x[0 ]; +static int early_res_count __initdata = +#ifdef CONFIG_X86_32 + 2 +#else + 1 +#endif + ; +static int __init find_overlapped_early (u64 start,u64 end) {int i;struct early_res *r; -for (i =0 ; i <MAX_EARLY_RES && early_res[i].end; i++) { +for (i =0 ; i < max_early_res && early_res[i].end; i++) { r = &early_res[i];if (end > r->start && start < r->end)break ;
@@ -768,13 +782,14 @@ static void __init drop_range(int i) {int j; -for (j = i +1 ; j <MAX_EARLY_RES && early_res[j].end; j++) +for (j = i +1 ; j < max_early_res && early_res[j].end; j++) ;memmove (&early_res[i], &early_res[i +1 ], (j -1 - i) *sizeof (struct early_res )); early_res[j -1 ].end =0 ; + early_res_count--; }/*
@@ -793,9 +808,9 @@ static void __init drop_overlaps_that_are_ok(u64 start, u64 end)struct early_res *r;u64 lower_start, lower_end;u64 upper_start, upper_end; -char name[16 ]; +char name[15 ]; -for (i =0 ; i <MAX_EARLY_RES && early_res[i].end; i++) { +for (i =0 ; i < max_early_res && early_res[i].end; i++) { r = &early_res[i];/* Continue past non-overlapping ranges */
@@ -851,7 +866,7 @@ static void __init __reserve_early(u64 start, u64 end, char *name,struct early_res *r; i =find_overlapped_early (start, end); -if (i >=MAX_EARLY_RES ) +if (i >= max_early_res)panic ("Too many early reservations" ); r = &early_res[i];if (r->end)
@@ -864,6 +879,7 @@ static void __init __reserve_early(u64 start, u64 end, char *name, r->overlap_ok = overlap_ok;if (name)strncpy (r->name, name,sizeof (r->name) -1 ); + early_res_count++; }/*
@@ -916,7 +932,7 @@ void __init free_early(u64 start, u64 end) i =find_overlapped_early (start, end); r = &early_res[i]; -if (i >=MAX_EARLY_RES || r->end != end || r->start != start) +if (i >= max_early_res || r->end != end || r->start != start)panic ("free_early on not reserved area: %llx-%llx!" , start, end -1 );
@@ -927,14 +943,15 @@ void __init early_res_to_bootmem(u64 start, u64 end) {int i, count;u64 final_start, final_end; +int idx =0 ; count =0 ; -for (i =0 ; i <MAX_EARLY_RES && early_res[i].end; i++) +for (i =0 ; i < max_early_res && early_res[i].end; i++) count++; -printk (KERN_INFO "(%d early reservations) ==> bootmem [%010llx - %010llx]\n" , - count, start, end); -for (i =0 ; i < count; i++) { +printk (KERN_INFO "(%d/%d early reservations) ==> bootmem [%010llx - %010llx]\n" , + count - idx, max_early_res, start, end); +for (i = idx; i < count; i++) {struct early_res *r = &early_res[i];printk (KERN_INFO " #%d [%010llx - %010llx] %16s" , i, r->start, r->end, r->name);
@@ -961,7 +978,7 @@ static inline int __init bad_addr(u64 *addrp, u64 size, u64 align) again: i =find_overlapped_early (addr, addr + size); r = &early_res[i]; -if (i <MAX_EARLY_RES && r->end) { +if (i < max_early_res && r->end) { *addrp = addr =round_up (r->end, align); changed =1 ; goto again;
@@ -978,7 +995,7 @@ static inline int __init bad_addr_size(u64 *addrp, u64 *sizep, u64 align)int changed =0 ; again: last = addr + size; -for (i =0 ; i <MAX_EARLY_RES && early_res[i].end; i++) { +for (i =0 ; i < max_early_res && early_res[i].end; i++) {struct early_res *r = &early_res[i];if (last > r->start && addr < r->start) { size = r->start - addr;
Signature · 1 line
1.6.4.2
PATCH 8/36 x86: dynamic increase early_res array size
In reply to Yinghai Luuse early_res_count to track the num, and use find_e820 to get new buffer. and copy from old to new one.
also clear early_res to prevent later invalid using
-v2 _check_and_double_early_res should take new start
--- arch/x86/kernel/e820.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 53 insertions(+), 0 deletions(-)
arch/x86/kernel/e820.c +53 -0
@@ -908,6 +908,48 @@ void __init reserve_early_overlap_ok(u64 start, u64 end, char *name)__reserve_early (start, end, name,1 ); } +static void __init __check_and_double_early_res (u64 start) +{ +u64 end, size, mem; +struct early_res *new; + +/* do we have enough slots left ? */ +if ((max_early_res - early_res_count) >max (max_early_res/8 ,2 )) +return ; + +/* double it */ + end = max_pfn_mapped <<PAGE_SHIFT ; + size =sizeof (struct early_res ) * max_early_res *2 ; + mem =find_e820_area (start, end, size,sizeof (struct early_res )); + +if (mem ==-1ULL ) +panic ("can not find more space for early_res array" ); + + new =__va (mem); +/* save the first one for own */ + new[0 ].start = mem; + new[0 ].end = mem + size; + new[0 ].overlap_ok =0 ; +/* copy old to new */ +if (early_res == early_res_x) { +memcpy (&new[1 ], &early_res[0 ], +sizeof (struct early_res ) * max_early_res); +memset (&new[max_early_res+1 ],0 , +sizeof (struct early_res ) * (max_early_res -1 )); + early_res_count++; + }else { +memcpy (&new[1 ], &early_res[1 ], +sizeof (struct early_res ) * (max_early_res -1 )); +memset (&new[max_early_res],0 , +sizeof (struct early_res ) * max_early_res); + } +memset (&early_res[0 ],0 ,sizeof (struct early_res ) * max_early_res); + early_res = new; + max_early_res *=2 ; +printk (KERN_DEBUG "early_res array is doubled to %d at [%llx - %llx]\n" , + max_early_res, mem, mem + size -1 ); +} +/* * Most early reservations come here. *
@@ -921,6 +963,8 @@ void __init reserve_early(u64 start, u64 end, char *name)if (start >= end)return ; +__check_and_double_early_res (end); +drop_overlaps_that_are_ok (start, end);__reserve_early (start, end, name,0 ); }
@@ -949,6 +993,10 @@ void __init early_res_to_bootmem(u64 start, u64 end)for (i =0 ; i < max_early_res && early_res[i].end; i++) count++; +/* need to skip first one ?*/ +if (early_res != early_res_x) + idx =1 ; +printk (KERN_INFO "(%d/%d early reservations) ==> bootmem [%010llx - %010llx]\n" , count - idx, max_early_res, start, end);for (i = idx; i < count; i++) {
@@ -966,6 +1014,11 @@ void __init early_res_to_bootmem(u64 start, u64 end)reserve_bootmem_generic (final_start, final_end - final_start,BOOTMEM_DEFAULT ); } +/* clear them */ +memset (&early_res[0 ],0 ,sizeof (struct early_res ) * max_early_res); + early_res =NULL ; + max_early_res =0 ; + early_res_count =0 ; }/* Check for already reserved areas */
Signature · 1 line
1.6.4.2
PATCH 9/36 x86: print bootmem free before pci_iommu_alloc and free_all_bootmem -v2
In reply to Yinghai Luso we could double check if we have enough low pages later
-v2: fix errors checkpatch.pl reported
--- arch/x86/mm/init_64.c | 2 + include/linux/bootmem.h | 2 + mm/bootmem.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 0 deletions(-)
arch/x86/mm/init_64.c +2 -0
@@ -654,6 +654,8 @@ void __init mem_init(void)long codesize, reservedpages, datasize, initsize;unsigned long absent_pages; +print_bootmem_free (); +pci_iommu_alloc ();/* clear_bss() already clear the empty_zero_page */
include/linux/bootmem.h +2 -0
@@ -55,6 +55,8 @@ extern void free_bootmem_node(pg_data_t *pgdat,extern void free_bootmem (unsigned long addr,unsigned long size);extern void free_bootmem_late (unsigned long addr,unsigned long size); +void print_bootmem_free (void ); +/* * Flags for reserve_bootmem (also if CONFIG_HAVE_ARCH_BOOTMEM_NODE, * the architecture-specific code should honor this).
mm/bootmem.c +92 -0
98 lines not on this page · raw message
Signature · 1 line
1.6.4.2
PATCH 10/36 x86: make early_node_mem get mem > 4g if possible
In reply to Yinghai Luso we could put pgdata for the node high, and later sparse vmmap will get the section nr that need.
with this patch will make <4g ram will not use sparse vmmap
before this patch, will get, before swiotlb try get bootmem
[ 0.000000] nid=1 start=0 end=2080000 aligned=1 [ 0.000000] free [10 - 96] [ 0.000000] free [b12 - 1000] [ 0.000000] free [359f - 38a3] [ 0.000000] free [38b5 - 3a00] [ 0.000000] free [41e01 - 42000] [ 0.000000] free [73dde - 73e00] [ 0.000000] free [73fdd - 74000] [ 0.000000] free [741dd - 74200] [ 0.000000] free [743dd - 74400] [ 0.000000] free [745dd - 74600] [ 0.000000] free [747dd - 74800] [ 0.000000] free [749dd - 74a00] [ 0.000000] free [74bdd - 74c00] [ 0.000000] free [74ddd - 74e00] [ 0.000000] free [74fdd - 75000] [ 0.000000] free [751dd - 75200] [ 0.000000] free [753dd - 75400] [ 0.000000] free [755dd - 75600] [ 0.000000] free [757dd - 75800] [ 0.000000] free [759dd - 75a00] [ 0.000000] free [75bdd - 7bf5f] [ 0.000000] free [7f730 - 7f750] [ 0.000000] free [100000 - 2080000] [ 0.000000] total free 1f87170 [ 93.301474] Placing 64MB software IO TLB between ffff880075bdd000 - ffff880079bdd000 [ 93.311814] software IO TLB at phys 0x75bdd000 - 0x79bdd000
with this patch will get: before swiotlb try get bootmem
[ 0.000000] nid=1 start=0 end=2080000 aligned=1 [ 0.000000] free [a - 96] [ 0.000000] free [702 - 1000] [ 0.000000] free [359f - 3600] [ 0.000000] free [37de - 3800] [ 0.000000] free [39dd - 3a00] [ 0.000000] free [3bdd - 3c00] [ 0.000000] free [3ddd - 3e00] [ 0.000000] free [3fdd - 4000] [ 0.000000] free [41dd - 4200] [ 0.000000] free [43dd - 4400] [ 0.000000] free [45dd - 4600] [ 0.000000] free [47dd - 4800] [ 0.000000] free [49dd - 4a00] [ 0.000000] free [4bdd - 4c00] [ 0.000000] free [4ddd - 4e00] [ 0.000000] free [4fdd - 5000] [ 0.000000] free [51dd - 5200] [ 0.000000] free [53dd - 5400] [ 0.000000] free [55dd - 7bf5f] [ 0.000000] free [7f730 - 7f750] [ 0.000000] free [100428 - 100600] [ 0.000000] free [13ea01 - 13ec00] [ 0.000000] free [170800 - 2080000] [ 0.000000] total free 1f87170
[ 92.689485] PCI-DMA: Using software bounce buffering for IO (SWIOTLB) [ 92.699799] Placing 64MB software IO TLB between ffff8800055dd000 - ffff8800095dd000 [ 92.710916] software IO TLB at phys 0x55dd000 - 0x95dd000
so will get enough space below 4G, aka pfn 0x100000
--- arch/x86/mm/numa_64.c | 23 ++++++++++++++++++----- 1 files changed, 18 insertions(+), 5 deletions(-)
arch/x86/mm/numa_64.c +17 -4
@@ -163,14 +163,27 @@ static void * __init early_node_mem(int nodeid, unsigned long start, unsigned long end, unsigned long size, unsigned long align) { - unsigned long mem = find_e820_area(start, end, size, align); + unsigned long mem; +/* +* put it on high as possible +* something will go with NODE_DATA +*/ +if (start < (MAX_DMA_PFN <<PAGE_SHIFT )) + start =MAX_DMA_PFN <<PAGE_SHIFT ; +if (start < (MAX_DMA32_PFN <<PAGE_SHIFT ) && + end > (MAX_DMA32_PFN <<PAGE_SHIFT )) + start =MAX_DMA32_PFN <<PAGE_SHIFT ; + mem =find_e820_area (start, end, size, align);if (mem !=-1L )return __va (mem); - - start =__pa (MAX_DMA_ADDRESS ); - end = max_low_pfn_mapped <<PAGE_SHIFT ; +/* extend the search scope */ + end = max_pfn_mapped <<PAGE_SHIFT ; +if (end > (MAX_DMA32_PFN <<PAGE_SHIFT )) + start =MAX_DMA32_PFN <<PAGE_SHIFT ; +else + start =MAX_DMA_PFN <<PAGE_SHIFT ; mem =find_e820_area (start, end, size, align);if (mem !=-1L )return __va (mem);
Signature · 1 line
1.6.4.2
PATCH 11/36 x86: only call dma32_reserve_bootmem 64bit !CONFIG_NUMA
In reply to Yinghai Lu64bit NUMA already make enough space under 4G with new early_node_mem
--- arch/x86/include/asm/pci.h | 2 ++ arch/x86/include/asm/pci_64.h | 2 -- arch/x86/kernel/pci-dma.c | 13 ++++++++++--- arch/x86/kernel/setup.c | 7 ------- 4 files changed, 12 insertions(+), 12 deletions(-)
arch/x86/include/asm/pci.h +2 -0
@@ -124,6 +124,8 @@ extern void pci_iommu_alloc(void);#include "pci_64.h" #endif +void dma32_reserve_bootmem (void ); +/* implement the pci_ DMA API in terms of the generic device dma_ one */ #include <asm-generic/pci-dma-compat.h>
arch/x86/include/asm/pci_64.h +0 -2
@@ -22,8 +22,6 @@ extern int (*pci_config_read)(int seg, int bus, int dev, int fn,extern int (*pci_config_write)(int seg,int bus,int dev,int fn,int reg,int len,u32 value); -extern void dma32_reserve_bootmem (void ); -#endif /* __KERNEL__ */ #endif /* _ASM_X86_PCI_64_H */
arch/x86/kernel/pci-dma.c +10 -3
@@ -65,7 +65,7 @@ int dma_set_mask(struct device *dev, u64 mask) }EXPORT_SYMBOL (dma_set_mask); -#ifdef CONFIG_X86_64 +#if defined(CONFIG_X86_64 ) && !defined(CONFIG_NUMA )static __initdata void *dma32_bootmem_ptr;static unsigned long dma32_bootmem_size__initdata = (128ULL <<20 );
@@ -116,14 +116,21 @@ static void __init dma32_free_bootmem(void) dma32_bootmem_ptr =NULL ; dma32_bootmem_size = 0; } +#else +void __init dma32_reserve_bootmem (void ) +{ +} +static void __init dma32_free_bootmem (void ) +{ +} +#endif void __init pci_iommu_alloc (void ) { -#ifdef CONFIG_X86_64 /* free the range so iommu could get some range less than 4G */ dma32_free_bootmem (); -#endif +if (pci_swiotlb_detect ()) goto out;
arch/x86/kernel/setup.c +0 -7
@@ -944,14 +944,7 @@ void __init setup_arch(char **cmdline_p)initmem_init (0 , max_pfn, acpi, k8);early_res_to_bootmem (0 , max_low_pfn<<PAGE_SHIFT ); -#ifdef CONFIG_X86_64 -/* -* dma32_reserve_bootmem() allocates bootmem which may conflict -* with the crashkernel command line, so do that after -* reserve_crashkernel() -*/ dma32_reserve_bootmem (); -#endif reserve_ibft_region ();
Signature · 1 line
1.6.4.2
PATCH 12/36 x86: make 64 bit use early_res instead of bootmem before slab
In reply to Yinghai Lufinally we can use early_res to replace bootmem for x86_64 now.
still can use CONFIG_NO_BOOTMEM to enable it or not
-v2: fix 32bit compiling about MAX_DMA32_PFN
--- arch/x86/Kconfig | 7 ++ arch/x86/include/asm/e820.h | 6 ++ arch/x86/kernel/e820.c | 159 ++++++++++++++++++++++++++++++++--- arch/x86/kernel/setup.c | 2 + arch/x86/mm/init_64.c | 7 ++- arch/x86/mm/numa_64.c | 20 ++++- include/linux/bootmem.h | 7 ++ include/linux/mm.h | 5 + include/linux/mmzone.h | 2 + mm/bootmem.c | 195 ++++++++++++++++++++++++++++++++++++++++++- mm/page_alloc.c | 59 +++++++++++++- mm/percpu.c | 3 + mm/sparse-vmemmap.c | 2 +- 13 files changed, 450 insertions(+), 24 deletions(-)
arch/x86/Kconfig +7 -0
@@ -568,6 +568,13 @@ config PARAVIRT_DEBUG Enable to debug paravirt_ops internals. Specifically, BUG if a paravirt_op is missing when it is called. +config NO_BOOTMEM + default y + bool "Disable Bootmem code" + depends on X86_64 + ---help--- + use early_res directly instead of bootmem before slab is ready. + config MEMTEST bool "Memtest" ---help---
arch/x86/include/asm/e820.h +6 -0
@@ -117,6 +117,12 @@ extern void free_early(u64 start, u64 end);extern void early_res_to_bootmem (u64 start,u64 end);extern u64 early_reserve_e820 (u64 startt,u64 sizet,u64 align); +void reserve_early_without_check (u64 start,u64 end,char *name); +u64 find_early_area (u64 ei_start,u64 ei_last,u64 start,u64 end, +u64 size,u64 align); +#include <linux/range.h> +int get_free_all_memory_range (struct range **rangep,int nodeid); +extern unsigned long e820_end_of_ram_pfn (void );extern unsigned long e820_end_of_low_ram_pfn (void ); extern int e820_find_active_region(const struct e820entry *ei,
arch/x86/kernel/e820.c +146 -13
194 lines not on this page · raw message
arch/x86/kernel/setup.c +2 -0
@@ -942,7 +942,9 @@ void __init setup_arch(char **cmdline_p)#endif initmem_init (0 , max_pfn, acpi, k8); +#ifndef CONFIG_NO_BOOTMEM early_res_to_bootmem (0 , max_low_pfn<<PAGE_SHIFT ); +#endif dma32_reserve_bootmem ();
arch/x86/mm/init_64.c +6 -1
@@ -571,6 +571,7 @@ kernel_physical_mapping_init(unsigned long start,void __init initmem_init (unsigned long start_pfn,unsigned long end_pfn,int acpi,int k8) { +#ifndef CONFIG_NO_BOOTMEM unsigned long bootmap_size, bootmap; bootmap_size =bootmem_bootmap_pages (end_pfn)<<PAGE_SHIFT ;
@@ -582,8 +583,10 @@ void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn,/* don't touch min_low_pfn */ bootmap_size =init_bootmem_node (NODE_DATA (0 ), bootmap >>PAGE_SHIFT ,0 , end_pfn); -e820_register_active_regions (0 , start_pfn, end_pfn);free_bootmem_with_active_regions (0 , end_pfn); +#else +e820_register_active_regions (0 , start_pfn, end_pfn); +#endif }#endif
@@ -654,7 +657,9 @@ void __init mem_init(void)long codesize, reservedpages, datasize, initsize;unsigned long absent_pages; +#ifndef CONFIG_NO_BOOTMEM print_bootmem_free (); +#endif pci_iommu_alloc ();
arch/x86/mm/numa_64.c +15 -5
@@ -198,11 +198,13 @@ static void * __init early_node_mem(int nodeid, unsigned long start,void __init setup_node_bootmem (int nodeid,unsigned long start,unsigned long end) { -unsigned long start_pfn, last_pfn, bootmap_pages, bootmap_size; +unsigned long start_pfn, last_pfn, nodedata_phys;const int pgdat_size =roundup (sizeof (pg_data_t),PAGE_SIZE ); -unsigned long bootmap_start, nodedata_phys; -void *bootmap;int nid; +#ifndef CONFIG_NO_BOOTMEM +unsigned long bootmap_start, bootmap_pages, bootmap_size; +void *bootmap; +#endif if (!end)return ;
@@ -216,7 +218,7 @@ setup_node_bootmem(int nodeid, unsigned long start, unsigned long end) start =roundup (start,ZONE_ALIGN ); -printk (KERN_INFO "Bootmem setup node %d %016lx-%016lx\n" , nodeid, +printk (KERN_INFO "Initmem setup node %d %016lx-%016lx\n" , nodeid, start, end); start_pfn = start >>PAGE_SHIFT ;
@@ -235,10 +237,13 @@ setup_node_bootmem(int nodeid, unsigned long start, unsigned long end)printk (KERN_INFO " NODE_DATA(%d) on node %d\n" , nodeid, nid);memset (NODE_DATA (nodeid),0 ,sizeof (pg_data_t)); -NODE_DATA (nodeid)->bdata = &bootmem_node_data[nodeid]; +NODE_DATA (nodeid)->node_id = nodeid;NODE_DATA (nodeid)->node_start_pfn = start_pfn;NODE_DATA (nodeid)->node_spanned_pages = last_pfn - start_pfn; +#ifndef CONFIG_NO_BOOTMEM +NODE_DATA (nodeid)->bdata = &bootmem_node_data[nodeid]; +/* * Find a place for the bootmem map * nodedata_phys could be on other nodes by alloc_bootmem,
@@ -275,6 +280,7 @@ setup_node_bootmem(int nodeid, unsigned long start, unsigned long end)printk (KERN_INFO " bootmap(%d) on node %d\n" , nodeid, nid);free_bootmem_with_active_regions (nodeid, end); +#endif node_set_online (nodeid); }
@@ -733,6 +739,10 @@ unsigned long __init numa_free_all_bootmem(void)for_each_online_node (i) pages +=free_all_bootmem_node (NODE_DATA (i)); +#ifdef CONFIG_NO_BOOTMEM + pages +=free_all_memory_core_early (MAX_NUMNODES ); +#endif +return pages; }
include/linux/bootmem.h +7 -0
@@ -23,6 +23,7 @@ extern unsigned long max_pfn;extern unsigned long saved_max_pfn;#endif +#ifndef CONFIG_NO_BOOTMEM /* * node_bootmem_map is a map pointer - the bits represent all physical * memory pages (including holes) on the node.
@@ -37,6 +38,7 @@ typedef struct bootmem_data { } bootmem_data_t;extern bootmem_data_t bootmem_node_data[]; +#endif extern unsigned long bootmem_bootmap_pages (unsigned long );
@@ -46,6 +48,7 @@ extern unsigned long init_bootmem_node(pg_data_t *pgdat, unsigned long endpfn);extern unsigned long init_bootmem (unsigned long addr,unsigned long memend); +unsigned long free_all_memory_core_early (int nodeid);extern unsigned long free_all_bootmem_node (pg_data_t *pgdat);extern unsigned long free_all_bootmem (void );
@@ -86,6 +89,10 @@ extern void *__alloc_bootmem_node(pg_data_t *pgdat,unsigned long size, unsigned long align, unsigned long goal); +void *__alloc_bootmem_node_high (pg_data_t *pgdat, +unsigned long size, +unsigned long align, +unsigned long goal); extern void *__alloc_bootmem_node_nopanic(pg_data_t *pgdat, unsigned long size, unsigned long align,
include/linux/mm.h +5 -0
@@ -12,6 +12,7 @@#include <linux/prio_tree.h> #include <linux/debug_locks.h> #include <linux/mm_types.h> +#include <linux/range.h> struct mempolicy ;struct anon_vma ;
@@ -1047,6 +1048,10 @@ extern void get_pfn_range_for_nid(unsigned int nid,extern unsigned long find_min_pfn_with_active_regions (void );extern void free_bootmem_with_active_regions (int nid,unsigned long max_low_pfn); +int add_from_early_node_map (struct range *range,int az, +int nr_range,int nid); +void *__alloc_memory_core_early (int nodeid,u64 size,u64 align, +u64 goal,u64 limit);typedef int (*work_fn_t )(unsigned long ,unsigned long ,void *);extern void work_with_active_regions (int nid,work_fn_t work_fn,void *data);extern void sparse_memory_present_with_active_regions (int nid);
include/linux/mmzone.h +2 -0
@@ -620,7 +620,9 @@ typedef struct pglist_data {struct page_cgroup *node_page_cgroup;#endif #endif +#ifndef CONFIG_NO_BOOTMEM struct bootmem_data *bdata; +#endif #ifdef CONFIG_MEMORY_HOTPLUG /* * Must be held any time you expect node_start_pfn, node_present_pages
mm/bootmem.c +192 -3
371 lines not on this page · raw message
mm/page_alloc.c +58 -1
71 lines not on this page · raw message
mm/percpu.c +3 -0
@@ -1929,7 +1929,10 @@ int __init pcpu_embed_first_chunk(size_t reserved_size, ssize_t dyn_size, }/* copy and return the unused part */ memcpy (ptr, __per_cpu_load, ai->static_size); +#ifndef CONFIG_NO_BOOTMEM +/* fix partial free ! */ free_fn (ptr + size_sum, ai->unit_size - size_sum); +#endif } }
mm/sparse-vmemmap.c +1 -1
@@ -40,7 +40,7 @@ static void * __init_refok __earlyonly_bootmem_alloc(int node,unsigned long align, unsigned long goal) { - return __alloc_bootmem_node(NODE_DATA(node), size, align, goal); + return __alloc_bootmem_node_high(NODE_DATA(node), size, align, goal); }
Signature · 1 line
1.6.4.2
PATCH 13/36 sparsemem: put usemap for one node together
In reply to Yinghai Lucould save some buf instead of applying one by one
could help that system that is going to use early_res instead of bootmem less entries in early_res make search more faster on system with more memory.
--- mm/sparse.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++------------ 1 files changed, 66 insertions(+), 18 deletions(-)
mm/sparse.c +66 -18
@@ -271,7 +271,8 @@ static unsigned long *__kmalloc_section_usemap(void)#ifdef CONFIG_MEMORY_HOTREMOVE static unsigned long *__init -sparse_early_usemap_alloc_pgdat_section (struct pglist_data *pgdat) +sparse_early_usemaps_alloc_pgdat_section (struct pglist_data *pgdat, +unsigned long count) {unsigned long section_nr;
@@ -286,7 +287,7 @@ sparse_early_usemap_alloc_pgdat_section(struct pglist_data *pgdat)* this problem. */ section_nr =pfn_to_section_nr (__pa (pgdat) >>PAGE_SHIFT ); -return alloc_bootmem_section (usemap_size (), section_nr); +return alloc_bootmem_section (usemap_size () * count, section_nr); }static void __init check_usemap_section_nr (int nid,unsigned long *usemap)
@@ -329,7 +330,8 @@ static void __init check_usemap_section_nr(int nid, unsigned long *usemap) }#else static unsigned long *__init -sparse_early_usemap_alloc_pgdat_section (struct pglist_data *pgdat) +sparse_early_usemaps_alloc_pgdat_section (struct pglist_data *pgdat, +unsigned long count) {return NULL ; }
@@ -339,27 +341,40 @@ static void __init check_usemap_section_nr(int nid, unsigned long *usemap) }#endif /* CONFIG_MEMORY_HOTREMOVE */ -static unsigned long *__init sparse_early_usemap_alloc (unsigned long pnum) +static void __init sparse_early_usemaps_alloc_node (unsigned long **usemap_map, +unsigned long pnum_begin, +unsigned long pnum_end, +unsigned long usemap_count,int nodeid) { -unsigned long *usemap; -struct mem_section *ms =__nr_to_section (pnum); -int nid =sparse_early_nid (ms); - - usemap =sparse_early_usemap_alloc_pgdat_section (NODE_DATA (nid)); -if (usemap) -return usemap; +void *usemap; +unsigned long pnum; +int size =usemap_size (); - usemap =alloc_bootmem_node (NODE_DATA (nid),usemap_size ()); + usemap =sparse_early_usemaps_alloc_pgdat_section (NODE_DATA (nodeid), + usemap_count);if (usemap) { -check_usemap_section_nr (nid, usemap); -return usemap; +for (pnum = pnum_begin; pnum < pnum_end; pnum++) { +if (!present_section_nr (pnum)) +continue ; + usemap_map[pnum] = usemap; + usemap += size; + } +return ; } -/* Stupid: suppress gcc warning for SPARSEMEM && !NUMA */ - nid =0 ; + usemap =alloc_bootmem_node (NODE_DATA (nodeid), size * usemap_count); +if (usemap) { +for (pnum = pnum_begin; pnum < pnum_end; pnum++) { +if (!present_section_nr (pnum)) +continue ; + usemap_map[pnum] = usemap; + usemap += size; +check_usemap_section_nr (nodeid, usemap_map[pnum]); + } +return ; + }printk (KERN_WARNING "%s: allocation failed\n" , __func__); -return NULL ; }#ifndef CONFIG_SPARSEMEM_VMEMMAP
@@ -396,6 +411,7 @@ static struct page __init *sparse_early_mem_map_alloc(unsigned long pnum)void __attribute__((weak))__meminit vmemmap_populate_print_last (void ) { } +/* * Allocate the accumulated non-linear sections, allocate a mem_map * for each and record the physical to section mapping.
@@ -407,6 +423,9 @@ void __init sparse_init(void)unsigned long *usemap;unsigned long **usemap_map;int size; +int nodeid_begin =0 ; +unsigned long pnum_begin =0 ; +unsigned long usemap_count;/* * map is using big page (aka 2M in x86 64 bit)
@@ -425,10 +444,39 @@ void __init sparse_init(void)panic ("can not allocate usemap_map\n" );for (pnum =0 ; pnum <NR_MEM_SECTIONS ; pnum++) { +struct mem_section *ms; +if (!present_section_nr (pnum))continue ; - usemap_map[pnum] =sparse_early_usemap_alloc (pnum); + ms =__nr_to_section (pnum); + nodeid_begin =sparse_early_nid (ms); + pnum_begin = pnum; +break ; + } + usemap_count =1 ; +for (pnum = pnum_begin +1 ; pnum <NR_MEM_SECTIONS ; pnum++) { +struct mem_section *ms; +int nodeid; + +if (!present_section_nr (pnum)) +continue ; + ms =__nr_to_section (pnum); + nodeid =sparse_early_nid (ms); +if (nodeid == nodeid_begin) { + usemap_count++; +continue ; + } +/* ok, we need to take cake of from pnum_begin to pnum - 1*/ +sparse_early_usemaps_alloc_node (usemap_map, pnum_begin, pnum, + usemap_count, nodeid_begin); +/* new start, update count etc*/ + nodeid_begin = nodeid; + pnum_begin = pnum; + usemap_count =1 ; } +/* ok, last chunk */ +sparse_early_usemaps_alloc_node (usemap_map, pnum_begin,NR_MEM_SECTIONS , + usemap_count, nodeid_begin);for (pnum =0 ; pnum <NR_MEM_SECTIONS ; pnum++) {if (!present_section_nr (pnum))
Signature · 1 line
1.6.4.2
PATCH 14/36 sparsemem: put mem map for one node together.
In reply to Yinghai Luadd vmemmap_alloc_block_buf for mem map only.
it will fallback old wayif can not get that big.
before this patch, when node have 128g ram installed, memmap are split into
two parts or more.
[ 0.000000] [ffffea0000000000-ffffea003fffffff] PMD -> [ffff880100600000-ffff88013e9fffff] on node 1 [ 0.000000] [ffffea0040000000-ffffea006fffffff] PMD -> [ffff88013ec00000-ffff88016ebfffff] on node 1 [ 0.000000] [ffffea0070000000-ffffea007fffffff] PMD -> [ffff882000600000-ffff8820105fffff] on node 0 [ 0.000000] [ffffea0080000000-ffffea00bfffffff] PMD -> [ffff882010800000-ffff8820507fffff] on node 0 [ 0.000000] [ffffea00c0000000-ffffea00dfffffff] PMD -> [ffff882050a00000-ffff8820709fffff] on node 0 [ 0.000000] [ffffea00e0000000-ffffea00ffffffff] PMD -> [ffff884000600000-ffff8840205fffff] on node 2 [ 0.000000] [ffffea0100000000-ffffea013fffffff] PMD -> [ffff884020800000-ffff8840607fffff] on node 2 [ 0.000000] [ffffea0140000000-ffffea014fffffff] PMD -> [ffff884060a00000-ffff8840709fffff] on node 2 [ 0.000000] [ffffea0150000000-ffffea017fffffff] PMD -> [ffff886000600000-ffff8860305fffff] on node 3 [ 0.000000] [ffffea0180000000-ffffea01bfffffff] PMD -> [ffff886030800000-ffff8860707fffff] on node 3 [ 0.000000] [ffffea01c0000000-ffffea01ffffffff] PMD -> [ffff888000600000-ffff8880405fffff] on node 4 [ 0.000000] [ffffea0200000000-ffffea022fffffff] PMD -> [ffff888040800000-ffff8880707fffff] on node 4 [ 0.000000] [ffffea0230000000-ffffea023fffffff] PMD -> [ffff88a000600000-ffff88a0105fffff] on node 5 [ 0.000000] [ffffea0240000000-ffffea027fffffff] PMD -> [ffff88a010800000-ffff88a0507fffff] on node 5 [ 0.000000] [ffffea0280000000-ffffea029fffffff] PMD -> [ffff88a050a00000-ffff88a0709fffff] on node 5 [ 0.000000] [ffffea02a0000000-ffffea02bfffffff] PMD -> [ffff88c000600000-ffff88c0205fffff] on node 6 [ 0.000000] [ffffea02c0000000-ffffea02ffffffff] PMD -> [ffff88c020800000-ffff88c0607fffff] on node 6 [ 0.000000] [ffffea0300000000-ffffea030fffffff] PMD -> [ffff88c060a00000-ffff88c0709fffff] on node 6 [ 0.000000] [ffffea0310000000-ffffea033fffffff] PMD -> [ffff88e000600000-ffff88e0305fffff] on node 7 [ 0.000000] [ffffea0340000000-ffffea037fffffff] PMD -> [ffff88e030800000-ffff88e0707fffff] on node 7
after patch will get
[ 0.000000] [ffffea0000000000-ffffea006fffffff] PMD -> [ffff880100200000-ffff88016e5fffff] on node 0 [ 0.000000] [ffffea0070000000-ffffea00dfffffff] PMD -> [ffff882000200000-ffff8820701fffff] on node 1 [ 0.000000] [ffffea00e0000000-ffffea014fffffff] PMD -> [ffff884000200000-ffff8840701fffff] on node 2 [ 0.000000] [ffffea0150000000-ffffea01bfffffff] PMD -> [ffff886000200000-ffff8860701fffff] on node 3 [ 0.000000] [ffffea01c0000000-ffffea022fffffff] PMD -> [ffff888000200000-ffff8880701fffff] on node 4 [ 0.000000] [ffffea0230000000-ffffea029fffffff] PMD -> [ffff88a000200000-ffff88a0701fffff] on node 5 [ 0.000000] [ffffea02a0000000-ffffea030fffffff] PMD -> [ffff88c000200000-ffff88c0701fffff] on node 6 [ 0.000000] [ffffea0310000000-ffffea037fffffff] PMD -> [ffff88e000200000-ffff88e0701fffff] on node 7
-v2: change buf to vmemmap_buf instead according to Ingo
also add CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER according to Ingo
--- arch/x86/mm/init_64.c | 2 +- include/linux/mm.h | 7 +++ mm/Kconfig | 4 ++ mm/sparse-vmemmap.c | 75 ++++++++++++++++++++++++++++++++- mm/sparse.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 196 insertions(+), 3 deletions(-)
arch/x86/mm/init_64.c +1 -1
@@ -961,7 +961,7 @@ vmemmap_populate(struct page *start_page, unsigned long size, int node)if (pmd_none (*pmd)) {pte_t entry; - p =vmemmap_alloc_block (PMD_SIZE , node); + p =vmemmap_alloc_block_buf (PMD_SIZE , node);if (!p)return -ENOMEM ;
include/linux/mm.h +7 -0
@@ -1324,12 +1324,19 @@ extern int randomize_va_space;const char *arch_vma_name (struct vm_area_struct *vma);void print_vma_addr (char *prefix,unsigned long rip); +void sparse_mem_maps_populate_node (struct page **map_map, +unsigned long pnum_begin, +unsigned long pnum_end, +unsigned long map_count, +int nodeid); +struct page *sparse_mem_map_populate (unsigned long pnum,int nid);pgd_t *vmemmap_pgd_populate (unsigned long addr,int node);pud_t *vmemmap_pud_populate (pgd_t *pgd,unsigned long addr,int node);pmd_t *vmemmap_pmd_populate (pud_t *pud,unsigned long addr,int node);pte_t *vmemmap_pte_populate (pmd_t *pmd,unsigned long addr,int node);void *vmemmap_alloc_block (unsigned long size,int node); +void *vmemmap_alloc_block_buf (unsigned long size,int node);void vmemmap_verify (pte_t *,int ,unsigned long ,unsigned long );int vmemmap_populate_basepages (struct page *start_page,unsigned long pages,int node);
mm/Kconfig +4 -0
@@ -115,6 +115,10 @@ config SPARSEMEM_EXTREME config SPARSEMEM_VMEMMAP_ENABLE bool +config SPARSEMEM_ALLOC_MEM_MAP_TOGETHER + def_bool y + depends on SPARSEMEM && X86_64 + config SPARSEMEM_VMEMMAP bool "Sparse Memory virtual memmap" depends on SPARSEMEM && SPARSEMEM_VMEMMAP_ENABLE
mm/sparse-vmemmap.c +74 -1
96 lines not on this page · raw message
mm/sparse.c +110 -1
155 lines not on this page · raw message
Signature · 1 line
1.6.4.2
PATCH 15/36 x86: change range end to start+size
In reply to Yinghai Luso make interface more consistent with early_res.
later we can share some code with early_res.
--- arch/x86/kernel/cpu/mtrr/cleanup.c | 32 ++++++++++++++++---------------- arch/x86/kernel/e820.c | 2 +- arch/x86/pci/amd_bus.c | 24 ++++++++++++++---------- kernel/range.c | 20 ++++++++++---------- mm/bootmem.c | 2 +- mm/page_alloc.c | 2 +- 6 files changed, 43 insertions(+), 39 deletions(-)
arch/x86/kernel/cpu/mtrr/cleanup.c +16 -16
@@ -78,13 +78,13 @@ x86_get_mtrr_mem_range(struct range *range, int nr_range, base = range_state[i].base_pfn; size = range_state[i].size_pfn; nr_range =add_range_with_merge (range,RANGE_NUM , nr_range, - base, base + size -1 ); + base, base + size); }if (debug_print) {printk (KERN_DEBUG "After WB checking\n" );for (i =0 ; i < nr_range; i++)printk (KERN_DEBUG "MTRR MAP PFN: %016llx - %016llx\n" , - range[i].start, range[i].end +1 ); + range[i].start, range[i].end); }/* Take out UC ranges: */
@@ -106,11 +106,11 @@ x86_get_mtrr_mem_range(struct range *range, int nr_range, size -= (1 <<(20 -PAGE_SHIFT )) - base; base =1 <<(20 -PAGE_SHIFT ); } -subtract_range (range,RANGE_NUM , base, base + size -1 ); +subtract_range (range,RANGE_NUM , base, base + size); }if (extra_remove_size)subtract_range (range,RANGE_NUM , extra_remove_base, - extra_remove_base + extra_remove_size -1 ); + extra_remove_base + extra_remove_size);if (debug_print) {printk (KERN_DEBUG "After UC checking\n" );
@@ -118,7 +118,7 @@ x86_get_mtrr_mem_range(struct range *range, int nr_range,if (!range[i].end)continue ;printk (KERN_DEBUG "MTRR MAP PFN: %016llx - %016llx\n" , - range[i].start, range[i].end +1 ); + range[i].start, range[i].end); } }
@@ -128,7 +128,7 @@ x86_get_mtrr_mem_range(struct range *range, int nr_range,printk (KERN_DEBUG "After sorting\n" );for (i =0 ; i < nr_range; i++)printk (KERN_DEBUG "MTRR MAP PFN: %016llx - %016llx\n" , - range[i].start, range[i].end +1 ); + range[i].start, range[i].end); }return nr_range;
@@ -142,7 +142,7 @@ static unsigned long __init sum_ranges(struct range *range, int nr_range)int i;for (i =0 ; i < nr_range; i++) - sum += range[i].end +1 - range[i].start; + sum += range[i].end - range[i].start;return sum; }
@@ -489,7 +489,7 @@ x86_setup_var_mtrrs(struct range *range, int nr_range,/* Write the range: */ for (i =0 ; i < nr_range; i++) {set_var_mtrr_range (&var_state, range[i].start, - range[i].end - range[i].start +1 ); + range[i].end - range[i].start); }/* Write the last range: */
@@ -720,7 +720,7 @@ int __init mtrr_cleanup(unsigned address_bits)* and fixed mtrrs should take effect before var mtrr for it: */ nr_range =add_range_with_merge (range,RANGE_NUM , nr_range,0 , - (1ULL <<(20 -PAGE_SHIFT )) -1 ); +1ULL <<(20 -PAGE_SHIFT ));/* Sort the ranges: */ sort_range (range, nr_range);
@@ -939,9 +939,9 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn) nr_range =0 ;if (mtrr_tom2) { range[nr_range].start = (1ULL <<(32 -PAGE_SHIFT )); - range[nr_range].end = (mtrr_tom2 >>PAGE_SHIFT ) -1 ; -if (highest_pfn < range[nr_range].end +1 ) - highest_pfn = range[nr_range].end +1 ; + range[nr_range].end = mtrr_tom2 >>PAGE_SHIFT ; +if (highest_pfn < range[nr_range].end) + highest_pfn = range[nr_range].end; nr_range++; } nr_range =x86_get_mtrr_mem_range (range, nr_range,0 ,0 );
@@ -953,15 +953,15 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn)/* Check the holes: */ for (i =0 ; i < nr_range -1 ; i++) { -if (range[i].end +1 < range[i+1 ].start) - total_trim_size +=real_trim_memory (range[i].end +1 , +if (range[i].end < range[i+1 ].start) + total_trim_size +=real_trim_memory (range[i].end, range[i+1 ].start); }/* Check the top: */ i = nr_range -1 ; -if (range[i].end +1 < end_pfn) - total_trim_size +=real_trim_memory (range[i].end +1 , +if (range[i].end < end_pfn) + total_trim_size +=real_trim_memory (range[i].end, end_pfn);if (total_trim_size) {
arch/x86/kernel/e820.c +1 -1
@@ -1038,7 +1038,7 @@ static void __init subtract_early_res(struct range *range, int az)printk (KERN_CONT " subtract pfn [%010llx - %010llx]\n" , final_start, final_end);#endif -subtract_range (range, az, final_start, final_end -1 ); +subtract_range (range, az, final_start, final_end); } }
arch/x86/pci/amd_bus.c +14 -10
@@ -144,7 +144,7 @@ static int __init early_fill_mp_bus_info(void) def_link = (reg >>8 ) &0x03 ;memset (range,0 ,sizeof (range)); - range[0 ].end =0xffff ; +add_range (range,RANGE_NUM ,0 ,0 ,0xffff +1 );/* io port resource */ for (i =0 ; i <4 ; i++) { reg =read_pci_config (bus, slot,1 ,0xc0 + (i <<3 ));
@@ -174,7 +174,7 @@ static int __init early_fill_mp_bus_info(void)if (end >0xffff ) end =0xffff ;update_res (info, start, end,IORESOURCE_IO ,1 ); -subtract_range (range,RANGE_NUM , start, end); +subtract_range (range,RANGE_NUM , start, end +1 ); }/* add left over io port range to def node/link, [0, 0xffff] */ /* find the position */
@@ -189,14 +189,16 @@ static int __init early_fill_mp_bus_info(void)if (!range[i].end)continue ; -update_res (info, range[i].start, range[i].end, +update_res (info, range[i].start, range[i].end -1 ,IORESOURCE_IO ,1 ); } }memset (range,0 ,sizeof (range));/* 0xfd00000000-0xffffffffff for HT */ - range[0 ].end =cap_resource ((0xfdULL <<32 ) -1 ); + end =cap_resource ((0xfdULL <<32 ) -1 ); + end++; +add_range (range,RANGE_NUM ,0 ,0 , end);/* need to take out [0, TOM) for RAM*/ address =MSR_K8_TOP_MEM1 ;
@@ -204,14 +206,15 @@ static int __init early_fill_mp_bus_info(void) end = (val &0xffffff800000ULL );printk (KERN_INFO "TOM: %016llx aka %lldM\n" , end, end>>20 );if (end < (1ULL <<32 )) -subtract_range (range,RANGE_NUM ,0 , end -1 ); +subtract_range (range,RANGE_NUM ,0 , end);/* get mmconfig */ get_pci_mmcfg_amd_fam10h_range ();/* need to take out mmconf range */ if (fam10h_mmconf_end) {printk (KERN_DEBUG "Fam 10h mmconf [%llx, %llx]\n" , fam10h_mmconf_start, fam10h_mmconf_end); -subtract_range (range,RANGE_NUM , fam10h_mmconf_start, fam10h_mmconf_end); +subtract_range (range,RANGE_NUM , fam10h_mmconf_start, + fam10h_mmconf_end +1 ); }/* mmio resource */
@@ -266,7 +269,8 @@ static int __init early_fill_mp_bus_info(void)/* we got a hole */ endx = fam10h_mmconf_start -1 ;update_res (info, start, endx,IORESOURCE_MEM ,0 ); -subtract_range (range,RANGE_NUM , start, endx); +subtract_range (range,RANGE_NUM , start, + endx +1 );printk (KERN_CONT " ==> [%llx, %llx]" , start, endx); start = fam10h_mmconf_end +1 ; changed =1 ;
@@ -283,7 +287,7 @@ static int __init early_fill_mp_bus_info(void)update_res (info,cap_resource (start),cap_resource (end),IORESOURCE_MEM ,1 ); -subtract_range (range,RANGE_NUM , start, end); +subtract_range (range,RANGE_NUM , start, end +1 );printk (KERN_CONT "\n" ); }
@@ -298,7 +302,7 @@ static int __init early_fill_mp_bus_info(void)rdmsrl (address, val); end = (val &0xffffff800000ULL );printk (KERN_INFO "TOM2: %016llx aka %lldM\n" , end, end>>20 ); -subtract_range (range,RANGE_NUM ,1ULL <<32 , end -1 ); +subtract_range (range,RANGE_NUM ,1ULL <<32 , end); }/*
@@ -318,7 +322,7 @@ static int __init early_fill_mp_bus_info(void)continue ;update_res (info,cap_resource (range[i].start), -cap_resource (range[i].end), +cap_resource (range[i].end -1 ),IORESOURCE_MEM ,1 ); } }
kernel/range.c +10 -10
@@ -13,7 +13,7 @@int add_range (struct range *range,int az,int nr_range,u64 start,u64 end) { -if (start > end) +if (start >= end)return nr_range;/* Out of slots: */
@@ -33,7 +33,7 @@ int add_range_with_merge(struct range *range, int az, int nr_range, {int i; -if (start > end) +if (start >= end)return nr_range;/* Try to merge it with old one: */
@@ -46,7 +46,7 @@ int add_range_with_merge(struct range *range, int az, int nr_range, common_start =max (range[i].start, start); common_end =min (range[i].end, end); -if (common_start > common_end +1 ) +if (common_start > common_end)continue ; final_start =min (range[i].start, start);
@@ -65,7 +65,7 @@ void subtract_range(struct range *range, int az, u64 start, u64 end) {int i, j; -if (start > end) +if (start >= end)return ;for (j =0 ; j < az; j++) {
@@ -79,15 +79,15 @@ void subtract_range(struct range *range, int az, u64 start, u64 end) }if (start <= range[j].start && end < range[j].end && - range[j].start < end +1 ) { - range[j].start = end +1 ; + range[j].start < end) { + range[j].start = end;continue ; }if (start > range[j].start && end >= range[j].end && - range[j].end > start -1 ) { - range[j].end = start -1 ; + range[j].end > start) { + range[j].end = start;continue ; }
@@ -99,11 +99,11 @@ void subtract_range(struct range *range, int az, u64 start, u64 end) }if (i < az) { range[i].end = range[j].end; - range[i].start = end +1 ; + range[i].start = end; }else {printk (KERN_ERR "run of slot in ranges\n" ); } - range[j].end = start -1 ; + range[j].end = start;continue ; } }
mm/bootmem.c +1 -1
@@ -215,7 +215,7 @@ unsigned long __init free_all_memory_core_early(int nodeid)for (i =0 ; i < nr_range; i++) { start = range[i].start; - end = range[i].end +1 ; + end = range[i].end; count += end - start;__free_pages_memory (start, end); }
mm/page_alloc.c +1 -1
@@ -3444,7 +3444,7 @@ int __init add_from_early_node_map(struct range *range, int az,for_each_active_range_index_in_nid (i, nid) { start = early_node_map[i].start_pfn; end = early_node_map[i].end_pfn; - nr_range =add_range (range, az, nr_range, start, end -1 ); + nr_range =add_range (range, az, nr_range, start, end); }return nr_range; }
Signature · 1 line
1.6.4.2
PATCH 16/36 x86: move bios page reserve early to head32/64.c
In reply to Yinghai Luso prepare to make one more clean early_res.c
--- arch/x86/kernel/e820.c | 22 ++-------------------- arch/x86/kernel/head32.c | 12 ++++++++++++ arch/x86/kernel/head64.c | 2 ++ 3 files changed, 16 insertions(+), 20 deletions(-)
arch/x86/kernel/e820.c +2 -20
@@ -735,29 +735,11 @@ struct early_res {char name[15 ];char overlap_ok; }; -static struct early_res early_res_x[MAX_EARLY_RES_X ]__initdata = { - {0 ,PAGE_SIZE ,"BIOS data page" ,1 },/* BIOS data page */ -#if defined(CONFIG_X86_32) && defined(CONFIG_X86_TRAMPOLINE) -/* -* But first pinch a few for the stack/trampoline stuff -* FIXME: Don't need the extra page at 4K, but need to fix -* trampoline before removing it. (see the GDT stuff) -*/ - {PAGE_SIZE ,PAGE_SIZE +PAGE_SIZE ,"EX TRAMPOLINE" ,1 }, -#endif - - {} -}; +static struct early_res early_res_x[MAX_EARLY_RES_X ]__initdata ;static int max_early_res__initdata =MAX_EARLY_RES_X ;static struct early_res *early_res__initdata = &early_res_x[0 ]; -static int early_res_count __initdata = -#ifdef CONFIG_X86_32 - 2 -#else - 1 -#endif - ; +static int early_res_count__initdata ;static int __init find_overlapped_early (u64 start,u64 end) {
arch/x86/kernel/head32.c +12 -0
@@ -29,6 +29,18 @@ static void __init i386_default_early_setup(void)void __init i386_start_kernel (void ) { +reserve_early_overlap_ok (0 ,PAGE_SIZE ,"BIOS data page" ); + +#ifdef CONFIG_X86_TRAMPOLINE +/* +* But first pinch a few for the stack/trampoline stuff +* FIXME: Don't need the extra page at 4K, but need to fix +* trampoline before removing it. (see the GDT stuff) +*/ +reserve_early_overlap_ok (PAGE_SIZE ,PAGE_SIZE +PAGE_SIZE , +"EX TRAMPOLINE" ); +#endif +reserve_early (__pa_symbol (&_text),__pa_symbol (&__bss_stop),"TEXT DATA BSS" );#ifdef CONFIG_BLK_DEV_INITRD
arch/x86/kernel/head64.c +2 -0
@@ -98,6 +98,8 @@ void __init x86_64_start_reservations(char *real_mode_data) {copy_bootdata (__va (real_mode_data)); +reserve_early_overlap_ok (0 ,PAGE_SIZE ,"BIOS data page" ); +reserve_early (__pa_symbol (&_text),__pa_symbol (&__bss_stop),"TEXT DATA BSS" );#ifdef CONFIG_BLK_DEV_INITRD
Signature · 1 line
1.6.4.2
PATCH 17/36 x86: seperate early_res related code from e820.c
In reply to Yinghai Luto make e820.c smaller.
-v2: fix 32bit compiling with MAX_DMA32_PFN
--- arch/x86/include/asm/e820.h | 13 +- arch/x86/include/asm/early_res.h | 20 ++ arch/x86/kernel/Makefile | 2 +- arch/x86/kernel/e820.c | 541 +------------------------------------- arch/x86/kernel/early_res.c | 539 +++++++++++++++++++++++++++++++++++++ 5 files changed, 562 insertions(+), 553 deletions(-) create mode 100644 arch/x86/include/asm/early_res.h create mode 100644 arch/x86/kernel/early_res.c
arch/x86/include/asm/e820.h +1 -12
@@ -109,19 +109,8 @@ static inline void early_memtest(unsigned long start, unsigned long end)extern unsigned long end_user_pfn; -extern u64 find_e820_area (u64 start,u64 end,u64 size,u64 align); -extern u64 find_e820_area_size (u64 start,u64 *sizep,u64 align); -extern void reserve_early (u64 start,u64 end,char *name); -extern void reserve_early_overlap_ok (u64 start,u64 end,char *name); -extern void free_early (u64 start,u64 end); -extern void early_res_to_bootmem (u64 start,u64 end);extern u64 early_reserve_e820 (u64 startt,u64 sizet,u64 align); - -void reserve_early_without_check (u64 start,u64 end,char *name); -u64 find_early_area (u64 ei_start,u64 ei_last,u64 start,u64 end, -u64 size,u64 align); -#include <linux/range.h> -int get_free_all_memory_range (struct range **rangep,int nodeid); +#include <asm/early_res.h> extern unsigned long e820_end_of_ram_pfn (void );extern unsigned long e820_end_of_low_ram_pfn (void );
arch/x86/include/asm/early_res.h new file +20 -0
@@ -0,0 +1,20 @@ +#ifndef _ASM_X86_EARLY_RES_H +#define _ASM_X86_EARLY_RES_H +#ifdef __KERNEL__ + +extern u64 find_e820_area (u64 start,u64 end,u64 size,u64 align); +extern u64 find_e820_area_size (u64 start,u64 *sizep,u64 align); +extern void reserve_early (u64 start,u64 end,char *name); +extern void reserve_early_overlap_ok (u64 start,u64 end,char *name); +extern void free_early (u64 start,u64 end); +extern void early_res_to_bootmem (u64 start,u64 end); + +void reserve_early_without_check (u64 start,u64 end,char *name); +u64 find_early_area (u64 ei_start,u64 ei_last,u64 start,u64 end, +u64 size,u64 align); +#include <linux/range.h> +int get_free_all_memory_range (struct range **rangep,int nodeid); + +#endif /* __KERNEL__ */ + +#endif /* _ASM_X86_EARLY_RES_H */
arch/x86/kernel/Makefile +1 -1
@@ -38,7 +38,7 @@ obj-$(CONFIG_X86_32) += probe_roms_32.o obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o obj-$(CONFIG_X86_64) += syscall_64.o vsyscall_64.o -obj-y += bootflag.o e820.o +obj-y += bootflag.o e820.o early_res.o obj-y += pci-dma.o quirks.o i8237.o topology.o kdebugfs.o obj-y += alternative.o i8253.o pci-nommu.o hw_breakpoint.o obj-y += tsc.o io_delay.o rtc.o
arch/x86/kernel/e820.c +1 -540
560 lines not on this page · raw message
arch/x86/kernel/early_res.c new file +539 -0
539 lines not on this page · raw message
Signature · 1 line
1.6.4.2
PATCH 18/36 x86: add find_early_area_size
In reply to Yinghai Luprepare to move bck find_e820_area_size back to e820.c
--- arch/x86/kernel/early_res.c | 45 ++++++++++++++++++++++++++++++------------ 1 files changed, 32 insertions(+), 13 deletions(-)
arch/x86/kernel/early_res.c +32 -13
@@ -476,6 +476,29 @@ out:return -1ULL ; } +u64 __init find_early_area_size (u64 ei_start,u64 ei_last,u64 start, +u64 *sizep,u64 align) +{ +u64 addr, last; + + addr =round_up (ei_start, align); +if (addr < start) + addr =round_up (start, align); +if (addr >= ei_last) + goto out; + *sizep = ei_last - addr; +while (bad_addr_size (&addr, sizep, align) && addr + *sizep <= ei_last) + ; + last = addr + *sizep; +if (last > ei_last) + goto out; + +return addr; + +out: +return -1ULL ; +} +/* * Find a free area with specified alignment in a specific range. */
@@ -513,24 +536,20 @@ u64 __init find_e820_area_size(u64 start, u64 *sizep, u64 align)for (i =0 ; i < e820.nr_map; i++) {struct e820entry *ei = &e820.map[i]; -u64 addr, last; -u64 ei_last; +u64 addr; +u64 ei_start, ei_last;if (ei->type !=E820_RAM )continue ; - addr =round_up (ei->addr, align); + ei_last = ei->addr + ei->size; -if (addr < start) - addr =round_up (start, align); -if (addr >= ei_last) -continue ; - *sizep = ei_last - addr; -while (bad_addr_size (&addr, sizep, align) && - addr + *sizep <= ei_last) - ; - last = addr + *sizep; -if (last > ei_last) + ei_start = ei->addr; + addr =find_early_area_size (ei_start, ei_last, start, + sizep, align); + +if (addr ==-1ULL )continue ; +return addr; }
Signature · 1 line
1.6.4.2
PATCH 19/36 x86: move back find_e820_area to e820.c
In reply to Yinghai Lumake early_res.c more clean, so later could move it to /kernel
Signed-off: Yinghai Lu <[email protected]>
--- arch/x86/include/asm/e820.h | 2 + arch/x86/include/asm/early_res.h | 4 +- arch/x86/kernel/e820.c | 57 ++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/early_res.c | 56 ------------------------------------- 4 files changed, 61 insertions(+), 58 deletions(-)
arch/x86/include/asm/e820.h +2 -0
@@ -109,6 +109,8 @@ static inline void early_memtest(unsigned long start, unsigned long end)extern unsigned long end_user_pfn; +extern u64 find_e820_area (u64 start,u64 end,u64 size,u64 align); +extern u64 find_e820_area_size (u64 start,u64 *sizep,u64 align);extern u64 early_reserve_e820 (u64 startt,u64 sizet,u64 align);#include <asm/early_res.h>
arch/x86/include/asm/early_res.h +2 -2
@@ -2,8 +2,6 @@#define _ASM_X86_EARLY_RES_H#ifdef __KERNEL__ -extern u64 find_e820_area (u64 start,u64 end,u64 size,u64 align); -extern u64 find_e820_area_size (u64 start,u64 *sizep,u64 align);extern void reserve_early (u64 start,u64 end,char *name);extern void reserve_early_overlap_ok (u64 start,u64 end,char *name);extern void free_early (u64 start,u64 end);
@@ -12,6 +10,8 @@ extern void early_res_to_bootmem(u64 start, u64 end);void reserve_early_without_check (u64 start,u64 end,char *name);u64 find_early_area (u64 ei_start,u64 ei_last,u64 start,u64 end,u64 size,u64 align); +u64 find_early_area_size (u64 ei_start,u64 ei_last,u64 start, +u64 *sizep,u64 align);#include <linux/range.h> int get_free_all_memory_range (struct range **rangep,int nodeid);
arch/x86/kernel/e820.c +57 -0
63 lines not on this page · raw message
arch/x86/kernel/early_res.c +0 -56
60 lines not on this page · raw message
Signature · 1 line
1.6.4.2
PATCH 20/36 early_res: enhance check_and_double_early_res
In reply to Yinghai Luto make it always try to start from low at first.
so make it more safe for early_memtest to reserve bad range. aka put new early_res to range that is already tested.
--- arch/x86/kernel/early_res.c | 27 ++++++++++++++++++++------- 1 files changed, 20 insertions(+), 7 deletions(-)
arch/x86/kernel/early_res.c +20 -7
@@ -180,9 +180,9 @@ void __init reserve_early_overlap_ok(u64 start, u64 end, char *name)__reserve_early (start, end, name,1 ); } -static void __init __check_and_double_early_res (u64 start) +static void __init __check_and_double_early_res (u64 ex_start,u64 ex_end) { -u64 end, size, mem; +u64 start, end, size, mem;struct early_res *new;/* do we have enough slots left ? */
@@ -190,10 +190,23 @@ static void __init __check_and_double_early_res(u64 start)return ;/* double it */ - end = max_pfn_mapped <<PAGE_SHIFT ; + mem =-1ULL ; size =sizeof (struct early_res ) * max_early_res *2 ; - mem =find_e820_area (start, end, size,sizeof (struct early_res )); - +if (early_res == early_res_x) + start =0 ; +else + start = early_res[0 ].end; + end = ex_start; +if (start + size < end) + mem =find_e820_area (start, end, size, +sizeof (struct early_res )); +if (mem ==-1ULL ) { + start = ex_end; + end = max_pfn_mapped <<PAGE_SHIFT ; +if (start + size < end) + mem =find_e820_area (start, end, size, +sizeof (struct early_res )); + }if (mem ==-1ULL )panic ("can not find more space for early_res array" );
@@ -235,7 +248,7 @@ void __init reserve_early(u64 start, u64 end, char *name)if (start >= end)return ; -__check_and_double_early_res (end); +__check_and_double_early_res (start, end);drop_overlaps_that_are_ok (start, end);__reserve_early (start, end, name,0 );
@@ -248,7 +261,7 @@ void __init reserve_early_without_check(u64 start, u64 end, char *name)if (start >= end)return ; -__check_and_double_early_res (end); +__check_and_double_early_res (start, end); r = &early_res[early_res_count];
Signature · 1 line
1.6.4.2
PATCH 21/36 x86: make 32bit support NO_BOOTMEM
In reply to Yinghai Lulet's make 32bit consistent with 64bit
--- arch/x86/Kconfig | 1 - arch/x86/kernel/early_res.c | 3 +++ arch/x86/mm/init_32.c | 6 ++++++ arch/x86/mm/numa_32.c | 3 +++ 4 files changed, 12 insertions(+), 1 deletions(-)
arch/x86/Kconfig +0 -1
@@ -571,7 +571,6 @@ config PARAVIRT_DEBUG config NO_BOOTMEM default y bool "Disable Bootmem code" - depends on X86_64 ---help--- use early_res directly instead of bootmem before slab is ready.
arch/x86/kernel/early_res.c +3 -0
@@ -354,6 +354,9 @@ int __init get_free_all_memory_range(struct range **rangep, int nodeid)/* need to go over early_node_map to find out good range for node */ nr_range =add_from_early_node_map (range, count, nr_range, nodeid); +#ifdef CONFIG_X86_32 +subtract_range (range, count, max_low_pfn,-1UL ); +#endif subtract_early_res (range, count); nr_range =clean_sort_range (range, count);
arch/x86/mm/init_32.c +6 -0
@@ -748,6 +748,7 @@ static void __init zone_sizes_init(void)free_area_init_nodes (max_zone_pfns); } +#ifndef CONFIG_NO_BOOTMEM static unsigned long __init setup_node_bootmem(int nodeid, unsigned long start_pfn, unsigned long end_pfn,
@@ -767,9 +768,11 @@ static unsigned long __init setup_node_bootmem(int nodeid, return bootmap + bootmap_size; } +#endif void __init setup_bootmem_allocator (void ) { +#ifndef CONFIG_NO_BOOTMEM int nodeid;unsigned long bootmap_size, bootmap;/*
@@ -781,11 +784,13 @@ void __init setup_bootmem_allocator(void)if (bootmap ==-1L )panic ("Cannot find bootmem map of size %ld\n" , bootmap_size);reserve_early (bootmap, bootmap + bootmap_size,"BOOTMAP" ); +#endif printk (KERN_INFO " mapped low ram: 0 - %08lx\n" , max_pfn_mapped<<PAGE_SHIFT );printk (KERN_INFO " low ram: 0 - %08lx\n" , max_low_pfn<<PAGE_SHIFT ); +#ifndef CONFIG_NO_BOOTMEM for_each_online_node (nodeid) {unsigned long start_pfn, end_pfn;
@@ -803,6 +808,7 @@ void __init setup_bootmem_allocator(void) bootmap =setup_node_bootmem (nodeid, start_pfn, end_pfn, bootmap); } +#endif after_bootmem =1 ; }
arch/x86/mm/numa_32.c +3 -0
@@ -418,7 +418,10 @@ void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn,for_each_online_node (nid) {memset (NODE_DATA (nid),0 ,sizeof (struct pglist_data )); +NODE_DATA (nid)->node_id = nid; +#ifndef CONFIG_NO_BOOTMEM NODE_DATA (nid)->bdata = &bootmem_node_data[nid]; +#endif }setup_bootmem_allocator ();
Signature · 1 line
1.6.4.2
PATCH 22/36 move round_up/down to kernel.h
In reply to Yinghai Luprepare to early_res moving up
--- arch/x86/include/asm/proto.h | 10 ---------- include/linux/kernel.h | 10 ++++++++++ 2 files changed, 10 insertions(+), 10 deletions(-)
arch/x86/include/asm/proto.h +0 -10
@@ -23,14 +23,4 @@ extern int reboot_force;long do_arch_prctl (struct task_struct *task,int code,unsigned long addr); -/* -* This looks more complex than it should be. But we need to -* get the type for the ~ right in round_down (it needs to be -* as wide as the result!), and we want to evaluate the macro -* arguments just once each. -*/ -#define __round_mask (x,y) ((__typeof__(x))((y)-1)) -#define round_up (x,y) ((((x)-1) | __round_mask(x,y))+1) -#define round_down (x,y) ((x) & ~__round_mask(x,y)) -#endif /* _ASM_X86_PROTO_H */
include/linux/kernel.h +10 -0
@@ -44,6 +44,16 @@ extern const char linux_proc_banner[];#define ARRAY_SIZE (arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr)) +/* +* This looks more complex than it should be. But we need to +* get the type for the ~ right in round_down (it needs to be +* as wide as the result!), and we want to evaluate the macro +* arguments just once each. +*/ +#define __round_mask (x,y) ((__typeof__(x))((y)-1)) +#define round_up (x,y) ((((x)-1) | __round_mask(x,y))+1) +#define round_down (x,y) ((x) & ~__round_mask(x,y)) +#define FIELD_SIZEOF (t, f) (sizeof(((t*)0)->f))#define DIV_ROUND_UP (n,d) (((n) + (d) - 1) / (d))#define roundup (x, y) ((((x) + ((y) - 1)) / (y)) * (y))
Signature · 1 line
1.6.4.2
Re: [PATCH 22/36] move round_up/down to kernel.h
include/linux/kernel.h extern const char linux_proc_banner[]; · line 59
Quoted 12 lines · Yinghai Lu
+ * This looks more complex than it should be. But we need to
+ * get the type for the ~ right inround_down(it needs to be
+ * as wide as the result!), and we want to evaluate the macro
+ * arguments just once each.
+ */include/linux/kernel.h +4
-0+#define __round_mask (x,y) ((__typeof__(x))((y)-1)) +#define round_up (x,y) ((((x)-1) | __round_mask(x,y))+1) +#define round_down (x,y) ((x) & ~__round_mask(x,y)) +#define FIELD_SIZEOF (t, f) (sizeof(((t*)0)->f))#define DIV_ROUND_UP (n,d) (((n) + (d) - 1) / (d))#define roundup (x, y) ((((x) + ((y) - 1)) / (y)) * (y))
So we are back to the earlier version.
Two functions doing the same thing. round_up and roundup.
If they are different(are they really used that way?) then they should have names that emphasize the difference.
Re: [PATCH 22/36] move round_up/down to kernel.h
Quoted 17 lines · Christoph Lameter
include/linux/kernel.h extern const char linux_proc_banner[]; · line 59
Quoted 12 lines · Yinghai Lu
+ * This looks more complex than it should be. But we need to
+ * get the type for the ~ right inround_down(it needs to be
+ * as wide as the result!), and we want to evaluate the macro
+ * arguments just once each.
+ */include/linux/kernel.h +4
-0+#define __round_mask (x,y) ((__typeof__(x))((y)-1)) +#define round_up (x,y) ((((x)-1) | __round_mask(x,y))+1) +#define round_down (x,y) ((x) & ~__round_mask(x,y)) +#define FIELD_SIZEOF (t, f) (sizeof(((t*)0)->f))#define DIV_ROUND_UP (n,d) (((n) + (d) - 1) / (d))#define roundup (x, y) ((((x) + ((y) - 1)) / (y)) * (y))So we are back to the earlier version.
Quoted 4 lines
Two functions doing the same thing.
round_upand roundup.If they are different(are they really used that way?) then they should have names that emphasize the difference.
round_up() basically only works for power of two, but they should generate the same code for constants.
The only user right now is e820.c, but it uses the second argument with non constants, so would generate a slower true division with roundup() Right now it probably doesn't make much difference because e820 lists are small, but I saw a patchkit to let e820 replace bootmem and then they might not be anymore.
-Andi
Signature · 1 line
[email protected] -- Speaking for myself only.
PATCH 23/36 x86: add find_fw_memmap_area
In reply to Yinghai Luso could move early_res up
--- arch/x86/include/asm/early_res.h | 1 + arch/x86/kernel/e820.c | 4 ++++ arch/x86/kernel/early_res.c | 17 +++++++++++------ 3 files changed, 16 insertions(+), 6 deletions(-)
arch/x86/include/asm/early_res.h +1 -0
@@ -12,6 +12,7 @@ u64 find_early_area(u64 ei_start, u64 ei_last, u64 start, u64 end, u64 size, u64 align);u64 find_early_area_size (u64 ei_start,u64 ei_last,u64 start,u64 *sizep,u64 align); +u64 find_fw_memmap_area (u64 start,u64 end,u64 size,u64 align);#include <linux/range.h> int get_free_all_memory_range (struct range **rangep,int nodeid);
arch/x86/kernel/e820.c +4 -0
@@ -742,6 +742,10 @@ u64 __init find_e820_area(u64 start, u64 end, u64 size, u64 align)return -1ULL ; } +u64 __init find_fw_memmap_area (u64 start,u64 end,u64 size,u64 align) +{ +return find_e820_area (start, end, size, align); +}/* * Find next free range after *start */
arch/x86/kernel/early_res.c +11 -6
@@ -7,16 +7,14 @@#include <linux/bootmem.h> #include <linux/mm.h> -#include <asm/e820.h> #include <asm/early_res.h> -#include <asm/proto.h> /* * Early reserved memory areas. */ /* * need to make sure this one is bigger enough before -* find_e820_area could be used +* find_fw_memmap_area could be used */ #define MAX_EARLY_RES_X 32
@@ -180,6 +178,13 @@ void __init reserve_early_overlap_ok(u64 start, u64 end, char *name)__reserve_early (start, end, name,1 ); } +u64 __init __weak find_fw_memmap_area (u64 start,u64 end,u64 size,u64 align) +{ +panic ("should have find_fw_memmap_area defined with arch" ); + +return -1ULL ; +} +static void __init __check_and_double_early_res (u64 ex_start,u64 ex_end) {u64 start, end, size, mem;
@@ -198,13 +203,13 @@ static void __init __check_and_double_early_res(u64 ex_start, u64 ex_end) start = early_res[0 ].end; end = ex_start;if (start + size < end) - mem =find_e820_area (start, end, size, + mem =find_fw_memmap_area (start, end, size,sizeof (struct early_res ));if (mem ==-1ULL ) { start = ex_end; end = max_pfn_mapped <<PAGE_SHIFT ;if (start + size < end) - mem =find_e820_area (start, end, size, + mem =find_fw_memmap_area (start, end, size,sizeof (struct early_res )); }if (mem ==-1ULL )
@@ -343,7 +348,7 @@ int __init get_free_all_memory_range(struct range **rangep, int nodeid) start =MAX_DMA32_PFN <<PAGE_SHIFT ;#endif end = max_pfn_mapped <<PAGE_SHIFT ; - mem =find_e820_area (start, end, size,sizeof (struct range )); + mem =find_fw_memmap_area (start, end, size,sizeof (struct range ));if (mem ==-1ULL )panic ("can not find more space for range free" );
Signature · 1 line
1.6.4.2
PATCH 24/36 core: move early_res
In reply to Yinghai Lufrom arch/x86 to kernel/
--- arch/x86/include/asm/e820.h | 2 +- arch/x86/include/asm/early_res.h | 21 -- arch/x86/kernel/Makefile | 2 +- arch/x86/kernel/e820.c | 1 - arch/x86/kernel/early_res.c | 523 -------------------------------------- include/linux/early_res.h | 21 ++ kernel/Makefile | 2 +- kernel/early_res.c | 522 +++++++++++++++++++++++++++++++++++++ 8 files changed, 546 insertions(+), 548 deletions(-) delete mode 100644 arch/x86/include/asm/early_res.h delete mode 100644 arch/x86/kernel/early_res.c create mode 100644 include/linux/early_res.h create mode 100644 kernel/early_res.c
arch/x86/include/asm/e820.h +1 -1
@@ -112,7 +112,7 @@ extern unsigned long end_user_pfn;extern u64 find_e820_area (u64 start,u64 end,u64 size,u64 align);extern u64 find_e820_area_size (u64 start,u64 *sizep,u64 align);extern u64 early_reserve_e820 (u64 startt,u64 sizet,u64 align); -#include <asm/early_res.h> +#include <linux/early_res.h> extern unsigned long e820_end_of_ram_pfn (void );extern unsigned long e820_end_of_low_ram_pfn (void );
arch/x86/include/asm/early_res.h deleted +0 -21
@@ -1,21 +0,0 @@ -#ifndef _ASM_X86_EARLY_RES_H -#define _ASM_X86_EARLY_RES_H -#ifdef __KERNEL__ - -extern void reserve_early (u64 start,u64 end,char *name); -extern void reserve_early_overlap_ok (u64 start,u64 end,char *name); -extern void free_early (u64 start,u64 end); -extern void early_res_to_bootmem (u64 start,u64 end); - -void reserve_early_without_check (u64 start,u64 end,char *name); -u64 find_early_area (u64 ei_start,u64 ei_last,u64 start,u64 end, -u64 size,u64 align); -u64 find_early_area_size (u64 ei_start,u64 ei_last,u64 start, -u64 *sizep,u64 align); -u64 find_fw_memmap_area (u64 start,u64 end,u64 size,u64 align); -#include <linux/range.h> -int get_free_all_memory_range (struct range **rangep,int nodeid); - -#endif /* __KERNEL__ */ - -#endif /* _ASM_X86_EARLY_RES_H */
arch/x86/kernel/Makefile +1 -1
@@ -38,7 +38,7 @@ obj-$(CONFIG_X86_32) += probe_roms_32.o obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o obj-$(CONFIG_X86_64) += syscall_64.o vsyscall_64.o -obj-y += bootflag.o e820.o early_res.o +obj-y += bootflag.o e820.o obj-y += pci-dma.o quirks.o i8237.o topology.o kdebugfs.o obj-y += alternative.o i8253.o pci-nommu.o hw_breakpoint.o obj-y += tsc.o io_delay.o rtc.o
arch/x86/kernel/e820.c +0 -1
@@ -17,7 +17,6 @@#include <linux/firmware-map.h> #include <asm/e820.h> -#include <asm/early_res.h> #include <asm/proto.h> #include <asm/setup.h>
arch/x86/kernel/early_res.c deleted +0 -523
523 lines not on this page · raw message
include/linux/early_res.h new file +21 -0
@@ -0,0 +1,21 @@ +#ifndef _LINUX_EARLY_RES_H +#define _LINUX_EARLY_RES_H +#ifdef __KERNEL__ + +extern void reserve_early (u64 start,u64 end,char *name); +extern void reserve_early_overlap_ok (u64 start,u64 end,char *name); +extern void free_early (u64 start,u64 end); +extern void early_res_to_bootmem (u64 start,u64 end); + +void reserve_early_without_check (u64 start,u64 end,char *name); +u64 find_early_area (u64 ei_start,u64 ei_last,u64 start,u64 end, +u64 size,u64 align); +u64 find_early_area_size (u64 ei_start,u64 ei_last,u64 start, +u64 *sizep,u64 align); +u64 find_fw_memmap_area (u64 start,u64 end,u64 size,u64 align); +#include <linux/range.h> +int get_free_all_memory_range (struct range **rangep,int nodeid); + +#endif /* __KERNEL__ */ + +#endif /* _LINUX_EARLY_RES_H */
kernel/Makefile +1 -1
@@ -10,7 +10,7 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o \ kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \ notifier.o ksysfs.o pm_qos_params.o sched_clock.o cred.o \ - async.o range.o + async.o range.o early_res.o obj-y += groups.o ifdef CONFIG_FUNCTION_TRACER
kernel/early_res.c new file +522 -0
522 lines not on this page · raw message
Signature · 1 line
1.6.4.2
PATCH 25/36 x86: print out for RAM buffer
In reply to Yinghai Luso could check that early in bootlog
--- arch/x86/kernel/e820.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-)
arch/x86/kernel/e820.c +3 -0
@@ -1127,6 +1127,9 @@ void __init e820_reserve_resources_late(void) end =MAX_RESOURCE_SIZE ;if (start >= end)continue ; +printk (KERN_DEBUG "reserve RAM buffer: %016Lx - %016Lx " , + (unsigned long long ) start, + (unsigned long long ) end);reserve_region_with_split (&iomem_resource, start, end,"RAM buffer" ); }
Signature · 1 line
1.6.4.2
PATCH 26/36 x86: remove bios data range from e820
In reply to Yinghai Luto prepare move page_is_ram as generic one
--- arch/x86/kernel/e820.c | 8 ++++++++ arch/x86/kernel/head32.c | 2 -- arch/x86/kernel/head64.c | 2 -- arch/x86/kernel/setup.c | 19 ++++++++++++++++++- arch/x86/mm/ioremap.c | 16 ---------------- 5 files changed, 26 insertions(+), 21 deletions(-)
arch/x86/kernel/e820.c +8 -0
@@ -509,11 +509,19 @@ u64 __init e820_remove_range(u64 start, u64 size, unsigned old_type, int checktype) {int i; +u64 end;u64 real_removed_size =0 ;if (size > (ULLONG_MAX - start)) size =ULLONG_MAX - start; + end = start + size; +printk (KERN_DEBUG "e820 remove range: %016Lx - %016Lx " , + (unsigned long long ) start, + (unsigned long long ) end); +e820_print_type (old_type); +printk (KERN_CONT "\n" ); +for (i =0 ; i < e820.nr_map; i++) {struct e820entry *ei = &e820.map[i];u64 final_start, final_end;
arch/x86/kernel/head32.c +0 -2
@@ -29,8 +29,6 @@ static void __init i386_default_early_setup(void)void __init i386_start_kernel (void ) { -reserve_early_overlap_ok (0 ,PAGE_SIZE ,"BIOS data page" ); -#ifdef CONFIG_X86_TRAMPOLINE /* * But first pinch a few for the stack/trampoline stuff
arch/x86/kernel/head64.c +0 -2
@@ -98,8 +98,6 @@ void __init x86_64_start_reservations(char *real_mode_data) {copy_bootdata (__va (real_mode_data)); -reserve_early_overlap_ok (0 ,PAGE_SIZE ,"BIOS data page" ); -reserve_early (__pa_symbol (&_text),__pa_symbol (&__bss_stop),"TEXT DATA BSS" );#ifdef CONFIG_BLK_DEV_INITRD
arch/x86/kernel/setup.c +18 -1
@@ -659,6 +659,23 @@ static struct dmi_system_id __initdata bad_bios_dmi_table[] = { {} }; +static void __init e820_trim_bios_range (void ) +{ +/* +* A special case is the first 4Kb of memory; +* This is a BIOS owned area, not kernel ram, but generally +* not listed as such in the E820 table. +*/ +e820_update_range (0 ,PAGE_SIZE ,E820_RAM ,E820_RESERVED ); +/* +* special case: Some BIOSen report the PC BIOS +* area (640->1Mb) as ram even though it is not. +* take them out. +*/ +e820_remove_range (BIOS_BEGIN ,BIOS_END -BIOS_BEGIN ,E820_RAM ,1 ); +sanitize_e820_map (e820.map,ARRAY_SIZE (e820.map), &e820.nr_map); +} +/* * Determine if we were loaded by an EFI loader. If so, then we have also been * passed the efi memmap, systab, etc., so we should use these data structures
@@ -822,7 +839,7 @@ void __init setup_arch(char **cmdline_p)insert_resource (&iomem_resource, &data_resource);insert_resource (&iomem_resource, &bss_resource); - +e820_trim_bios_range ();#ifdef CONFIG_X86_32 if (ppro_with_ram_bug ()) { e820_update_range(0x70000000ULL, 0x40000ULL, E820_RAM,
arch/x86/mm/ioremap.c +0 -16
@@ -29,22 +29,6 @@ int page_is_ram(unsigned long pagenr)resource_size_t addr, end;int i; -/* -* A special case is the first 4Kb of memory; -* This is a BIOS owned area, not kernel ram, but generally -* not listed as such in the E820 table. -*/ -if (pagenr ==0 ) -return 0 ; - -/* -* Second special case: Some BIOSen report the PC BIOS -* area (640->1Mb) as ram even though it is not. -*/ -if (pagenr >= (BIOS_BEGIN >>PAGE_SHIFT ) && - pagenr < (BIOS_END >>PAGE_SHIFT )) -return 0 ; -for (i =0 ; i < e820.nr_map; i++) {/* * Not usable memory:
Signature · 1 line
1.6.4.2
PATCH 27/36 x86/pci: add mmconf range into e820 for when it is from MSR with amd faml0h
In reply to Yinghai Lufor AMD Fam10h, it we read mmconf from MSR early, we should just trust it because we check it and correct it already.
so add it to e820
--- arch/x86/kernel/mmconf-fam10h_64.c | 40 ++++++++++++++++++++--------------- 1 files changed, 23 insertions(+), 17 deletions(-)
arch/x86/kernel/mmconf-fam10h_64.c +23 -17
@@ -16,6 +16,7 @@#include <asm/acpi.h> #include <asm/mmconfig.h> #include <asm/pci_x86.h> +#include <asm/e820.h> struct pci_hostbridge_probe {u32 bus;
@@ -27,23 +28,26 @@ struct pci_hostbridge_probe {static u64 __cpuinitdata fam10h_pci_mmconf_base;static int __cpuinitdata fam10h_pci_mmconf_base_status; +/* only on BSP */ +static void __init_refok e820_add_mmconf_range(int busnbits) +{ +u64 end; + + end = fam10h_pci_mmconf_base + (1ULL <<(busnbits +20 )) -1 ; +if (!e820_all_mapped (fam10h_pci_mmconf_base, end+1 ,E820_RESERVED )) { +printk (KERN_DEBUG "Fam 10h mmconf [%llx, %llx]\n" , + fam10h_pci_mmconf_base, end); +e820_add_region (fam10h_pci_mmconf_base,1ULL <<(busnbits +20 ), +E820_RESERVED ); +sanitize_e820_map (e820.map,ARRAY_SIZE (e820.map), &e820.nr_map); + } +} +static struct pci_hostbridge_probe pci_probes[]__cpuinitdata = { {0 ,0x18 ,PCI_VENDOR_ID_AMD ,0x1200 }, {0xff ,0 ,PCI_VENDOR_ID_AMD ,0x1200 }, }; -static int __cpuinit cmp_range (const void *x1,const void *x2) -{ -const struct range *r1 = x1; -const struct range *r2 = x2; -int start1, start2; - - start1 = r1->start >>32 ; - start2 = r2->start >>32 ; - -return start1 - start2; -} -/*[47:0] */ /* need to avoid (0xfd<<32) and (0xfe<<32), ht used space */ #define FAM10H_PCI_MMCONF_BASE (0xfcULL<<32)
@@ -115,6 +119,7 @@ static void __cpuinit get_fam10h_pci_mmconf_base(void)* above 4G */ hi_mmio_num =0 ; +memset (range,0 ,sizeof (range));for (i =0 ; i <8 ; i++) {u32 reg;u64 start;
@@ -130,16 +135,14 @@ static void __cpuinit get_fam10h_pci_mmconf_base(void)if (!end)continue ; - range[hi_mmio_num].start = start; - range[hi_mmio_num].end = end; - hi_mmio_num++; + hi_mmio_num =add_range (range,8 , hi_mmio_num, start, end); }if (!hi_mmio_num) goto out;/* sort the range */ -sort (range, hi_mmio_num,sizeof (struct range ), cmp_range,NULL ); +sort_range (range, hi_mmio_num);if (range[hi_mmio_num -1 ].end < base) goto out;
@@ -169,6 +172,7 @@ fail: out: fam10h_pci_mmconf_base = base; fam10h_pci_mmconf_base_status =1 ; +e820_add_mmconf_range (8 ); }void __cpuinit fam10h_check_enable_mmcfg (void )
@@ -191,10 +195,12 @@ void __cpuinit fam10h_check_enable_mmcfg(void)/* only trust the one handle 256 buses, if acpi=off */ if (!acpi_pci_disabled || busnbits >=8 ) {u64 base; - base = val & (0xffffULL <<32 ); + base = val & (FAM10H_MMIO_CONF_BASE_MASK << +FAM10H_MMIO_CONF_BASE_SHIFT );if (fam10h_pci_mmconf_base_status <=0 ) { fam10h_pci_mmconf_base = base; fam10h_pci_mmconf_base_status =1 ; +e820_add_mmconf_range (busnbits);return ; }else if (fam10h_pci_mmconf_base == base)return ;
Signature · 1 line
1.6.4.2
PATCH 28/36 irq: remove not need bootmem code
In reply to Yinghai Lumem_init is moved early already.
--- kernel/irq/handle.c | 14 +++----------- 1 files changed, 3 insertions(+), 11 deletions(-)
kernel/irq/handle.c +3 -11
@@ -19,7 +19,6 @@#include <linux/kernel_stat.h> #include <linux/rculist.h> #include <linux/hash.h> -#include <linux/bootmem.h> #include <trace/events/irq.h> #include "internals.h"
@@ -87,12 +86,8 @@ void __ref init_kstat_irqs(struct irq_desc *desc, int node, int nr) {void *ptr; -if (slab_is_available ()) - ptr =kzalloc_node (nr *sizeof (*desc->kstat_irqs), -GFP_ATOMIC , node); -else - ptr =alloc_bootmem_node (NODE_DATA (node), - nr *sizeof (*desc->kstat_irqs)); + ptr =kzalloc_node (nr *sizeof (*desc->kstat_irqs), +GFP_ATOMIC , node);/* * don't overwite if can not get new one
@@ -219,10 +214,7 @@ struct irq_desc * __ref irq_to_desc_alloc_node(unsigned int irq, int node)if (desc) goto out_unlock; -if (slab_is_available ()) - desc =kzalloc_node (sizeof (*desc),GFP_ATOMIC , node); -else - desc =alloc_bootmem_node (NODE_DATA (node),sizeof (*desc)); + desc =kzalloc_node (sizeof (*desc),GFP_ATOMIC , node);printk (KERN_DEBUG " alloc irq_desc for %d on node %d\n" , irq, node);if (!desc) {
Signature · 1 line
1.6.4.2
PATCH 29/36 radix: move radix init early
In reply to Yinghai Luprepare to use it in early_irq_init()
--- init/main.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
init/main.c +1 -1
@@ -584,6 +584,7 @@ asmlinkage void __init start_kernel(void)local_irq_disable (); }rcu_init (); +radix_tree_init ();/* init some links before init_ISA_irqs() */ early_irq_init ();init_IRQ ();
@@ -659,7 +660,6 @@ asmlinkage void __init start_kernel(void)key_init ();security_init ();vfs_caches_init (totalram_pages); -radix_tree_init ();signals_init ();/* rootfs populating might need page-writeback */ page_writeback_init ();
Signature · 1 line
1.6.4.2
PATCH 30/36 sparseirq: change irq_desc_ptrs to static
In reply to Yinghai Luadd replace_irq_desc()
-v2: remove unneeded boundary check in replace_irq_desc
--- kernel/irq/handle.c | 7 ++++++- kernel/irq/internals.h | 6 +----- kernel/irq/numa_migrate.c | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-)
kernel/irq/handle.c +6 -1
@@ -127,7 +127,7 @@ static void init_one_irq_desc(int irq, struct irq_desc *desc, int node)*/ DEFINE_RAW_SPINLOCK (sparse_irq_lock); -struct irq_desc **irq_desc_ptrs__read_mostly ; +static struct irq_desc **irq_desc_ptrs__read_mostly ; static struct irq_desc irq_desc_legacy[NR_IRQS_LEGACY] __cacheline_aligned_in_smp = { [0 ...NR_IRQS_LEGACY -1 ] = {
@@ -192,6 +192,11 @@ struct irq_desc *irq_to_desc(unsigned int irq)return NULL ; } +void replace_irq_desc (unsigned int irq,struct irq_desc *desc) +{ + irq_desc_ptrs[irq] = desc; +} +struct irq_desc *__ref irq_to_desc_alloc_node (unsigned int irq,int node) {struct irq_desc *desc;
kernel/irq/internals.h +1 -5
@@ -21,11 +21,7 @@ extern void clear_kstat_irqs(struct irq_desc *desc);extern raw_spinlock_t sparse_irq_lock;#ifdef CONFIG_SPARSE_IRQ -/* irq_desc_ptrs allocated at boot time */ -extern struct irq_desc **irq_desc_ptrs; -#else -/* irq_desc_ptrs is a fixed size array */ -extern struct irq_desc *irq_desc_ptrs[NR_IRQS ]; +void replace_irq_desc (unsigned int irq,struct irq_desc *desc);#endif #ifdef CONFIG_PROC_FS
kernel/irq/numa_migrate.c +2 -2
@@ -70,7 +70,7 @@ static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc,raw_spin_lock_irqsave (&sparse_irq_lock, flags);/* We have to check it to avoid races with another CPU */ - desc = irq_desc_ptrs[irq]; + desc =irq_to_desc (irq);if (desc && old_desc != desc) goto out_unlock;
@@ -90,7 +90,7 @@ static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc, goto out_unlock; } - irq_desc_ptrs[irq] = desc; +replace_irq_desc (irq, desc);raw_spin_unlock_irqrestore (&sparse_irq_lock, flags);/* free the old one */
Signature · 1 line
1.6.4.2
PATCH 31/36 sparseirq: use radix_tree instead of ptrs array
In reply to Yinghai Luuse radix_tree irq_desc_tree instead of irq_desc_ptrs.
-v2: according to Eric and cyrill to use radix_tree_lookup_slot and radix_tree_replace_slot
--- kernel/irq/handle.c | 49 +++++++++++++++++++++++++------------------------ 1 files changed, 25 insertions(+), 24 deletions(-)
kernel/irq/handle.c +25 -24
@@ -19,6 +19,7 @@#include <linux/kernel_stat.h> #include <linux/rculist.h> #include <linux/hash.h> +#include <linux/radix-tree.h> #include <trace/events/irq.h> #include "internals.h"
@@ -127,7 +128,26 @@ static void init_one_irq_desc(int irq, struct irq_desc *desc, int node)*/ DEFINE_RAW_SPINLOCK (sparse_irq_lock); -static struct irq_desc **irq_desc_ptrs__read_mostly ; +static RADIX_TREE(irq_desc_tree, GFP_ATOMIC); + +static void set_irq_desc (unsigned int irq,struct irq_desc *desc) +{ +radix_tree_insert (&irq_desc_tree, irq, desc); +} + +struct irq_desc *irq_to_desc (unsigned int irq) +{ +return radix_tree_lookup (&irq_desc_tree, irq); +} + +void replace_irq_desc (unsigned int irq,struct irq_desc *desc) +{ +void **ptr; + + ptr =radix_tree_lookup_slot (&irq_desc_tree, irq); +if (ptr) +radix_tree_replace_slot (ptr, desc); +} static struct irq_desc irq_desc_legacy[NR_IRQS_LEGACY] __cacheline_aligned_in_smp = { [0 ...NR_IRQS_LEGACY -1 ] = {
@@ -159,9 +179,6 @@ int __init early_irq_init(void) legacy_count =ARRAY_SIZE (irq_desc_legacy); node = first_online_node; -/* allocate irq_desc_ptrs array based on nr_irqs */ - irq_desc_ptrs =kcalloc (nr_irqs,sizeof (void *),GFP_NOWAIT ); -/* allocate based on nr_cpu_ids */ kstat_irqs_legacy =kzalloc_node (NR_IRQS_LEGACY * nr_cpu_ids *sizeof (int ),GFP_NOWAIT , node);
@@ -175,28 +192,12 @@ int __init early_irq_init(void)lockdep_set_class (&desc[i].lock, &irq_desc_lock_class);alloc_desc_masks (&desc[i], node, true);init_desc_masks (&desc[i]); - irq_desc_ptrs[i] = desc + i; +set_irq_desc (i, &desc[i]); } -for (i = legacy_count; i < nr_irqs; i++) - irq_desc_ptrs[i] =NULL ; -return arch_early_irq_init (); } -struct irq_desc *irq_to_desc (unsigned int irq) -{ -if (irq_desc_ptrs && irq < nr_irqs) -return irq_desc_ptrs[irq]; - -return NULL ; -} - -void replace_irq_desc (unsigned int irq,struct irq_desc *desc) -{ - irq_desc_ptrs[irq] = desc; -} -struct irq_desc *__ref irq_to_desc_alloc_node (unsigned int irq,int node) {struct irq_desc *desc;
@@ -208,14 +209,14 @@ struct irq_desc * __ref irq_to_desc_alloc_node(unsigned int irq, int node)return NULL ; } - desc = irq_desc_ptrs[irq]; + desc =irq_to_desc (irq);if (desc)return desc;raw_spin_lock_irqsave (&sparse_irq_lock, flags);/* We have to check it to avoid races with another CPU */ - desc = irq_desc_ptrs[irq]; + desc =irq_to_desc (irq);if (desc) goto out_unlock;
@@ -228,7 +229,7 @@ struct irq_desc * __ref irq_to_desc_alloc_node(unsigned int irq, int node) }init_one_irq_desc (irq, desc, node); - irq_desc_ptrs[irq] = desc; +set_irq_desc (irq, desc); out_unlock:raw_spin_unlock_irqrestore (&sparse_irq_lock, flags);
Signature · 1 line
1.6.4.2
PATCH 32/36 x86: remove arch_probe_nr_irqs
In reply to Yinghai Luso keep nr_irqs == NR_IRQS
--- arch/x86/kernel/apic/io_apic.c | 22 ---------------------- 1 files changed, 0 insertions(+), 22 deletions(-)
arch/x86/kernel/apic/io_apic.c +0 -22
@@ -3822,28 +3822,6 @@ void __init probe_nr_irqs_gsi(void)printk (KERN_DEBUG "nr_irqs_gsi: %d\n" , nr_irqs_gsi); } -#ifdef CONFIG_SPARSE_IRQ -int __init arch_probe_nr_irqs (void ) -{ -int nr; - -if (nr_irqs > (NR_VECTORS * nr_cpu_ids)) - nr_irqs =NR_VECTORS * nr_cpu_ids; - - nr = nr_irqs_gsi +8 * nr_cpu_ids; -#if defined(CONFIG_PCI_MSI ) || defined(CONFIG_HT_IRQ ) -/* -* for MSI and HT dyn irq -*/ - nr += nr_irqs_gsi *64 ; -#endif -if (nr < nr_irqs) - nr_irqs = nr; - -return 0 ; -} -#endif -static int __io_apic_set_pci_routing (struct device *dev,int irq,struct io_apic_irq_attr *irq_attr) {
Signature · 1 line
1.6.4.2
PATCH 33/36 use nr_cpus= to set nr_cpu_ids early
In reply to Yinghai Luon x86, before prefill_possible_map(), nr_cpu_ids will be NR_CPUS aka CONFIG_NR_CPUS
add nr_cpus= to set nr_cpu_ids. so we can simulate cpus <=8 are installed on normal config.
-v2: accordging to Christoph, acpi_numa_init should use nr_cpu_ids in stead of
NR_CPUS.
--- arch/ia64/kernel/acpi.c | 4 ++-- arch/x86/kernel/smpboot.c | 7 ++++--- drivers/acpi/numa.c | 4 ++-- init/main.c | 14 ++++++++++++++ 4 files changed, 22 insertions(+), 7 deletions(-)
arch/ia64/kernel/acpi.c +2 -2
@@ -881,8 +881,8 @@ __init void prefill_possible_map(void) possible = available_cpus + additional_cpus; -if (possible >NR_CPUS ) - possible =NR_CPUS ; +if (possible > nr_cpu_ids) + possible = nr_cpu_ids;printk (KERN_INFO "SMP: Allowing %d CPUs, %d hotplug CPUs\n" , possible,max ((possible - available_cpus),0 ));
arch/x86/kernel/smpboot.c +4 -3
@@ -1213,11 +1213,12 @@ __init void prefill_possible_map(void) total_cpus =max_t (int, possible, num_processors + disabled_cpus); -if (possible >CONFIG_NR_CPUS ) { +/* nr_cpu_ids could be reduced via nr_cpus= */ +if (possible > nr_cpu_ids) {printk (KERN_WARNING "%d Processors exceeds NR_CPUS limit of %d\n" , - possible,CONFIG_NR_CPUS ); - possible =CONFIG_NR_CPUS ; + possible, nr_cpu_ids); + possible = nr_cpu_ids; } printk(KERN_INFO "SMP: Allowing %d CPUs, %d hotplug CPUs\n",
drivers/acpi/numa.c +2 -2
@@ -279,9 +279,9 @@ int __init acpi_numa_init(void)/* SRAT: Static Resource Affinity Table */ if (!acpi_table_parse (ACPI_SIG_SRAT , acpi_parse_srat)) {acpi_table_parse_srat (ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY , - acpi_parse_x2apic_affinity,NR_CPUS ); + acpi_parse_x2apic_affinity, nr_cpu_ids);acpi_table_parse_srat (ACPI_SRAT_TYPE_CPU_AFFINITY , - acpi_parse_processor_affinity,NR_CPUS ); + acpi_parse_processor_affinity, nr_cpu_ids); ret =acpi_table_parse_srat (ACPI_SRAT_TYPE_MEMORY_AFFINITY , acpi_parse_memory_affinity,NR_NODE_MEMBLKS );
init/main.c +14 -0
@@ -149,6 +149,20 @@ static int __init nosmp(char *str)early_param ("nosmp" , nosmp); +/* this is hard limit */ +static int __init nrcpus (char *str) +{ +int nr_cpus; + +get_option (&str, &nr_cpus); +if (nr_cpus >0 && nr_cpus < nr_cpu_ids) + nr_cpu_ids = nr_cpus; + +return 0 ; +} + +early_param ("nr_cpus" , nrcpus); +static int __init maxcpus (char *str) {get_option (&str, &setup_max_cpus);
Signature · 1 line
1.6.4.2
PATCH 34/36 x86: according to nr_cpu_ids to decide if need to leave logical flat
In reply to Yinghai Lushould use nr_cpu_ids instead of num_processor, in case we have hotplug cpus.
if current only have 8 cpus is up, but if we will have more cpus that will be hot added later, we should use physical flat at first.
nr_cpu_ids is the total cpus that could be supported.
-v2: per linus, chenage default_setup_apic_routing to _init, and call it for uni_processor
--- arch/x86/kernel/apic/apic.c | 2 -- arch/x86/kernel/apic/probe_32.c | 20 ++++++++++++++++++-- arch/x86/kernel/apic/probe_64.c | 6 +++++- arch/x86/kernel/smpboot.c | 2 -- 4 files changed, 23 insertions(+), 7 deletions(-)
arch/x86/kernel/apic/apic.c +0 -2
@@ -1641,9 +1641,7 @@ int __init APIC_init_uniprocessor(void)#endif enable_IR_x2apic (); -#ifdef CONFIG_X86_64 default_setup_apic_routing (); -#endif verify_local_APIC ();connect_bsp_APIC ();
arch/x86/kernel/apic/probe_32.c +18 -2
@@ -52,7 +52,7 @@ static int __init print_ipi_mode(void) }late_initcall (print_ipi_mode); -void default_setup_apic_routing (void ) +static void local_default_setup_apic_routing (void ) {#ifdef CONFIG_X86_IO_APIC printk(KERN_INFO
@@ -103,7 +103,7 @@ struct apic apic_default = { .init_apic_ldr = default_init_apic_ldr, .ioapic_phys_id_map = default_ioapic_phys_id_map, - .setup_apic_routing = default_setup_apic_routing, + .setup_apic_routing = local_default_setup_apic_routing, .multi_timer_check = NULL, .apicid_to_node = default_apicid_to_node, .cpu_to_logical_apicid = default_cpu_to_logical_apicid,
@@ -212,6 +212,22 @@ void __init generic_bigsmp_probe(void)#endif } +void __init default_setup_apic_routing (void ) +{ +#ifdef CONFIG_X86_BIGSMP +/* +* make sure we go to bigsmp according to real nr_cpu_ids +*/ +if (!cmdline_apic && apic == &apic_default) { +if (nr_cpu_ids >8 ) { + apic = &apic_bigsmp; +printk (KERN_INFO "Overriding APIC driver with %s\n" , + apic->name); + } + } +#endif +} +void __init generic_apic_probe (void ) {if (!cmdline_apic) {
arch/x86/kernel/apic/probe_64.c +5 -1
@@ -67,7 +67,11 @@ void __init default_setup_apic_routing(void) }#endif -if (apic == &apic_flat && num_processors >8 ) +/* +* not just num_processors, we could have hotplug cpus plugged +* in later +*/ +if (apic == &apic_flat && nr_cpu_ids >8 ) apic = &apic_physflat;printk (KERN_INFO "Setting APIC routing to %s\n" , apic->name);
arch/x86/kernel/smpboot.c +0 -2
@@ -1083,9 +1083,7 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)set_cpu_sibling_map (0 );enable_IR_x2apic (); -#ifdef CONFIG_X86_64 default_setup_apic_routing (); -#endif if (smp_sanity_check (max_cpus) <0 ) {printk (KERN_INFO "SMP disabled\n" );
Signature · 1 line
1.6.4.2
PATCH 35/36 x86: make 32bit apic flat to physflat switch like 64bit
In reply to Yinghai Lukill def_to_bigsmp
and move switch from default to bigsmp at default_setup_apic_routing... so make default_setup_apic_routing more like 64 bit
also make the dmi relate code to be __init/__initdata
--- arch/x86/include/asm/apic.h | 3 - arch/x86/include/asm/mpspec.h | 1 - arch/x86/kernel/acpi/boot.c | 3 - arch/x86/kernel/apic/apic.c | 15 ------- arch/x86/kernel/apic/bigsmp_32.c | 48 +---------------------- arch/x86/kernel/apic/probe_32.c | 80 ++++++++++++++++++++----------------- arch/x86/kernel/mpparse.c | 4 -- arch/x86/kernel/setup.c | 2 - arch/x86/kernel/smpboot.c | 2 +- 9 files changed, 46 insertions(+), 112 deletions(-)
arch/x86/include/asm/apic.h +0 -3
@@ -456,9 +456,6 @@ static inline void default_wait_for_init_deassert(atomic_t *deassert)return ; } -extern void generic_bigsmp_probe (void ); - -#ifdef CONFIG_X86_LOCAL_APIC #include <asm/smp.h>
arch/x86/include/asm/mpspec.h +0 -1
@@ -23,7 +23,6 @@ extern int pic_mode;#define MAX_IRQ_SOURCES 256 -extern unsigned int def_to_bigsmp;extern u8 apicid_2_node[];#ifdef CONFIG_X86_NUMAQ
arch/x86/kernel/acpi/boot.c +0 -3
@@ -1185,9 +1185,6 @@ static void __init acpi_process_madt(void)if (!error) { acpi_lapic =1 ; -#ifdef CONFIG_X86_BIGSMP -generic_bigsmp_probe (); -#endif /* * Parse MADT IO-APIC entries */
arch/x86/kernel/apic/apic.c +0 -15
@@ -1889,21 +1889,6 @@ void __cpuinit generic_processor_info(int apicid, int version)if (apicid > max_physical_apicid) max_physical_apicid = apicid; -#ifdef CONFIG_X86_32 -if (num_processors >8 ) { -switch (boot_cpu_data.x86_vendor) { -case X86_VENDOR_INTEL : -if (!APIC_XAPIC (version)) { - def_to_bigsmp =0 ; -break ; - } -/* If P4 and above fall through */ -case X86_VENDOR_AMD : - def_to_bigsmp =1 ; - } - } -#endif -#if defined(CONFIG_SMP ) || defined(CONFIG_X86_64 )early_per_cpu (x86_cpu_to_apicid, cpu) = apicid;early_per_cpu (x86_bios_cpu_apicid, cpu) = apicid;
arch/x86/kernel/apic/bigsmp_32.c +2 -46
81 lines not on this page · raw message
arch/x86/kernel/apic/probe_32.c +43 -37
138 lines not on this page · raw message
arch/x86/kernel/mpparse.c +0 -4
@@ -359,10 +359,6 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early) x86_init.mpparse.mpc_record (1 ); } -#ifdef CONFIG_X86_BIGSMP -generic_bigsmp_probe (); -#endif -if (apic->setup_apic_routing) apic->setup_apic_routing ();
arch/x86/kernel/setup.c +0 -2
@@ -184,8 +184,6 @@ static void set_mca_bus(int x)#endif } -unsigned int def_to_bigsmp; -/* for MCA, but anyone else can use it if they want */ unsigned int machine_id;unsigned int machine_submodel_id;
arch/x86/kernel/smpboot.c +1 -1
@@ -946,7 +946,7 @@ static int __init smp_sanity_check(unsigned max_cpus)preempt_disable ();#if !defined(CONFIG_X86_BIGSMP ) && defined(CONFIG_X86_32 ) -if (def_to_bigsmp && nr_cpu_ids >8 ) { +if (apic == &apic_default && nr_cpu_ids >8 ) {unsigned int cpu;unsigned nr;
Signature · 1 line
1.6.4.2
PATCH 36/36 x86: use num_processors for possible cpus
In reply to Yinghai Lusome systems that have disable cpus entries because same
BIOS will support 2 sockets and 4 sockets and more at same time, BIOS just leave some disable entries, but those system do not support cpu hotplug. we don't need treat disabled_cpus as hotplug cpus.
so we can make nr_cpu_ids smaller and save more space
(pcpu data allocations), and could make some systems run with logical flat instead of physical flat apic mode
-v2: change to black list instead
-v3: just remove that, and the one use possible_cpus= directly.
--- arch/x86/kernel/smpboot.c | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-)
arch/x86/kernel/smpboot.c +1 -2
@@ -1190,7 +1190,6 @@ early_param("possible_cpus", _setup_possible_cpus);* - Ashok Raj * * Three ways to find out the number of additional hotplug CPUs: -* - If the BIOS specified disabled CPUs in ACPI/mptables use that. * - The user can overwrite it with possible_cpus=NUM * - Otherwise don't reserve additional CPUs. * We do this because additional CPUs waste a lot of memory.
@@ -1205,7 +1204,7 @@ __init void prefill_possible_map(void) num_processors =1 ;if (setup_possible_cpus ==-1 ) - possible = num_processors + disabled_cpus; + possible = num_processors;else possible = setup_possible_cpus;
Signature · 1 line
1.6.4.2