diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-31 00:01:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-31 00:01:36 -0400 |
commit | bad60e6f259a01cf9f29a1ef8d435ab6c60b2de9 (patch) | |
tree | c9aaa8166735659761239c117af2b11b022bc6cb /arch/powerpc/mm | |
parent | dd0f0cf58af70dc9267409f113bea772d57f675c (diff) | |
parent | 719dbb2df78fc9a40e28392b07cd715bfc5a665c (diff) |
Merge tag 'powerpc-4.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
Pull powerpc updates from Michael Ellerman:
"Highlights:
- PowerNV PCI hotplug support.
- Lots more Power9 support.
- eBPF JIT support on ppc64le.
- Lots of cxl updates.
- Boot code consolidation.
Bug fixes:
- Fix spin_unlock_wait() from Boqun Feng
- Fix stack pointer corruption in __tm_recheckpoint() from Michael
Neuling
- Fix multiple bugs in memory_hotplug_max() from Bharata B Rao
- mm: Ensure "special" zones are empty from Oliver O'Halloran
- ftrace: Separate the heuristics for checking call sites from
Michael Ellerman
- modules: Never restore r2 for a mprofile-kernel style mcount() call
from Michael Ellerman
- Fix endianness when reading TCEs from Alexey Kardashevskiy
- start rtasd before PCI probing from Greg Kurz
- PCI: rpaphp: Fix slot registration for multiple slots under a PHB
from Tyrel Datwyler
- powerpc/mm: Add memory barrier in __hugepte_alloc() from Sukadev
Bhattiprolu
Cleanups & fixes:
- Drop support for MPIC in pseries from Rashmica Gupta
- Define and use PPC64_ELF_ABI_v2/v1 from Michael Ellerman
- Remove unused symbols in asm-offsets.c from Rashmica Gupta
- Fix SRIOV not building without EEH enabled from Russell Currey
- Remove kretprobe_trampoline_holder from Thiago Jung Bauermann
- Reduce log level of PCI I/O space warning from Benjamin
Herrenschmidt
- Add array bounds checking to crash_shutdown_handlers from Suraj
Jitindar Singh
- Avoid -maltivec when using clang integrated assembler from Anton
Blanchard
- Fix array overrun in ppc_rtas() syscall from Andrew Donnellan
- Fix error return value in cmm_mem_going_offline() from Rasmus
Villemoes
- export cpu_to_core_id() from Mauricio Faria de Oliveira
- Remove old symbols from defconfigs from Andrew Donnellan
- Update obsolete comments in setup_32.c about entry conditions from
Benjamin Herrenschmidt
- Add comment explaining the purpose of setup_kdump_trampoline() from
Benjamin Herrenschmidt
- Merge the RELOCATABLE config entries for ppc32 and ppc64 from Kevin
Hao
- Remove RELOCATABLE_PPC32 from Kevin Hao
- Fix .long's in tlb-radix.c to more meaningful from Balbir Singh
Minor cleanups & fixes:
- Andrew Donnellan, Anna-Maria Gleixner, Anton Blanchard, Benjamin
Herrenschmidt, Bharata B Rao, Christophe Leroy, Colin Ian King,
Geliang Tang, Greg Kurz, Madhavan Srinivasan, Michael Ellerman,
Michael Ellerman, Stephen Rothwell, Stewart Smith.
Freescale updates from Scott:
- "Highlights include more 8xx optimizations, device tree updates,
and MVME7100 support."
PowerNV PCI hotplug from Gavin Shan:
- PCI: Add pcibios_setup_bridge()
- Override pcibios_setup_bridge()
- Remove PCI_RESET_DELAY_US
- Move pnv_pci_ioda_setup_opal_tce_kill() around
- Increase PE# capacity
- Allocate PE# in reverse order
- Create PEs in pcibios_setup_bridge()
- Setup PE for root bus
- Extend PCI bridge resources
- Make pnv_ioda_deconfigure_pe() visible
- Dynamically release PE
- Update bridge windows on PCI plug
- Delay populating pdn
- Support PCI slot ID
- Use PCI slot reset infrastructure
- Introduce pnv_pci_get_slot_id()
- Functions to get/set PCI slot state
- PCI/hotplug: PowerPC PowerNV PCI hotplug driver
- Print correct PHB type names
Power9 idle support from Shreyas B. Prabhu:
- set power_save func after the idle states are initialized
- Use PNV_THREAD_WINKLE macro while requesting for winkle
- make hypervisor state restore a function
- Rename idle_power7.S to idle_book3s.S
- Rename reusable idle functions to hardware agnostic names
- Make pnv_powersave_common more generic
- abstraction for saving SPRs before entering deep idle states
- Add platform support for stop instruction
- cpuidle/powernv: Use CPUIDLE_STATE_MAX instead of MAX_POWERNV_IDLE_STATES
- cpuidle/powernv: cleanup cpuidle-powernv.c
- cpuidle/powernv: Add support for POWER ISA v3 idle states
- Use deepest stop state when cpu is offlined
Power9 PMU from Madhavan Srinivasan:
- factor out power8 pmu macros and defines
- factor out power8 pmu functions
- factor out power8 __init_pmu code
- Add power9 event list macros for generic and cache events
- Power9 PMU support
- Export Power9 generic and cache events to sysfs
Power9 preliminary interrupt & PCI support from Benjamin Herrenschmidt:
- Add XICS emulation APIs
- Move a few exception common handlers to make room
- Add support for HV virtualization interrupts
- Add mechanism to force a replay of interrupts
- Add ICP OPAL backend
- Discover IODA3 PHBs
- pci: Remove obsolete SW invalidate
- opal: Add real mode call wrappers
- Rename TCE invalidation calls
- Remove SWINV constants and obsolete TCE code
- Rework accessing the TCE invalidate register
- Fallback to OPAL for TCE invalidations
- Use the device-tree to get available range of M64's
- Check status of a PHB before using it
- pci: Don't try to allocate resources that will be reassigned
Other Power9:
- Send SIGBUS on unaligned copy and paste from Chris Smart
- Large Decrementer support from Oliver O'Halloran
- Load Monitor Register Support from Jack Miller
Performance improvements from Anton Blanchard:
- Avoid load hit store in __giveup_fpu() and __giveup_altivec()
- Avoid load hit store in setup_sigcontext()
- Remove assembly versions of strcpy, strcat, strlen and strcmp
- Align hot loops of some string functions
eBPF JIT from Naveen N. Rao:
- Fix/enhance 32-bit Load Immediate implementation
- Optimize 64-bit Immediate loads
- Introduce rotate immediate instructions
- A few cleanups
- Isolate classic BPF JIT specifics into a separate header
- Implement JIT compiler for extended BPF
Operator Panel driver from Suraj Jitindar Singh:
- devicetree/bindings: Add binding for operator panel on FSP machines
- Add inline function to get rc from an ASYNC_COMP opal_msg
- Add driver for operator panel on FSP machines
Sparse fixes from Daniel Axtens:
- make some things static
- Introduce asm-prototypes.h
- Include headers containing prototypes
- Use #ifdef __BIG_ENDIAN__ #else for REG_BYTE
- kvm: Clarify __user annotations
- Pass endianness to sparse
- Make ppc_md.{halt, restart} __noreturn
MM fixes & cleanups from Aneesh Kumar K.V:
- radix: Update LPCR HR bit as per ISA
- use _raw variant of page table accessors
- Compile out radix related functions if RADIX_MMU is disabled
- Clear top 16 bits of va only on older cpus
- Print formation regarding the the MMU mode
- hash: Update SDR1 size encoding as documented in ISA 3.0
- radix: Update PID switch sequence
- radix: Update machine call back to support new HCALL.
- radix: Add LPID based tlb flush helpers
- radix: Add a kernel command line to disable radix
- Cleanup LPCR defines
Boot code consolidation from Benjamin Herrenschmidt:
- Move epapr_paravirt_early_init() to early_init_devtree()
- cell: Don't use flat device-tree after boot
- ge_imp3a: Don't use the flat device-tree after boot
- mpc85xx_ds: Don't use the flat device-tree after boot
- mpc85xx_rdb: Don't use the flat device-tree after boot
- Don't test for machine type in rtas_initialize()
- Don't test for machine type in smp_setup_cpu_maps()
- dt: Add of_device_compatible_match()
- Factor do_feature_fixup calls
- Move 64-bit feature fixup earlier
- Move 64-bit memory reserves to setup_arch()
- Use a cachable DART
- Move FW feature probing out of pseries probe()
- Put exception configuration in a common place
- Remove early allocation of the SMU command buffer
- Move MMU backend selection out of platform code
- pasemi: Remove IOBMAP allocation from platform probe()
- mm/hash: Don't use machine_is() early during boot
- Don't test for machine type to detect HEA special case
- pmac: Remove spurrious machine type test
- Move hash table ops to a separate structure
- Ensure that ppc_md is empty before probing for machine type
- Move 64-bit probe_machine() to later in the boot process
- Move 32-bit probe() machine to later in the boot process
- Get rid of ppc_md.init_early()
- Move the boot time info banner to a separate function
- Move setting of {i,d}cache_bsize to initialize_cache_info()
- Move the content of setup_system() to setup_arch()
- Move cache info inits to a separate function
- Re-order the call to smp_setup_cpu_maps()
- Re-order setup_panic()
- Make a few boot functions __init
- Merge 32-bit and 64-bit setup_arch()
Other new features:
- tty/hvc: Use IRQF_SHARED for OPAL hvc consoles from Sam Mendoza-Jonas
- tty/hvc: Use opal irqchip interface if available from Sam Mendoza-Jonas
- powerpc: Add module autoloading based on CPU features from Alastair D'Silva
- crypto: vmx - Convert to CPU feature based module autoloading from Alastair D'Silva
- Wake up kopald polling thread before waiting for events from Benjamin Herrenschmidt
- xmon: Dump ISA 2.06 SPRs from Michael Ellerman
- xmon: Dump ISA 2.07 SPRs from Michael Ellerman
- Add a parameter to disable 1TB segs from Oliver O'Halloran
- powerpc/boot: Add OPAL console to epapr wrappers from Oliver O'Halloran
- Assign fixed PHB number based on device-tree properties from Guilherme G. Piccoli
- pseries: Add pseries hotplug workqueue from John Allen
- pseries: Add support for hotplug interrupt source from John Allen
- pseries: Use kernel hotplug queue for PowerVM hotplug events from John Allen
- pseries: Move property cloning into its own routine from Nathan Fontenot
- pseries: Dynamic add entires to associativity lookup array from Nathan Fontenot
- pseries: Auto-online hotplugged memory from Nathan Fontenot
- pseries: Remove call to memblock_add() from Nathan Fontenot
cxl:
- Add set and get private data to context struct from Michael Neuling
- make base more explicitly non-modular from Paul Gortmaker
- Use for_each_compatible_node() macro from Wei Yongjun
- Frederic Barrat
- Abstract the differences between the PSL and XSL
- Make vPHB device node match adapter's
- Philippe Bergheaud
- Add mechanism for delivering AFU driver specific events
- Ignore CAPI adapters misplaced in switched slots
- Refine slice error debug messages
- Andrew Donnellan
- static-ify variables to fix sparse warnings
- PCI/hotplug: pnv_php: export symbols and move struct types needed by cxl
- PCI/hotplug: pnv_php: handle OPAL_PCI_SLOT_OFFLINE power state
- Add cxl_check_and_switch_mode() API to switch bi-modal cards
- remove dead Kconfig options
- fix potential NULL dereference in free_adapter()
- Ian Munsie
- Update process element after allocating interrupts
- Add support for CAPP DMA mode
- Fix allowing bogus AFU descriptors with 0 maximum processes
- Fix allocating a minimum of 2 pages for the SPA
- Fix bug where AFU disable operation had no effect
- Workaround XSL bug that does not clear the RA bit after a reset
- Fix NULL pointer dereference on kernel contexts with no AFU interrupts
- powerpc/powernv: Split cxl code out into a separate file
- Add cxl_slot_is_supported API
- Enable bus mastering for devices using CAPP DMA mode
- Move cxl_afu_get / cxl_afu_put to base
- Allow a default context to be associated with an external pci_dev
- Do not create vPHB if there are no AFU configuration records
- powerpc/powernv: Add support for the cxl kernel api on the real phb
- Add support for using the kernel API with a real PHB
- Add kernel APIs to get & set the max irqs per context
- Add preliminary workaround for CX4 interrupt limitation
- Add support for interrupts on the Mellanox CX4
- Workaround PE=0 hardware limitation in Mellanox CX4
- powerpc/powernv: Fix pci-cxl.c build when CONFIG_MODULES=n
selftests:
- Test unaligned copy and paste from Chris Smart
- Load Monitor Register Tests from Jack Miller
- Cyril Bur
- exec() with suspended transaction
- Use signed long to read perf_event_paranoid
- Fix usage message in context_switch
- Fix generation of vector instructions/types in context_switch
- Michael Ellerman
- Use "Delta" rather than "Error" in normal output
- Import Anton's mmap & futex micro benchmarks
- Add a test for PROT_SAO"
* tag 'powerpc-4.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: (263 commits)
powerpc/mm: Parenthesise IS_ENABLED() in if condition
tty/hvc: Use opal irqchip interface if available
tty/hvc: Use IRQF_SHARED for OPAL hvc consoles
selftests/powerpc: exec() with suspended transaction
powerpc: Improve comment explaining why we modify VRSAVE
powerpc/mm: Drop unused externs for hpte_init_beat[_v3]()
powerpc/mm: Rename hpte_init_lpar() and move the fallback to a header
powerpc/mm: Fix build break when PPC_NATIVE=n
crypto: vmx - Convert to CPU feature based module autoloading
powerpc: Add module autoloading based on CPU features
powerpc/powernv/ioda: Fix endianness when reading TCEs
powerpc/mm: Add memory barrier in __hugepte_alloc()
powerpc/modules: Never restore r2 for a mprofile-kernel style mcount() call
powerpc/ftrace: Separate the heuristics for checking call sites
powerpc: Merge 32-bit and 64-bit setup_arch()
powerpc/64: Make a few boot functions __init
powerpc: Re-order setup_panic()
powerpc: Re-order the call to smp_setup_cpu_maps()
powerpc/32: Move cache info inits to a separate function
powerpc/64: Move the content of setup_system() to setup_arch()
...
Diffstat (limited to 'arch/powerpc/mm')
-rw-r--r-- | arch/powerpc/mm/8xx_mmu.c | 131 | ||||
-rw-r--r-- | arch/powerpc/mm/hash64_4k.c | 18 | ||||
-rw-r--r-- | arch/powerpc/mm/hash64_64k.c | 39 | ||||
-rw-r--r-- | arch/powerpc/mm/hash_native_64.c | 36 | ||||
-rw-r--r-- | arch/powerpc/mm/hash_utils_64.c | 153 | ||||
-rw-r--r-- | arch/powerpc/mm/hugepage-hash64.c | 17 | ||||
-rw-r--r-- | arch/powerpc/mm/hugetlbpage-hash64.c | 4 | ||||
-rw-r--r-- | arch/powerpc/mm/hugetlbpage.c | 7 | ||||
-rw-r--r-- | arch/powerpc/mm/init_32.c | 5 | ||||
-rw-r--r-- | arch/powerpc/mm/mem.c | 18 | ||||
-rw-r--r-- | arch/powerpc/mm/mmu_context_book3s64.c | 5 | ||||
-rw-r--r-- | arch/powerpc/mm/mmu_decl.h | 3 | ||||
-rw-r--r-- | arch/powerpc/mm/numa.c | 36 | ||||
-rw-r--r-- | arch/powerpc/mm/pgtable-radix.c | 17 | ||||
-rw-r--r-- | arch/powerpc/mm/tlb-radix.c | 65 |
15 files changed, 361 insertions, 193 deletions
diff --git a/arch/powerpc/mm/8xx_mmu.c b/arch/powerpc/mm/8xx_mmu.c index 949100577db5..6c5025e81236 100644 --- a/arch/powerpc/mm/8xx_mmu.c +++ b/arch/powerpc/mm/8xx_mmu.c | |||
@@ -13,62 +13,115 @@ | |||
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/memblock.h> | 15 | #include <linux/memblock.h> |
16 | #include <asm/fixmap.h> | ||
17 | #include <asm/code-patching.h> | ||
16 | 18 | ||
17 | #include "mmu_decl.h" | 19 | #include "mmu_decl.h" |
18 | 20 | ||
21 | #define IMMR_SIZE (FIX_IMMR_SIZE << PAGE_SHIFT) | ||
22 | |||
19 | extern int __map_without_ltlbs; | 23 | extern int __map_without_ltlbs; |
24 | |||
20 | /* | 25 | /* |
21 | * MMU_init_hw does the chip-specific initialization of the MMU hardware. | 26 | * Return PA for this VA if it is in IMMR area, or 0 |
22 | */ | 27 | */ |
23 | void __init MMU_init_hw(void) | 28 | phys_addr_t v_block_mapped(unsigned long va) |
24 | { | 29 | { |
25 | /* Nothing to do for the time being but keep it similar to other PPC */ | 30 | unsigned long p = PHYS_IMMR_BASE; |
31 | |||
32 | if (__map_without_ltlbs) | ||
33 | return 0; | ||
34 | if (va >= VIRT_IMMR_BASE && va < VIRT_IMMR_BASE + IMMR_SIZE) | ||
35 | return p + va - VIRT_IMMR_BASE; | ||
36 | return 0; | ||
37 | } | ||
38 | |||
39 | /* | ||
40 | * Return VA for a given PA or 0 if not mapped | ||
41 | */ | ||
42 | unsigned long p_block_mapped(phys_addr_t pa) | ||
43 | { | ||
44 | unsigned long p = PHYS_IMMR_BASE; | ||
45 | |||
46 | if (__map_without_ltlbs) | ||
47 | return 0; | ||
48 | if (pa >= p && pa < p + IMMR_SIZE) | ||
49 | return VIRT_IMMR_BASE + pa - p; | ||
50 | return 0; | ||
26 | } | 51 | } |
27 | 52 | ||
28 | #define LARGE_PAGE_SIZE_4M (1<<22) | ||
29 | #define LARGE_PAGE_SIZE_8M (1<<23) | 53 | #define LARGE_PAGE_SIZE_8M (1<<23) |
30 | #define LARGE_PAGE_SIZE_64M (1<<26) | ||
31 | 54 | ||
32 | unsigned long __init mmu_mapin_ram(unsigned long top) | 55 | /* |
56 | * MMU_init_hw does the chip-specific initialization of the MMU hardware. | ||
57 | */ | ||
58 | void __init MMU_init_hw(void) | ||
33 | { | 59 | { |
34 | unsigned long v, s, mapped; | 60 | /* PIN up to the 3 first 8Mb after IMMR in DTLB table */ |
35 | phys_addr_t p; | 61 | #ifdef CONFIG_PIN_TLB |
62 | unsigned long ctr = mfspr(SPRN_MD_CTR) & 0xfe000000; | ||
63 | unsigned long flags = 0xf0 | MD_SPS16K | _PAGE_SHARED | _PAGE_DIRTY; | ||
64 | #ifdef CONFIG_PIN_TLB_IMMR | ||
65 | int i = 29; | ||
66 | #else | ||
67 | int i = 28; | ||
68 | #endif | ||
69 | unsigned long addr = 0; | ||
70 | unsigned long mem = total_lowmem; | ||
71 | |||
72 | for (; i < 32 && mem >= LARGE_PAGE_SIZE_8M; i++) { | ||
73 | mtspr(SPRN_MD_CTR, ctr | (i << 8)); | ||
74 | mtspr(SPRN_MD_EPN, (unsigned long)__va(addr) | MD_EVALID); | ||
75 | mtspr(SPRN_MD_TWC, MD_PS8MEG | MD_SVALID); | ||
76 | mtspr(SPRN_MD_RPN, addr | flags | _PAGE_PRESENT); | ||
77 | addr += LARGE_PAGE_SIZE_8M; | ||
78 | mem -= LARGE_PAGE_SIZE_8M; | ||
79 | } | ||
80 | #endif | ||
81 | } | ||
36 | 82 | ||
37 | v = KERNELBASE; | 83 | static void mmu_mapin_immr(void) |
38 | p = 0; | 84 | { |
39 | s = top; | 85 | unsigned long p = PHYS_IMMR_BASE; |
86 | unsigned long v = VIRT_IMMR_BASE; | ||
87 | unsigned long f = pgprot_val(PAGE_KERNEL_NCG); | ||
88 | int offset; | ||
40 | 89 | ||
41 | if (__map_without_ltlbs) | 90 | for (offset = 0; offset < IMMR_SIZE; offset += PAGE_SIZE) |
42 | return 0; | 91 | map_page(v + offset, p + offset, f); |
92 | } | ||
43 | 93 | ||
44 | #ifdef CONFIG_PPC_4K_PAGES | 94 | /* Address of instructions to patch */ |
45 | while (s >= LARGE_PAGE_SIZE_8M) { | 95 | #ifndef CONFIG_PIN_TLB_IMMR |
46 | pmd_t *pmdp; | 96 | extern unsigned int DTLBMiss_jmp; |
47 | unsigned long val = p | MD_PS8MEG; | 97 | #endif |
98 | extern unsigned int DTLBMiss_cmp, FixupDAR_cmp; | ||
48 | 99 | ||
49 | pmdp = pmd_offset(pud_offset(pgd_offset_k(v), v), v); | 100 | void mmu_patch_cmp_limit(unsigned int *addr, unsigned long mapped) |
50 | *pmdp++ = __pmd(val); | 101 | { |
51 | *pmdp++ = __pmd(val + LARGE_PAGE_SIZE_4M); | 102 | unsigned int instr = *addr; |
52 | 103 | ||
53 | v += LARGE_PAGE_SIZE_8M; | 104 | instr &= 0xffff0000; |
54 | p += LARGE_PAGE_SIZE_8M; | 105 | instr |= (unsigned long)__va(mapped) >> 16; |
55 | s -= LARGE_PAGE_SIZE_8M; | 106 | patch_instruction(addr, instr); |
56 | } | 107 | } |
57 | #else /* CONFIG_PPC_16K_PAGES */ | ||
58 | while (s >= LARGE_PAGE_SIZE_64M) { | ||
59 | pmd_t *pmdp; | ||
60 | unsigned long val = p | MD_PS8MEG; | ||
61 | 108 | ||
62 | pmdp = pmd_offset(pud_offset(pgd_offset_k(v), v), v); | 109 | unsigned long __init mmu_mapin_ram(unsigned long top) |
63 | *pmdp++ = __pmd(val); | 110 | { |
111 | unsigned long mapped; | ||
64 | 112 | ||
65 | v += LARGE_PAGE_SIZE_64M; | 113 | if (__map_without_ltlbs) { |
66 | p += LARGE_PAGE_SIZE_64M; | 114 | mapped = 0; |
67 | s -= LARGE_PAGE_SIZE_64M; | 115 | mmu_mapin_immr(); |
68 | } | 116 | #ifndef CONFIG_PIN_TLB_IMMR |
117 | patch_instruction(&DTLBMiss_jmp, PPC_INST_NOP); | ||
69 | #endif | 118 | #endif |
119 | } else { | ||
120 | mapped = top & ~(LARGE_PAGE_SIZE_8M - 1); | ||
121 | } | ||
70 | 122 | ||
71 | mapped = top - s; | 123 | mmu_patch_cmp_limit(&DTLBMiss_cmp, mapped); |
124 | mmu_patch_cmp_limit(&FixupDAR_cmp, mapped); | ||
72 | 125 | ||
73 | /* If the size of RAM is not an exact power of two, we may not | 126 | /* If the size of RAM is not an exact power of two, we may not |
74 | * have covered RAM in its entirety with 8 MiB | 127 | * have covered RAM in its entirety with 8 MiB |
@@ -77,7 +130,8 @@ unsigned long __init mmu_mapin_ram(unsigned long top) | |||
77 | * coverage with normal-sized pages (or other reasons) do not | 130 | * coverage with normal-sized pages (or other reasons) do not |
78 | * attempt to allocate outside the allowed range. | 131 | * attempt to allocate outside the allowed range. |
79 | */ | 132 | */ |
80 | memblock_set_current_limit(mapped); | 133 | if (mapped) |
134 | memblock_set_current_limit(mapped); | ||
81 | 135 | ||
82 | return mapped; | 136 | return mapped; |
83 | } | 137 | } |
@@ -90,13 +144,8 @@ void setup_initial_memory_limit(phys_addr_t first_memblock_base, | |||
90 | */ | 144 | */ |
91 | BUG_ON(first_memblock_base != 0); | 145 | BUG_ON(first_memblock_base != 0); |
92 | 146 | ||
93 | #ifdef CONFIG_PIN_TLB | ||
94 | /* 8xx can only access 24MB at the moment */ | 147 | /* 8xx can only access 24MB at the moment */ |
95 | memblock_set_current_limit(min_t(u64, first_memblock_size, 0x01800000)); | 148 | memblock_set_current_limit(min_t(u64, first_memblock_size, 0x01800000)); |
96 | #else | ||
97 | /* 8xx can only access 8MB at the moment */ | ||
98 | memblock_set_current_limit(min_t(u64, first_memblock_size, 0x00800000)); | ||
99 | #endif | ||
100 | } | 149 | } |
101 | 150 | ||
102 | /* | 151 | /* |
diff --git a/arch/powerpc/mm/hash64_4k.c b/arch/powerpc/mm/hash64_4k.c index 6333b273d2d5..42c702b3be1f 100644 --- a/arch/powerpc/mm/hash64_4k.c +++ b/arch/powerpc/mm/hash64_4k.c | |||
@@ -70,8 +70,8 @@ int __hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid, | |||
70 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; | 70 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; |
71 | slot += (old_pte & H_PAGE_F_GIX) >> H_PAGE_F_GIX_SHIFT; | 71 | slot += (old_pte & H_PAGE_F_GIX) >> H_PAGE_F_GIX_SHIFT; |
72 | 72 | ||
73 | if (ppc_md.hpte_updatepp(slot, rflags, vpn, MMU_PAGE_4K, | 73 | if (mmu_hash_ops.hpte_updatepp(slot, rflags, vpn, MMU_PAGE_4K, |
74 | MMU_PAGE_4K, ssize, flags) == -1) | 74 | MMU_PAGE_4K, ssize, flags) == -1) |
75 | old_pte &= ~_PAGE_HPTEFLAGS; | 75 | old_pte &= ~_PAGE_HPTEFLAGS; |
76 | } | 76 | } |
77 | 77 | ||
@@ -84,21 +84,23 @@ repeat: | |||
84 | hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; | 84 | hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; |
85 | 85 | ||
86 | /* Insert into the hash table, primary slot */ | 86 | /* Insert into the hash table, primary slot */ |
87 | slot = ppc_md.hpte_insert(hpte_group, vpn, pa, rflags, 0, | 87 | slot = mmu_hash_ops.hpte_insert(hpte_group, vpn, pa, rflags, 0, |
88 | MMU_PAGE_4K, MMU_PAGE_4K, ssize); | 88 | MMU_PAGE_4K, MMU_PAGE_4K, ssize); |
89 | /* | 89 | /* |
90 | * Primary is full, try the secondary | 90 | * Primary is full, try the secondary |
91 | */ | 91 | */ |
92 | if (unlikely(slot == -1)) { | 92 | if (unlikely(slot == -1)) { |
93 | hpte_group = ((~hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; | 93 | hpte_group = ((~hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; |
94 | slot = ppc_md.hpte_insert(hpte_group, vpn, pa, | 94 | slot = mmu_hash_ops.hpte_insert(hpte_group, vpn, pa, |
95 | rflags, HPTE_V_SECONDARY, | 95 | rflags, |
96 | MMU_PAGE_4K, MMU_PAGE_4K, ssize); | 96 | HPTE_V_SECONDARY, |
97 | MMU_PAGE_4K, | ||
98 | MMU_PAGE_4K, ssize); | ||
97 | if (slot == -1) { | 99 | if (slot == -1) { |
98 | if (mftb() & 0x1) | 100 | if (mftb() & 0x1) |
99 | hpte_group = ((hash & htab_hash_mask) * | 101 | hpte_group = ((hash & htab_hash_mask) * |
100 | HPTES_PER_GROUP) & ~0x7UL; | 102 | HPTES_PER_GROUP) & ~0x7UL; |
101 | ppc_md.hpte_remove(hpte_group); | 103 | mmu_hash_ops.hpte_remove(hpte_group); |
102 | /* | 104 | /* |
103 | * FIXME!! Should be try the group from which we removed ? | 105 | * FIXME!! Should be try the group from which we removed ? |
104 | */ | 106 | */ |
diff --git a/arch/powerpc/mm/hash64_64k.c b/arch/powerpc/mm/hash64_64k.c index 16644e1f4e6b..3bbbea07378c 100644 --- a/arch/powerpc/mm/hash64_64k.c +++ b/arch/powerpc/mm/hash64_64k.c | |||
@@ -133,9 +133,9 @@ int __hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid, | |||
133 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; | 133 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; |
134 | slot += hidx & _PTEIDX_GROUP_IX; | 134 | slot += hidx & _PTEIDX_GROUP_IX; |
135 | 135 | ||
136 | ret = ppc_md.hpte_updatepp(slot, rflags, vpn, | 136 | ret = mmu_hash_ops.hpte_updatepp(slot, rflags, vpn, |
137 | MMU_PAGE_4K, MMU_PAGE_4K, | 137 | MMU_PAGE_4K, MMU_PAGE_4K, |
138 | ssize, flags); | 138 | ssize, flags); |
139 | /* | 139 | /* |
140 | *if we failed because typically the HPTE wasn't really here | 140 | *if we failed because typically the HPTE wasn't really here |
141 | * we try an insertion. | 141 | * we try an insertion. |
@@ -166,21 +166,22 @@ repeat: | |||
166 | hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; | 166 | hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; |
167 | 167 | ||
168 | /* Insert into the hash table, primary slot */ | 168 | /* Insert into the hash table, primary slot */ |
169 | slot = ppc_md.hpte_insert(hpte_group, vpn, pa, rflags, 0, | 169 | slot = mmu_hash_ops.hpte_insert(hpte_group, vpn, pa, rflags, 0, |
170 | MMU_PAGE_4K, MMU_PAGE_4K, ssize); | 170 | MMU_PAGE_4K, MMU_PAGE_4K, ssize); |
171 | /* | 171 | /* |
172 | * Primary is full, try the secondary | 172 | * Primary is full, try the secondary |
173 | */ | 173 | */ |
174 | if (unlikely(slot == -1)) { | 174 | if (unlikely(slot == -1)) { |
175 | hpte_group = ((~hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; | 175 | hpte_group = ((~hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; |
176 | slot = ppc_md.hpte_insert(hpte_group, vpn, pa, | 176 | slot = mmu_hash_ops.hpte_insert(hpte_group, vpn, pa, |
177 | rflags, HPTE_V_SECONDARY, | 177 | rflags, HPTE_V_SECONDARY, |
178 | MMU_PAGE_4K, MMU_PAGE_4K, ssize); | 178 | MMU_PAGE_4K, MMU_PAGE_4K, |
179 | ssize); | ||
179 | if (slot == -1) { | 180 | if (slot == -1) { |
180 | if (mftb() & 0x1) | 181 | if (mftb() & 0x1) |
181 | hpte_group = ((hash & htab_hash_mask) * | 182 | hpte_group = ((hash & htab_hash_mask) * |
182 | HPTES_PER_GROUP) & ~0x7UL; | 183 | HPTES_PER_GROUP) & ~0x7UL; |
183 | ppc_md.hpte_remove(hpte_group); | 184 | mmu_hash_ops.hpte_remove(hpte_group); |
184 | /* | 185 | /* |
185 | * FIXME!! Should be try the group from which we removed ? | 186 | * FIXME!! Should be try the group from which we removed ? |
186 | */ | 187 | */ |
@@ -272,8 +273,9 @@ int __hash_page_64K(unsigned long ea, unsigned long access, | |||
272 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; | 273 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; |
273 | slot += (old_pte & H_PAGE_F_GIX) >> H_PAGE_F_GIX_SHIFT; | 274 | slot += (old_pte & H_PAGE_F_GIX) >> H_PAGE_F_GIX_SHIFT; |
274 | 275 | ||
275 | if (ppc_md.hpte_updatepp(slot, rflags, vpn, MMU_PAGE_64K, | 276 | if (mmu_hash_ops.hpte_updatepp(slot, rflags, vpn, MMU_PAGE_64K, |
276 | MMU_PAGE_64K, ssize, flags) == -1) | 277 | MMU_PAGE_64K, ssize, |
278 | flags) == -1) | ||
277 | old_pte &= ~_PAGE_HPTEFLAGS; | 279 | old_pte &= ~_PAGE_HPTEFLAGS; |
278 | } | 280 | } |
279 | 281 | ||
@@ -286,21 +288,24 @@ repeat: | |||
286 | hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; | 288 | hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; |
287 | 289 | ||
288 | /* Insert into the hash table, primary slot */ | 290 | /* Insert into the hash table, primary slot */ |
289 | slot = ppc_md.hpte_insert(hpte_group, vpn, pa, rflags, 0, | 291 | slot = mmu_hash_ops.hpte_insert(hpte_group, vpn, pa, rflags, 0, |
290 | MMU_PAGE_64K, MMU_PAGE_64K, ssize); | 292 | MMU_PAGE_64K, MMU_PAGE_64K, |
293 | ssize); | ||
291 | /* | 294 | /* |
292 | * Primary is full, try the secondary | 295 | * Primary is full, try the secondary |
293 | */ | 296 | */ |
294 | if (unlikely(slot == -1)) { | 297 | if (unlikely(slot == -1)) { |
295 | hpte_group = ((~hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; | 298 | hpte_group = ((~hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; |
296 | slot = ppc_md.hpte_insert(hpte_group, vpn, pa, | 299 | slot = mmu_hash_ops.hpte_insert(hpte_group, vpn, pa, |
297 | rflags, HPTE_V_SECONDARY, | 300 | rflags, |
298 | MMU_PAGE_64K, MMU_PAGE_64K, ssize); | 301 | HPTE_V_SECONDARY, |
302 | MMU_PAGE_64K, | ||
303 | MMU_PAGE_64K, ssize); | ||
299 | if (slot == -1) { | 304 | if (slot == -1) { |
300 | if (mftb() & 0x1) | 305 | if (mftb() & 0x1) |
301 | hpte_group = ((hash & htab_hash_mask) * | 306 | hpte_group = ((hash & htab_hash_mask) * |
302 | HPTES_PER_GROUP) & ~0x7UL; | 307 | HPTES_PER_GROUP) & ~0x7UL; |
303 | ppc_md.hpte_remove(hpte_group); | 308 | mmu_hash_ops.hpte_remove(hpte_group); |
304 | /* | 309 | /* |
305 | * FIXME!! Should be try the group from which we removed ? | 310 | * FIXME!! Should be try the group from which we removed ? |
306 | */ | 311 | */ |
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c index f8a871a72985..88ce7d212320 100644 --- a/arch/powerpc/mm/hash_native_64.c +++ b/arch/powerpc/mm/hash_native_64.c | |||
@@ -55,7 +55,7 @@ static inline void __tlbie(unsigned long vpn, int psize, int apsize, int ssize) | |||
55 | * We need 14 to 65 bits of va for a tlibe of 4K page | 55 | * We need 14 to 65 bits of va for a tlibe of 4K page |
56 | * With vpn we ignore the lower VPN_SHIFT bits already. | 56 | * With vpn we ignore the lower VPN_SHIFT bits already. |
57 | * And top two bits are already ignored because we can | 57 | * And top two bits are already ignored because we can |
58 | * only accomadate 76 bits in a 64 bit vpn with a VPN_SHIFT | 58 | * only accomodate 76 bits in a 64 bit vpn with a VPN_SHIFT |
59 | * of 12. | 59 | * of 12. |
60 | */ | 60 | */ |
61 | va = vpn << VPN_SHIFT; | 61 | va = vpn << VPN_SHIFT; |
@@ -64,7 +64,8 @@ static inline void __tlbie(unsigned long vpn, int psize, int apsize, int ssize) | |||
64 | * Older versions of the architecture (2.02 and earler) require the | 64 | * Older versions of the architecture (2.02 and earler) require the |
65 | * masking of the top 16 bits. | 65 | * masking of the top 16 bits. |
66 | */ | 66 | */ |
67 | va &= ~(0xffffULL << 48); | 67 | if (mmu_has_feature(MMU_FTR_TLBIE_CROP_VA)) |
68 | va &= ~(0xffffULL << 48); | ||
68 | 69 | ||
69 | switch (psize) { | 70 | switch (psize) { |
70 | case MMU_PAGE_4K: | 71 | case MMU_PAGE_4K: |
@@ -113,7 +114,8 @@ static inline void __tlbiel(unsigned long vpn, int psize, int apsize, int ssize) | |||
113 | * Older versions of the architecture (2.02 and earler) require the | 114 | * Older versions of the architecture (2.02 and earler) require the |
114 | * masking of the top 16 bits. | 115 | * masking of the top 16 bits. |
115 | */ | 116 | */ |
116 | va &= ~(0xffffULL << 48); | 117 | if (mmu_has_feature(MMU_FTR_TLBIE_CROP_VA)) |
118 | va &= ~(0xffffULL << 48); | ||
117 | 119 | ||
118 | switch (psize) { | 120 | switch (psize) { |
119 | case MMU_PAGE_4K: | 121 | case MMU_PAGE_4K: |
@@ -605,7 +607,7 @@ static void hpte_decode(struct hash_pte *hpte, unsigned long slot, | |||
605 | * crashdump and all bets are off anyway. | 607 | * crashdump and all bets are off anyway. |
606 | * | 608 | * |
607 | * TODO: add batching support when enabled. remember, no dynamic memory here, | 609 | * TODO: add batching support when enabled. remember, no dynamic memory here, |
608 | * athough there is the control page available... | 610 | * although there is the control page available... |
609 | */ | 611 | */ |
610 | static void native_hpte_clear(void) | 612 | static void native_hpte_clear(void) |
611 | { | 613 | { |
@@ -723,23 +725,29 @@ static void native_flush_hash_range(unsigned long number, int local) | |||
723 | local_irq_restore(flags); | 725 | local_irq_restore(flags); |
724 | } | 726 | } |
725 | 727 | ||
726 | static int native_update_partition_table(u64 patb1) | 728 | static int native_register_proc_table(unsigned long base, unsigned long page_size, |
729 | unsigned long table_size) | ||
727 | { | 730 | { |
731 | unsigned long patb1 = base << 25; /* VSID */ | ||
732 | |||
733 | patb1 |= (page_size << 5); /* sllp */ | ||
734 | patb1 |= table_size; | ||
735 | |||
728 | partition_tb->patb1 = cpu_to_be64(patb1); | 736 | partition_tb->patb1 = cpu_to_be64(patb1); |
729 | return 0; | 737 | return 0; |
730 | } | 738 | } |
731 | 739 | ||
732 | void __init hpte_init_native(void) | 740 | void __init hpte_init_native(void) |
733 | { | 741 | { |
734 | ppc_md.hpte_invalidate = native_hpte_invalidate; | 742 | mmu_hash_ops.hpte_invalidate = native_hpte_invalidate; |
735 | ppc_md.hpte_updatepp = native_hpte_updatepp; | 743 | mmu_hash_ops.hpte_updatepp = native_hpte_updatepp; |
736 | ppc_md.hpte_updateboltedpp = native_hpte_updateboltedpp; | 744 | mmu_hash_ops.hpte_updateboltedpp = native_hpte_updateboltedpp; |
737 | ppc_md.hpte_insert = native_hpte_insert; | 745 | mmu_hash_ops.hpte_insert = native_hpte_insert; |
738 | ppc_md.hpte_remove = native_hpte_remove; | 746 | mmu_hash_ops.hpte_remove = native_hpte_remove; |
739 | ppc_md.hpte_clear_all = native_hpte_clear; | 747 | mmu_hash_ops.hpte_clear_all = native_hpte_clear; |
740 | ppc_md.flush_hash_range = native_flush_hash_range; | 748 | mmu_hash_ops.flush_hash_range = native_flush_hash_range; |
741 | ppc_md.hugepage_invalidate = native_hugepage_invalidate; | 749 | mmu_hash_ops.hugepage_invalidate = native_hugepage_invalidate; |
742 | 750 | ||
743 | if (cpu_has_feature(CPU_FTR_ARCH_300)) | 751 | if (cpu_has_feature(CPU_FTR_ARCH_300)) |
744 | ppc_md.update_partition_table = native_update_partition_table; | 752 | ppc_md.register_process_table = native_register_proc_table; |
745 | } | 753 | } |
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 2971ea18c768..b78b5d211278 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/signal.h> | 34 | #include <linux/signal.h> |
35 | #include <linux/memblock.h> | 35 | #include <linux/memblock.h> |
36 | #include <linux/context_tracking.h> | 36 | #include <linux/context_tracking.h> |
37 | #include <linux/libfdt.h> | ||
37 | 38 | ||
38 | #include <asm/processor.h> | 39 | #include <asm/processor.h> |
39 | #include <asm/pgtable.h> | 40 | #include <asm/pgtable.h> |
@@ -58,6 +59,7 @@ | |||
58 | #include <asm/firmware.h> | 59 | #include <asm/firmware.h> |
59 | #include <asm/tm.h> | 60 | #include <asm/tm.h> |
60 | #include <asm/trace.h> | 61 | #include <asm/trace.h> |
62 | #include <asm/ps3.h> | ||
61 | 63 | ||
62 | #ifdef DEBUG | 64 | #ifdef DEBUG |
63 | #define DBG(fmt...) udbg_printf(fmt) | 65 | #define DBG(fmt...) udbg_printf(fmt) |
@@ -87,10 +89,6 @@ | |||
87 | * | 89 | * |
88 | */ | 90 | */ |
89 | 91 | ||
90 | #ifdef CONFIG_U3_DART | ||
91 | extern unsigned long dart_tablebase; | ||
92 | #endif /* CONFIG_U3_DART */ | ||
93 | |||
94 | static unsigned long _SDR1; | 92 | static unsigned long _SDR1; |
95 | struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; | 93 | struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; |
96 | EXPORT_SYMBOL_GPL(mmu_psize_defs); | 94 | EXPORT_SYMBOL_GPL(mmu_psize_defs); |
@@ -120,6 +118,8 @@ static u8 *linear_map_hash_slots; | |||
120 | static unsigned long linear_map_hash_count; | 118 | static unsigned long linear_map_hash_count; |
121 | static DEFINE_SPINLOCK(linear_map_hash_lock); | 119 | static DEFINE_SPINLOCK(linear_map_hash_lock); |
122 | #endif /* CONFIG_DEBUG_PAGEALLOC */ | 120 | #endif /* CONFIG_DEBUG_PAGEALLOC */ |
121 | struct mmu_hash_ops mmu_hash_ops; | ||
122 | EXPORT_SYMBOL(mmu_hash_ops); | ||
123 | 123 | ||
124 | /* There are definitions of page sizes arrays to be used when none | 124 | /* There are definitions of page sizes arrays to be used when none |
125 | * is provided by the firmware. | 125 | * is provided by the firmware. |
@@ -278,9 +278,10 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend, | |||
278 | hash = hpt_hash(vpn, shift, ssize); | 278 | hash = hpt_hash(vpn, shift, ssize); |
279 | hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP); | 279 | hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP); |
280 | 280 | ||
281 | BUG_ON(!ppc_md.hpte_insert); | 281 | BUG_ON(!mmu_hash_ops.hpte_insert); |
282 | ret = ppc_md.hpte_insert(hpteg, vpn, paddr, tprot, | 282 | ret = mmu_hash_ops.hpte_insert(hpteg, vpn, paddr, tprot, |
283 | HPTE_V_BOLTED, psize, psize, ssize); | 283 | HPTE_V_BOLTED, psize, psize, |
284 | ssize); | ||
284 | 285 | ||
285 | if (ret < 0) | 286 | if (ret < 0) |
286 | break; | 287 | break; |
@@ -305,11 +306,11 @@ int htab_remove_mapping(unsigned long vstart, unsigned long vend, | |||
305 | shift = mmu_psize_defs[psize].shift; | 306 | shift = mmu_psize_defs[psize].shift; |
306 | step = 1 << shift; | 307 | step = 1 << shift; |
307 | 308 | ||
308 | if (!ppc_md.hpte_removebolted) | 309 | if (!mmu_hash_ops.hpte_removebolted) |
309 | return -ENODEV; | 310 | return -ENODEV; |
310 | 311 | ||
311 | for (vaddr = vstart; vaddr < vend; vaddr += step) { | 312 | for (vaddr = vstart; vaddr < vend; vaddr += step) { |
312 | rc = ppc_md.hpte_removebolted(vaddr, psize, ssize); | 313 | rc = mmu_hash_ops.hpte_removebolted(vaddr, psize, ssize); |
313 | if (rc == -ENOENT) { | 314 | if (rc == -ENOENT) { |
314 | ret = -ENOENT; | 315 | ret = -ENOENT; |
315 | continue; | 316 | continue; |
@@ -321,6 +322,15 @@ int htab_remove_mapping(unsigned long vstart, unsigned long vend, | |||
321 | return ret; | 322 | return ret; |
322 | } | 323 | } |
323 | 324 | ||
325 | static bool disable_1tb_segments = false; | ||
326 | |||
327 | static int __init parse_disable_1tb_segments(char *p) | ||
328 | { | ||
329 | disable_1tb_segments = true; | ||
330 | return 0; | ||
331 | } | ||
332 | early_param("disable_1tb_segments", parse_disable_1tb_segments); | ||
333 | |||
324 | static int __init htab_dt_scan_seg_sizes(unsigned long node, | 334 | static int __init htab_dt_scan_seg_sizes(unsigned long node, |
325 | const char *uname, int depth, | 335 | const char *uname, int depth, |
326 | void *data) | 336 | void *data) |
@@ -339,6 +349,12 @@ static int __init htab_dt_scan_seg_sizes(unsigned long node, | |||
339 | for (; size >= 4; size -= 4, ++prop) { | 349 | for (; size >= 4; size -= 4, ++prop) { |
340 | if (be32_to_cpu(prop[0]) == 40) { | 350 | if (be32_to_cpu(prop[0]) == 40) { |
341 | DBG("1T segment support detected\n"); | 351 | DBG("1T segment support detected\n"); |
352 | |||
353 | if (disable_1tb_segments) { | ||
354 | DBG("1T segments disabled by command line\n"); | ||
355 | break; | ||
356 | } | ||
357 | |||
342 | cur_cpu_spec->mmu_features |= MMU_FTR_1T_SEGMENT; | 358 | cur_cpu_spec->mmu_features |= MMU_FTR_1T_SEGMENT; |
343 | return 1; | 359 | return 1; |
344 | } | 360 | } |
@@ -514,7 +530,8 @@ static bool might_have_hea(void) | |||
514 | * we will never see an HEA ethernet device. | 530 | * we will never see an HEA ethernet device. |
515 | */ | 531 | */ |
516 | #ifdef CONFIG_IBMEBUS | 532 | #ifdef CONFIG_IBMEBUS |
517 | return !cpu_has_feature(CPU_FTR_ARCH_207S); | 533 | return !cpu_has_feature(CPU_FTR_ARCH_207S) && |
534 | !firmware_has_feature(FW_FEATURE_SPLPAR); | ||
518 | #else | 535 | #else |
519 | return false; | 536 | return false; |
520 | #endif | 537 | #endif |
@@ -580,7 +597,7 @@ found: | |||
580 | * would stop us accessing the HEA ethernet. So if we | 597 | * would stop us accessing the HEA ethernet. So if we |
581 | * have the chance of ever seeing one, stay at 4k. | 598 | * have the chance of ever seeing one, stay at 4k. |
582 | */ | 599 | */ |
583 | if (!might_have_hea() || !machine_is(pseries)) | 600 | if (!might_have_hea()) |
584 | mmu_io_psize = MMU_PAGE_64K; | 601 | mmu_io_psize = MMU_PAGE_64K; |
585 | } else | 602 | } else |
586 | mmu_ci_restrictions = 1; | 603 | mmu_ci_restrictions = 1; |
@@ -699,10 +716,9 @@ int remove_section_mapping(unsigned long start, unsigned long end) | |||
699 | #endif /* CONFIG_MEMORY_HOTPLUG */ | 716 | #endif /* CONFIG_MEMORY_HOTPLUG */ |
700 | 717 | ||
701 | static void __init hash_init_partition_table(phys_addr_t hash_table, | 718 | static void __init hash_init_partition_table(phys_addr_t hash_table, |
702 | unsigned long pteg_count) | 719 | unsigned long htab_size) |
703 | { | 720 | { |
704 | unsigned long ps_field; | 721 | unsigned long ps_field; |
705 | unsigned long htab_size; | ||
706 | unsigned long patb_size = 1UL << PATB_SIZE_SHIFT; | 722 | unsigned long patb_size = 1UL << PATB_SIZE_SHIFT; |
707 | 723 | ||
708 | /* | 724 | /* |
@@ -710,7 +726,7 @@ static void __init hash_init_partition_table(phys_addr_t hash_table, | |||
710 | * We can ignore that for lpid 0 | 726 | * We can ignore that for lpid 0 |
711 | */ | 727 | */ |
712 | ps_field = 0; | 728 | ps_field = 0; |
713 | htab_size = __ilog2(pteg_count) - 11; | 729 | htab_size = __ilog2(htab_size) - 18; |
714 | 730 | ||
715 | BUILD_BUG_ON_MSG((PATB_SIZE_SHIFT > 24), "Partition table size too large."); | 731 | BUILD_BUG_ON_MSG((PATB_SIZE_SHIFT > 24), "Partition table size too large."); |
716 | partition_tb = __va(memblock_alloc_base(patb_size, patb_size, | 732 | partition_tb = __va(memblock_alloc_base(patb_size, patb_size, |
@@ -724,7 +740,7 @@ static void __init hash_init_partition_table(phys_addr_t hash_table, | |||
724 | * For now UPRT is 0 for us. | 740 | * For now UPRT is 0 for us. |
725 | */ | 741 | */ |
726 | partition_tb->patb1 = 0; | 742 | partition_tb->patb1 = 0; |
727 | DBG("Partition table %p\n", partition_tb); | 743 | pr_info("Partition table %p\n", partition_tb); |
728 | /* | 744 | /* |
729 | * update partition table control register, | 745 | * update partition table control register, |
730 | * 64 K size. | 746 | * 64 K size. |
@@ -738,7 +754,7 @@ static void __init htab_initialize(void) | |||
738 | unsigned long table; | 754 | unsigned long table; |
739 | unsigned long pteg_count; | 755 | unsigned long pteg_count; |
740 | unsigned long prot; | 756 | unsigned long prot; |
741 | unsigned long base = 0, size = 0, limit; | 757 | unsigned long base = 0, size = 0; |
742 | struct memblock_region *reg; | 758 | struct memblock_region *reg; |
743 | 759 | ||
744 | DBG(" -> htab_initialize()\n"); | 760 | DBG(" -> htab_initialize()\n"); |
@@ -764,7 +780,8 @@ static void __init htab_initialize(void) | |||
764 | 780 | ||
765 | htab_hash_mask = pteg_count - 1; | 781 | htab_hash_mask = pteg_count - 1; |
766 | 782 | ||
767 | if (firmware_has_feature(FW_FEATURE_LPAR)) { | 783 | if (firmware_has_feature(FW_FEATURE_LPAR) || |
784 | firmware_has_feature(FW_FEATURE_PS3_LV1)) { | ||
768 | /* Using a hypervisor which owns the htab */ | 785 | /* Using a hypervisor which owns the htab */ |
769 | htab_address = NULL; | 786 | htab_address = NULL; |
770 | _SDR1 = 0; | 787 | _SDR1 = 0; |
@@ -775,20 +792,26 @@ static void __init htab_initialize(void) | |||
775 | * Clear the htab if firmware assisted dump is active so | 792 | * Clear the htab if firmware assisted dump is active so |
776 | * that we dont end up using old mappings. | 793 | * that we dont end up using old mappings. |
777 | */ | 794 | */ |
778 | if (is_fadump_active() && ppc_md.hpte_clear_all) | 795 | if (is_fadump_active() && mmu_hash_ops.hpte_clear_all) |
779 | ppc_md.hpte_clear_all(); | 796 | mmu_hash_ops.hpte_clear_all(); |
780 | #endif | 797 | #endif |
781 | } else { | 798 | } else { |
782 | /* Find storage for the HPT. Must be contiguous in | 799 | unsigned long limit = MEMBLOCK_ALLOC_ANYWHERE; |
783 | * the absolute address space. On cell we want it to be | 800 | |
784 | * in the first 2 Gig so we can use it for IOMMU hacks. | 801 | #ifdef CONFIG_PPC_CELL |
802 | /* | ||
803 | * Cell may require the hash table down low when using the | ||
804 | * Axon IOMMU in order to fit the dynamic region over it, see | ||
805 | * comments in cell/iommu.c | ||
785 | */ | 806 | */ |
786 | if (machine_is(cell)) | 807 | if (fdt_subnode_offset(initial_boot_params, 0, "axon") > 0) { |
787 | limit = 0x80000000; | 808 | limit = 0x80000000; |
788 | else | 809 | pr_info("Hash table forced below 2G for Axon IOMMU\n"); |
789 | limit = MEMBLOCK_ALLOC_ANYWHERE; | 810 | } |
811 | #endif /* CONFIG_PPC_CELL */ | ||
790 | 812 | ||
791 | table = memblock_alloc_base(htab_size_bytes, htab_size_bytes, limit); | 813 | table = memblock_alloc_base(htab_size_bytes, htab_size_bytes, |
814 | limit); | ||
792 | 815 | ||
793 | DBG("Hash table allocated at %lx, size: %lx\n", table, | 816 | DBG("Hash table allocated at %lx, size: %lx\n", table, |
794 | htab_size_bytes); | 817 | htab_size_bytes); |
@@ -796,7 +819,7 @@ static void __init htab_initialize(void) | |||
796 | htab_address = __va(table); | 819 | htab_address = __va(table); |
797 | 820 | ||
798 | /* htab absolute addr + encoded htabsize */ | 821 | /* htab absolute addr + encoded htabsize */ |
799 | _SDR1 = table + __ilog2(pteg_count) - 11; | 822 | _SDR1 = table + __ilog2(htab_size_bytes) - 18; |
800 | 823 | ||
801 | /* Initialize the HPT with no entries */ | 824 | /* Initialize the HPT with no entries */ |
802 | memset((void *)table, 0, htab_size_bytes); | 825 | memset((void *)table, 0, htab_size_bytes); |
@@ -805,7 +828,7 @@ static void __init htab_initialize(void) | |||
805 | /* Set SDR1 */ | 828 | /* Set SDR1 */ |
806 | mtspr(SPRN_SDR1, _SDR1); | 829 | mtspr(SPRN_SDR1, _SDR1); |
807 | else | 830 | else |
808 | hash_init_partition_table(table, pteg_count); | 831 | hash_init_partition_table(table, htab_size_bytes); |
809 | } | 832 | } |
810 | 833 | ||
811 | prot = pgprot_val(PAGE_KERNEL); | 834 | prot = pgprot_val(PAGE_KERNEL); |
@@ -832,34 +855,6 @@ static void __init htab_initialize(void) | |||
832 | DBG("creating mapping for region: %lx..%lx (prot: %lx)\n", | 855 | DBG("creating mapping for region: %lx..%lx (prot: %lx)\n", |
833 | base, size, prot); | 856 | base, size, prot); |
834 | 857 | ||
835 | #ifdef CONFIG_U3_DART | ||
836 | /* Do not map the DART space. Fortunately, it will be aligned | ||
837 | * in such a way that it will not cross two memblock regions and | ||
838 | * will fit within a single 16Mb page. | ||
839 | * The DART space is assumed to be a full 16Mb region even if | ||
840 | * we only use 2Mb of that space. We will use more of it later | ||
841 | * for AGP GART. We have to use a full 16Mb large page. | ||
842 | */ | ||
843 | DBG("DART base: %lx\n", dart_tablebase); | ||
844 | |||
845 | if (dart_tablebase != 0 && dart_tablebase >= base | ||
846 | && dart_tablebase < (base + size)) { | ||
847 | unsigned long dart_table_end = dart_tablebase + 16 * MB; | ||
848 | if (base != dart_tablebase) | ||
849 | BUG_ON(htab_bolt_mapping(base, dart_tablebase, | ||
850 | __pa(base), prot, | ||
851 | mmu_linear_psize, | ||
852 | mmu_kernel_ssize)); | ||
853 | if ((base + size) > dart_table_end) | ||
854 | BUG_ON(htab_bolt_mapping(dart_tablebase+16*MB, | ||
855 | base + size, | ||
856 | __pa(dart_table_end), | ||
857 | prot, | ||
858 | mmu_linear_psize, | ||
859 | mmu_kernel_ssize)); | ||
860 | continue; | ||
861 | } | ||
862 | #endif /* CONFIG_U3_DART */ | ||
863 | BUG_ON(htab_bolt_mapping(base, base + size, __pa(base), | 858 | BUG_ON(htab_bolt_mapping(base, base + size, __pa(base), |
864 | prot, mmu_linear_psize, mmu_kernel_ssize)); | 859 | prot, mmu_linear_psize, mmu_kernel_ssize)); |
865 | } | 860 | } |
@@ -926,12 +921,24 @@ void __init hash__early_init_mmu(void) | |||
926 | pci_io_base = ISA_IO_BASE; | 921 | pci_io_base = ISA_IO_BASE; |
927 | #endif | 922 | #endif |
928 | 923 | ||
924 | /* Select appropriate backend */ | ||
925 | if (firmware_has_feature(FW_FEATURE_PS3_LV1)) | ||
926 | ps3_early_mm_init(); | ||
927 | else if (firmware_has_feature(FW_FEATURE_LPAR)) | ||
928 | hpte_init_pseries(); | ||
929 | else if (IS_ENABLED(CONFIG_PPC_NATIVE)) | ||
930 | hpte_init_native(); | ||
931 | |||
932 | if (!mmu_hash_ops.hpte_insert) | ||
933 | panic("hash__early_init_mmu: No MMU hash ops defined!\n"); | ||
934 | |||
929 | /* Initialize the MMU Hash table and create the linear mapping | 935 | /* Initialize the MMU Hash table and create the linear mapping |
930 | * of memory. Has to be done before SLB initialization as this is | 936 | * of memory. Has to be done before SLB initialization as this is |
931 | * currently where the page size encoding is obtained. | 937 | * currently where the page size encoding is obtained. |
932 | */ | 938 | */ |
933 | htab_initialize(); | 939 | htab_initialize(); |
934 | 940 | ||
941 | pr_info("Initializing hash mmu with SLB\n"); | ||
935 | /* Initialize SLB management */ | 942 | /* Initialize SLB management */ |
936 | slb_initialize(); | 943 | slb_initialize(); |
937 | } | 944 | } |
@@ -1474,7 +1481,8 @@ void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize, int ssize, | |||
1474 | * We use same base page size and actual psize, because we don't | 1481 | * We use same base page size and actual psize, because we don't |
1475 | * use these functions for hugepage | 1482 | * use these functions for hugepage |
1476 | */ | 1483 | */ |
1477 | ppc_md.hpte_invalidate(slot, vpn, psize, psize, ssize, local); | 1484 | mmu_hash_ops.hpte_invalidate(slot, vpn, psize, psize, |
1485 | ssize, local); | ||
1478 | } pte_iterate_hashed_end(); | 1486 | } pte_iterate_hashed_end(); |
1479 | 1487 | ||
1480 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | 1488 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM |
@@ -1515,9 +1523,9 @@ void flush_hash_hugepage(unsigned long vsid, unsigned long addr, | |||
1515 | if (!hpte_slot_array) | 1523 | if (!hpte_slot_array) |
1516 | return; | 1524 | return; |
1517 | 1525 | ||
1518 | if (ppc_md.hugepage_invalidate) { | 1526 | if (mmu_hash_ops.hugepage_invalidate) { |
1519 | ppc_md.hugepage_invalidate(vsid, s_addr, hpte_slot_array, | 1527 | mmu_hash_ops.hugepage_invalidate(vsid, s_addr, hpte_slot_array, |
1520 | psize, ssize, local); | 1528 | psize, ssize, local); |
1521 | goto tm_abort; | 1529 | goto tm_abort; |
1522 | } | 1530 | } |
1523 | /* | 1531 | /* |
@@ -1544,8 +1552,8 @@ void flush_hash_hugepage(unsigned long vsid, unsigned long addr, | |||
1544 | 1552 | ||
1545 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; | 1553 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; |
1546 | slot += hidx & _PTEIDX_GROUP_IX; | 1554 | slot += hidx & _PTEIDX_GROUP_IX; |
1547 | ppc_md.hpte_invalidate(slot, vpn, psize, | 1555 | mmu_hash_ops.hpte_invalidate(slot, vpn, psize, |
1548 | MMU_PAGE_16M, ssize, local); | 1556 | MMU_PAGE_16M, ssize, local); |
1549 | } | 1557 | } |
1550 | tm_abort: | 1558 | tm_abort: |
1551 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | 1559 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM |
@@ -1569,8 +1577,8 @@ tm_abort: | |||
1569 | 1577 | ||
1570 | void flush_hash_range(unsigned long number, int local) | 1578 | void flush_hash_range(unsigned long number, int local) |
1571 | { | 1579 | { |
1572 | if (ppc_md.flush_hash_range) | 1580 | if (mmu_hash_ops.flush_hash_range) |
1573 | ppc_md.flush_hash_range(number, local); | 1581 | mmu_hash_ops.flush_hash_range(number, local); |
1574 | else { | 1582 | else { |
1575 | int i; | 1583 | int i; |
1576 | struct ppc64_tlb_batch *batch = | 1584 | struct ppc64_tlb_batch *batch = |
@@ -1615,22 +1623,22 @@ repeat: | |||
1615 | HPTES_PER_GROUP) & ~0x7UL; | 1623 | HPTES_PER_GROUP) & ~0x7UL; |
1616 | 1624 | ||
1617 | /* Insert into the hash table, primary slot */ | 1625 | /* Insert into the hash table, primary slot */ |
1618 | slot = ppc_md.hpte_insert(hpte_group, vpn, pa, rflags, vflags, | 1626 | slot = mmu_hash_ops.hpte_insert(hpte_group, vpn, pa, rflags, vflags, |
1619 | psize, psize, ssize); | 1627 | psize, psize, ssize); |
1620 | 1628 | ||
1621 | /* Primary is full, try the secondary */ | 1629 | /* Primary is full, try the secondary */ |
1622 | if (unlikely(slot == -1)) { | 1630 | if (unlikely(slot == -1)) { |
1623 | hpte_group = ((~hash & htab_hash_mask) * | 1631 | hpte_group = ((~hash & htab_hash_mask) * |
1624 | HPTES_PER_GROUP) & ~0x7UL; | 1632 | HPTES_PER_GROUP) & ~0x7UL; |
1625 | slot = ppc_md.hpte_insert(hpte_group, vpn, pa, rflags, | 1633 | slot = mmu_hash_ops.hpte_insert(hpte_group, vpn, pa, rflags, |
1626 | vflags | HPTE_V_SECONDARY, | 1634 | vflags | HPTE_V_SECONDARY, |
1627 | psize, psize, ssize); | 1635 | psize, psize, ssize); |
1628 | if (slot == -1) { | 1636 | if (slot == -1) { |
1629 | if (mftb() & 0x1) | 1637 | if (mftb() & 0x1) |
1630 | hpte_group = ((hash & htab_hash_mask) * | 1638 | hpte_group = ((hash & htab_hash_mask) * |
1631 | HPTES_PER_GROUP)&~0x7UL; | 1639 | HPTES_PER_GROUP)&~0x7UL; |
1632 | 1640 | ||
1633 | ppc_md.hpte_remove(hpte_group); | 1641 | mmu_hash_ops.hpte_remove(hpte_group); |
1634 | goto repeat; | 1642 | goto repeat; |
1635 | } | 1643 | } |
1636 | } | 1644 | } |
@@ -1680,8 +1688,9 @@ static void kernel_unmap_linear_page(unsigned long vaddr, unsigned long lmi) | |||
1680 | hash = ~hash; | 1688 | hash = ~hash; |
1681 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; | 1689 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; |
1682 | slot += hidx & _PTEIDX_GROUP_IX; | 1690 | slot += hidx & _PTEIDX_GROUP_IX; |
1683 | ppc_md.hpte_invalidate(slot, vpn, mmu_linear_psize, mmu_linear_psize, | 1691 | mmu_hash_ops.hpte_invalidate(slot, vpn, mmu_linear_psize, |
1684 | mmu_kernel_ssize, 0); | 1692 | mmu_linear_psize, |
1693 | mmu_kernel_ssize, 0); | ||
1685 | } | 1694 | } |
1686 | 1695 | ||
1687 | void __kernel_map_pages(struct page *page, int numpages, int enable) | 1696 | void __kernel_map_pages(struct page *page, int numpages, int enable) |
diff --git a/arch/powerpc/mm/hugepage-hash64.c b/arch/powerpc/mm/hugepage-hash64.c index ba3fc229468a..f20d16f849c5 100644 --- a/arch/powerpc/mm/hugepage-hash64.c +++ b/arch/powerpc/mm/hugepage-hash64.c | |||
@@ -103,8 +103,8 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, | |||
103 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; | 103 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; |
104 | slot += hidx & _PTEIDX_GROUP_IX; | 104 | slot += hidx & _PTEIDX_GROUP_IX; |
105 | 105 | ||
106 | ret = ppc_md.hpte_updatepp(slot, rflags, vpn, | 106 | ret = mmu_hash_ops.hpte_updatepp(slot, rflags, vpn, |
107 | psize, lpsize, ssize, flags); | 107 | psize, lpsize, ssize, flags); |
108 | /* | 108 | /* |
109 | * We failed to update, try to insert a new entry. | 109 | * We failed to update, try to insert a new entry. |
110 | */ | 110 | */ |
@@ -131,23 +131,24 @@ repeat: | |||
131 | hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; | 131 | hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; |
132 | 132 | ||
133 | /* Insert into the hash table, primary slot */ | 133 | /* Insert into the hash table, primary slot */ |
134 | slot = ppc_md.hpte_insert(hpte_group, vpn, pa, rflags, 0, | 134 | slot = mmu_hash_ops.hpte_insert(hpte_group, vpn, pa, rflags, 0, |
135 | psize, lpsize, ssize); | 135 | psize, lpsize, ssize); |
136 | /* | 136 | /* |
137 | * Primary is full, try the secondary | 137 | * Primary is full, try the secondary |
138 | */ | 138 | */ |
139 | if (unlikely(slot == -1)) { | 139 | if (unlikely(slot == -1)) { |
140 | hpte_group = ((~hash & htab_hash_mask) * | 140 | hpte_group = ((~hash & htab_hash_mask) * |
141 | HPTES_PER_GROUP) & ~0x7UL; | 141 | HPTES_PER_GROUP) & ~0x7UL; |
142 | slot = ppc_md.hpte_insert(hpte_group, vpn, pa, | 142 | slot = mmu_hash_ops.hpte_insert(hpte_group, vpn, pa, |
143 | rflags, HPTE_V_SECONDARY, | 143 | rflags, |
144 | psize, lpsize, ssize); | 144 | HPTE_V_SECONDARY, |
145 | psize, lpsize, ssize); | ||
145 | if (slot == -1) { | 146 | if (slot == -1) { |
146 | if (mftb() & 0x1) | 147 | if (mftb() & 0x1) |
147 | hpte_group = ((hash & htab_hash_mask) * | 148 | hpte_group = ((hash & htab_hash_mask) * |
148 | HPTES_PER_GROUP) & ~0x7UL; | 149 | HPTES_PER_GROUP) & ~0x7UL; |
149 | 150 | ||
150 | ppc_md.hpte_remove(hpte_group); | 151 | mmu_hash_ops.hpte_remove(hpte_group); |
151 | goto repeat; | 152 | goto repeat; |
152 | } | 153 | } |
153 | } | 154 | } |
diff --git a/arch/powerpc/mm/hugetlbpage-hash64.c b/arch/powerpc/mm/hugetlbpage-hash64.c index 3058560b6121..d5026f3800b6 100644 --- a/arch/powerpc/mm/hugetlbpage-hash64.c +++ b/arch/powerpc/mm/hugetlbpage-hash64.c | |||
@@ -79,8 +79,8 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid, | |||
79 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; | 79 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; |
80 | slot += (old_pte & H_PAGE_F_GIX) >> H_PAGE_F_GIX_SHIFT; | 80 | slot += (old_pte & H_PAGE_F_GIX) >> H_PAGE_F_GIX_SHIFT; |
81 | 81 | ||
82 | if (ppc_md.hpte_updatepp(slot, rflags, vpn, mmu_psize, | 82 | if (mmu_hash_ops.hpte_updatepp(slot, rflags, vpn, mmu_psize, |
83 | mmu_psize, ssize, flags) == -1) | 83 | mmu_psize, ssize, flags) == -1) |
84 | old_pte &= ~_PAGE_HPTEFLAGS; | 84 | old_pte &= ~_PAGE_HPTEFLAGS; |
85 | } | 85 | } |
86 | 86 | ||
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index 119d18611500..7372ee13eb1e 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c | |||
@@ -81,6 +81,13 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp, | |||
81 | if (! new) | 81 | if (! new) |
82 | return -ENOMEM; | 82 | return -ENOMEM; |
83 | 83 | ||
84 | /* | ||
85 | * Make sure other cpus find the hugepd set only after a | ||
86 | * properly initialized page table is visible to them. | ||
87 | * For more details look for comment in __pte_alloc(). | ||
88 | */ | ||
89 | smp_wmb(); | ||
90 | |||
84 | spin_lock(&mm->page_table_lock); | 91 | spin_lock(&mm->page_table_lock); |
85 | #ifdef CONFIG_PPC_FSL_BOOK3E | 92 | #ifdef CONFIG_PPC_FSL_BOOK3E |
86 | /* | 93 | /* |
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c index c899fe340bbd..448685fbf27c 100644 --- a/arch/powerpc/mm/init_32.c +++ b/arch/powerpc/mm/init_32.c | |||
@@ -64,7 +64,7 @@ EXPORT_SYMBOL(memstart_addr); | |||
64 | phys_addr_t kernstart_addr; | 64 | phys_addr_t kernstart_addr; |
65 | EXPORT_SYMBOL(kernstart_addr); | 65 | EXPORT_SYMBOL(kernstart_addr); |
66 | 66 | ||
67 | #ifdef CONFIG_RELOCATABLE_PPC32 | 67 | #ifdef CONFIG_RELOCATABLE |
68 | /* Used in __va()/__pa() */ | 68 | /* Used in __va()/__pa() */ |
69 | long long virt_phys_offset; | 69 | long long virt_phys_offset; |
70 | EXPORT_SYMBOL(virt_phys_offset); | 70 | EXPORT_SYMBOL(virt_phys_offset); |
@@ -80,9 +80,6 @@ EXPORT_SYMBOL(agp_special_page); | |||
80 | 80 | ||
81 | void MMU_init(void); | 81 | void MMU_init(void); |
82 | 82 | ||
83 | /* XXX should be in current.h -- paulus */ | ||
84 | extern struct task_struct *current_set[NR_CPUS]; | ||
85 | |||
86 | /* | 83 | /* |
87 | * this tells the system to map all of ram with the segregs | 84 | * this tells the system to map all of ram with the segregs |
88 | * (i.e. page tables) instead of the bats. | 85 | * (i.e. page tables) instead of the bats. |
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 2fd57fa48429..5f844337de21 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c | |||
@@ -116,6 +116,16 @@ int memory_add_physaddr_to_nid(u64 start) | |||
116 | } | 116 | } |
117 | #endif | 117 | #endif |
118 | 118 | ||
119 | int __weak create_section_mapping(unsigned long start, unsigned long end) | ||
120 | { | ||
121 | return -ENODEV; | ||
122 | } | ||
123 | |||
124 | int __weak remove_section_mapping(unsigned long start, unsigned long end) | ||
125 | { | ||
126 | return -ENODEV; | ||
127 | } | ||
128 | |||
119 | int arch_add_memory(int nid, u64 start, u64 size, bool for_device) | 129 | int arch_add_memory(int nid, u64 start, u64 size, bool for_device) |
120 | { | 130 | { |
121 | struct pglist_data *pgdata; | 131 | struct pglist_data *pgdata; |
@@ -239,8 +249,14 @@ static int __init mark_nonram_nosave(void) | |||
239 | 249 | ||
240 | static bool zone_limits_final; | 250 | static bool zone_limits_final; |
241 | 251 | ||
252 | /* | ||
253 | * The memory zones past TOP_ZONE are managed by generic mm code. | ||
254 | * These should be set to zero since that's what every other | ||
255 | * architecture does. | ||
256 | */ | ||
242 | static unsigned long max_zone_pfns[MAX_NR_ZONES] = { | 257 | static unsigned long max_zone_pfns[MAX_NR_ZONES] = { |
243 | [0 ... MAX_NR_ZONES - 1] = ~0UL | 258 | [0 ... TOP_ZONE ] = ~0UL, |
259 | [TOP_ZONE + 1 ... MAX_NR_ZONES - 1] = 0 | ||
244 | }; | 260 | }; |
245 | 261 | ||
246 | /* | 262 | /* |
diff --git a/arch/powerpc/mm/mmu_context_book3s64.c b/arch/powerpc/mm/mmu_context_book3s64.c index 196222227e82..b114f8b93ec9 100644 --- a/arch/powerpc/mm/mmu_context_book3s64.c +++ b/arch/powerpc/mm/mmu_context_book3s64.c | |||
@@ -181,7 +181,10 @@ void destroy_context(struct mm_struct *mm) | |||
181 | #ifdef CONFIG_PPC_RADIX_MMU | 181 | #ifdef CONFIG_PPC_RADIX_MMU |
182 | void radix__switch_mmu_context(struct mm_struct *prev, struct mm_struct *next) | 182 | void radix__switch_mmu_context(struct mm_struct *prev, struct mm_struct *next) |
183 | { | 183 | { |
184 | mtspr(SPRN_PID, next->context.id); | ||
185 | asm volatile("isync": : :"memory"); | 184 | asm volatile("isync": : :"memory"); |
185 | mtspr(SPRN_PID, next->context.id); | ||
186 | asm volatile("isync \n" | ||
187 | PPC_SLBIA(0x7) | ||
188 | : : :"memory"); | ||
186 | } | 189 | } |
187 | #endif | 190 | #endif |
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h index 6af65327c993..f988db655e5b 100644 --- a/arch/powerpc/mm/mmu_decl.h +++ b/arch/powerpc/mm/mmu_decl.h | |||
@@ -154,9 +154,10 @@ struct tlbcam { | |||
154 | }; | 154 | }; |
155 | #endif | 155 | #endif |
156 | 156 | ||
157 | #if defined(CONFIG_6xx) || defined(CONFIG_FSL_BOOKE) | 157 | #if defined(CONFIG_6xx) || defined(CONFIG_FSL_BOOKE) || defined(CONFIG_PPC_8xx) |
158 | /* 6xx have BATS */ | 158 | /* 6xx have BATS */ |
159 | /* FSL_BOOKE have TLBCAM */ | 159 | /* FSL_BOOKE have TLBCAM */ |
160 | /* 8xx have LTLB */ | ||
160 | phys_addr_t v_block_mapped(unsigned long va); | 161 | phys_addr_t v_block_mapped(unsigned long va); |
161 | unsigned long p_block_mapped(phys_addr_t pa); | 162 | unsigned long p_block_mapped(phys_addr_t pa); |
162 | #else | 163 | #else |
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 6dc07ddbfd04..75b9cd6150cc 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c | |||
@@ -1153,18 +1153,34 @@ int hot_add_scn_to_nid(unsigned long scn_addr) | |||
1153 | 1153 | ||
1154 | static u64 hot_add_drconf_memory_max(void) | 1154 | static u64 hot_add_drconf_memory_max(void) |
1155 | { | 1155 | { |
1156 | struct device_node *memory = NULL; | 1156 | struct device_node *memory = NULL; |
1157 | unsigned int drconf_cell_cnt = 0; | 1157 | struct device_node *dn = NULL; |
1158 | u64 lmb_size = 0; | 1158 | unsigned int drconf_cell_cnt = 0; |
1159 | u64 lmb_size = 0; | ||
1159 | const __be32 *dm = NULL; | 1160 | const __be32 *dm = NULL; |
1161 | const __be64 *lrdr = NULL; | ||
1162 | struct of_drconf_cell drmem; | ||
1163 | |||
1164 | dn = of_find_node_by_path("/rtas"); | ||
1165 | if (dn) { | ||
1166 | lrdr = of_get_property(dn, "ibm,lrdr-capacity", NULL); | ||
1167 | of_node_put(dn); | ||
1168 | if (lrdr) | ||
1169 | return be64_to_cpup(lrdr); | ||
1170 | } | ||
1171 | |||
1172 | memory = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory"); | ||
1173 | if (memory) { | ||
1174 | drconf_cell_cnt = of_get_drconf_memory(memory, &dm); | ||
1175 | lmb_size = of_get_lmb_size(memory); | ||
1160 | 1176 | ||
1161 | memory = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory"); | 1177 | /* Advance to the last cell, each cell has 6 32 bit integers */ |
1162 | if (memory) { | 1178 | dm += (drconf_cell_cnt - 1) * 6; |
1163 | drconf_cell_cnt = of_get_drconf_memory(memory, &dm); | 1179 | read_drconf_cell(&drmem, &dm); |
1164 | lmb_size = of_get_lmb_size(memory); | 1180 | of_node_put(memory); |
1165 | of_node_put(memory); | 1181 | return drmem.base_addr + lmb_size; |
1166 | } | 1182 | } |
1167 | return lmb_size * drconf_cell_cnt; | 1183 | return 0; |
1168 | } | 1184 | } |
1169 | 1185 | ||
1170 | /* | 1186 | /* |
diff --git a/arch/powerpc/mm/pgtable-radix.c b/arch/powerpc/mm/pgtable-radix.c index 7931e1496f0d..003ff48a11b6 100644 --- a/arch/powerpc/mm/pgtable-radix.c +++ b/arch/powerpc/mm/pgtable-radix.c | |||
@@ -21,8 +21,11 @@ | |||
21 | 21 | ||
22 | #include <trace/events/thp.h> | 22 | #include <trace/events/thp.h> |
23 | 23 | ||
24 | static int native_update_partition_table(u64 patb1) | 24 | static int native_register_process_table(unsigned long base, unsigned long pg_sz, |
25 | unsigned long table_size) | ||
25 | { | 26 | { |
27 | unsigned long patb1 = base | table_size | PATB_GR; | ||
28 | |||
26 | partition_tb->patb1 = cpu_to_be64(patb1); | 29 | partition_tb->patb1 = cpu_to_be64(patb1); |
27 | return 0; | 30 | return 0; |
28 | } | 31 | } |
@@ -168,7 +171,7 @@ redo: | |||
168 | * of process table here. But our linear mapping also enable us to use | 171 | * of process table here. But our linear mapping also enable us to use |
169 | * physical address here. | 172 | * physical address here. |
170 | */ | 173 | */ |
171 | ppc_md.update_partition_table(__pa(process_tb) | (PRTB_SIZE_SHIFT - 12) | PATB_GR); | 174 | ppc_md.register_process_table(__pa(process_tb), 0, PRTB_SIZE_SHIFT - 12); |
172 | pr_info("Process table %p and radix root for kernel: %p\n", process_tb, init_mm.pgd); | 175 | pr_info("Process table %p and radix root for kernel: %p\n", process_tb, init_mm.pgd); |
173 | } | 176 | } |
174 | 177 | ||
@@ -182,7 +185,8 @@ static void __init radix_init_partition_table(void) | |||
182 | partition_tb = early_alloc_pgtable(1UL << PATB_SIZE_SHIFT); | 185 | partition_tb = early_alloc_pgtable(1UL << PATB_SIZE_SHIFT); |
183 | partition_tb->patb0 = cpu_to_be64(rts_field | __pa(init_mm.pgd) | | 186 | partition_tb->patb0 = cpu_to_be64(rts_field | __pa(init_mm.pgd) | |
184 | RADIX_PGD_INDEX_SIZE | PATB_HR); | 187 | RADIX_PGD_INDEX_SIZE | PATB_HR); |
185 | printk("Partition table %p\n", partition_tb); | 188 | pr_info("Initializing Radix MMU\n"); |
189 | pr_info("Partition table %p\n", partition_tb); | ||
186 | 190 | ||
187 | memblock_set_current_limit(MEMBLOCK_ALLOC_ANYWHERE); | 191 | memblock_set_current_limit(MEMBLOCK_ALLOC_ANYWHERE); |
188 | /* | 192 | /* |
@@ -194,7 +198,7 @@ static void __init radix_init_partition_table(void) | |||
194 | 198 | ||
195 | void __init radix_init_native(void) | 199 | void __init radix_init_native(void) |
196 | { | 200 | { |
197 | ppc_md.update_partition_table = native_update_partition_table; | 201 | ppc_md.register_process_table = native_register_process_table; |
198 | } | 202 | } |
199 | 203 | ||
200 | static int __init get_idx_from_shift(unsigned int shift) | 204 | static int __init get_idx_from_shift(unsigned int shift) |
@@ -341,8 +345,9 @@ void __init radix__early_init_mmu(void) | |||
341 | 345 | ||
342 | radix_init_page_sizes(); | 346 | radix_init_page_sizes(); |
343 | if (!firmware_has_feature(FW_FEATURE_LPAR)) { | 347 | if (!firmware_has_feature(FW_FEATURE_LPAR)) { |
348 | radix_init_native(); | ||
344 | lpcr = mfspr(SPRN_LPCR); | 349 | lpcr = mfspr(SPRN_LPCR); |
345 | mtspr(SPRN_LPCR, lpcr | LPCR_UPRT); | 350 | mtspr(SPRN_LPCR, lpcr | LPCR_UPRT | LPCR_HR); |
346 | radix_init_partition_table(); | 351 | radix_init_partition_table(); |
347 | } | 352 | } |
348 | 353 | ||
@@ -357,7 +362,7 @@ void radix__early_init_mmu_secondary(void) | |||
357 | */ | 362 | */ |
358 | if (!firmware_has_feature(FW_FEATURE_LPAR)) { | 363 | if (!firmware_has_feature(FW_FEATURE_LPAR)) { |
359 | lpcr = mfspr(SPRN_LPCR); | 364 | lpcr = mfspr(SPRN_LPCR); |
360 | mtspr(SPRN_LPCR, lpcr | LPCR_UPRT); | 365 | mtspr(SPRN_LPCR, lpcr | LPCR_UPRT | LPCR_HR); |
361 | 366 | ||
362 | mtspr(SPRN_PTCR, | 367 | mtspr(SPRN_PTCR, |
363 | __pa(partition_tb) | (PATB_SIZE_SHIFT - 12)); | 368 | __pa(partition_tb) | (PATB_SIZE_SHIFT - 12)); |
diff --git a/arch/powerpc/mm/tlb-radix.c b/arch/powerpc/mm/tlb-radix.c index ab2f60e812e2..e1f22700fb16 100644 --- a/arch/powerpc/mm/tlb-radix.c +++ b/arch/powerpc/mm/tlb-radix.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/mm.h> | 12 | #include <linux/mm.h> |
13 | #include <linux/hugetlb.h> | 13 | #include <linux/hugetlb.h> |
14 | #include <linux/memblock.h> | 14 | #include <linux/memblock.h> |
15 | #include <asm/ppc-opcode.h> | ||
15 | 16 | ||
16 | #include <asm/tlb.h> | 17 | #include <asm/tlb.h> |
17 | #include <asm/tlbflush.h> | 18 | #include <asm/tlbflush.h> |
@@ -34,8 +35,7 @@ static inline void __tlbiel_pid(unsigned long pid, int set, | |||
34 | r = 1; /* raidx format */ | 35 | r = 1; /* raidx format */ |
35 | 36 | ||
36 | asm volatile("ptesync": : :"memory"); | 37 | asm volatile("ptesync": : :"memory"); |
37 | asm volatile(".long 0x7c000224 | (%0 << 11) | (%1 << 16) |" | 38 | asm volatile(PPC_TLBIEL(%0, %4, %3, %2, %1) |
38 | "(%2 << 17) | (%3 << 18) | (%4 << 21)" | ||
39 | : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory"); | 39 | : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory"); |
40 | asm volatile("ptesync": : :"memory"); | 40 | asm volatile("ptesync": : :"memory"); |
41 | } | 41 | } |
@@ -63,8 +63,7 @@ static inline void _tlbie_pid(unsigned long pid, unsigned long ric) | |||
63 | r = 1; /* raidx format */ | 63 | r = 1; /* raidx format */ |
64 | 64 | ||
65 | asm volatile("ptesync": : :"memory"); | 65 | asm volatile("ptesync": : :"memory"); |
66 | asm volatile(".long 0x7c000264 | (%0 << 11) | (%1 << 16) |" | 66 | asm volatile(PPC_TLBIE_5(%0, %4, %3, %2, %1) |
67 | "(%2 << 17) | (%3 << 18) | (%4 << 21)" | ||
68 | : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory"); | 67 | : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory"); |
69 | asm volatile("eieio; tlbsync; ptesync": : :"memory"); | 68 | asm volatile("eieio; tlbsync; ptesync": : :"memory"); |
70 | } | 69 | } |
@@ -81,8 +80,7 @@ static inline void _tlbiel_va(unsigned long va, unsigned long pid, | |||
81 | r = 1; /* raidx format */ | 80 | r = 1; /* raidx format */ |
82 | 81 | ||
83 | asm volatile("ptesync": : :"memory"); | 82 | asm volatile("ptesync": : :"memory"); |
84 | asm volatile(".long 0x7c000224 | (%0 << 11) | (%1 << 16) |" | 83 | asm volatile(PPC_TLBIEL(%0, %4, %3, %2, %1) |
85 | "(%2 << 17) | (%3 << 18) | (%4 << 21)" | ||
86 | : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory"); | 84 | : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory"); |
87 | asm volatile("ptesync": : :"memory"); | 85 | asm volatile("ptesync": : :"memory"); |
88 | } | 86 | } |
@@ -99,8 +97,7 @@ static inline void _tlbie_va(unsigned long va, unsigned long pid, | |||
99 | r = 1; /* raidx format */ | 97 | r = 1; /* raidx format */ |
100 | 98 | ||
101 | asm volatile("ptesync": : :"memory"); | 99 | asm volatile("ptesync": : :"memory"); |
102 | asm volatile(".long 0x7c000264 | (%0 << 11) | (%1 << 16) |" | 100 | asm volatile(PPC_TLBIE_5(%0, %4, %3, %2, %1) |
103 | "(%2 << 17) | (%3 << 18) | (%4 << 21)" | ||
104 | : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory"); | 101 | : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory"); |
105 | asm volatile("eieio; tlbsync; ptesync": : :"memory"); | 102 | asm volatile("eieio; tlbsync; ptesync": : :"memory"); |
106 | } | 103 | } |
@@ -285,9 +282,61 @@ void radix__flush_tlb_range(struct vm_area_struct *vma, unsigned long start, | |||
285 | } | 282 | } |
286 | EXPORT_SYMBOL(radix__flush_tlb_range); | 283 | EXPORT_SYMBOL(radix__flush_tlb_range); |
287 | 284 | ||
285 | static int radix_get_mmu_psize(int page_size) | ||
286 | { | ||
287 | int psize; | ||
288 | |||
289 | if (page_size == (1UL << mmu_psize_defs[mmu_virtual_psize].shift)) | ||
290 | psize = mmu_virtual_psize; | ||
291 | else if (page_size == (1UL << mmu_psize_defs[MMU_PAGE_2M].shift)) | ||
292 | psize = MMU_PAGE_2M; | ||
293 | else if (page_size == (1UL << mmu_psize_defs[MMU_PAGE_1G].shift)) | ||
294 | psize = MMU_PAGE_1G; | ||
295 | else | ||
296 | return -1; | ||
297 | return psize; | ||
298 | } | ||
288 | 299 | ||
289 | void radix__tlb_flush(struct mmu_gather *tlb) | 300 | void radix__tlb_flush(struct mmu_gather *tlb) |
290 | { | 301 | { |
291 | struct mm_struct *mm = tlb->mm; | 302 | struct mm_struct *mm = tlb->mm; |
292 | radix__flush_tlb_mm(mm); | 303 | radix__flush_tlb_mm(mm); |
293 | } | 304 | } |
305 | |||
306 | void radix__flush_tlb_lpid_va(unsigned long lpid, unsigned long gpa, | ||
307 | unsigned long page_size) | ||
308 | { | ||
309 | unsigned long rb,rs,prs,r; | ||
310 | unsigned long ap; | ||
311 | unsigned long ric = RIC_FLUSH_TLB; | ||
312 | |||
313 | ap = mmu_get_ap(radix_get_mmu_psize(page_size)); | ||
314 | rb = gpa & ~(PPC_BITMASK(52, 63)); | ||
315 | rb |= ap << PPC_BITLSHIFT(58); | ||
316 | rs = lpid & ((1UL << 32) - 1); | ||
317 | prs = 0; /* process scoped */ | ||
318 | r = 1; /* raidx format */ | ||
319 | |||
320 | asm volatile("ptesync": : :"memory"); | ||
321 | asm volatile(PPC_TLBIE_5(%0, %4, %3, %2, %1) | ||
322 | : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory"); | ||
323 | asm volatile("eieio; tlbsync; ptesync": : :"memory"); | ||
324 | } | ||
325 | EXPORT_SYMBOL(radix__flush_tlb_lpid_va); | ||
326 | |||
327 | void radix__flush_tlb_lpid(unsigned long lpid) | ||
328 | { | ||
329 | unsigned long rb,rs,prs,r; | ||
330 | unsigned long ric = RIC_FLUSH_ALL; | ||
331 | |||
332 | rb = 0x2 << PPC_BITLSHIFT(53); /* IS = 2 */ | ||
333 | rs = lpid & ((1UL << 32) - 1); | ||
334 | prs = 0; /* partition scoped */ | ||
335 | r = 1; /* raidx format */ | ||
336 | |||
337 | asm volatile("ptesync": : :"memory"); | ||
338 | asm volatile(PPC_TLBIE_5(%0, %4, %3, %2, %1) | ||
339 | : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory"); | ||
340 | asm volatile("eieio; tlbsync; ptesync": : :"memory"); | ||
341 | } | ||
342 | EXPORT_SYMBOL(radix__flush_tlb_lpid); | ||