2013-09-02 10:32:20

by Tang Chen

[permalink] [raw]
Subject: [PATCH RESEND 0/3] x86, ACPI, mm: Cleanup for {max|low|max_low}_pfn_mapped.

This patch-set does the following:
1. Kill max_low_pfn_mapped as it is useless.
This patch is from Yinghai.
2. Update min_pfn_mapped and max_pfn_mapped together in add_pfn_range_mapped().
3. Move definition of max_pfn_mapped tp init.c together with min_pfn_mapped.


Tang Chen (2):
x86, mm: Update min_pfn_mapped in add_pfn_range_mapped().
x86, mm: Move max_pfn_mapped definition to init.c.

Yinghai Lu (1):
x86, ACPI, mm: Kill max_low_pfn_mapped.

arch/x86/include/asm/page_types.h | 1 -
arch/x86/kernel/setup.c | 10 ----------
arch/x86/mm/init.c | 15 ++++++++++-----
drivers/acpi/osl.c | 6 +++---
4 files changed, 13 insertions(+), 19 deletions(-)


2013-09-02 10:32:15

by Tang Chen

[permalink] [raw]
Subject: [PATCH RESEND 2/3] x86, mm: Update min_pfn_mapped in add_pfn_range_mapped().

In current kernel, we update min_pfn_mapped and max_pfn_mapped like this:

init_mem_mapping()
{
while ( a loop iterates all memory ranges ) {
init_range_memory_mapping();
|->init_memory_mapping()
|->kernel_physical_mapping_init()
|->add_pfn_range_mapped()
|-> update max_pfn_mapped;

update min_pfn_mapped;
}
}

max_pfn_mapped is updated in add_pfn_range_mapped() when a range of memory
is mapped. But min_pfn_mapped is updated in init_mem_mapping(). We can also
update min_pfn_mapped in add_pfn_range_mapped().

Signed-off-by: Tang Chen <[email protected]>
---
arch/x86/mm/init.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index 5b2eaca..a97749f 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -313,6 +313,7 @@ static void add_pfn_range_mapped(unsigned long start_pfn, unsigned long end_pfn)
nr_pfn_mapped = clean_sort_range(pfn_mapped, E820_X_MAX);

max_pfn_mapped = max(max_pfn_mapped, end_pfn);
+ min_pfn_mapped = min(min_pfn_mapped, start_pfn);
}

bool pfn_range_is_mapped(unsigned long start_pfn, unsigned long end_pfn)
@@ -442,7 +443,6 @@ void __init init_mem_mapping(void)
new_mapped_ram_size = init_range_memory_mapping(start,
last_start);
last_start = start;
- min_pfn_mapped = last_start >> PAGE_SHIFT;
/* only increase step_size after big range get mapped */
if (new_mapped_ram_size > mapped_ram_size)
step_size <<= STEP_SIZE_SHIFT;
--
1.7.1

2013-09-02 10:32:19

by Tang Chen

[permalink] [raw]
Subject: [PATCH RESEND 3/3] x86, mm: Move max_pfn_mapped definition to init.c.

min_pfn_mapped is defined in init.c, we can also define max_pfn_mapped here.

Signed-off-by: Tang Chen <[email protected]>
---
arch/x86/kernel/setup.c | 8 --------
arch/x86/mm/init.c | 9 +++++++++
2 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 7fa1ec3..698b9c6 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -111,14 +111,6 @@
#include <asm/alternative.h>
#include <asm/prom.h>

-/*
- * max_pfn_mapped: highest direct mapped pfn
- *
- * The direct mapping only covers E820_RAM regions, so the ranges and gaps are
- * represented by pfn_mapped
- */
-unsigned long max_pfn_mapped;
-
#ifdef CONFIG_DMI
RESERVE_BRK(dmi_alloc, 65536);
#endif
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index a97749f..793204b 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -24,6 +24,15 @@ static unsigned long __initdata pgt_buf_start;
static unsigned long __initdata pgt_buf_end;
static unsigned long __initdata pgt_buf_top;

+/*
+ * max_pfn_mapped: highest direct mapped pfn
+ * min_pfn_mapped: lowest direct mapped pfn
+ *
+ * The direct mapping only covers E820_RAM regions, so the ranges and gaps are
+ * represented by pfn_mapped
+ */
+
+unsigned long max_pfn_mapped;
static unsigned long min_pfn_mapped;

static bool __initdata can_use_brk_pgt = true;
--
1.7.1

2013-09-02 10:32:47

by Tang Chen

[permalink] [raw]
Subject: [PATCH RESEND 1/3] x86, ACPI, mm: Kill max_low_pfn_mapped.

From: Yinghai Lu <[email protected]>

Now we have pfn_mapped[] in , and max_low_pfn_mapped should not be used anymore.

User should use pfn_mapped[] or just 1UL<<(32-PAGE_SHIFT) instead.

Only user is ACPI_INITRD_TABLE_OVERRIDE, and it should not use that,
as later accessing is using early_ioremap(). We could change to use
1U<<(32_PAGE_SHIFT) with it, aka under 4G.

-v2: Leave alone max_low_pfn_mapped in i915 code according to tj.

Suggested-by: H. Peter Anvin <[email protected]>
Signed-off-by: Yinghai Lu <[email protected]>
Signed-off-by: Tang Chen <[email protected]>
Cc: "Rafael J. Wysocki" <[email protected]>
Cc: Jacob Shin <[email protected]>
Cc: Pekka Enberg <[email protected]>
Cc: [email protected]
Tested-by: Thomas Renninger <[email protected]>
Reviewed-by: Tang Chen <[email protected]>
Tested-by: Tang Chen <[email protected]>
---
arch/x86/include/asm/page_types.h | 1 -
arch/x86/kernel/setup.c | 4 +---
arch/x86/mm/init.c | 4 ----
drivers/acpi/osl.c | 6 +++---
4 files changed, 4 insertions(+), 11 deletions(-)

diff --git a/arch/x86/include/asm/page_types.h b/arch/x86/include/asm/page_types.h
index 54c9787..b012b82 100644
--- a/arch/x86/include/asm/page_types.h
+++ b/arch/x86/include/asm/page_types.h
@@ -43,7 +43,6 @@

extern int devmem_is_allowed(unsigned long pagenr);

-extern unsigned long max_low_pfn_mapped;
extern unsigned long max_pfn_mapped;

static inline phys_addr_t get_max_mapped(void)
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index f8ec578..7fa1ec3 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -112,13 +112,11 @@
#include <asm/prom.h>

/*
- * max_low_pfn_mapped: highest direct mapped pfn under 4GB
- * max_pfn_mapped: highest direct mapped pfn over 4GB
+ * max_pfn_mapped: highest direct mapped pfn
*
* The direct mapping only covers E820_RAM regions, so the ranges and gaps are
* represented by pfn_mapped
*/
-unsigned long max_low_pfn_mapped;
unsigned long max_pfn_mapped;

#ifdef CONFIG_DMI
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index 2ec29ac..5b2eaca 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -313,10 +313,6 @@ static void add_pfn_range_mapped(unsigned long start_pfn, unsigned long end_pfn)
nr_pfn_mapped = clean_sort_range(pfn_mapped, E820_X_MAX);

max_pfn_mapped = max(max_pfn_mapped, end_pfn);
-
- if (start_pfn < (1UL<<(32-PAGE_SHIFT)))
- max_low_pfn_mapped = max(max_low_pfn_mapped,
- min(end_pfn, 1UL<<(32-PAGE_SHIFT)));
}

bool pfn_range_is_mapped(unsigned long start_pfn, unsigned long end_pfn)
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 6ab2c35..378de0d 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -624,9 +624,9 @@ void __init acpi_initrd_override(void *data, size_t size)
if (table_nr == 0)
return;

- acpi_tables_addr =
- memblock_find_in_range(0, max_low_pfn_mapped << PAGE_SHIFT,
- all_tables_size, PAGE_SIZE);
+ /* under 4G at first, then above 4G */
+ acpi_tables_addr = memblock_find_in_range(0, (1ULL<<32) - 1,
+ all_tables_size, PAGE_SIZE);
if (!acpi_tables_addr) {
WARN_ON(1);
return;
--
1.7.1

2013-09-02 18:41:47

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH RESEND 2/3] x86, mm: Update min_pfn_mapped in add_pfn_range_mapped().

On Mon, Sep 2, 2013 at 3:30 AM, Tang Chen <[email protected]> wrote:
> In current kernel, we update min_pfn_mapped and max_pfn_mapped like this:
>
> init_mem_mapping()
> {
> while ( a loop iterates all memory ranges ) {
> init_range_memory_mapping();
> |->init_memory_mapping()
> |->kernel_physical_mapping_init()
> |->add_pfn_range_mapped()
> |-> update max_pfn_mapped;
>
> update min_pfn_mapped;
> }
> }
>
> max_pfn_mapped is updated in add_pfn_range_mapped() when a range of memory
> is mapped. But min_pfn_mapped is updated in init_mem_mapping(). We can also
> update min_pfn_mapped in add_pfn_range_mapped().
>
> Signed-off-by: Tang Chen <[email protected]>
> ---
> arch/x86/mm/init.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
> index 5b2eaca..a97749f 100644
> --- a/arch/x86/mm/init.c
> +++ b/arch/x86/mm/init.c
> @@ -313,6 +313,7 @@ static void add_pfn_range_mapped(unsigned long start_pfn, unsigned long end_pfn)
> nr_pfn_mapped = clean_sort_range(pfn_mapped, E820_X_MAX);
>
> max_pfn_mapped = max(max_pfn_mapped, end_pfn);
> + min_pfn_mapped = min(min_pfn_mapped, start_pfn);
> }
>
> bool pfn_range_is_mapped(unsigned long start_pfn, unsigned long end_pfn)
> @@ -442,7 +443,6 @@ void __init init_mem_mapping(void)
> new_mapped_ram_size = init_range_memory_mapping(start,
> last_start);
> last_start = start;
> - min_pfn_mapped = last_start >> PAGE_SHIFT;
> /* only increase step_size after big range get mapped */
> if (new_mapped_ram_size > mapped_ram_size)
> step_size <<= STEP_SIZE_SHIFT;


Nak, you can not move that.

min_pfn_mapped should not be updated before init_range_memory_mapping
is returned. as it need to refer old min_pfn_mapped.
and init_range_memory_mapping still init mapping from low to high locally.
min_pfn_mapped can not be updated too early.

Yinghai

2013-09-03 01:07:35

by Tang Chen

[permalink] [raw]
Subject: Re: [PATCH RESEND 2/3] x86, mm: Update min_pfn_mapped in add_pfn_range_mapped().

Hi Yinghai,

On 09/03/2013 02:41 AM, Yinghai Lu wrote:
......
>
> Nak, you can not move that.
>
> min_pfn_mapped should not be updated before init_range_memory_mapping
> is returned. as it need to refer old min_pfn_mapped.
> and init_range_memory_mapping still init mapping from low to high locally.
> min_pfn_mapped can not be updated too early.

The current code is like this:

init_mem_mapping()
{
while (from high to low) {
init_range_memory_mapping()
{
/* Here is from low to high */
for (from low to high) {
init_memory_mapping()
{
for () {
/* Need to refer min_pfn_mapped here */
kernel_physical_mapping_init();
}
/* So if updating min_pfn_mapped here, it is too low */
add_pfn_range_mapped();
}
}
}
}
}

How about change the "for (from low to high)" in
init_range_memory_mapping() to
"for_rev(from high to low)" ?
Then we can update min_pfn_mapped in add_pfn_range_mapped().

And also, the outer loop is from high to low, we can change the inner
loop to be from high
to low too.

I think updating min_pfn_mapped in init_mem_mapping() is less readable.
And min_pfn_mapped
and max_pfn_mapped should be updated together.

Thanks.

2013-09-03 02:48:15

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH RESEND 2/3] x86, mm: Update min_pfn_mapped in add_pfn_range_mapped().

On Mon, Sep 2, 2013 at 6:06 PM, Tang Chen <[email protected]> wrote:
> Hi Yinghai,
>
> On 09/03/2013 02:41 AM, Yinghai Lu wrote:

> How about change the "for (from low to high)" in init_range_memory_mapping()
> to
> "for_rev(from high to low)" ?
> Then we can update min_pfn_mapped in add_pfn_range_mapped().
>
> And also, the outer loop is from high to low, we can change the inner loop
> to be from high
> to low too.

No. there is other reason for doing local from low to high.

kernel_physical_mapping_init() could clear some mapping near the end
of PUG/PMD entries but not the head.

>
> I think updating min_pfn_mapped in init_mem_mapping() is less readable. And
> min_pfn_mapped
> and max_pfn_mapped should be updated together.

min_pfn_mapped is early local variable to control allocation in alloc_low_pages.
put it in init_mem_mapping is more readable.

Yinghai

2013-09-03 05:39:40

by Tang Chen

[permalink] [raw]
Subject: Re: [PATCH RESEND 2/3] x86, mm: Update min_pfn_mapped in add_pfn_range_mapped().

On 09/03/2013 10:48 AM, Yinghai Lu wrote:
> On Mon, Sep 2, 2013 at 6:06 PM, Tang Chen<[email protected]> wrote:
>> Hi Yinghai,
>>
>> On 09/03/2013 02:41 AM, Yinghai Lu wrote:
>
>> How about change the "for (from low to high)" in init_range_memory_mapping()
>> to
>> "for_rev(from high to low)" ?
>> Then we can update min_pfn_mapped in add_pfn_range_mapped().
>>
>> And also, the outer loop is from high to low, we can change the inner loop
>> to be from high
>> to low too.
>
> No. there is other reason for doing local from low to high.
>
> kernel_physical_mapping_init() could clear some mapping near the end
> of PUG/PMD entries but not the head.

Thanks for your explanation. But sorry, I'd like to understand it more
clearly.

Are you talking about the following code ?
phys_pud_init()
{
if (addr >= end) {
if (!after_bootmem &&
!e820_any_mapped(addr & PUD_MASK, next,
E820_RAM) &&
!e820_any_mapped(addr & PUD_MASK, next,
E820_RESERVED_KERN))
set_pud(pud, __pud(0));
continue;
}
}
It will clear the PUD/PMD out of range.


But,
init_mem_mapping()
{
while (from high to low) {
init_range_memory_mapping()
{
for (from low to high) { /* I'm saying changing this
loop */
init_memory_mapping()
{
for () { /* Not this one */
kernel_physical_mapping_init();
}
add_pfn_range_mapped();
}
}
}
}
}

I'm saying changing the outer loop in init_range_memory_mapping(), not
the one in init_memory_mapping().
I think it is OK to call init_memory_mapping() with any order. The loop
is out of init_memory_mapping(), right ?

In init_memory_mapping(), it is still from low to high. But when the
kernel_physical_mapping_init() finished,
we can update min_pfn_mapped in add_pfn_range_mapped() because the outer
loop is from high to low.

Am I missing something here ? Please tell me.

>
>>
>> I think updating min_pfn_mapped in init_mem_mapping() is less readable. And
>> min_pfn_mapped
>> and max_pfn_mapped should be updated together.
>
> min_pfn_mapped is early local variable to control allocation in alloc_low_pages.
> put it in init_mem_mapping is more readable.
>

But add_pfn_range_mapped() is in the same file with init_mem_mapping().
I think
it is OK to update min_pfn_mapped in it.

Thanks.

2013-09-03 06:34:55

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH RESEND 2/3] x86, mm: Update min_pfn_mapped in add_pfn_range_mapped().

On Mon, Sep 2, 2013 at 10:38 PM, Tang Chen <[email protected]> wrote:
> On 09/03/2013 10:48 AM, Yinghai Lu wrote:
>>
>> On Mon, Sep 2, 2013 at 6:06 PM, Tang Chen<[email protected]> wrote:
>>>
>>> Hi Yinghai,
>>>
>>> On 09/03/2013 02:41 AM, Yinghai Lu wrote:
>>
>>
>>> How about change the "for (from low to high)" in
>>> init_range_memory_mapping()
>>> to
>>> "for_rev(from high to low)" ?
>>> Then we can update min_pfn_mapped in add_pfn_range_mapped().
>>>
>>> And also, the outer loop is from high to low, we can change the inner
>>> loop
>>> to be from high
>>> to low too.
>>
>>
>> No. there is other reason for doing local from low to high.
>>
>> kernel_physical_mapping_init() could clear some mapping near the end
>> of PUG/PMD entries but not the head.
>
>
> Thanks for your explanation. But sorry, I'd like to understand it more
> clearly.
>
> Are you talking about the following code ?
> phys_pud_init()
> {
> if (addr >= end) {
> if (!after_bootmem &&
> !e820_any_mapped(addr & PUD_MASK, next,
> E820_RAM) &&
> !e820_any_mapped(addr & PUD_MASK, next,
> E820_RESERVED_KERN))
> set_pud(pud, __pud(0));
> continue;
> }
> }
> It will clear the PUD/PMD out of range.
>
>
> But,
>
> init_mem_mapping()
> {
> while (from high to low) {
> init_range_memory_mapping()
> {
> for (from low to high) {
> /* I'm saying changing this loop */
> init_memory_mapping()
> {
> for () {
> /* Not this one */
> kernel_physical_mapping_init();
> }
> add_pfn_range_mapped();
> }
> }
> }
> }
> }
>
> I'm saying changing the outer loop in init_range_memory_mapping(), not the
> one in init_memory_mapping().
> I think it is OK to call init_memory_mapping() with any order. The loop is
> out of init_memory_mapping(), right ?
>
> In init_memory_mapping(), it is still from low to high. But when the
> kernel_physical_mapping_init() finished,
> we can update min_pfn_mapped in add_pfn_range_mapped() because the outer
> loop is from high to low.
>
> Am I missing something here ? Please tell me.

Yes, that looks ok,

but will make the code more hard to understand, aka more dependency.

the only purpose for min_pfn_mapped is for control allocation for
alloc_low_pages.

so put it's updating in init_mem_mapping is clear and less twisting.

also in my patchset that put page table in local node, min_pfn_mapped
is replaced by
local_min_pfn_mapped per node.

Yinghai