mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-19 02:04:19 +08:00
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:
commit
b5f1bf48f2
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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 */
|
||||||
|
@ -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>
|
||||||
|
@ -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);
|
||||||
|
@ -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"
|
||||||
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user