powerpc fixes for 4.7 #5

- tm: Always reclaim in start_thread() for exec() class syscalls from Cyril Bur
  - tm: Avoid SLB faults in treclaim/trecheckpoint when RI=0 from Michael Neuling
  - eeh: Fix wrong argument passed to eeh_rmv_device() from Gavin Shan
  - Initialise pci_io_base as early as possible from Darren Stevens
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJXeEmsAAoJEFHr6jzI4aWAwMMQAKs/u9rwB3gpOkNJSHajN1Dd
 kdqDufzLxLDwbWnMfqM1+bcO2EOjPhKbtpbzhG6oeiET8undRRoLsjHS5rZeYK5h
 cviRPEJ/Yz8ZWaIgFGI8+02gXwU0MJhuTY8NPexXmsh4FRdKYwEuCIJShl30lg22
 P7UrJ2SCNM+H/uZyS07B7thiwBeAKSp6VkLTpuW/QDz2j1ra/F22dTh7c0Agdahd
 INAMAnh9nYeuMVYn4XjOOlQ07JnBTuf1/W5Wxlw4i/86rVq+Hy8zh5r1X52oysR5
 lZl63B9q3agKG9cc9lSN2ibTDVerlFMwB2QysX2a6Uy7+y2SB3hS7VS1RTXCh3hg
 /omApGGVW3Hh+E2CuKfFLQySU55NRpLAoTGravGr/KsH4wZP/n/fkrctldCrqm7P
 sTPT52+t+iJQk4fiskRY3yQ7DTTnt3rTC8MJRGqvLuCheolLll4NQaWOF75AJP+7
 WFWtC4QHOTPERMkhqLnZDG2vNuDg1H8chuZ2+PxtIs6G1vuOEun+MTZAYh4u6XWE
 bAIT9rV3xBdE17bzYOQz7lU1y7yNVtP7xkm0HIOAHlU4gUrjQp5u8F3TnPW3/M0m
 8GeaZdrPjhsaNg31YZODAeM8Ddf+N9d2a2VPIr/fzytURhMe0ss3Z/MdMoYRATab
 Lh1o+G3gDo9MVaphoJ3w
 =oEAY
 -----END PGP SIGNATURE-----

Merge tag 'powerpc-4.7-5' into next

Pull in the fixes we sent during 4.7, we have code we want to merge into
next that depends on some of them.
This commit is contained in:
Michael Ellerman 2016-07-15 14:57:47 +10:00
commit b5f1bf48f2
18 changed files with 201 additions and 69 deletions

View File

@ -102,7 +102,6 @@ static inline void pgtable_free_tlb(struct mmu_gather *tlb,
static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table, static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table,
unsigned long address) unsigned long address)
{ {
tlb_flush_pgtable(tlb, address);
pgtable_page_dtor(table); pgtable_page_dtor(table);
pgtable_free_tlb(tlb, page_address(table), 0); pgtable_free_tlb(tlb, page_address(table), 0);
} }

View File

@ -88,6 +88,7 @@
#define HPTE_R_RPN_SHIFT 12 #define HPTE_R_RPN_SHIFT 12
#define HPTE_R_RPN ASM_CONST(0x0ffffffffffff000) #define HPTE_R_RPN ASM_CONST(0x0ffffffffffff000)
#define HPTE_R_PP ASM_CONST(0x0000000000000003) #define HPTE_R_PP ASM_CONST(0x0000000000000003)
#define HPTE_R_PPP ASM_CONST(0x8000000000000003)
#define HPTE_R_N ASM_CONST(0x0000000000000004) #define HPTE_R_N ASM_CONST(0x0000000000000004)
#define HPTE_R_G ASM_CONST(0x0000000000000008) #define HPTE_R_G ASM_CONST(0x0000000000000008)
#define HPTE_R_M ASM_CONST(0x0000000000000010) #define HPTE_R_M ASM_CONST(0x0000000000000010)

View File

@ -110,6 +110,11 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud, static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
unsigned long address) unsigned long address)
{ {
/*
* By now all the pud entries should be none entries. So go
* ahead and flush the page walk cache
*/
flush_tlb_pgtable(tlb, address);
pgtable_free_tlb(tlb, pud, PUD_INDEX_SIZE); pgtable_free_tlb(tlb, pud, PUD_INDEX_SIZE);
} }
@ -127,6 +132,11 @@ static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd, static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
unsigned long address) unsigned long address)
{ {
/*
* By now all the pud entries should be none entries. So go
* ahead and flush the page walk cache
*/
flush_tlb_pgtable(tlb, address);
return pgtable_free_tlb(tlb, pmd, PMD_CACHE_INDEX); return pgtable_free_tlb(tlb, pmd, PMD_CACHE_INDEX);
} }
@ -198,7 +208,11 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage)
static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table, static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table,
unsigned long address) unsigned long address)
{ {
tlb_flush_pgtable(tlb, address); /*
* By now all the pud entries should be none entries. So go
* ahead and flush the page walk cache
*/
flush_tlb_pgtable(tlb, address);
pgtable_free_tlb(tlb, table, 0); pgtable_free_tlb(tlb, table, 0);
} }

View File

@ -230,6 +230,7 @@ extern unsigned long __kernel_virt_size;
#define KERN_VIRT_SIZE __kernel_virt_size #define KERN_VIRT_SIZE __kernel_virt_size
extern struct page *vmemmap; extern struct page *vmemmap;
extern unsigned long ioremap_bot; extern unsigned long ioremap_bot;
extern unsigned long pci_io_base;
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#include <asm/book3s/64/hash.h> #include <asm/book3s/64/hash.h>

View File

@ -228,5 +228,20 @@ extern void radix__vmemmap_remove_mapping(unsigned long start,
extern int radix__map_kernel_page(unsigned long ea, unsigned long pa, extern int radix__map_kernel_page(unsigned long ea, unsigned long pa,
pgprot_t flags, unsigned int psz); pgprot_t flags, unsigned int psz);
static inline unsigned long radix__get_tree_size(void)
{
unsigned long rts_field;
/*
* we support 52 bits, hence 52-31 = 21, 0b10101
* RTS encoding details
* bits 0 - 3 of rts -> bits 6 - 8 unsigned long
* bits 4 - 5 of rts -> bits 62 - 63 of unsigned long
*/
rts_field = (0x5UL << 5); /* 6 - 8 bits */
rts_field |= (0x2UL << 61);
return rts_field;
}
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#endif #endif

View File

@ -18,16 +18,19 @@ extern void radix__local_flush_tlb_mm(struct mm_struct *mm);
extern void radix__local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); extern void radix__local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
extern void radix___local_flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr, extern void radix___local_flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
unsigned long ap, int nid); unsigned long ap, int nid);
extern void radix__local_flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr);
extern void radix__tlb_flush(struct mmu_gather *tlb); extern void radix__tlb_flush(struct mmu_gather *tlb);
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
extern void radix__flush_tlb_mm(struct mm_struct *mm); extern void radix__flush_tlb_mm(struct mm_struct *mm);
extern void radix__flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); extern void radix__flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
extern void radix___flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr, extern void radix___flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
unsigned long ap, int nid); unsigned long ap, int nid);
extern void radix__flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr);
#else #else
#define radix__flush_tlb_mm(mm) radix__local_flush_tlb_mm(mm) #define radix__flush_tlb_mm(mm) radix__local_flush_tlb_mm(mm)
#define radix__flush_tlb_page(vma,addr) radix__local_flush_tlb_page(vma,addr) #define radix__flush_tlb_page(vma,addr) radix__local_flush_tlb_page(vma,addr)
#define radix___flush_tlb_page(mm,addr,p,i) radix___local_flush_tlb_page(mm,addr,p,i) #define radix___flush_tlb_page(mm,addr,p,i) radix___local_flush_tlb_page(mm,addr,p,i)
#define radix__flush_tlb_pwc(tlb, addr) radix__local_flush_tlb_pwc(tlb, addr)
#endif #endif
#endif #endif

View File

@ -72,5 +72,19 @@ static inline void flush_tlb_page(struct vm_area_struct *vma,
#define flush_tlb_mm(mm) local_flush_tlb_mm(mm) #define flush_tlb_mm(mm) local_flush_tlb_mm(mm)
#define flush_tlb_page(vma, addr) local_flush_tlb_page(vma, addr) #define flush_tlb_page(vma, addr) local_flush_tlb_page(vma, addr)
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
/*
* flush the page walk cache for the address
*/
static inline void flush_tlb_pgtable(struct mmu_gather *tlb, unsigned long address)
{
/*
* Flush the page table walk cache on freeing a page table. We already
* have marked the upper/higher level page table entry none by now.
* So it is safe to flush PWC here.
*/
if (!radix_enabled())
return;
radix__flush_tlb_pwc(tlb, address);
}
#endif /* _ASM_POWERPC_BOOK3S_64_TLBFLUSH_H */ #endif /* _ASM_POWERPC_BOOK3S_64_TLBFLUSH_H */

View File

@ -4,11 +4,6 @@
#include <linux/mm.h> #include <linux/mm.h>
extern void tlb_remove_table(struct mmu_gather *tlb, void *table); extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
static inline void tlb_flush_pgtable(struct mmu_gather *tlb,
unsigned long address)
{
}
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
#include <asm/book3s/64/pgalloc.h> #include <asm/book3s/64/pgalloc.h>

View File

@ -642,13 +642,12 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus,
if (pe->type & EEH_PE_VF) { if (pe->type & EEH_PE_VF) {
eeh_pe_dev_traverse(pe, eeh_rmv_device, NULL); eeh_pe_dev_traverse(pe, eeh_rmv_device, NULL);
} else { } else {
eeh_pe_state_clear(pe, EEH_PE_PRI_BUS);
pci_lock_rescan_remove(); pci_lock_rescan_remove();
pci_hp_remove_devices(bus); pci_hp_remove_devices(bus);
pci_unlock_rescan_remove(); pci_unlock_rescan_remove();
} }
} else if (frozen_bus) { } else if (frozen_bus) {
eeh_pe_dev_traverse(pe, eeh_rmv_device, &rmv_data); eeh_pe_dev_traverse(pe, eeh_rmv_device, rmv_data);
} }
/* /*
@ -692,10 +691,12 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus,
*/ */
edev = list_first_entry(&pe->edevs, struct eeh_dev, list); edev = list_first_entry(&pe->edevs, struct eeh_dev, list);
eeh_pe_traverse(pe, eeh_pe_detach_dev, NULL); eeh_pe_traverse(pe, eeh_pe_detach_dev, NULL);
if (pe->type & EEH_PE_VF) if (pe->type & EEH_PE_VF) {
eeh_add_virt_device(edev, NULL); eeh_add_virt_device(edev, NULL);
else } else {
eeh_pe_state_clear(pe, EEH_PE_PRI_BUS);
pci_hp_add_devices(bus); pci_hp_add_devices(bus);
}
} else if (frozen_bus && rmv_data->removed) { } else if (frozen_bus && rmv_data->removed) {
pr_info("EEH: Sleep 5s ahead of partial hotplug\n"); pr_info("EEH: Sleep 5s ahead of partial hotplug\n");
ssleep(5); ssleep(5);

View File

@ -1399,11 +1399,12 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_RADIX)
lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */
mtlr r10 mtlr r10
BEGIN_MMU_FTR_SECTION
b 2f
END_MMU_FTR_SECTION_IFSET(MMU_FTR_RADIX)
andi. r10,r12,MSR_RI /* check for unrecoverable exception */ andi. r10,r12,MSR_RI /* check for unrecoverable exception */
BEGIN_MMU_FTR_SECTION
beq- 2f beq- 2f
FTR_SECTION_ELSE
b 2f
ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_RADIX)
.machine push .machine push
.machine "power4" .machine "power4"

View File

@ -47,7 +47,6 @@ static int __init pcibios_init(void)
printk(KERN_INFO "PCI: Probing PCI hardware\n"); printk(KERN_INFO "PCI: Probing PCI hardware\n");
pci_io_base = ISA_IO_BASE;
/* For now, override phys_mem_access_prot. If we need it,g /* For now, override phys_mem_access_prot. If we need it,g
* later, we may move that initialization to each ppc_md * later, we may move that initialization to each ppc_md
*/ */

View File

@ -1527,6 +1527,16 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
current->thread.regs = regs - 1; current->thread.regs = regs - 1;
} }
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
/*
* Clear any transactional state, we're exec()ing. The cause is
* not important as there will never be a recheckpoint so it's not
* user visible.
*/
if (MSR_TM_SUSPENDED(mfmsr()))
tm_reclaim_current(0);
#endif
memset(regs->gpr, 0, sizeof(regs->gpr)); memset(regs->gpr, 0, sizeof(regs->gpr));
regs->ctr = 0; regs->ctr = 0;
regs->link = 0; regs->link = 0;

View File

@ -110,17 +110,11 @@ _GLOBAL(tm_reclaim)
std r3, STK_PARAM(R3)(r1) std r3, STK_PARAM(R3)(r1)
SAVE_NVGPRS(r1) SAVE_NVGPRS(r1)
/* We need to setup MSR for VSX register save instructions. Here we /* We need to setup MSR for VSX register save instructions. */
* also clear the MSR RI since when we do the treclaim, we won't have a
* valid kernel pointer for a while. We clear RI here as it avoids
* adding another mtmsr closer to the treclaim. This makes the region
* maked as non-recoverable wider than it needs to be but it saves on
* inserting another mtmsrd later.
*/
mfmsr r14 mfmsr r14
mr r15, r14 mr r15, r14
ori r15, r15, MSR_FP ori r15, r15, MSR_FP
li r16, MSR_RI li r16, 0
ori r16, r16, MSR_EE /* IRQs hard off */ ori r16, r16, MSR_EE /* IRQs hard off */
andc r15, r15, r16 andc r15, r15, r16
oris r15, r15, MSR_VEC@h oris r15, r15, MSR_VEC@h
@ -176,7 +170,17 @@ dont_backup_fp:
1: tdeqi r6, 0 1: tdeqi r6, 0
EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,0 EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,0
/* The moment we treclaim, ALL of our GPRs will switch /* Clear MSR RI since we are about to change r1, EE is already off. */
li r4, 0
mtmsrd r4, 1
/*
* BE CAREFUL HERE:
* At this point we can't take an SLB miss since we have MSR_RI
* off. Load only to/from the stack/paca which are in SLB bolted regions
* until we turn MSR RI back on.
*
* The moment we treclaim, ALL of our GPRs will switch
* to user register state. (FPRs, CCR etc. also!) * to user register state. (FPRs, CCR etc. also!)
* Use an sprg and a tm_scratch in the PACA to shuffle. * Use an sprg and a tm_scratch in the PACA to shuffle.
*/ */
@ -197,6 +201,11 @@ dont_backup_fp:
/* Store the PPR in r11 and reset to decent value */ /* Store the PPR in r11 and reset to decent value */
std r11, GPR11(r1) /* Temporary stash */ std r11, GPR11(r1) /* Temporary stash */
/* Reset MSR RI so we can take SLB faults again */
li r11, MSR_RI
mtmsrd r11, 1
mfspr r11, SPRN_PPR mfspr r11, SPRN_PPR
HMT_MEDIUM HMT_MEDIUM
@ -397,11 +406,6 @@ restore_gprs:
ld r5, THREAD_TM_DSCR(r3) ld r5, THREAD_TM_DSCR(r3)
ld r6, THREAD_TM_PPR(r3) ld r6, THREAD_TM_PPR(r3)
/* Clear the MSR RI since we are about to change R1. EE is already off
*/
li r4, 0
mtmsrd r4, 1
REST_GPR(0, r7) /* GPR0 */ REST_GPR(0, r7) /* GPR0 */
REST_2GPRS(2, r7) /* GPR2-3 */ REST_2GPRS(2, r7) /* GPR2-3 */
REST_GPR(4, r7) /* GPR4 */ REST_GPR(4, r7) /* GPR4 */
@ -439,10 +443,33 @@ restore_gprs:
ld r6, _CCR(r7) ld r6, _CCR(r7)
mtcr r6 mtcr r6
REST_GPR(1, r7) /* GPR1 */
REST_GPR(5, r7) /* GPR5-7 */
REST_GPR(6, r7) REST_GPR(6, r7)
ld r7, GPR7(r7)
/*
* Store r1 and r5 on the stack so that we can access them
* after we clear MSR RI.
*/
REST_GPR(5, r7)
std r5, -8(r1)
ld r5, GPR1(r7)
std r5, -16(r1)
REST_GPR(7, r7)
/* Clear MSR RI since we are about to change r1. EE is already off */
li r5, 0
mtmsrd r5, 1
/*
* BE CAREFUL HERE:
* At this point we can't take an SLB miss since we have MSR_RI
* off. Load only to/from the stack/paca which are in SLB bolted regions
* until we turn MSR RI back on.
*/
ld r5, -8(r1)
ld r1, -16(r1)
/* Commit register state as checkpointed state: */ /* Commit register state as checkpointed state: */
TRECHKPT TRECHKPT

View File

@ -316,8 +316,8 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
DBG_LOW(" -> hit\n"); DBG_LOW(" -> hit\n");
/* Update the HPTE */ /* Update the HPTE */
hptep->r = cpu_to_be64((be64_to_cpu(hptep->r) & hptep->r = cpu_to_be64((be64_to_cpu(hptep->r) &
~(HPTE_R_PP | HPTE_R_N)) | ~(HPTE_R_PPP | HPTE_R_N)) |
(newpp & (HPTE_R_PP | HPTE_R_N | (newpp & (HPTE_R_PPP | HPTE_R_N |
HPTE_R_C))); HPTE_R_C)));
} }
native_unlock_hpte(hptep); native_unlock_hpte(hptep);
@ -385,8 +385,8 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
/* Update the HPTE */ /* Update the HPTE */
hptep->r = cpu_to_be64((be64_to_cpu(hptep->r) & hptep->r = cpu_to_be64((be64_to_cpu(hptep->r) &
~(HPTE_R_PP | HPTE_R_N)) | ~(HPTE_R_PPP | HPTE_R_N)) |
(newpp & (HPTE_R_PP | HPTE_R_N))); (newpp & (HPTE_R_PPP | HPTE_R_N)));
/* /*
* Ensure it is out of the tlb too. Bolted entries base and * Ensure it is out of the tlb too. Bolted entries base and
* actual page size will be same. * actual page size will be same.

View File

@ -201,9 +201,8 @@ unsigned long htab_convert_pte_flags(unsigned long pteflags)
/* /*
* We can't allow hardware to update hpte bits. Hence always * We can't allow hardware to update hpte bits. Hence always
* set 'R' bit and set 'C' if it is a write fault * set 'R' bit and set 'C' if it is a write fault
* Memory coherence is always enabled
*/ */
rflags |= HPTE_R_R | HPTE_R_M; rflags |= HPTE_R_R;
if (pteflags & _PAGE_DIRTY) if (pteflags & _PAGE_DIRTY)
rflags |= HPTE_R_C; rflags |= HPTE_R_C;
@ -213,10 +212,15 @@ unsigned long htab_convert_pte_flags(unsigned long pteflags)
if ((pteflags & _PAGE_CACHE_CTL) == _PAGE_TOLERANT) if ((pteflags & _PAGE_CACHE_CTL) == _PAGE_TOLERANT)
rflags |= HPTE_R_I; rflags |= HPTE_R_I;
if ((pteflags & _PAGE_CACHE_CTL ) == _PAGE_NON_IDEMPOTENT) else if ((pteflags & _PAGE_CACHE_CTL) == _PAGE_NON_IDEMPOTENT)
rflags |= (HPTE_R_I | HPTE_R_G); rflags |= (HPTE_R_I | HPTE_R_G);
if ((pteflags & _PAGE_CACHE_CTL) == _PAGE_SAO) else if ((pteflags & _PAGE_CACHE_CTL) == _PAGE_SAO)
rflags |= (HPTE_R_I | HPTE_R_W); rflags |= (HPTE_R_W | HPTE_R_I | HPTE_R_M);
else
/*
* Add memory coherence if cache inhibited is not set
*/
rflags |= HPTE_R_M;
return rflags; return rflags;
} }
@ -933,6 +937,10 @@ void __init hash__early_init_mmu(void)
vmemmap = (struct page *)H_VMEMMAP_BASE; vmemmap = (struct page *)H_VMEMMAP_BASE;
ioremap_bot = IOREMAP_BASE; ioremap_bot = IOREMAP_BASE;
#ifdef CONFIG_PCI
pci_io_base = ISA_IO_BASE;
#endif
/* Initialize the MMU Hash table and create the linear mapping /* Initialize the MMU Hash table and create the linear mapping
* of memory. Has to be done before SLB initialization as this is * of memory. Has to be done before SLB initialization as this is
* currently where the page size encoding is obtained. * currently where the page size encoding is obtained.

View File

@ -65,7 +65,7 @@ static int radix__init_new_context(struct mm_struct *mm, int index)
/* /*
* set the process table entry, * set the process table entry,
*/ */
rts_field = 3ull << PPC_BITLSHIFT(2); rts_field = radix__get_tree_size();
process_tb[index].prtb0 = cpu_to_be64(rts_field | __pa(mm->pgd) | RADIX_PGD_INDEX_SIZE); process_tb[index].prtb0 = cpu_to_be64(rts_field | __pa(mm->pgd) | RADIX_PGD_INDEX_SIZE);
return 0; return 0;
} }

View File

@ -160,9 +160,8 @@ redo:
process_tb = early_alloc_pgtable(1UL << PRTB_SIZE_SHIFT); process_tb = early_alloc_pgtable(1UL << PRTB_SIZE_SHIFT);
/* /*
* Fill in the process table. * Fill in the process table.
* we support 52 bits, hence 52-28 = 24, 11000
*/ */
rts_field = 3ull << PPC_BITLSHIFT(2); rts_field = radix__get_tree_size();
process_tb->prtb0 = cpu_to_be64(rts_field | __pa(init_mm.pgd) | RADIX_PGD_INDEX_SIZE); process_tb->prtb0 = cpu_to_be64(rts_field | __pa(init_mm.pgd) | RADIX_PGD_INDEX_SIZE);
/* /*
* Fill in the partition table. We are suppose to use effective address * Fill in the partition table. We are suppose to use effective address
@ -176,10 +175,8 @@ redo:
static void __init radix_init_partition_table(void) static void __init radix_init_partition_table(void)
{ {
unsigned long rts_field; unsigned long rts_field;
/*
* we support 52 bits, hence 52-28 = 24, 11000 rts_field = radix__get_tree_size();
*/
rts_field = 3ull << PPC_BITLSHIFT(2);
BUILD_BUG_ON_MSG((PATB_SIZE_SHIFT > 24), "Partition table size too large."); BUILD_BUG_ON_MSG((PATB_SIZE_SHIFT > 24), "Partition table size too large.");
partition_tb = early_alloc_pgtable(1UL << PATB_SIZE_SHIFT); partition_tb = early_alloc_pgtable(1UL << PATB_SIZE_SHIFT);
@ -331,6 +328,11 @@ void __init radix__early_init_mmu(void)
__vmalloc_end = RADIX_VMALLOC_END; __vmalloc_end = RADIX_VMALLOC_END;
vmemmap = (struct page *)RADIX_VMEMMAP_BASE; vmemmap = (struct page *)RADIX_VMEMMAP_BASE;
ioremap_bot = IOREMAP_BASE; ioremap_bot = IOREMAP_BASE;
#ifdef CONFIG_PCI
pci_io_base = ISA_IO_BASE;
#endif
/* /*
* For now radix also use the same frag size * For now radix also use the same frag size
*/ */

View File

@ -18,16 +18,20 @@
static DEFINE_RAW_SPINLOCK(native_tlbie_lock); static DEFINE_RAW_SPINLOCK(native_tlbie_lock);
static inline void __tlbiel_pid(unsigned long pid, int set) #define RIC_FLUSH_TLB 0
#define RIC_FLUSH_PWC 1
#define RIC_FLUSH_ALL 2
static inline void __tlbiel_pid(unsigned long pid, int set,
unsigned long ric)
{ {
unsigned long rb,rs,ric,prs,r; unsigned long rb,rs,prs,r;
rb = PPC_BIT(53); /* IS = 1 */ rb = PPC_BIT(53); /* IS = 1 */
rb |= set << PPC_BITLSHIFT(51); rb |= set << PPC_BITLSHIFT(51);
rs = ((unsigned long)pid) << PPC_BITLSHIFT(31); rs = ((unsigned long)pid) << PPC_BITLSHIFT(31);
prs = 1; /* process scoped */ prs = 1; /* process scoped */
r = 1; /* raidx format */ r = 1; /* raidx format */
ric = 2; /* invalidate all the caches */
asm volatile("ptesync": : :"memory"); asm volatile("ptesync": : :"memory");
asm volatile(".long 0x7c000224 | (%0 << 11) | (%1 << 16) |" asm volatile(".long 0x7c000224 | (%0 << 11) | (%1 << 16) |"
@ -39,25 +43,24 @@ static inline void __tlbiel_pid(unsigned long pid, int set)
/* /*
* We use 128 set in radix mode and 256 set in hpt mode. * We use 128 set in radix mode and 256 set in hpt mode.
*/ */
static inline void _tlbiel_pid(unsigned long pid) static inline void _tlbiel_pid(unsigned long pid, unsigned long ric)
{ {
int set; int set;
for (set = 0; set < POWER9_TLB_SETS_RADIX ; set++) { for (set = 0; set < POWER9_TLB_SETS_RADIX ; set++) {
__tlbiel_pid(pid, set); __tlbiel_pid(pid, set, ric);
} }
return; return;
} }
static inline void _tlbie_pid(unsigned long pid) static inline void _tlbie_pid(unsigned long pid, unsigned long ric)
{ {
unsigned long rb,rs,ric,prs,r; unsigned long rb,rs,prs,r;
rb = PPC_BIT(53); /* IS = 1 */ rb = PPC_BIT(53); /* IS = 1 */
rs = pid << PPC_BITLSHIFT(31); rs = pid << PPC_BITLSHIFT(31);
prs = 1; /* process scoped */ prs = 1; /* process scoped */
r = 1; /* raidx format */ r = 1; /* raidx format */
ric = 2; /* invalidate all the caches */
asm volatile("ptesync": : :"memory"); asm volatile("ptesync": : :"memory");
asm volatile(".long 0x7c000264 | (%0 << 11) | (%1 << 16) |" asm volatile(".long 0x7c000264 | (%0 << 11) | (%1 << 16) |"
@ -67,16 +70,15 @@ static inline void _tlbie_pid(unsigned long pid)
} }
static inline void _tlbiel_va(unsigned long va, unsigned long pid, static inline void _tlbiel_va(unsigned long va, unsigned long pid,
unsigned long ap) unsigned long ap, unsigned long ric)
{ {
unsigned long rb,rs,ric,prs,r; unsigned long rb,rs,prs,r;
rb = va & ~(PPC_BITMASK(52, 63)); rb = va & ~(PPC_BITMASK(52, 63));
rb |= ap << PPC_BITLSHIFT(58); rb |= ap << PPC_BITLSHIFT(58);
rs = pid << PPC_BITLSHIFT(31); rs = pid << PPC_BITLSHIFT(31);
prs = 1; /* process scoped */ prs = 1; /* process scoped */
r = 1; /* raidx format */ r = 1; /* raidx format */
ric = 0; /* no cluster flush yet */
asm volatile("ptesync": : :"memory"); asm volatile("ptesync": : :"memory");
asm volatile(".long 0x7c000224 | (%0 << 11) | (%1 << 16) |" asm volatile(".long 0x7c000224 | (%0 << 11) | (%1 << 16) |"
@ -86,16 +88,15 @@ static inline void _tlbiel_va(unsigned long va, unsigned long pid,
} }
static inline void _tlbie_va(unsigned long va, unsigned long pid, static inline void _tlbie_va(unsigned long va, unsigned long pid,
unsigned long ap) unsigned long ap, unsigned long ric)
{ {
unsigned long rb,rs,ric,prs,r; unsigned long rb,rs,prs,r;
rb = va & ~(PPC_BITMASK(52, 63)); rb = va & ~(PPC_BITMASK(52, 63));
rb |= ap << PPC_BITLSHIFT(58); rb |= ap << PPC_BITLSHIFT(58);
rs = pid << PPC_BITLSHIFT(31); rs = pid << PPC_BITLSHIFT(31);
prs = 1; /* process scoped */ prs = 1; /* process scoped */
r = 1; /* raidx format */ r = 1; /* raidx format */
ric = 0; /* no cluster flush yet */
asm volatile("ptesync": : :"memory"); asm volatile("ptesync": : :"memory");
asm volatile(".long 0x7c000264 | (%0 << 11) | (%1 << 16) |" asm volatile(".long 0x7c000264 | (%0 << 11) | (%1 << 16) |"
@ -122,11 +123,26 @@ void radix__local_flush_tlb_mm(struct mm_struct *mm)
preempt_disable(); preempt_disable();
pid = mm->context.id; pid = mm->context.id;
if (pid != MMU_NO_CONTEXT) if (pid != MMU_NO_CONTEXT)
_tlbiel_pid(pid); _tlbiel_pid(pid, RIC_FLUSH_ALL);
preempt_enable(); preempt_enable();
} }
EXPORT_SYMBOL(radix__local_flush_tlb_mm); EXPORT_SYMBOL(radix__local_flush_tlb_mm);
void radix__local_flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr)
{
unsigned long pid;
struct mm_struct *mm = tlb->mm;
preempt_disable();
pid = mm->context.id;
if (pid != MMU_NO_CONTEXT)
_tlbiel_pid(pid, RIC_FLUSH_PWC);
preempt_enable();
}
EXPORT_SYMBOL(radix__local_flush_tlb_pwc);
void radix___local_flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr, void radix___local_flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
unsigned long ap, int nid) unsigned long ap, int nid)
{ {
@ -135,7 +151,7 @@ void radix___local_flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
preempt_disable(); preempt_disable();
pid = mm ? mm->context.id : 0; pid = mm ? mm->context.id : 0;
if (pid != MMU_NO_CONTEXT) if (pid != MMU_NO_CONTEXT)
_tlbiel_va(vmaddr, pid, ap); _tlbiel_va(vmaddr, pid, ap, RIC_FLUSH_TLB);
preempt_enable(); preempt_enable();
} }
@ -172,16 +188,42 @@ void radix__flush_tlb_mm(struct mm_struct *mm)
if (lock_tlbie) if (lock_tlbie)
raw_spin_lock(&native_tlbie_lock); raw_spin_lock(&native_tlbie_lock);
_tlbie_pid(pid); _tlbie_pid(pid, RIC_FLUSH_ALL);
if (lock_tlbie) if (lock_tlbie)
raw_spin_unlock(&native_tlbie_lock); raw_spin_unlock(&native_tlbie_lock);
} else } else
_tlbiel_pid(pid); _tlbiel_pid(pid, RIC_FLUSH_ALL);
no_context: no_context:
preempt_enable(); preempt_enable();
} }
EXPORT_SYMBOL(radix__flush_tlb_mm); EXPORT_SYMBOL(radix__flush_tlb_mm);
void radix__flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr)
{
unsigned long pid;
struct mm_struct *mm = tlb->mm;
preempt_disable();
pid = mm->context.id;
if (unlikely(pid == MMU_NO_CONTEXT))
goto no_context;
if (!mm_is_core_local(mm)) {
int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
if (lock_tlbie)
raw_spin_lock(&native_tlbie_lock);
_tlbie_pid(pid, RIC_FLUSH_PWC);
if (lock_tlbie)
raw_spin_unlock(&native_tlbie_lock);
} else
_tlbiel_pid(pid, RIC_FLUSH_PWC);
no_context:
preempt_enable();
}
EXPORT_SYMBOL(radix__flush_tlb_pwc);
void radix___flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr, void radix___flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
unsigned long ap, int nid) unsigned long ap, int nid)
{ {
@ -196,11 +238,11 @@ void radix___flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
if (lock_tlbie) if (lock_tlbie)
raw_spin_lock(&native_tlbie_lock); raw_spin_lock(&native_tlbie_lock);
_tlbie_va(vmaddr, pid, ap); _tlbie_va(vmaddr, pid, ap, RIC_FLUSH_TLB);
if (lock_tlbie) if (lock_tlbie)
raw_spin_unlock(&native_tlbie_lock); raw_spin_unlock(&native_tlbie_lock);
} else } else
_tlbiel_va(vmaddr, pid, ap); _tlbiel_va(vmaddr, pid, ap, RIC_FLUSH_TLB);
bail: bail:
preempt_enable(); preempt_enable();
} }
@ -224,7 +266,7 @@ void radix__flush_tlb_kernel_range(unsigned long start, unsigned long end)
if (lock_tlbie) if (lock_tlbie)
raw_spin_lock(&native_tlbie_lock); raw_spin_lock(&native_tlbie_lock);
_tlbie_pid(0); _tlbie_pid(0, RIC_FLUSH_ALL);
if (lock_tlbie) if (lock_tlbie)
raw_spin_unlock(&native_tlbie_lock); raw_spin_unlock(&native_tlbie_lock);
} }