[patch 80/85] x86, cpa: dont use large pages for kernel identitymapping with DEBUG_PAGEALLOC

From: Greg KH
Date: Thu Jan 15 2009 - 17:48:39 EST


2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------

From: Suresh Siddha <suresh.b.siddha@xxxxxxxxx>

commit 0b8fdcbcd287a1fbe66817491e6149841ae25705 upstream.

Don't use large pages for kernel identity mapping with DEBUG_PAGEALLOC.
This will remove the need to split the large page for the
allocated kernel page in the interrupt context.

This will simplify cpa code(as we don't do the split any more from the
interrupt context). cpa code simplication in the subsequent patches.

Tested-by: Tony Battersby <tonyb@xxxxxxxxxxxxxxx>
Signed-off-by: Suresh Siddha <suresh.b.siddha@xxxxxxxxx>
Cc: Suresh Siddha <suresh.b.siddha@xxxxxxxxx>
Cc: arjan@xxxxxxxxxxxxxxx
Cc: venkatesh.pallipadi@xxxxxxxxx
Cc: jeremy@xxxxxxxx
Signed-off-by: Ingo Molnar <mingo@xxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxx>

---
arch/x86/mm/init_32.c | 18 ++++++++++++++----
arch/x86/mm/init_64.c | 26 ++++++++++++++++++++------
2 files changed, 34 insertions(+), 10 deletions(-)

--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -718,7 +718,7 @@ void __init setup_bootmem_allocator(void
after_init_bootmem = 1;
}

-static void __init find_early_table_space(unsigned long end)
+static void __init find_early_table_space(unsigned long end, int use_pse)
{
unsigned long puds, pmds, ptes, tables, start;

@@ -728,7 +728,7 @@ static void __init find_early_table_spac
pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
tables += PAGE_ALIGN(pmds * sizeof(pmd_t));

- if (cpu_has_pse) {
+ if (use_pse) {
unsigned long extra;

extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT);
@@ -768,12 +768,22 @@ unsigned long __init_refok init_memory_m
pgd_t *pgd_base = swapper_pg_dir;
unsigned long start_pfn, end_pfn;
unsigned long big_page_start;
+#ifdef CONFIG_DEBUG_PAGEALLOC
+ /*
+ * For CONFIG_DEBUG_PAGEALLOC, identity mapping will use small pages.
+ * This will simplify cpa(), which otherwise needs to support splitting
+ * large pages into small in interrupt context, etc.
+ */
+ int use_pse = 0;
+#else
+ int use_pse = cpu_has_pse;
+#endif

/*
* Find space for the kernel direct mapping tables.
*/
if (!after_init_bootmem)
- find_early_table_space(end);
+ find_early_table_space(end, use_pse);

#ifdef CONFIG_X86_PAE
set_nx();
@@ -819,7 +829,7 @@ unsigned long __init_refok init_memory_m
end_pfn = (end>>PMD_SHIFT) << (PMD_SHIFT - PAGE_SHIFT);
if (start_pfn < end_pfn)
kernel_physical_mapping_init(pgd_base, start_pfn, end_pfn,
- cpu_has_pse);
+ use_pse);

/* tail is not big page alignment ? */
start_pfn = end_pfn;
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -446,13 +446,14 @@ phys_pud_update(pgd_t *pgd, unsigned lon
return phys_pud_init(pud, addr, end, page_size_mask);
}

-static void __init find_early_table_space(unsigned long end)
+static void __init find_early_table_space(unsigned long end, int use_pse,
+ int use_gbpages)
{
unsigned long puds, pmds, ptes, tables, start;

puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
tables = round_up(puds * sizeof(pud_t), PAGE_SIZE);
- if (direct_gbpages) {
+ if (use_gbpages) {
unsigned long extra;
extra = end - ((end>>PUD_SHIFT) << PUD_SHIFT);
pmds = (extra + PMD_SIZE - 1) >> PMD_SHIFT;
@@ -460,7 +461,7 @@ static void __init find_early_table_spac
pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
tables += round_up(pmds * sizeof(pmd_t), PAGE_SIZE);

- if (cpu_has_pse) {
+ if (use_pse) {
unsigned long extra;
extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT);
ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT;
@@ -571,6 +572,7 @@ unsigned long __init_refok init_memory_m

struct map_range mr[NR_RANGE_MR];
int nr_range, i;
+ int use_pse, use_gbpages;

printk(KERN_INFO "init_memory_mapping\n");

@@ -584,9 +586,21 @@ unsigned long __init_refok init_memory_m
if (!after_bootmem)
init_gbpages();

- if (direct_gbpages)
+#ifdef CONFIG_DEBUG_PAGEALLOC
+ /*
+ * For CONFIG_DEBUG_PAGEALLOC, identity mapping will use small pages.
+ * This will simplify cpa(), which otherwise needs to support splitting
+ * large pages into small in interrupt context, etc.
+ */
+ use_pse = use_gbpages = 0;
+#else
+ use_pse = cpu_has_pse;
+ use_gbpages = direct_gbpages;
+#endif
+
+ if (use_gbpages)
page_size_mask |= 1 << PG_LEVEL_1G;
- if (cpu_has_pse)
+ if (use_pse)
page_size_mask |= 1 << PG_LEVEL_2M;

memset(mr, 0, sizeof(mr));
@@ -647,7 +661,7 @@ unsigned long __init_refok init_memory_m
(mr[i].page_size_mask & (1<<PG_LEVEL_2M))?"2M":"4k"));

if (!after_bootmem)
- find_early_table_space(end);
+ find_early_table_space(end, use_pse, use_gbpages);

for (i = 0; i < nr_range; i++)
last_map_addr = kernel_physical_mapping_init(

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/