aboutsummaryrefslogtreecommitdiff
path: root/arch/powerpc/include
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/include')
-rw-r--r--arch/powerpc/include/asm/bootx.h2
-rw-r--r--arch/powerpc/include/asm/code-patching.h4
-rw-r--r--arch/powerpc/include/asm/cputable.h4
-rw-r--r--arch/powerpc/include/asm/dbell.h43
-rw-r--r--arch/powerpc/include/asm/elf.h14
-rw-r--r--arch/powerpc/include/asm/ftrace.h39
-rw-r--r--arch/powerpc/include/asm/highmem.h2
-rw-r--r--arch/powerpc/include/asm/kvm.h2
-rw-r--r--arch/powerpc/include/asm/mmu-book3e.h (renamed from arch/powerpc/include/asm/mmu-fsl-booke.h)66
-rw-r--r--arch/powerpc/include/asm/mmu.h6
-rw-r--r--arch/powerpc/include/asm/pgtable-4k.h2
-rw-r--r--arch/powerpc/include/asm/pgtable-64k.h2
-rw-r--r--arch/powerpc/include/asm/pgtable-ppc32.h58
-rw-r--r--arch/powerpc/include/asm/pgtable-ppc64.h29
-rw-r--r--arch/powerpc/include/asm/pgtable.h84
-rw-r--r--arch/powerpc/include/asm/ppc-opcode.h73
-rw-r--r--arch/powerpc/include/asm/ppc_asm.h6
-rw-r--r--arch/powerpc/include/asm/ps3fb.h1
-rw-r--r--arch/powerpc/include/asm/spu_info.h3
-rw-r--r--arch/powerpc/include/asm/swab.h2
-rw-r--r--arch/powerpc/include/asm/system.h2
-rw-r--r--arch/powerpc/include/asm/thread_info.h7
22 files changed, 330 insertions, 121 deletions
diff --git a/arch/powerpc/include/asm/bootx.h b/arch/powerpc/include/asm/bootx.h
index 57b82e3f89c..60a3c9ef301 100644
--- a/arch/powerpc/include/asm/bootx.h
+++ b/arch/powerpc/include/asm/bootx.h
@@ -9,7 +9,7 @@
#ifndef __ASM_BOOTX_H__
#define __ASM_BOOTX_H__
-#include <asm/types.h>
+#include <linux/types.h>
#ifdef macintosh
#include <Types.h>
diff --git a/arch/powerpc/include/asm/code-patching.h b/arch/powerpc/include/asm/code-patching.h
index 107d9b915e3..37c32aba79b 100644
--- a/arch/powerpc/include/asm/code-patching.h
+++ b/arch/powerpc/include/asm/code-patching.h
@@ -11,9 +11,7 @@
*/
#include <asm/types.h>
-
-#define PPC_NOP_INSTR 0x60000000
-#define PPC_LWSYNC_INSTR 0x7c2004ac
+#include <asm/ppc-opcode.h>
/* Flags for create_branch:
* "b" == create_branch(addr, target, 0);
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index 4911104791c..fca161190db 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -145,6 +145,7 @@ extern const char *powerpc_base_platform;
#define CPU_FTR_USE_TB ASM_CONST(0x0000000000000040)
#define CPU_FTR_L2CSR ASM_CONST(0x0000000000000080)
#define CPU_FTR_601 ASM_CONST(0x0000000000000100)
+#define CPU_FTR_DBELL ASM_CONST(0x0000000000000200)
#define CPU_FTR_CAN_NAP ASM_CONST(0x0000000000000400)
#define CPU_FTR_L3CR ASM_CONST(0x0000000000000800)
#define CPU_FTR_L3_DISABLE_NAP ASM_CONST(0x0000000000001000)
@@ -373,7 +374,8 @@ extern const char *powerpc_base_platform;
CPU_FTR_NODSISRALIGN | CPU_FTR_NOEXECUTE)
#define CPU_FTRS_E500MC (CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_NODSISRALIGN | \
- CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE)
+ CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE | \
+ CPU_FTR_DBELL)
#define CPU_FTRS_GENERIC_32 (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)
/* 64-bit CPUs */
diff --git a/arch/powerpc/include/asm/dbell.h b/arch/powerpc/include/asm/dbell.h
new file mode 100644
index 00000000000..501189a543d
--- /dev/null
+++ b/arch/powerpc/include/asm/dbell.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2009 Freescale Semicondutor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * provides masks and opcode images for use by code generation, emulation
+ * and for instructions that older assemblers might not know about
+ */
+#ifndef _ASM_POWERPC_DBELL_H
+#define _ASM_POWERPC_DBELL_H
+
+#include <linux/smp.h>
+#include <linux/threads.h>
+
+#include <asm/ppc-opcode.h>
+
+#define PPC_DBELL_MSG_BRDCAST (0x04000000)
+#define PPC_DBELL_TYPE(x) (((x) & 0xf) << 28)
+enum ppc_dbell {
+ PPC_DBELL = 0, /* doorbell */
+ PPC_DBELL_CRIT = 1, /* critical doorbell */
+ PPC_G_DBELL = 2, /* guest doorbell */
+ PPC_G_DBELL_CRIT = 3, /* guest critical doorbell */
+ PPC_G_DBELL_MC = 4, /* guest mcheck doorbell */
+};
+
+#ifdef CONFIG_SMP
+extern unsigned long dbell_smp_message[NR_CPUS];
+extern void smp_dbell_message_pass(int target, int msg);
+#endif
+
+static inline void ppc_msgsnd(enum ppc_dbell type, u32 flags, u32 tag)
+{
+ u32 msg = PPC_DBELL_TYPE(type) | (flags & PPC_DBELL_MSG_BRDCAST) |
+ (tag & 0x07ffffff);
+
+ __asm__ __volatile__ (PPC_MSGSND(%0) : : "r" (msg));
+}
+
+#endif /* _ASM_POWERPC_DBELL_H */
diff --git a/arch/powerpc/include/asm/elf.h b/arch/powerpc/include/asm/elf.h
index cd46f023ec6..1a856b15226 100644
--- a/arch/powerpc/include/asm/elf.h
+++ b/arch/powerpc/include/asm/elf.h
@@ -7,7 +7,8 @@
#include <asm/string.h>
#endif
-#include <asm/types.h>
+#include <linux/types.h>
+
#include <asm/ptrace.h>
#include <asm/cputable.h>
#include <asm/auxvec.h>
@@ -178,7 +179,8 @@ typedef elf_fpreg_t elf_vsrreghalf_t32[ELF_NVSRHALFREG];
the loader. We need to make sure that it is out of the way of the program
that it will "exec", and that there is sufficient room for the brk. */
-#define ELF_ET_DYN_BASE (0x20000000)
+extern unsigned long randomize_et_dyn(unsigned long base);
+#define ELF_ET_DYN_BASE (randomize_et_dyn(0x20000000))
/*
* Our registers are always unsigned longs, whether we're a 32 bit
@@ -270,6 +272,14 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
int uses_interp);
#define VDSO_AUX_ENT(a,b) NEW_AUX_ENT(a,b);
+/* 1GB for 64bit, 8MB for 32bit */
+#define STACK_RND_MASK (is_32bit_task() ? \
+ (0x7ff >> (PAGE_SHIFT - 12)) : \
+ (0x3ffff >> (PAGE_SHIFT - 12)))
+
+extern unsigned long arch_randomize_brk(struct mm_struct *mm);
+#define arch_randomize_brk arch_randomize_brk
+
#endif /* __KERNEL__ */
/*
diff --git a/arch/powerpc/include/asm/ftrace.h b/arch/powerpc/include/asm/ftrace.h
index e5f2ae8362f..dde1296b8b4 100644
--- a/arch/powerpc/include/asm/ftrace.h
+++ b/arch/powerpc/include/asm/ftrace.h
@@ -5,7 +5,44 @@
#define MCOUNT_ADDR ((long)(_mcount))
#define MCOUNT_INSN_SIZE 4 /* sizeof mcount call */
-#ifndef __ASSEMBLY__
+#ifdef __ASSEMBLY__
+
+/* Based off of objdump optput from glibc */
+
+#define MCOUNT_SAVE_FRAME \
+ stwu r1,-48(r1); \
+ stw r3, 12(r1); \
+ stw r4, 16(r1); \
+ stw r5, 20(r1); \
+ stw r6, 24(r1); \
+ mflr r3; \
+ lwz r4, 52(r1); \
+ mfcr r5; \
+ stw r7, 28(r1); \
+ stw r8, 32(r1); \
+ stw r9, 36(r1); \
+ stw r10,40(r1); \
+ stw r3, 44(r1); \
+ stw r5, 8(r1)
+
+#define MCOUNT_RESTORE_FRAME \
+ lwz r6, 8(r1); \
+ lwz r0, 44(r1); \
+ lwz r3, 12(r1); \
+ mtctr r0; \
+ lwz r4, 16(r1); \
+ mtcr r6; \
+ lwz r5, 20(r1); \
+ lwz r6, 24(r1); \
+ lwz r0, 52(r1); \
+ lwz r7, 28(r1); \
+ lwz r8, 32(r1); \
+ mtlr r0; \
+ lwz r9, 36(r1); \
+ lwz r10,40(r1); \
+ addi r1, r1, 48
+
+#else /* !__ASSEMBLY__ */
extern void _mcount(void);
#ifdef CONFIG_DYNAMIC_FTRACE
diff --git a/arch/powerpc/include/asm/highmem.h b/arch/powerpc/include/asm/highmem.h
index a2907595067..545028f8648 100644
--- a/arch/powerpc/include/asm/highmem.h
+++ b/arch/powerpc/include/asm/highmem.h
@@ -99,7 +99,7 @@ static inline void *kmap_atomic_prot(struct page *page, enum km_type type, pgpro
#ifdef CONFIG_DEBUG_HIGHMEM
BUG_ON(!pte_none(*(kmap_pte-idx)));
#endif
- __set_pte_at(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot));
+ __set_pte_at(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot), 1);
local_flush_tlb_page(NULL, vaddr);
return (void*) vaddr;
diff --git a/arch/powerpc/include/asm/kvm.h b/arch/powerpc/include/asm/kvm.h
index f993e4198d5..4e0cf65f7f5 100644
--- a/arch/powerpc/include/asm/kvm.h
+++ b/arch/powerpc/include/asm/kvm.h
@@ -20,7 +20,7 @@
#ifndef __LINUX_KVM_POWERPC_H
#define __LINUX_KVM_POWERPC_H
-#include <asm/types.h>
+#include <linux/types.h>
struct kvm_regs {
__u64 pc;
diff --git a/arch/powerpc/include/asm/mmu-fsl-booke.h b/arch/powerpc/include/asm/mmu-book3e.h
index 3f941c0f7e8..c5363c3a720 100644
--- a/arch/powerpc/include/asm/mmu-fsl-booke.h
+++ b/arch/powerpc/include/asm/mmu-book3e.h
@@ -1,26 +1,42 @@
-#ifndef _ASM_POWERPC_MMU_FSL_BOOKE_H_
-#define _ASM_POWERPC_MMU_FSL_BOOKE_H_
+#ifndef _ASM_POWERPC_MMU_BOOK3E_H_
+#define _ASM_POWERPC_MMU_BOOK3E_H_
/*
- * Freescale Book-E MMU support
+ * Freescale Book-E/Book-3e (ISA 2.06+) MMU support
*/
-/* Book-E defined page sizes */
-#define BOOKE_PAGESZ_1K 0
-#define BOOKE_PAGESZ_4K 1
-#define BOOKE_PAGESZ_16K 2
-#define BOOKE_PAGESZ_64K 3
-#define BOOKE_PAGESZ_256K 4
-#define BOOKE_PAGESZ_1M 5
-#define BOOKE_PAGESZ_4M 6
-#define BOOKE_PAGESZ_16M 7
-#define BOOKE_PAGESZ_64M 8
-#define BOOKE_PAGESZ_256M 9
-#define BOOKE_PAGESZ_1GB 10
-#define BOOKE_PAGESZ_4GB 11
-#define BOOKE_PAGESZ_16GB 12
-#define BOOKE_PAGESZ_64GB 13
-#define BOOKE_PAGESZ_256GB 14
-#define BOOKE_PAGESZ_1TB 15
+/* Book-3e defined page sizes */
+#define BOOK3E_PAGESZ_1K 0
+#define BOOK3E_PAGESZ_2K 1
+#define BOOK3E_PAGESZ_4K 2
+#define BOOK3E_PAGESZ_8K 3
+#define BOOK3E_PAGESZ_16K 4
+#define BOOK3E_PAGESZ_32K 5
+#define BOOK3E_PAGESZ_64K 6
+#define BOOK3E_PAGESZ_128K 7
+#define BOOK3E_PAGESZ_256K 8
+#define BOOK3E_PAGESZ_512K 9
+#define BOOK3E_PAGESZ_1M 10
+#define BOOK3E_PAGESZ_2M 11
+#define BOOK3E_PAGESZ_4M 12
+#define BOOK3E_PAGESZ_8M 13
+#define BOOK3E_PAGESZ_16M 14
+#define BOOK3E_PAGESZ_32M 15
+#define BOOK3E_PAGESZ_64M 16
+#define BOOK3E_PAGESZ_128M 17
+#define BOOK3E_PAGESZ_256M 18
+#define BOOK3E_PAGESZ_512M 19
+#define BOOK3E_PAGESZ_1GB 20
+#define BOOK3E_PAGESZ_2GB 21
+#define BOOK3E_PAGESZ_4GB 22
+#define BOOK3E_PAGESZ_8GB 23
+#define BOOK3E_PAGESZ_16GB 24
+#define BOOK3E_PAGESZ_32GB 25
+#define BOOK3E_PAGESZ_64GB 26
+#define BOOK3E_PAGESZ_128GB 27
+#define BOOK3E_PAGESZ_256GB 28
+#define BOOK3E_PAGESZ_512GB 29
+#define BOOK3E_PAGESZ_1TB 30
+#define BOOK3E_PAGESZ_2TB 31
#define MAS0_TLBSEL(x) ((x << 28) & 0x30000000)
#define MAS0_ESEL(x) ((x << 16) & 0x0FFF0000)
@@ -29,8 +45,9 @@
#define MAS1_VALID 0x80000000
#define MAS1_IPROT 0x40000000
#define MAS1_TID(x) ((x << 16) & 0x3FFF0000)
+#define MAS1_IND 0x00002000
#define MAS1_TS 0x00001000
-#define MAS1_TSIZE(x) ((x << 8) & 0x00000F00)
+#define MAS1_TSIZE(x) ((x << 7) & 0x00000F80)
#define MAS2_EPN 0xFFFFF000
#define MAS2_X0 0x00000040
@@ -40,7 +57,7 @@
#define MAS2_M 0x00000004
#define MAS2_G 0x00000002
#define MAS2_E 0x00000001
-#define MAS2_EPN_MASK(size) (~0 << (2*(size) + 10))
+#define MAS2_EPN_MASK(size) (~0 << (size + 10))
#define MAS2_VAL(addr, size, flags) ((addr) & MAS2_EPN_MASK(size) | (flags))
#define MAS3_RPN 0xFFFFF000
@@ -56,7 +73,7 @@
#define MAS3_SR 0x00000001
#define MAS4_TLBSELD(x) MAS0_TLBSEL(x)
-#define MAS4_TIDDSEL 0x000F0000
+#define MAS4_INDD 0x00008000
#define MAS4_TSIZED(x) MAS1_TSIZE(x)
#define MAS4_X0D 0x00000040
#define MAS4_X1D 0x00000020
@@ -68,6 +85,7 @@
#define MAS6_SPID0 0x3FFF0000
#define MAS6_SPID1 0x00007FFE
+#define MAS6_ISIZE(x) MAS1_TSIZE(x)
#define MAS6_SAS 0x00000001
#define MAS6_SPID MAS6_SPID0
@@ -82,4 +100,4 @@ typedef struct {
} mm_context_t;
#endif /* !__ASSEMBLY__ */
-#endif /* _ASM_POWERPC_MMU_FSL_BOOKE_H_ */
+#endif /* _ASM_POWERPC_MMU_BOOK3E_H_ */
diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h
index 6e763991131..5c78079cfa3 100644
--- a/arch/powerpc/include/asm/mmu.h
+++ b/arch/powerpc/include/asm/mmu.h
@@ -71,9 +71,9 @@ extern unsigned int __start___mmu_ftr_fixup, __stop___mmu_ftr_fixup;
#elif defined(CONFIG_44x)
/* 44x-style software loaded TLB */
# include <asm/mmu-44x.h>
-#elif defined(CONFIG_FSL_BOOKE)
-/* Freescale Book-E software loaded TLB */
-# include <asm/mmu-fsl-booke.h>
+#elif defined(CONFIG_PPC_BOOK3E_MMU)
+/* Freescale Book-E software loaded TLB or Book-3e (ISA 2.06+) MMU */
+# include <asm/mmu-book3e.h>
#elif defined (CONFIG_PPC_8xx)
/* Motorola/Freescale 8xx software loaded TLB */
# include <asm/mmu-8xx.h>
diff --git a/arch/powerpc/include/asm/pgtable-4k.h b/arch/powerpc/include/asm/pgtable-4k.h
index 6b18ba9d2d8..1dbca4e7de6 100644
--- a/arch/powerpc/include/asm/pgtable-4k.h
+++ b/arch/powerpc/include/asm/pgtable-4k.h
@@ -60,7 +60,7 @@
/* It should be preserving the high 48 bits and then specifically */
/* preserving _PAGE_SECONDARY | _PAGE_GROUP_IX */
#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | \
- _PAGE_HPTEFLAGS)
+ _PAGE_HPTEFLAGS | _PAGE_SPECIAL)
/* Bits to mask out from a PMD to get to the PTE page */
#define PMD_MASKED_BITS 0
diff --git a/arch/powerpc/include/asm/pgtable-64k.h b/arch/powerpc/include/asm/pgtable-64k.h
index 07b0d8f09cb..7389003349a 100644
--- a/arch/powerpc/include/asm/pgtable-64k.h
+++ b/arch/powerpc/include/asm/pgtable-64k.h
@@ -114,7 +114,7 @@ static inline struct subpage_prot_table *pgd_subpage_prot(pgd_t *pgd)
* pgprot changes
*/
#define _PAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_HPTEFLAGS | _PAGE_DIRTY | \
- _PAGE_ACCESSED)
+ _PAGE_ACCESSED | _PAGE_SPECIAL)
/* Bits to mask out from a PMD to get to the PTE page */
#define PMD_MASKED_BITS 0x1ff
diff --git a/arch/powerpc/include/asm/pgtable-ppc32.h b/arch/powerpc/include/asm/pgtable-ppc32.h
index f69a4d97772..98bd7c5fcd0 100644
--- a/arch/powerpc/include/asm/pgtable-ppc32.h
+++ b/arch/powerpc/include/asm/pgtable-ppc32.h
@@ -429,8 +429,10 @@ extern int icache_44x_need_flush;
#define PMD_PAGE_SIZE(pmd) bad_call_to_PMD_PAGE_SIZE()
#endif
-#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define _PAGE_HPTEFLAGS _PAGE_HASHPTE
+#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | \
+ _PAGE_SPECIAL)
#define PAGE_PROT_BITS (_PAGE_GUARDED | _PAGE_COHERENT | _PAGE_NO_CACHE | \
_PAGE_WRITETHRU | _PAGE_ENDIAN | \
@@ -667,44 +669,6 @@ static inline unsigned long long pte_update(pte_t *p,
#endif /* CONFIG_PTE_64BIT */
/*
- * set_pte stores a linux PTE into the linux page table.
- * On machines which use an MMU hash table we avoid changing the
- * _PAGE_HASHPTE bit.
- */
-
-static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
- pte_t *ptep, pte_t pte)
-{
-#if (_PAGE_HASHPTE != 0) && defined(CONFIG_SMP) && !defined(CONFIG_PTE_64BIT)
- pte_update(ptep, ~_PAGE_HASHPTE, pte_val(pte) & ~_PAGE_HASHPTE);
-#elif defined(CONFIG_PTE_64BIT) && defined(CONFIG_SMP)
-#if _PAGE_HASHPTE != 0
- if (pte_val(*ptep) & _PAGE_HASHPTE)
- flush_hash_entry(mm, ptep, addr);
-#endif
- __asm__ __volatile__("\
- stw%U0%X0 %2,%0\n\
- eieio\n\
- stw%U0%X0 %L2,%1"
- : "=m" (*ptep), "=m" (*((unsigned char *)ptep+4))
- : "r" (pte) : "memory");
-#else
- *ptep = __pte((pte_val(*ptep) & _PAGE_HASHPTE)
- | (pte_val(pte) & ~_PAGE_HASHPTE));
-#endif
-}
-
-
-static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
- pte_t *ptep, pte_t pte)
-{
-#if defined(CONFIG_PTE_64BIT) && defined(CONFIG_SMP) && defined(CONFIG_DEBUG_VM)
- WARN_ON(pte_present(*ptep));
-#endif
- __set_pte_at(mm, addr, ptep, pte);
-}
-
-/*
* 2.6 calls this without flushing the TLB entry; this is wrong
* for our hash-based implementation, we fix that up here.
*/
@@ -744,24 +708,14 @@ static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
}
-#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
-static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry, int dirty)
+static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry)
{
unsigned long bits = pte_val(entry) &
- (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW);
+ (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW |
+ _PAGE_HWEXEC | _PAGE_EXEC);
pte_update(ptep, 0, bits);
}
-#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
-({ \
- int __changed = !pte_same(*(__ptep), __entry); \
- if (__changed) { \
- __ptep_set_access_flags(__ptep, __entry, __dirty); \
- flush_tlb_page_nohash(__vma, __address); \
- } \
- __changed; \
-})
-
#define __HAVE_ARCH_PTE_SAME
#define pte_same(A,B) (((pte_val(A) ^ pte_val(B)) & ~_PAGE_HASHPTE) == 0)
diff --git a/arch/powerpc/include/asm/pgtable-ppc64.h b/arch/powerpc/include/asm/pgtable-ppc64.h
index b0f18be81d9..c627877fcf1 100644
--- a/arch/powerpc/include/asm/pgtable-ppc64.h
+++ b/arch/powerpc/include/asm/pgtable-ppc64.h
@@ -125,6 +125,8 @@
#define _PTEIDX_SECONDARY 0x8
#define _PTEIDX_GROUP_IX 0x7
+/* To make some generic powerpc code happy */
+#define _PAGE_HWEXEC 0
/*
* POWER4 and newer have per page execute protection, older chips can only
@@ -285,6 +287,10 @@ static inline unsigned long pte_update(struct mm_struct *mm,
: "r" (ptep), "r" (clr), "m" (*ptep), "i" (_PAGE_BUSY)
: "cc" );
+ /* huge pages use the old page table lock */
+ if (!huge)
+ assert_pte_locked(mm, addr);
+
if (old & _PAGE_HASHPTE)
hpte_need_flush(mm, addr, ptep, old, huge);
return old;
@@ -359,23 +365,11 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr,
pte_update(mm, addr, ptep, ~0UL, 0);
}
-/*
- * set_pte stores a linux PTE into the linux page table.
- */
-static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
- pte_t *ptep, pte_t pte)
-{
- if (pte_present(*ptep))
- pte_clear(mm, addr, ptep);
- pte = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS);
- *ptep = pte;
-}
/* Set the dirty and/or accessed bits atomically in a linux PTE, this
* function doesn't need to flush the hash entry
*/
-#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
-static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry, int dirty)
+static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry)
{
unsigned long bits = pte_val(entry) &
(_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC);
@@ -392,15 +386,6 @@ static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry, int dirty)
:"r" (bits), "r" (ptep), "m" (*ptep), "i" (_PAGE_BUSY)
:"cc");
}
-#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
-({ \
- int __changed = !pte_same(*(__ptep), __entry); \
- if (__changed) { \
- __ptep_set_access_flags(__ptep, __entry, __dirty); \
- flush_tlb_page_nohash(__vma, __address); \
- } \
- __changed; \
-})
#define __HAVE_ARCH_PTE_SAME
#define pte_same(A,B) (((pte_val(A) ^ pte_val(B)) & ~_PAGE_HPTEFLAGS) == 0)
diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h
index 07f55e60169..5c1c4880723 100644
--- a/arch/powerpc/include/asm/pgtable.h
+++ b/arch/powerpc/include/asm/pgtable.h
@@ -6,7 +6,17 @@
#include <asm/processor.h> /* For TASK_SIZE */
#include <asm/mmu.h>
#include <asm/page.h>
+
struct mm_struct;
+
+#ifdef CONFIG_DEBUG_VM
+extern void assert_pte_locked(struct mm_struct *mm, unsigned long addr);
+#else /* CONFIG_DEBUG_VM */
+static inline void assert_pte_locked(struct mm_struct *mm, unsigned long addr)
+{
+}
+#endif /* !CONFIG_DEBUG_VM */
+
#endif /* !__ASSEMBLY__ */
#if defined(CONFIG_PPC64)
@@ -17,6 +27,80 @@ struct mm_struct;
#ifndef __ASSEMBLY__
+/* Insert a PTE, top-level function is out of line. It uses an inline
+ * low level function in the respective pgtable-* files
+ */
+extern void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep,
+ pte_t pte);
+
+/* This low level function performs the actual PTE insertion
+ * Setting the PTE depends on the MMU type and other factors. It's
+ * an horrible mess that I'm not going to try to clean up now but
+ * I'm keeping it in one place rather than spread around
+ */
+static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pte, int percpu)
+{
+#if defined(CONFIG_PPC_STD_MMU_32) && defined(CONFIG_SMP) && !defined(CONFIG_PTE_64BIT)
+ /* First case is 32-bit Hash MMU in SMP mode with 32-bit PTEs. We use the
+ * helper pte_update() which does an atomic update. We need to do that
+ * because a concurrent invalidation can clear _PAGE_HASHPTE. If it's a
+ * per-CPU PTE such as a kmap_atomic, we do a simple update preserving
+ * the hash bits instead (ie, same as the non-SMP case)
+ */
+ if (percpu)
+ *ptep = __pte((pte_val(*ptep) & _PAGE_HASHPTE)
+ | (pte_val(pte) & ~_PAGE_HASHPTE));
+ else
+ pte_update(ptep, ~_PAGE_HASHPTE, pte_val(pte));
+
+#elif defined(CONFIG_PPC32) && defined(CONFIG_PTE_64BIT) && defined(CONFIG_SMP)
+ /* Second case is 32-bit with 64-bit PTE in SMP mode. In this case, we
+ * can just store as long as we do the two halves in the right order
+ * with a barrier in between. This is possible because we take care,
+ * in the hash code, to pre-invalidate if the PTE was already hashed,
+ * which synchronizes us with any concurrent invalidation.
+ * In the percpu case, we also fallback to the simple update preserving
+ * the hash bits
+ */
+ if (percpu) {
+ *ptep = __pte((pte_val(*ptep) & _PAGE_HASHPTE)
+ | (pte_val(pte) & ~_PAGE_HASHPTE));
+ return;
+ }
+#if _PAGE_HASHPTE != 0
+ if (pte_val(*ptep) & _PAGE_HASHPTE)
+ flush_hash_entry(mm, ptep, addr);
+#endif
+ __asm__ __volatile__("\
+ stw%U0%X0 %2,%0\n\
+ eieio\n\
+ stw%U0%X0 %L2,%1"
+ : "=m" (*ptep), "=m" (*((unsigned char *)ptep+4))
+ : "r" (pte) : "memory");
+
+#elif defined(CONFIG_PPC_STD_MMU_32)
+ /* Third case is 32-bit hash table in UP mode, we need to preserve
+ * the _PAGE_HASHPTE bit since we may not have invalidated the previous
+ * translation in the hash yet (done in a subsequent flush_tlb_xxx())
+ * and see we need to keep track that this PTE needs invalidating
+ */
+ *ptep = __pte((pte_val(*ptep) & _PAGE_HASHPTE)
+ | (pte_val(pte) & ~_PAGE_HASHPTE));
+
+#else
+ /* Anything else just stores the PTE normally. That covers all 64-bit
+ * cases, and 32-bit non-hash with 64-bit PTEs in UP mode
+ */
+ *ptep = pte;
+#endif
+}
+
+
+#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
+extern int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address,
+ pte_t *ptep, pte_t entry, int dirty);
+
/*
* Macro to mark a page protection value as "uncacheable".
*/
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
new file mode 100644
index 00000000000..f4a4db8d555
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2009 Freescale Semicondutor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * provides masks and opcode images for use by code generation, emulation
+ * and for instructions that older assemblers might not know about
+ */
+#ifndef _ASM_POWERPC_PPC_OPCODE_H
+#define _ASM_POWERPC_PPC_OPCODE_H
+
+#include <linux/stringify.h>
+#include <asm/asm-compat.h>
+
+/* sorted alphabetically */
+#define PPC_INST_DCBA 0x7c0005ec
+#define PPC_INST_DCBA_MASK 0xfc0007fe
+#define PPC_INST_DCBAL 0x7c2005ec
+#define PPC_INST_DCBZL 0x7c2007ec
+#define PPC_INST_ISEL 0x7c00001e
+#define PPC_INST_ISEL_MASK 0xfc00003e
+#define PPC_INST_LSWI 0x7c0004aa
+#define PPC_INST_LSWX 0x7c00042a
+#define PPC_INST_LWSYNC 0x7c2004ac
+#define PPC_INST_MCRXR 0x7c000400
+#define PPC_INST_MCRXR_MASK 0xfc0007fe
+#define PPC_INST_MFSPR_PVR 0x7c1f42a6
+#define PPC_INST_MFSPR_PVR_MASK 0xfc1fffff
+#define PPC_INST_MSGSND 0x7c00019c
+#define PPC_INST_NOP 0x60000000
+#define PPC_INST_POPCNTB 0x7c0000f4
+#define PPC_INST_POPCNTB_MASK 0xfc0007fe
+#define PPC_INST_RFCI 0x4c000066
+#define PPC_INST_RFDI 0x4c00004e
+#define PPC_INST_RFMCI 0x4c00004c
+
+#define PPC_INST_STRING 0x7c00042a
+#define PPC_INST_STRING_MASK 0xfc0007fe
+#define PPC_INST_STRING_GEN_MASK 0xfc00067e
+
+#define PPC_INST_STSWI 0x7c0005aa
+#define PPC_INST_STSWX 0x7c00052a
+#define PPC_INST_TLBILX 0x7c000626
+#define PPC_INST_WAIT 0x7c00007c
+
+/* macros to insert fields into opcodes */
+#define __PPC_RA(a) ((a & 0x1f) << 16)
+#define __PPC_RB(b) ((b & 0x1f) << 11)
+#define __PPC_T_TLB(t) ((t & 0x3) << 21)
+#define __PPC_WC(w) ((w & 0x3) << 21)
+
+/* Deal with instructions that older assemblers aren't aware of */
+#define PPC_DCBAL(a, b) stringify_in_c(.long PPC_INST_DCBAL | \
+ __PPC_RA(a) | __PPC_RB(b))
+#define PPC_DCBZL(a, b) stringify_in_c(.long PPC_INST_DCBZL | \
+ __PPC_RA(a) | __PPC_RB(b))
+#define PPC_MSGSND(b) stringify_in_c(.long PPC_INST_MSGSND | \
+ __PPC_RB(b))
+#define PPC_RFCI stringify_in_c(.long PPC_INST_RFCI)
+#define PPC_RFDI stringify_in_c(.long PPC_INST_RFDI)
+#define PPC_RFMCI stringify_in_c(.long PPC_INST_RFMCI)
+#define PPC_TLBILX(t, a, b) stringify_in_c(.long PPC_INST_TLBILX | \
+ __PPC_T_TLB(t) | __PPC_RA(a) | __PPC_RB(b))
+#define PPC_TLBILX_ALL(a, b) PPC_TLBILX(0, a, b)
+#define PPC_TLBILX_PID(a, b) PPC_TLBILX(1, a, b)
+#define PPC_TLBILX_VA(a, b) PPC_TLBILX(3, a, b)
+#define PPC_WAIT(w) stringify_in_c(.long PPC_INST_WAIT | \
+ __PPC_WC(w))
+
+#endif /* _ASM_POWERPC_PPC_OPCODE_H */
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 1a0d628eb11..f59a66684ae 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -7,6 +7,7 @@
#include <linux/stringify.h>
#include <asm/asm-compat.h>
#include <asm/processor.h>
+#include <asm/ppc-opcode.h>
#ifndef __ASSEMBLY__
#error __FILE__ should only be used in assembler files
@@ -167,11 +168,6 @@ END_FTR_SECTION_IFCLR(CPU_FTR_PURR); \
#define HMT_MEDIUM_HIGH or 5,5,5 # medium high priority
#define HMT_HIGH or 3,3,3
-/* handle instructions that older assemblers may not know */
-#define RFCI .long 0x4c000066 /* rfci instruction */
-#define RFDI .long 0x4c00004e /* rfdi instruction */
-#define RFMCI .long 0x4c00004c /* rfmci instruction */
-
#ifdef __KERNEL__
#ifdef CONFIG_PPC64
diff --git a/arch/powerpc/include/asm/ps3fb.h b/arch/powerpc/include/asm/ps3fb.h
index 3f121fe4010..1a91daf362c 100644
--- a/arch/powerpc/include/asm/ps3fb.h
+++ b/arch/powerpc/include/asm/ps3fb.h
@@ -20,6 +20,7 @@
#define _ASM_POWERPC_PS3FB_H_
#include <linux/ioctl.h>
+#include <linux/types.h>
/* ioctl */
#define PS3FB_IOCTL_SETMODE _IOW('r', 1, int) /* set video mode */
diff --git a/arch/powerpc/include/asm/spu_info.h b/arch/powerpc/include/asm/spu_info.h
index 3545efbf989..1286c823f0d 100644
--- a/arch/powerpc/include/asm/spu_info.h
+++ b/arch/powerpc/include/asm/spu_info.h
@@ -23,9 +23,10 @@
#ifndef _SPU_INFO_H
#define _SPU_INFO_H
+#include <linux/types.h>
+
#ifdef __KERNEL__
#include <asm/spu.h>
-#include <linux/types.h>
#else
struct mfc_cq_sr {
__u64 mfc_cq_data0_RW;
diff --git a/arch/powerpc/include/asm/swab.h b/arch/powerpc/include/asm/swab.h
index ef824ae4b79..c581e3ef73e 100644
--- a/arch/powerpc/include/asm/swab.h
+++ b/arch/powerpc/include/asm/swab.h
@@ -8,7 +8,7 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <asm/types.h>
+#include <linux/types.h>
#include <linux/compiler.h>
#ifdef __GNUC__
diff --git a/arch/powerpc/include/asm/system.h b/arch/powerpc/include/asm/system.h
index 2a4be19a92c..f612798e1c9 100644
--- a/arch/powerpc/include/asm/system.h
+++ b/arch/powerpc/include/asm/system.h
@@ -531,7 +531,7 @@ __cmpxchg_local(volatile void *ptr, unsigned long old, unsigned long new,
#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
#endif
-#define arch_align_stack(x) (x)
+extern unsigned long arch_align_stack(unsigned long sp);
/* Used in very early kernel initialization. */
extern unsigned long reloc_offset(void);
diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h
index e04286f92f6..9aba5a38a7c 100644
--- a/arch/powerpc/include/asm/thread_info.h
+++ b/arch/powerpc/include/asm/thread_info.h
@@ -156,6 +156,13 @@ static inline void set_restore_sigmask(void)
ti->local_flags |= _TLF_RESTORE_SIGMASK;
set_bit(TIF_SIGPENDING, &ti->flags);
}
+
+#ifdef CONFIG_PPC64
+#define is_32bit_task() (test_thread_flag(TIF_32BIT))
+#else
+#define is_32bit_task() (1)
+#endif
+
#endif /* !__ASSEMBLY__ */
#endif /* __KERNEL__ */