Skip to content

Commit 6b63783

Browse files
Toshi Kanitorvalds
authored andcommitted
x86, mm: support huge KVA mappings on x86
Implement huge KVA mapping interfaces on x86. On x86, MTRRs can override PAT memory types with a 4KB granularity. When using a huge page, MTRRs can override the memory type of the huge page, which may lead a performance penalty. The processor can also behave in an undefined manner if a huge page is mapped to a memory range that MTRRs have mapped with multiple different memory types. Therefore, the mapping code falls back to use a smaller page size toward 4KB when a mapping range is covered by non-WB type of MTRRs. The WB type of MTRRs has no affect on the PAT memory types. pud_set_huge() and pmd_set_huge() call mtrr_type_lookup() to see if a given range is covered by MTRRs. MTRR_TYPE_WRBACK indicates that the range is either covered by WB or not covered and the MTRR default value is set to WB. 0xFF indicates that MTRRs are disabled. HAVE_ARCH_HUGE_VMAP is selected when X86_64 or X86_32 with X86_PAE is set. X86_32 without X86_PAE is not supported since such config can unlikey be benefited from this feature, and there was an issue found in testing. [[email protected]: ioremap_pud_capable can be static] Signed-off-by: Toshi Kani <[email protected]> Cc: "H. Peter Anvin" <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Arnd Bergmann <[email protected]> Cc: Dave Hansen <[email protected]> Cc: Robert Elliott <[email protected]> Signed-off-by: Fengguang Wu <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 5d72b4f commit 6b63783

File tree

3 files changed

+69
-3
lines changed

3 files changed

+69
-3
lines changed

arch/x86/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ config X86
9999
select IRQ_FORCED_THREADING
100100
select HAVE_BPF_JIT if X86_64
101101
select HAVE_ARCH_TRANSPARENT_HUGEPAGE
102+
select HAVE_ARCH_HUGE_VMAP if X86_64 || (X86_32 && X86_PAE)
102103
select ARCH_HAS_SG_CHAIN
103104
select CLKEVT_I8253
104105
select ARCH_HAVE_NMI_SAFE_CMPXCHG

arch/x86/mm/pgtable.c

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <asm/pgtable.h>
55
#include <asm/tlb.h>
66
#include <asm/fixmap.h>
7+
#include <asm/mtrr.h>
78

89
#define PGALLOC_GFP GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO
910

@@ -560,3 +561,67 @@ void native_set_fixmap(enum fixed_addresses idx, phys_addr_t phys,
560561
{
561562
__native_set_fixmap(idx, pfn_pte(phys >> PAGE_SHIFT, flags));
562563
}
564+
565+
#ifdef CONFIG_HAVE_ARCH_HUGE_VMAP
566+
int pud_set_huge(pud_t *pud, phys_addr_t addr, pgprot_t prot)
567+
{
568+
u8 mtrr;
569+
570+
/*
571+
* Do not use a huge page when the range is covered by non-WB type
572+
* of MTRRs.
573+
*/
574+
mtrr = mtrr_type_lookup(addr, addr + PUD_SIZE);
575+
if ((mtrr != MTRR_TYPE_WRBACK) && (mtrr != 0xFF))
576+
return 0;
577+
578+
prot = pgprot_4k_2_large(prot);
579+
580+
set_pte((pte_t *)pud, pfn_pte(
581+
(u64)addr >> PAGE_SHIFT,
582+
__pgprot(pgprot_val(prot) | _PAGE_PSE)));
583+
584+
return 1;
585+
}
586+
587+
int pmd_set_huge(pmd_t *pmd, phys_addr_t addr, pgprot_t prot)
588+
{
589+
u8 mtrr;
590+
591+
/*
592+
* Do not use a huge page when the range is covered by non-WB type
593+
* of MTRRs.
594+
*/
595+
mtrr = mtrr_type_lookup(addr, addr + PMD_SIZE);
596+
if ((mtrr != MTRR_TYPE_WRBACK) && (mtrr != 0xFF))
597+
return 0;
598+
599+
prot = pgprot_4k_2_large(prot);
600+
601+
set_pte((pte_t *)pmd, pfn_pte(
602+
(u64)addr >> PAGE_SHIFT,
603+
__pgprot(pgprot_val(prot) | _PAGE_PSE)));
604+
605+
return 1;
606+
}
607+
608+
int pud_clear_huge(pud_t *pud)
609+
{
610+
if (pud_large(*pud)) {
611+
pud_clear(pud);
612+
return 1;
613+
}
614+
615+
return 0;
616+
}
617+
618+
int pmd_clear_huge(pmd_t *pmd)
619+
{
620+
if (pmd_large(*pmd)) {
621+
pmd_clear(pmd);
622+
return 1;
623+
}
624+
625+
return 0;
626+
}
627+
#endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */

lib/ioremap.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
#include <asm/pgtable.h>
1515

1616
#ifdef CONFIG_HAVE_ARCH_HUGE_VMAP
17-
int __read_mostly ioremap_pud_capable;
18-
int __read_mostly ioremap_pmd_capable;
19-
int __read_mostly ioremap_huge_disabled;
17+
static int __read_mostly ioremap_pud_capable;
18+
static int __read_mostly ioremap_pmd_capable;
19+
static int __read_mostly ioremap_huge_disabled;
2020

2121
static int __init set_nohugeiomap(char *str)
2222
{

0 commit comments

Comments
 (0)