You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: [POWERPC] Further fixes for the removal of 4level-fixup hack from ppc32 [POWERPC] EEH: log all PCI-X and PCI-E AER registers [POWERPC] EEH: capture and log pci state on error [POWERPC] EEH: Split up long error msg [POWERPC] EEH: log error only after driver notification. [POWERPC] fsl_soc: Make mac_addr const in fs_enet_of_init(). [POWERPC] Don't use SLAB/SLUB for PTE pages [POWERPC] Spufs support for 64K LS mappings on 4K kernels [POWERPC] Add ability to 4K kernel to hash in 64K pages [POWERPC] Introduce address space "slices" [POWERPC] Small fixes & cleanups in segment page size demotion [POWERPC] iSeries: Make HVC_ISERIES the default [POWERPC] iSeries: suppress build warning in lparmap.c [POWERPC] Mark pages that don't exist as nosave [POWERPC] swsusp: Introduce register_nosave_region_late
This commit is contained in:
+11
-13
@@ -120,19 +120,6 @@ config GENERIC_BUG
|
||||
config SYS_SUPPORTS_APM_EMULATION
|
||||
bool
|
||||
|
||||
#
|
||||
# Powerpc uses the slab allocator to manage its ptes and the
|
||||
# page structs of ptes are used for splitting the page table
|
||||
# lock for configurations supporting more than SPLIT_PTLOCK_CPUS.
|
||||
#
|
||||
# In that special configuration the page structs of slabs are modified.
|
||||
# This setting disables the selection of SLUB as a slab allocator.
|
||||
#
|
||||
config ARCH_USES_SLAB_PAGE_STRUCT
|
||||
bool
|
||||
default y
|
||||
depends on SPLIT_PTLOCK_CPUS <= NR_CPUS
|
||||
|
||||
config DEFAULT_UIMAGE
|
||||
bool
|
||||
help
|
||||
@@ -352,6 +339,11 @@ config PPC_STD_MMU_32
|
||||
def_bool y
|
||||
depends on PPC_STD_MMU && PPC32
|
||||
|
||||
config PPC_MM_SLICES
|
||||
bool
|
||||
default y if HUGETLB_PAGE
|
||||
default n
|
||||
|
||||
config VIRT_CPU_ACCOUNTING
|
||||
bool "Deterministic task and CPU time accounting"
|
||||
depends on PPC64
|
||||
@@ -541,9 +533,15 @@ config NODES_SPAN_OTHER_NODES
|
||||
def_bool y
|
||||
depends on NEED_MULTIPLE_NODES
|
||||
|
||||
config PPC_HAS_HASH_64K
|
||||
bool
|
||||
depends on PPC64
|
||||
default n
|
||||
|
||||
config PPC_64K_PAGES
|
||||
bool "64k page size"
|
||||
depends on PPC64
|
||||
select PPC_HAS_HASH_64K
|
||||
help
|
||||
This option changes the kernel logical page size to 64k. On machines
|
||||
without processor support for 64k pages, the kernel will simulate
|
||||
|
||||
@@ -122,12 +122,18 @@ int main(void)
|
||||
DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache));
|
||||
DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr));
|
||||
DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id));
|
||||
DEFINE(PACACONTEXTSLLP, offsetof(struct paca_struct, context.sllp));
|
||||
DEFINE(PACAVMALLOCSLLP, offsetof(struct paca_struct, vmalloc_sllp));
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
DEFINE(PACALOWHTLBAREAS, offsetof(struct paca_struct, context.low_htlb_areas));
|
||||
DEFINE(PACAHIGHHTLBAREAS, offsetof(struct paca_struct, context.high_htlb_areas));
|
||||
#endif /* CONFIG_HUGETLB_PAGE */
|
||||
#ifdef CONFIG_PPC_MM_SLICES
|
||||
DEFINE(PACALOWSLICESPSIZE, offsetof(struct paca_struct,
|
||||
context.low_slices_psize));
|
||||
DEFINE(PACAHIGHSLICEPSIZE, offsetof(struct paca_struct,
|
||||
context.high_slices_psize));
|
||||
DEFINE(MMUPSIZEDEFSIZE, sizeof(struct mmu_psize_def));
|
||||
DEFINE(MMUPSIZESLLP, offsetof(struct mmu_psize_def, sllp));
|
||||
#else
|
||||
DEFINE(PACACONTEXTSLLP, offsetof(struct paca_struct, context.sllp));
|
||||
|
||||
#endif /* CONFIG_PPC_MM_SLICES */
|
||||
DEFINE(PACA_EXGEN, offsetof(struct paca_struct, exgen));
|
||||
DEFINE(PACA_EXMC, offsetof(struct paca_struct, exmc));
|
||||
DEFINE(PACA_EXSLB, offsetof(struct paca_struct, exslb));
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/iseries/lpar_map.h>
|
||||
|
||||
const struct LparMap __attribute__((__section__(".text"))) xLparMap = {
|
||||
/* The # is to stop gcc trying to make .text nonexecutable */
|
||||
const struct LparMap __attribute__((__section__(".text #"))) xLparMap = {
|
||||
.xNumberEsids = HvEsidsToMap,
|
||||
.xNumberRanges = HvRangesToMap,
|
||||
.xSegmentTableOffs = STAB0_PAGE,
|
||||
|
||||
@@ -18,4 +18,5 @@ obj-$(CONFIG_40x) += 4xx_mmu.o
|
||||
obj-$(CONFIG_44x) += 44x_mmu.o
|
||||
obj-$(CONFIG_FSL_BOOKE) += fsl_booke_mmu.o
|
||||
obj-$(CONFIG_NEED_MULTIPLE_NODES) += numa.o
|
||||
obj-$(CONFIG_PPC_MM_SLICES) += slice.o
|
||||
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
|
||||
|
||||
@@ -615,6 +615,9 @@ htab_pte_insert_failure:
|
||||
li r3,-1
|
||||
b htab_bail
|
||||
|
||||
#endif /* CONFIG_PPC_64K_PAGES */
|
||||
|
||||
#ifdef CONFIG_PPC_HAS_HASH_64K
|
||||
|
||||
/*****************************************************************************
|
||||
* *
|
||||
@@ -870,7 +873,7 @@ ht64_pte_insert_failure:
|
||||
b ht64_bail
|
||||
|
||||
|
||||
#endif /* CONFIG_PPC_64K_PAGES */
|
||||
#endif /* CONFIG_PPC_HAS_HASH_64K */
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
#include <asm/cputable.h>
|
||||
#include <asm/abs_addr.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/spu.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DBG(fmt...) udbg_printf(fmt)
|
||||
@@ -419,7 +420,7 @@ static void __init htab_finish_init(void)
|
||||
extern unsigned int *htab_call_hpte_remove;
|
||||
extern unsigned int *htab_call_hpte_updatepp;
|
||||
|
||||
#ifdef CONFIG_PPC_64K_PAGES
|
||||
#ifdef CONFIG_PPC_HAS_HASH_64K
|
||||
extern unsigned int *ht64_call_hpte_insert1;
|
||||
extern unsigned int *ht64_call_hpte_insert2;
|
||||
extern unsigned int *ht64_call_hpte_remove;
|
||||
@@ -596,22 +597,23 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap)
|
||||
* Demote a segment to using 4k pages.
|
||||
* For now this makes the whole process use 4k pages.
|
||||
*/
|
||||
void demote_segment_4k(struct mm_struct *mm, unsigned long addr)
|
||||
{
|
||||
#ifdef CONFIG_PPC_64K_PAGES
|
||||
static void demote_segment_4k(struct mm_struct *mm, unsigned long addr)
|
||||
{
|
||||
if (mm->context.user_psize == MMU_PAGE_4K)
|
||||
return;
|
||||
#ifdef CONFIG_PPC_MM_SLICES
|
||||
slice_set_user_psize(mm, MMU_PAGE_4K);
|
||||
#else /* CONFIG_PPC_MM_SLICES */
|
||||
mm->context.user_psize = MMU_PAGE_4K;
|
||||
mm->context.sllp = SLB_VSID_USER | mmu_psize_defs[MMU_PAGE_4K].sllp;
|
||||
get_paca()->context = mm->context;
|
||||
slb_flush_and_rebolt();
|
||||
#endif /* CONFIG_PPC_MM_SLICES */
|
||||
|
||||
#ifdef CONFIG_SPE_BASE
|
||||
spu_flush_all_slbs(mm);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(demote_segment_4k);
|
||||
#endif /* CONFIG_PPC_64K_PAGES */
|
||||
|
||||
/* Result code is:
|
||||
* 0 - handled
|
||||
@@ -646,7 +648,11 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
|
||||
return 1;
|
||||
}
|
||||
vsid = get_vsid(mm->context.id, ea);
|
||||
#ifdef CONFIG_PPC_MM_SLICES
|
||||
psize = get_slice_psize(mm, ea);
|
||||
#else
|
||||
psize = mm->context.user_psize;
|
||||
#endif
|
||||
break;
|
||||
case VMALLOC_REGION_ID:
|
||||
mm = &init_mm;
|
||||
@@ -674,11 +680,22 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
|
||||
if (user_region && cpus_equal(mm->cpu_vm_mask, tmp))
|
||||
local = 1;
|
||||
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
/* Handle hugepage regions */
|
||||
if (unlikely(in_hugepage_area(mm->context, ea))) {
|
||||
if (HPAGE_SHIFT && psize == mmu_huge_psize) {
|
||||
DBG_LOW(" -> huge page !\n");
|
||||
return hash_huge_page(mm, access, ea, vsid, local, trap);
|
||||
}
|
||||
#endif /* CONFIG_HUGETLB_PAGE */
|
||||
|
||||
#ifndef CONFIG_PPC_64K_PAGES
|
||||
/* If we use 4K pages and our psize is not 4K, then we are hitting
|
||||
* a special driver mapping, we need to align the address before
|
||||
* we fetch the PTE
|
||||
*/
|
||||
if (psize != MMU_PAGE_4K)
|
||||
ea &= ~((1ul << mmu_psize_defs[psize].shift) - 1);
|
||||
#endif /* CONFIG_PPC_64K_PAGES */
|
||||
|
||||
/* Get PTE and page size from page tables */
|
||||
ptep = find_linux_pte(pgdir, ea);
|
||||
@@ -702,54 +719,56 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
|
||||
}
|
||||
|
||||
/* Do actual hashing */
|
||||
#ifndef CONFIG_PPC_64K_PAGES
|
||||
rc = __hash_page_4K(ea, access, vsid, ptep, trap, local);
|
||||
#else
|
||||
#ifdef CONFIG_PPC_64K_PAGES
|
||||
/* If _PAGE_4K_PFN is set, make sure this is a 4k segment */
|
||||
if (pte_val(*ptep) & _PAGE_4K_PFN) {
|
||||
demote_segment_4k(mm, ea);
|
||||
psize = MMU_PAGE_4K;
|
||||
}
|
||||
|
||||
if (mmu_ci_restrictions) {
|
||||
/* If this PTE is non-cacheable, switch to 4k */
|
||||
if (psize == MMU_PAGE_64K &&
|
||||
(pte_val(*ptep) & _PAGE_NO_CACHE)) {
|
||||
if (user_region) {
|
||||
demote_segment_4k(mm, ea);
|
||||
psize = MMU_PAGE_4K;
|
||||
} else if (ea < VMALLOC_END) {
|
||||
/*
|
||||
* some driver did a non-cacheable mapping
|
||||
* in vmalloc space, so switch vmalloc
|
||||
* to 4k pages
|
||||
*/
|
||||
printk(KERN_ALERT "Reducing vmalloc segment "
|
||||
"to 4kB pages because of "
|
||||
"non-cacheable mapping\n");
|
||||
psize = mmu_vmalloc_psize = MMU_PAGE_4K;
|
||||
}
|
||||
/* If this PTE is non-cacheable and we have restrictions on
|
||||
* using non cacheable large pages, then we switch to 4k
|
||||
*/
|
||||
if (mmu_ci_restrictions && psize == MMU_PAGE_64K &&
|
||||
(pte_val(*ptep) & _PAGE_NO_CACHE)) {
|
||||
if (user_region) {
|
||||
demote_segment_4k(mm, ea);
|
||||
psize = MMU_PAGE_4K;
|
||||
} else if (ea < VMALLOC_END) {
|
||||
/*
|
||||
* some driver did a non-cacheable mapping
|
||||
* in vmalloc space, so switch vmalloc
|
||||
* to 4k pages
|
||||
*/
|
||||
printk(KERN_ALERT "Reducing vmalloc segment "
|
||||
"to 4kB pages because of "
|
||||
"non-cacheable mapping\n");
|
||||
psize = mmu_vmalloc_psize = MMU_PAGE_4K;
|
||||
#ifdef CONFIG_SPE_BASE
|
||||
spu_flush_all_slbs(mm);
|
||||
#endif
|
||||
}
|
||||
if (user_region) {
|
||||
if (psize != get_paca()->context.user_psize) {
|
||||
get_paca()->context = mm->context;
|
||||
slb_flush_and_rebolt();
|
||||
}
|
||||
} else if (get_paca()->vmalloc_sllp !=
|
||||
mmu_psize_defs[mmu_vmalloc_psize].sllp) {
|
||||
get_paca()->vmalloc_sllp =
|
||||
mmu_psize_defs[mmu_vmalloc_psize].sllp;
|
||||
}
|
||||
if (user_region) {
|
||||
if (psize != get_paca()->context.user_psize) {
|
||||
get_paca()->context.user_psize =
|
||||
mm->context.user_psize;
|
||||
slb_flush_and_rebolt();
|
||||
}
|
||||
} else if (get_paca()->vmalloc_sllp !=
|
||||
mmu_psize_defs[mmu_vmalloc_psize].sllp) {
|
||||
get_paca()->vmalloc_sllp =
|
||||
mmu_psize_defs[mmu_vmalloc_psize].sllp;
|
||||
slb_flush_and_rebolt();
|
||||
}
|
||||
#endif /* CONFIG_PPC_64K_PAGES */
|
||||
|
||||
#ifdef CONFIG_PPC_HAS_HASH_64K
|
||||
if (psize == MMU_PAGE_64K)
|
||||
rc = __hash_page_64K(ea, access, vsid, ptep, trap, local);
|
||||
else
|
||||
#endif /* CONFIG_PPC_HAS_HASH_64K */
|
||||
rc = __hash_page_4K(ea, access, vsid, ptep, trap, local);
|
||||
#endif /* CONFIG_PPC_64K_PAGES */
|
||||
|
||||
#ifndef CONFIG_PPC_64K_PAGES
|
||||
DBG_LOW(" o-pte: %016lx\n", pte_val(*ptep));
|
||||
@@ -772,42 +791,55 @@ void hash_preload(struct mm_struct *mm, unsigned long ea,
|
||||
unsigned long flags;
|
||||
int local = 0;
|
||||
|
||||
/* We don't want huge pages prefaulted for now
|
||||
*/
|
||||
if (unlikely(in_hugepage_area(mm->context, ea)))
|
||||
BUG_ON(REGION_ID(ea) != USER_REGION_ID);
|
||||
|
||||
#ifdef CONFIG_PPC_MM_SLICES
|
||||
/* We only prefault standard pages for now */
|
||||
if (unlikely(get_slice_psize(mm, ea) != mm->context.user_psize));
|
||||
return;
|
||||
#endif
|
||||
|
||||
DBG_LOW("hash_preload(mm=%p, mm->pgdir=%p, ea=%016lx, access=%lx,"
|
||||
" trap=%lx\n", mm, mm->pgd, ea, access, trap);
|
||||
|
||||
/* Get PTE, VSID, access mask */
|
||||
/* Get Linux PTE if available */
|
||||
pgdir = mm->pgd;
|
||||
if (pgdir == NULL)
|
||||
return;
|
||||
ptep = find_linux_pte(pgdir, ea);
|
||||
if (!ptep)
|
||||
return;
|
||||
|
||||
#ifdef CONFIG_PPC_64K_PAGES
|
||||
/* If either _PAGE_4K_PFN or _PAGE_NO_CACHE is set (and we are on
|
||||
* a 64K kernel), then we don't preload, hash_page() will take
|
||||
* care of it once we actually try to access the page.
|
||||
* That way we don't have to duplicate all of the logic for segment
|
||||
* page size demotion here
|
||||
*/
|
||||
if (pte_val(*ptep) & (_PAGE_4K_PFN | _PAGE_NO_CACHE))
|
||||
return;
|
||||
#endif /* CONFIG_PPC_64K_PAGES */
|
||||
|
||||
/* Get VSID */
|
||||
vsid = get_vsid(mm->context.id, ea);
|
||||
|
||||
/* Hash it in */
|
||||
/* Hash doesn't like irqs */
|
||||
local_irq_save(flags);
|
||||
|
||||
/* Is that local to this CPU ? */
|
||||
mask = cpumask_of_cpu(smp_processor_id());
|
||||
if (cpus_equal(mm->cpu_vm_mask, mask))
|
||||
local = 1;
|
||||
#ifndef CONFIG_PPC_64K_PAGES
|
||||
__hash_page_4K(ea, access, vsid, ptep, trap, local);
|
||||
#else
|
||||
if (mmu_ci_restrictions) {
|
||||
/* If this PTE is non-cacheable, switch to 4k */
|
||||
if (mm->context.user_psize == MMU_PAGE_64K &&
|
||||
(pte_val(*ptep) & _PAGE_NO_CACHE))
|
||||
demote_segment_4k(mm, ea);
|
||||
}
|
||||
|
||||
/* Hash it in */
|
||||
#ifdef CONFIG_PPC_HAS_HASH_64K
|
||||
if (mm->context.user_psize == MMU_PAGE_64K)
|
||||
__hash_page_64K(ea, access, vsid, ptep, trap, local);
|
||||
else
|
||||
__hash_page_4K(ea, access, vsid, ptep, trap, local);
|
||||
#endif /* CONFIG_PPC_64K_PAGES */
|
||||
__hash_page_4K(ea, access, vsid, ptep, trap, local);
|
||||
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -146,21 +146,16 @@ static void zero_ctor(void *addr, struct kmem_cache *cache, unsigned long flags)
|
||||
memset(addr, 0, kmem_cache_size(cache));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC_64K_PAGES
|
||||
static const unsigned int pgtable_cache_size[3] = {
|
||||
PTE_TABLE_SIZE, PMD_TABLE_SIZE, PGD_TABLE_SIZE
|
||||
};
|
||||
static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = {
|
||||
"pte_pmd_cache", "pmd_cache", "pgd_cache",
|
||||
};
|
||||
#else
|
||||
static const unsigned int pgtable_cache_size[2] = {
|
||||
PTE_TABLE_SIZE, PMD_TABLE_SIZE
|
||||
PGD_TABLE_SIZE, PMD_TABLE_SIZE
|
||||
};
|
||||
static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = {
|
||||
"pgd_pte_cache", "pud_pmd_cache",
|
||||
};
|
||||
#ifdef CONFIG_PPC_64K_PAGES
|
||||
"pgd_cache", "pmd_cache",
|
||||
#else
|
||||
"pgd_cache", "pud_pmd_cache",
|
||||
#endif /* CONFIG_PPC_64K_PAGES */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
/* Hugepages need one extra cache, initialized in hugetlbpage.c. We
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/initrd.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/suspend.h>
|
||||
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/prom.h>
|
||||
@@ -276,6 +277,28 @@ void __init do_init_bootmem(void)
|
||||
init_bootmem_done = 1;
|
||||
}
|
||||
|
||||
/* mark pages that don't exist as nosave */
|
||||
static int __init mark_nonram_nosave(void)
|
||||
{
|
||||
unsigned long lmb_next_region_start_pfn,
|
||||
lmb_region_max_pfn;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < lmb.memory.cnt - 1; i++) {
|
||||
lmb_region_max_pfn =
|
||||
(lmb.memory.region[i].base >> PAGE_SHIFT) +
|
||||
(lmb.memory.region[i].size >> PAGE_SHIFT);
|
||||
lmb_next_region_start_pfn =
|
||||
lmb.memory.region[i+1].base >> PAGE_SHIFT;
|
||||
|
||||
if (lmb_region_max_pfn < lmb_next_region_start_pfn)
|
||||
register_nosave_region(lmb_region_max_pfn,
|
||||
lmb_next_region_start_pfn);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* paging_init() sets up the page tables - in fact we've already done this.
|
||||
*/
|
||||
@@ -307,6 +330,8 @@ void __init paging_init(void)
|
||||
max_zone_pfns[ZONE_DMA] = top_of_ram >> PAGE_SHIFT;
|
||||
#endif
|
||||
free_area_init_nodes(max_zone_pfns);
|
||||
|
||||
mark_nonram_nosave();
|
||||
}
|
||||
#endif /* ! CONFIG_NEED_MULTIPLE_NODES */
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
|
||||
{
|
||||
int index;
|
||||
int err;
|
||||
int new_context = (mm->context.id == 0);
|
||||
|
||||
again:
|
||||
if (!idr_pre_get(&mmu_context_idr, GFP_KERNEL))
|
||||
@@ -50,9 +51,18 @@ again:
|
||||
}
|
||||
|
||||
mm->context.id = index;
|
||||
#ifdef CONFIG_PPC_MM_SLICES
|
||||
/* The old code would re-promote on fork, we don't do that
|
||||
* when using slices as it could cause problem promoting slices
|
||||
* that have been forced down to 4K
|
||||
*/
|
||||
if (new_context)
|
||||
slice_set_user_psize(mm, mmu_virtual_psize);
|
||||
#else
|
||||
mm->context.user_psize = mmu_virtual_psize;
|
||||
mm->context.sllp = SLB_VSID_USER |
|
||||
mmu_psize_defs[mmu_virtual_psize].sllp;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@ void hash_preload(struct mm_struct *mm, unsigned long ea,
|
||||
|
||||
if (Hash == 0)
|
||||
return;
|
||||
pmd = pmd_offset(pgd_offset(mm, ea), ea);
|
||||
pmd = pmd_offset(pud_offset(pgd_offset(mm, ea), ea), ea);
|
||||
if (!pmd_none(*pmd))
|
||||
add_hash_page(mm->context.id, ea, pmd_val(*pmd));
|
||||
}
|
||||
|
||||
@@ -198,12 +198,6 @@ void slb_initialize(void)
|
||||
static int slb_encoding_inited;
|
||||
extern unsigned int *slb_miss_kernel_load_linear;
|
||||
extern unsigned int *slb_miss_kernel_load_io;
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
extern unsigned int *slb_miss_user_load_huge;
|
||||
unsigned long huge_llp;
|
||||
|
||||
huge_llp = mmu_psize_defs[mmu_huge_psize].sllp;
|
||||
#endif
|
||||
|
||||
/* Prepare our SLB miss handler based on our page size */
|
||||
linear_llp = mmu_psize_defs[mmu_linear_psize].sllp;
|
||||
@@ -220,11 +214,6 @@ void slb_initialize(void)
|
||||
|
||||
DBG("SLB: linear LLP = %04x\n", linear_llp);
|
||||
DBG("SLB: io LLP = %04x\n", io_llp);
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
patch_slb_encoding(slb_miss_user_load_huge,
|
||||
SLB_VSID_USER | huge_llp);
|
||||
DBG("SLB: huge LLP = %04x\n", huge_llp);
|
||||
#endif
|
||||
}
|
||||
|
||||
get_paca()->stab_rr = SLB_NUM_BOLTED;
|
||||
|
||||
+33
-19
@@ -82,31 +82,45 @@ _GLOBAL(slb_miss_kernel_load_io)
|
||||
srdi. r9,r10,USER_ESID_BITS
|
||||
bne- 8f /* invalid ea bits set */
|
||||
|
||||
/* Figure out if the segment contains huge pages */
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
BEGIN_FTR_SECTION
|
||||
b 1f
|
||||
END_FTR_SECTION_IFCLR(CPU_FTR_16M_PAGE)
|
||||
|
||||
/* when using slices, we extract the psize off the slice bitmaps
|
||||
* and then we need to get the sllp encoding off the mmu_psize_defs
|
||||
* array.
|
||||
*
|
||||
* XXX This is a bit inefficient especially for the normal case,
|
||||
* so we should try to implement a fast path for the standard page
|
||||
* size using the old sllp value so we avoid the array. We cannot
|
||||
* really do dynamic patching unfortunately as processes might flip
|
||||
* between 4k and 64k standard page size
|
||||
*/
|
||||
#ifdef CONFIG_PPC_MM_SLICES
|
||||
cmpldi r10,16
|
||||
|
||||
lhz r9,PACALOWHTLBAREAS(r13)
|
||||
mr r11,r10
|
||||
/* Get the slice index * 4 in r11 and matching slice size mask in r9 */
|
||||
ld r9,PACALOWSLICESPSIZE(r13)
|
||||
sldi r11,r10,2
|
||||
blt 5f
|
||||
ld r9,PACAHIGHSLICEPSIZE(r13)
|
||||
srdi r11,r10,(SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT - 2)
|
||||
andi. r11,r11,0x3c
|
||||
|
||||
lhz r9,PACAHIGHHTLBAREAS(r13)
|
||||
srdi r11,r10,(HTLB_AREA_SHIFT-SID_SHIFT)
|
||||
|
||||
5: srd r9,r9,r11
|
||||
andi. r9,r9,1
|
||||
beq 1f
|
||||
_GLOBAL(slb_miss_user_load_huge)
|
||||
li r11,0
|
||||
b 2f
|
||||
1:
|
||||
#endif /* CONFIG_HUGETLB_PAGE */
|
||||
5: /* Extract the psize and multiply to get an array offset */
|
||||
srd r9,r9,r11
|
||||
andi. r9,r9,0xf
|
||||
mulli r9,r9,MMUPSIZEDEFSIZE
|
||||
|
||||
/* Now get to the array and obtain the sllp
|
||||
*/
|
||||
ld r11,PACATOC(r13)
|
||||
ld r11,mmu_psize_defs@got(r11)
|
||||
add r11,r11,r9
|
||||
ld r11,MMUPSIZESLLP(r11)
|
||||
ori r11,r11,SLB_VSID_USER
|
||||
#else
|
||||
/* paca context sllp already contains the SLB_VSID_USER bits */
|
||||
lhz r11,PACACONTEXTSLLP(r13)
|
||||
2:
|
||||
#endif /* CONFIG_PPC_MM_SLICES */
|
||||
|
||||
ld r9,PACACONTEXTID(r13)
|
||||
rldimi r10,r9,USER_ESID_BITS,0
|
||||
b slb_finish_load
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -111,7 +111,7 @@ static void flush_range(struct mm_struct *mm, unsigned long start,
|
||||
if (start >= end)
|
||||
return;
|
||||
end = (end - 1) | ~PAGE_MASK;
|
||||
pmd = pmd_offset(pgd_offset(mm, start), start);
|
||||
pmd = pmd_offset(pud_offset(pgd_offset(mm, start), start), start);
|
||||
for (;;) {
|
||||
pmd_end = ((start + PGDIR_SIZE) & PGDIR_MASK) - 1;
|
||||
if (pmd_end > end)
|
||||
@@ -169,7 +169,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
|
||||
return;
|
||||
}
|
||||
mm = (vmaddr < TASK_SIZE)? vma->vm_mm: &init_mm;
|
||||
pmd = pmd_offset(pgd_offset(mm, vmaddr), vmaddr);
|
||||
pmd = pmd_offset(pud_offset(pgd_offset(mm, vmaddr), vmaddr), vmaddr);
|
||||
if (!pmd_none(*pmd))
|
||||
flush_hash_pages(mm->context.id, vmaddr, pmd_val(*pmd), 1);
|
||||
FINISH_FLUSH;
|
||||
|
||||
@@ -143,16 +143,22 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
|
||||
*/
|
||||
addr &= PAGE_MASK;
|
||||
|
||||
/* Get page size (maybe move back to caller) */
|
||||
/* Get page size (maybe move back to caller).
|
||||
*
|
||||
* NOTE: when using special 64K mappings in 4K environment like
|
||||
* for SPEs, we obtain the page size from the slice, which thus
|
||||
* must still exist (and thus the VMA not reused) at the time
|
||||
* of this call
|
||||
*/
|
||||
if (huge) {
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
psize = mmu_huge_psize;
|
||||
#else
|
||||
BUG();
|
||||
psize = pte_pagesize_index(pte); /* shutup gcc */
|
||||
psize = pte_pagesize_index(mm, addr, pte); /* shutup gcc */
|
||||
#endif
|
||||
} else
|
||||
psize = pte_pagesize_index(pte);
|
||||
psize = pte_pagesize_index(mm, addr, pte);
|
||||
|
||||
/* Build full vaddr */
|
||||
if (!is_kernel_addr(addr)) {
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/pci-bridge.h>
|
||||
#include <asm-powerpc/mpic.h>
|
||||
#include <asm/mpc86xx.h>
|
||||
|
||||
@@ -35,6 +35,21 @@ config SPU_FS
|
||||
Units on machines implementing the Broadband Processor
|
||||
Architecture.
|
||||
|
||||
config SPU_FS_64K_LS
|
||||
bool "Use 64K pages to map SPE local store"
|
||||
# we depend on PPC_MM_SLICES for now rather than selecting
|
||||
# it because we depend on hugetlbfs hooks being present. We
|
||||
# will fix that when the generic code has been improved to
|
||||
# not require hijacking hugetlbfs hooks.
|
||||
depends on SPU_FS && PPC_MM_SLICES && !PPC_64K_PAGES
|
||||
default y
|
||||
select PPC_HAS_HASH_64K
|
||||
help
|
||||
This option causes SPE local stores to be mapped in process
|
||||
address spaces using 64K pages while the rest of the kernel
|
||||
uses 4K pages. This can improve performances of applications
|
||||
using multiple SPEs by lowering the TLB pressure on them.
|
||||
|
||||
config SPU_BASE
|
||||
bool
|
||||
default n
|
||||
|
||||
@@ -144,12 +144,11 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
|
||||
|
||||
switch(REGION_ID(ea)) {
|
||||
case USER_REGION_ID:
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
if (in_hugepage_area(mm->context, ea))
|
||||
psize = mmu_huge_psize;
|
||||
else
|
||||
#ifdef CONFIG_PPC_MM_SLICES
|
||||
psize = get_slice_psize(mm, ea);
|
||||
#else
|
||||
psize = mm->context.user_psize;
|
||||
#endif
|
||||
psize = mm->context.user_psize;
|
||||
vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) |
|
||||
SLB_VSID_USER;
|
||||
break;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
obj-y += switch.o fault.o
|
||||
obj-y += switch.o fault.o lscsa_alloc.o
|
||||
|
||||
obj-$(CONFIG_SPU_FS) += spufs.o
|
||||
spufs-y += inode.o file.o context.o syscalls.o coredump.o
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user