diff options
Diffstat (limited to 'arch/powerpc/include')
34 files changed, 931 insertions, 348 deletions
diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h index 897eade3afbe..56f2f2ea5631 100644 --- a/arch/powerpc/include/asm/bitops.h +++ b/arch/powerpc/include/asm/bitops.h @@ -56,174 +56,102 @@ #define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) #define BITOP_LE_SWIZZLE ((BITS_PER_LONG-1) & ~0x7) +/* Macro for generating the ***_bits() functions */ +#define DEFINE_BITOP(fn, op, prefix, postfix) \ +static __inline__ void fn(unsigned long mask, \ + volatile unsigned long *_p) \ +{ \ + unsigned long old; \ + unsigned long *p = (unsigned long *)_p; \ + __asm__ __volatile__ ( \ + prefix \ +"1:" PPC_LLARX "%0,0,%3\n" \ + stringify_in_c(op) "%0,%0,%2\n" \ + PPC405_ERR77(0,%3) \ + PPC_STLCX "%0,0,%3\n" \ + "bne- 1b\n" \ + postfix \ + : "=&r" (old), "+m" (*p) \ + : "r" (mask), "r" (p) \ + : "cc", "memory"); \ +} + +DEFINE_BITOP(set_bits, or, "", "") +DEFINE_BITOP(clear_bits, andc, "", "") +DEFINE_BITOP(clear_bits_unlock, andc, LWSYNC_ON_SMP, "") +DEFINE_BITOP(change_bits, xor, "", "") + static __inline__ void set_bit(int nr, volatile unsigned long *addr) { - unsigned long old; - unsigned long mask = BITOP_MASK(nr); - unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); - - __asm__ __volatile__( -"1:" PPC_LLARX "%0,0,%3 # set_bit\n" - "or %0,%0,%2\n" - PPC405_ERR77(0,%3) - PPC_STLCX "%0,0,%3\n" - "bne- 1b" - : "=&r" (old), "+m" (*p) - : "r" (mask), "r" (p) - : "cc" ); + set_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr)); } static __inline__ void clear_bit(int nr, volatile unsigned long *addr) { - unsigned long old; - unsigned long mask = BITOP_MASK(nr); - unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); - - __asm__ __volatile__( -"1:" PPC_LLARX "%0,0,%3 # clear_bit\n" - "andc %0,%0,%2\n" - PPC405_ERR77(0,%3) - PPC_STLCX "%0,0,%3\n" - "bne- 1b" - : "=&r" (old), "+m" (*p) - : "r" (mask), "r" (p) - : "cc" ); + clear_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr)); } static __inline__ void clear_bit_unlock(int nr, volatile unsigned long *addr) { - unsigned long old; - unsigned long mask = BITOP_MASK(nr); - unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); - - __asm__ __volatile__( - LWSYNC_ON_SMP -"1:" PPC_LLARX "%0,0,%3 # clear_bit_unlock\n" - "andc %0,%0,%2\n" - PPC405_ERR77(0,%3) - PPC_STLCX "%0,0,%3\n" - "bne- 1b" - : "=&r" (old), "+m" (*p) - : "r" (mask), "r" (p) - : "cc", "memory"); + clear_bits_unlock(BITOP_MASK(nr), addr + BITOP_WORD(nr)); } static __inline__ void change_bit(int nr, volatile unsigned long *addr) { - unsigned long old; - unsigned long mask = BITOP_MASK(nr); - unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); - - __asm__ __volatile__( -"1:" PPC_LLARX "%0,0,%3 # change_bit\n" - "xor %0,%0,%2\n" - PPC405_ERR77(0,%3) - PPC_STLCX "%0,0,%3\n" - "bne- 1b" - : "=&r" (old), "+m" (*p) - : "r" (mask), "r" (p) - : "cc" ); + change_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr)); +} + +/* Like DEFINE_BITOP(), with changes to the arguments to 'op' and the output + * operands. */ +#define DEFINE_TESTOP(fn, op, prefix, postfix) \ +static __inline__ unsigned long fn( \ + unsigned long mask, \ + volatile unsigned long *_p) \ +{ \ + unsigned long old, t; \ + unsigned long *p = (unsigned long *)_p; \ + __asm__ __volatile__ ( \ + prefix \ +"1:" PPC_LLARX "%0,0,%3\n" \ + stringify_in_c(op) "%1,%0,%2\n" \ + PPC405_ERR77(0,%3) \ + PPC_STLCX "%1,0,%3\n" \ + "bne- 1b\n" \ + postfix \ + : "=&r" (old), "=&r" (t) \ + : "r" (mask), "r" (p) \ + : "cc", "memory"); \ + return (old & mask); \ } +DEFINE_TESTOP(test_and_set_bits, or, LWSYNC_ON_SMP, ISYNC_ON_SMP) +DEFINE_TESTOP(test_and_set_bits_lock, or, "", ISYNC_ON_SMP) +DEFINE_TESTOP(test_and_clear_bits, andc, LWSYNC_ON_SMP, ISYNC_ON_SMP) +DEFINE_TESTOP(test_and_change_bits, xor, LWSYNC_ON_SMP, ISYNC_ON_SMP) + static __inline__ int test_and_set_bit(unsigned long nr, volatile unsigned long *addr) { - unsigned long old, t; - unsigned long mask = BITOP_MASK(nr); - unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); - - __asm__ __volatile__( - LWSYNC_ON_SMP -"1:" PPC_LLARX "%0,0,%3 # test_and_set_bit\n" - "or %1,%0,%2 \n" - PPC405_ERR77(0,%3) - PPC_STLCX "%1,0,%3 \n" - "bne- 1b" - ISYNC_ON_SMP - : "=&r" (old), "=&r" (t) - : "r" (mask), "r" (p) - : "cc", "memory"); - - return (old & mask) != 0; + return test_and_set_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr)) != 0; } static __inline__ int test_and_set_bit_lock(unsigned long nr, volatile unsigned long *addr) { - unsigned long old, t; - unsigned long mask = BITOP_MASK(nr); - unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); - - __asm__ __volatile__( -"1:" PPC_LLARX "%0,0,%3 # test_and_set_bit_lock\n" - "or %1,%0,%2 \n" - PPC405_ERR77(0,%3) - PPC_STLCX "%1,0,%3 \n" - "bne- 1b" - ISYNC_ON_SMP - : "=&r" (old), "=&r" (t) - : "r" (mask), "r" (p) - : "cc", "memory"); - - return (old & mask) != 0; + return test_and_set_bits_lock(BITOP_MASK(nr), + addr + BITOP_WORD(nr)) != 0; } static __inline__ int test_and_clear_bit(unsigned long nr, volatile unsigned long *addr) { - unsigned long old, t; - unsigned long mask = BITOP_MASK(nr); - unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); - - __asm__ __volatile__( - LWSYNC_ON_SMP -"1:" PPC_LLARX "%0,0,%3 # test_and_clear_bit\n" - "andc %1,%0,%2 \n" - PPC405_ERR77(0,%3) - PPC_STLCX "%1,0,%3 \n" - "bne- 1b" - ISYNC_ON_SMP - : "=&r" (old), "=&r" (t) - : "r" (mask), "r" (p) - : "cc", "memory"); - - return (old & mask) != 0; + return test_and_clear_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr)) != 0; } static __inline__ int test_and_change_bit(unsigned long nr, volatile unsigned long *addr) { - unsigned long old, t; - unsigned long mask = BITOP_MASK(nr); - unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); - - __asm__ __volatile__( - LWSYNC_ON_SMP -"1:" PPC_LLARX "%0,0,%3 # test_and_change_bit\n" - "xor %1,%0,%2 \n" - PPC405_ERR77(0,%3) - PPC_STLCX "%1,0,%3 \n" - "bne- 1b" - ISYNC_ON_SMP - : "=&r" (old), "=&r" (t) - : "r" (mask), "r" (p) - : "cc", "memory"); - - return (old & mask) != 0; -} - -static __inline__ void set_bits(unsigned long mask, unsigned long *addr) -{ - unsigned long old; - - __asm__ __volatile__( -"1:" PPC_LLARX "%0,0,%3 # set_bits\n" - "or %0,%0,%2\n" - PPC_STLCX "%0,0,%3\n" - "bne- 1b" - : "=&r" (old), "+m" (*addr) - : "r" (mask), "r" (addr) - : "cc"); + return test_and_change_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr)) != 0; } #include <asm-generic/bitops/non-atomic.h> diff --git a/arch/powerpc/include/asm/cell-regs.h b/arch/powerpc/include/asm/cell-regs.h index fd6fd00434ef..fdf64fd25950 100644 --- a/arch/powerpc/include/asm/cell-regs.h +++ b/arch/powerpc/include/asm/cell-regs.h @@ -303,6 +303,17 @@ struct cbe_mic_tm_regs { extern struct cbe_mic_tm_regs __iomem *cbe_get_mic_tm_regs(struct device_node *np); extern struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu); + +/* Cell page table entries */ +#define CBE_IOPTE_PP_W 0x8000000000000000ul /* protection: write */ +#define CBE_IOPTE_PP_R 0x4000000000000000ul /* protection: read */ +#define CBE_IOPTE_M 0x2000000000000000ul /* coherency required */ +#define CBE_IOPTE_SO_R 0x1000000000000000ul /* ordering: writes */ +#define CBE_IOPTE_SO_RW 0x1800000000000000ul /* ordering: r & w */ +#define CBE_IOPTE_RPN_Mask 0x07fffffffffff000ul /* RPN */ +#define CBE_IOPTE_H 0x0000000000000800ul /* cache hint */ +#define CBE_IOPTE_IOID_Mask 0x00000000000007fful /* ioid */ + /* some utility functions to deal with SMT */ extern u32 cbe_get_hw_thread_id(int cpu); extern u32 cbe_cpu_to_node(int cpu); diff --git a/arch/powerpc/include/asm/cputhreads.h b/arch/powerpc/include/asm/cputhreads.h index fb11b0c459b8..a8e18447c62b 100644 --- a/arch/powerpc/include/asm/cputhreads.h +++ b/arch/powerpc/include/asm/cputhreads.h @@ -5,6 +5,15 @@ /* * Mapping of threads to cores + * + * Note: This implementation is limited to a power of 2 number of + * threads per core and the same number for each core in the system + * (though it would work if some processors had less threads as long + * as the CPU numbers are still allocated, just not brought offline). + * + * However, the API allows for a different implementation in the future + * if needed, as long as you only use the functions and not the variables + * directly. */ #ifdef CONFIG_SMP @@ -67,5 +76,12 @@ static inline int cpu_first_thread_in_core(int cpu) return cpu & ~(threads_per_core - 1); } +static inline int cpu_last_thread_in_core(int cpu) +{ + return cpu | (threads_per_core - 1); +} + + + #endif /* _ASM_POWERPC_CPUTHREADS_H */ diff --git a/arch/powerpc/include/asm/exception-64e.h b/arch/powerpc/include/asm/exception-64e.h new file mode 100644 index 000000000000..94cb3d79d125 --- /dev/null +++ b/arch/powerpc/include/asm/exception-64e.h @@ -0,0 +1,201 @@ +/* + * Definitions for use by exception code on Book3-E + * + * Copyright (C) 2008 Ben. Herrenschmidt (benh@kernel.crashing.org), IBM Corp. + * + * 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. + */ +#ifndef _ASM_POWERPC_EXCEPTION_64E_H +#define _ASM_POWERPC_EXCEPTION_64E_H + +/* + * SPRGs usage an other considerations... + * + * Since TLB miss and other standard exceptions can be interrupted by + * critical exceptions which can themselves be interrupted by machine + * checks, and since the two later can themselves cause a TLB miss when + * hitting the linear mapping for the kernel stacks, we need to be a bit + * creative on how we use SPRGs. + * + * The base idea is that we have one SRPG reserved for critical and one + * for machine check interrupts. Those are used to save a GPR that can + * then be used to get the PACA, and store as much context as we need + * to save in there. That includes saving the SPRGs used by the TLB miss + * handler for linear mapping misses and the associated SRR0/1 due to + * the above re-entrancy issue. + * + * So here's the current usage pattern. It's done regardless of which + * SPRGs are user-readable though, thus we might have to change some of + * this later. In order to do that more easily, we use special constants + * for naming them + * + * WARNING: Some of these SPRGs are user readable. We need to do something + * about it as some point by making sure they can't be used to leak kernel + * critical data + */ + + +/* We are out of SPRGs so we save some things in the PACA. The normal + * exception frame is smaller than the CRIT or MC one though + */ +#define EX_R1 (0 * 8) +#define EX_CR (1 * 8) +#define EX_R10 (2 * 8) +#define EX_R11 (3 * 8) +#define EX_R14 (4 * 8) +#define EX_R15 (5 * 8) + +/* The TLB miss exception uses different slots */ + +#define EX_TLB_R10 ( 0 * 8) +#define EX_TLB_R11 ( 1 * 8) +#define EX_TLB_R12 ( 2 * 8) +#define EX_TLB_R13 ( 3 * 8) +#define EX_TLB_R14 ( 4 * 8) +#define EX_TLB_R15 ( 5 * 8) +#define EX_TLB_R16 ( 6 * 8) +#define EX_TLB_CR ( 7 * 8) +#define EX_TLB_DEAR ( 8 * 8) /* Level 0 and 2 only */ +#define EX_TLB_ESR ( 9 * 8) /* Level 0 and 2 only */ +#define EX_TLB_SRR0 (10 * 8) +#define EX_TLB_SRR1 (11 * 8) +#define EX_TLB_MMUCR0 (12 * 8) /* Level 0 */ +#define EX_TLB_MAS1 (12 * 8) /* Level 0 */ +#define EX_TLB_MAS2 (13 * 8) /* Level 0 */ +#ifdef CONFIG_BOOK3E_MMU_TLB_STATS +#define EX_TLB_R8 (14 * 8) +#define EX_TLB_R9 (15 * 8) +#define EX_TLB_LR (16 * 8) +#define EX_TLB_SIZE (17 * 8) +#else +#define EX_TLB_SIZE (14 * 8) +#endif + +#define START_EXCEPTION(label) \ + .globl exc_##label##_book3e; \ +exc_##label##_book3e: + +/* TLB miss exception prolog + * + * This prolog handles re-entrancy (up to 3 levels supported in the PACA + * though we currently don't test for overflow). It provides you with a + * re-entrancy safe working space of r10...r16 and CR with r12 being used + * as the exception area pointer in the PACA for that level of re-entrancy + * and r13 containing the PACA pointer. + * + * SRR0 and SRR1 are saved, but DEAR and ESR are not, since they don't apply + * as-is for instruction exceptions. It's up to the actual exception code + * to save them as well if required. + */ +#define TLB_MISS_PROLOG \ + mtspr SPRN_SPRG_TLB_SCRATCH,r12; \ + mfspr r12,SPRN_SPRG_TLB_EXFRAME; \ + std r10,EX_TLB_R10(r12); \ + mfcr r10; \ + std r11,EX_TLB_R11(r12); \ + mfspr r11,SPRN_SPRG_TLB_SCRATCH; \ + std r13,EX_TLB_R13(r12); \ + mfspr r13,SPRN_SPRG_PACA; \ + std r14,EX_TLB_R14(r12); \ + addi r14,r12,EX_TLB_SIZE; \ + std r15,EX_TLB_R15(r12); \ + mfspr r15,SPRN_SRR1; \ + std r16,EX_TLB_R16(r12); \ + mfspr r16,SPRN_SRR0; \ + std r10,EX_TLB_CR(r12); \ + std r11,EX_TLB_R12(r12); \ + mtspr SPRN_SPRG_TLB_EXFRAME,r14; \ + std r15,EX_TLB_SRR1(r12); \ + std r16,EX_TLB_SRR0(r12); \ + TLB_MISS_PROLOG_STATS + +/* And these are the matching epilogs that restores things + * + * There are 3 epilogs: + * + * - SUCCESS : Unwinds one level + * - ERROR : restore from level 0 and reset + * - ERROR_SPECIAL : restore from current level and reset + * + * Normal errors use ERROR, that is, they restore the initial fault context + * and trigger a fault. However, there is a special case for linear mapping + * errors. Those should basically never happen, but if they do happen, we + * want the error to point out the context that did that linear mapping + * fault, not the initial level 0 (basically, we got a bogus PGF or something + * like that). For userland errors on the linear mapping, there is no + * difference since those are always level 0 anyway + */ + +#define TLB_MISS_RESTORE(freg) \ + ld r14,EX_TLB_CR(r12); \ + ld r10,EX_TLB_R10(r12); \ + ld r15,EX_TLB_SRR0(r12); \ + ld r16,EX_TLB_SRR1(r12); \ + mtspr SPRN_SPRG_TLB_EXFRAME,freg; \ + ld r11,EX_TLB_R11(r12); \ + mtcr r14; \ + ld r13,EX_TLB_R13(r12); \ + ld r14,EX_TLB_R14(r12); \ + mtspr SPRN_SRR0,r15; \ + ld r15,EX_TLB_R15(r12); \ + mtspr SPRN_SRR1,r16; \ + TLB_MISS_RESTORE_STATS \ + ld r16,EX_TLB_R16(r12); \ + ld r12,EX_TLB_R12(r12); \ + +#define TLB_MISS_EPILOG_SUCCESS \ + TLB_MISS_RESTORE(r12) + +#define TLB_MISS_EPILOG_ERROR \ + addi r12,r13,PACA_EXTLB; \ + TLB_MISS_RESTORE(r12) + +#define TLB_MISS_EPILOG_ERROR_SPECIAL \ + addi r11,r13,PACA_EXTLB; \ + TLB_MISS_RESTORE(r11) + +#ifdef CONFIG_BOOK3E_MMU_TLB_STATS +#define TLB_MISS_PROLOG_STATS \ + mflr r10; \ + std r8,EX_TLB_R8(r12); \ + std r9,EX_TLB_R9(r12); \ + std r10,EX_TLB_LR(r12); +#define TLB_MISS_RESTORE_STATS \ + ld r16,EX_TLB_LR(r12); \ + ld r9,EX_TLB_R9(r12); \ + ld r8,EX_TLB_R8(r12); \ + mtlr r16; +#define TLB_MISS_STATS_D(name) \ + addi r9,r13,MMSTAT_DSTATS+name; \ + bl .tlb_stat_inc; +#define TLB_MISS_STATS_I(name) \ + addi r9,r13,MMSTAT_ISTATS+name; \ + bl .tlb_stat_inc; +#define TLB_MISS_STATS_X(name) \ + ld r8,PACA_EXTLB+EX_TLB_ESR(r13); \ + cmpdi cr2,r8,-1; \ + beq cr2,61f; \ + addi r9,r13,MMSTAT_DSTATS+name; \ + b 62f; \ +61: addi r9,r13,MMSTAT_ISTATS+name; \ +62: bl .tlb_stat_inc; +#define TLB_MISS_STATS_SAVE_INFO \ + std r14,EX_TLB_ESR(r12); /* save ESR */ \ + + +#else +#define TLB_MISS_PROLOG_STATS +#define TLB_MISS_RESTORE_STATS +#define TLB_MISS_STATS_D(name) +#define TLB_MISS_STATS_I(name) +#define TLB_MISS_STATS_X(name) +#define TLB_MISS_STATS_Y(name) +#define TLB_MISS_STATS_SAVE_INFO +#endif + + +#endif /* _ASM_POWERPC_EXCEPTION_64E_H */ + diff --git a/arch/powerpc/include/asm/exception.h b/arch/powerpc/include/asm/exception-64s.h index d3d4534e3c74..a98653b26231 100644 --- a/arch/powerpc/include/asm/exception.h +++ b/arch/powerpc/include/asm/exception-64s.h @@ -57,17 +57,16 @@ addi reg,reg,(label)-_stext; /* virt addr of handler ... */ #define EXCEPTION_PROLOG_1(area) \ - mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \ + mfspr r13,SPRN_SPRG_PACA; /* get paca address into r13 */ \ std r9,area+EX_R9(r13); /* save r9 - r12 */ \ std r10,area+EX_R10(r13); \ std r11,area+EX_R11(r13); \ std r12,area+EX_R12(r13); \ - mfspr r9,SPRN_SPRG1; \ + mfspr r9,SPRN_SPRG_SCRATCH0; \ std r9,area+EX_R13(r13); \ mfcr r9 -#define EXCEPTION_PROLOG_PSERIES(area, label) \ - EXCEPTION_PROLOG_1(area); \ +#define EXCEPTION_PROLOG_PSERIES_1(label) \ ld r12,PACAKBASE(r13); /* get high part of &label */ \ ld r10,PACAKMSR(r13); /* get MSR value for kernel */ \ mfspr r11,SPRN_SRR0; /* save SRR0 */ \ @@ -78,6 +77,10 @@ rfid; \ b . /* prevent speculative execution */ +#define EXCEPTION_PROLOG_PSERIES(area, label) \ + EXCEPTION_PROLOG_1(area); \ + EXCEPTION_PROLOG_PSERIES_1(label); + /* * The common exception prolog is used for all except a few exceptions * such as a segment miss on a kernel address. We have to be prepared @@ -144,7 +147,7 @@ .globl label##_pSeries; \ label##_pSeries: \ HMT_MEDIUM; \ - mtspr SPRN_SPRG1,r13; /* save r13 */ \ + mtspr SPRN_SPRG_SCRATCH0,r13; /* save r13 */ \ EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) #define HSTD_EXCEPTION_PSERIES(n, label) \ @@ -152,13 +155,13 @@ label##_pSeries: \ .globl label##_pSeries; \ label##_pSeries: \ HMT_MEDIUM; \ - mtspr SPRN_SPRG1,r20; /* save r20 */ \ + mtspr SPRN_SPRG_SCRATCH0,r20; /* save r20 */ \ mfspr r20,SPRN_HSRR0; /* copy HSRR0 to SRR0 */ \ mtspr SPRN_SRR0,r20; \ mfspr r20,SPRN_HSRR1; /* copy HSRR0 to SRR0 */ \ mtspr SPRN_SRR1,r20; \ - mfspr r20,SPRN_SPRG1; /* restore r20 */ \ - mtspr SPRN_SPRG1,r13; /* save r13 */ \ + mfspr r20,SPRN_SPRG_SCRATCH0; /* restore r20 */ \ + mtspr SPRN_SPRG_SCRATCH0,r13; /* save r13 */ \ EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) @@ -167,15 +170,15 @@ label##_pSeries: \ .globl label##_pSeries; \ label##_pSeries: \ HMT_MEDIUM; \ - mtspr SPRN_SPRG1,r13; /* save r13 */ \ - mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \ + mtspr SPRN_SPRG_SCRATCH0,r13; /* save r13 */ \ + mfspr r13,SPRN_SPRG_PACA; /* get paca address into r13 */ \ std r9,PACA_EXGEN+EX_R9(r13); /* save r9, r10 */ \ std r10,PACA_EXGEN+EX_R10(r13); \ lbz r10,PACASOFTIRQEN(r13); \ mfcr r9; \ cmpwi r10,0; \ beq masked_interrupt; \ - mfspr r10,SPRN_SPRG1; \ + mfspr r10,SPRN_SPRG_SCRATCH0; \ std r10,PACA_EXGEN+EX_R13(r13); \ std r11,PACA_EXGEN+EX_R11(r13); \ std r12,PACA_EXGEN+EX_R12(r13); \ diff --git a/arch/powerpc/include/asm/hardirq.h b/arch/powerpc/include/asm/hardirq.h index 288e14d53b7f..fb3c05a0cbbf 100644 --- a/arch/powerpc/include/asm/hardirq.h +++ b/arch/powerpc/include/asm/hardirq.h @@ -1,29 +1 @@ -#ifndef _ASM_POWERPC_HARDIRQ_H -#define _ASM_POWERPC_HARDIRQ_H -#ifdef __KERNEL__ - -#include <asm/irq.h> -#include <asm/bug.h> - -/* The __last_jiffy_stamp field is needed to ensure that no decrementer - * interrupt is lost on SMP machines. Since on most CPUs it is in the same - * cache line as local_irq_count, it is cheap to access and is also used on UP - * for uniformity. - */ -typedef struct { - unsigned int __softirq_pending; /* set_bit is used on this */ - unsigned int __last_jiffy_stamp; -} ____cacheline_aligned irq_cpustat_t; - -#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ - -#define last_jiffy_stamp(cpu) __IRQ_STAT((cpu), __last_jiffy_stamp) - -static inline void ack_bad_irq(int irq) -{ - printk(KERN_CRIT "illegal vector %d received!\n", irq); - BUG(); -} - -#endif /* __KERNEL__ */ -#endif /* _ASM_POWERPC_HARDIRQ_H */ +#include <asm-generic/hardirq.h> diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h index 8b505eaaa38a..e73d554538dd 100644 --- a/arch/powerpc/include/asm/hw_irq.h +++ b/arch/powerpc/include/asm/hw_irq.h @@ -49,8 +49,13 @@ extern void iseries_handle_interrupts(void); #define raw_irqs_disabled() (local_get_flags() == 0) #define raw_irqs_disabled_flags(flags) ((flags) == 0) +#ifdef CONFIG_PPC_BOOK3E +#define __hard_irq_enable() __asm__ __volatile__("wrteei 1": : :"memory"); +#define __hard_irq_disable() __asm__ __volatile__("wrteei 0": : :"memory"); +#else #define __hard_irq_enable() __mtmsrd(mfmsr() | MSR_EE, 1) #define __hard_irq_disable() __mtmsrd(mfmsr() & ~MSR_EE, 1) +#endif #define hard_irq_disable() \ do { \ diff --git a/arch/powerpc/include/asm/iommu.h b/arch/powerpc/include/asm/iommu.h index 7ead7c16fb7c..7464c0daddd1 100644 --- a/arch/powerpc/include/asm/iommu.h +++ b/arch/powerpc/include/asm/iommu.h @@ -35,16 +35,6 @@ #define IOMMU_PAGE_MASK (~((1 << IOMMU_PAGE_SHIFT) - 1)) #define IOMMU_PAGE_ALIGN(addr) _ALIGN_UP(addr, IOMMU_PAGE_SIZE) -/* Cell page table entries */ -#define CBE_IOPTE_PP_W 0x8000000000000000ul /* protection: write */ -#define CBE_IOPTE_PP_R 0x4000000000000000ul /* protection: read */ -#define CBE_IOPTE_M 0x2000000000000000ul /* coherency required */ -#define CBE_IOPTE_SO_R 0x1000000000000000ul /* ordering: writes */ -#define CBE_IOPTE_SO_RW 0x1800000000000000ul /* ordering: r & w */ -#define CBE_IOPTE_RPN_Mask 0x07fffffffffff000ul /* RPN */ -#define CBE_IOPTE_H 0x0000000000000800ul /* cache hint */ -#define CBE_IOPTE_IOID_Mask 0x00000000000007fful /* ioid */ - /* Boot time flags */ extern int iommu_is_off; extern int iommu_force_on; diff --git a/arch/powerpc/include/asm/mmu-40x.h b/arch/powerpc/include/asm/mmu-40x.h index 776f415a36aa..34916865eaef 100644 --- a/arch/powerpc/include/asm/mmu-40x.h +++ b/arch/powerpc/include/asm/mmu-40x.h @@ -61,4 +61,7 @@ typedef struct { #endif /* !__ASSEMBLY__ */ +#define mmu_virtual_psize MMU_PAGE_4K +#define mmu_linear_psize MMU_PAGE_256M + #endif /* _ASM_POWERPC_MMU_40X_H_ */ diff --git a/arch/powerpc/include/asm/mmu-44x.h b/arch/powerpc/include/asm/mmu-44x.h index 3c86576bfefa..0372669383a8 100644 --- a/arch/powerpc/include/asm/mmu-44x.h +++ b/arch/powerpc/include/asm/mmu-44x.h @@ -79,16 +79,22 @@ typedef struct { #if (PAGE_SHIFT == 12) #define PPC44x_TLBE_SIZE PPC44x_TLB_4K +#define mmu_virtual_psize MMU_PAGE_4K #elif (PAGE_SHIFT == 14) #define PPC44x_TLBE_SIZE PPC44x_TLB_16K +#define mmu_virtual_psize MMU_PAGE_16K #elif (PAGE_SHIFT == 16) #define PPC44x_TLBE_SIZE PPC44x_TLB_64K +#define mmu_virtual_psize MMU_PAGE_64K #elif (PAGE_SHIFT == 18) #define PPC44x_TLBE_SIZE PPC44x_TLB_256K +#define mmu_virtual_psize MMU_PAGE_256K #else #error "Unsupported PAGE_SIZE" #endif +#define mmu_linear_psize MMU_PAGE_256M + #define PPC44x_PGD_OFF_SHIFT (32 - PGDIR_SHIFT + PGD_T_LOG2) #define PPC44x_PGD_OFF_MASK_BIT (PGDIR_SHIFT - PGD_T_LOG2) #define PPC44x_PTE_ADD_SHIFT (32 - PGDIR_SHIFT + PTE_SHIFT + PTE_T_LOG2) diff --git a/arch/powerpc/include/asm/mmu-8xx.h b/arch/powerpc/include/asm/mmu-8xx.h index 07865a357848..3d11d3ce79ec 100644 --- a/arch/powerpc/include/asm/mmu-8xx.h +++ b/arch/powerpc/include/asm/mmu-8xx.h @@ -143,4 +143,7 @@ typedef struct { } mm_context_t; #endif /* !__ASSEMBLY__ */ +#define mmu_virtual_psize MMU_PAGE_4K +#define mmu_linear_psize MMU_PAGE_8M + #endif /* _ASM_POWERPC_MMU_8XX_H_ */ diff --git a/arch/powerpc/include/asm/mmu-book3e.h b/arch/powerpc/include/asm/mmu-book3e.h index 7e74cff81d86..d74580469361 100644 --- a/arch/powerpc/include/asm/mmu-book3e.h +++ b/arch/powerpc/include/asm/mmu-book3e.h @@ -38,58 +38,128 @@ #define BOOK3E_PAGESZ_1TB 30 #define BOOK3E_PAGESZ_2TB 31 -#define MAS0_TLBSEL(x) ((x << 28) & 0x30000000) -#define MAS0_ESEL(x) ((x << 16) & 0x0FFF0000) -#define MAS0_NV(x) ((x) & 0x00000FFF) - -#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 << 7) & 0x00000F80) - -#define MAS2_EPN 0xFFFFF000 -#define MAS2_X0 0x00000040 -#define MAS2_X1 0x00000020 -#define MAS2_W 0x00000010 -#define MAS2_I 0x00000008 -#define MAS2_M 0x00000004 -#define MAS2_G 0x00000002 -#define MAS2_E 0x00000001 +/* MAS registers bit definitions */ + +#define MAS0_TLBSEL(x) ((x << 28) & 0x30000000) +#define MAS0_ESEL(x) ((x << 16) & 0x0FFF0000) +#define MAS0_NV(x) ((x) & 0x00000FFF) +#define MAS0_HES 0x00004000 +#define MAS0_WQ_ALLWAYS 0x00000000 +#define MAS0_WQ_COND 0x00001000 +#define MAS0_WQ_CLR_RSRV 0x00002000 + +#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_MASK 0x00000f80 +#define MAS1_TSIZE_SHIFT 7 +#define MAS1_TSIZE(x) ((x << MAS1_TSIZE_SHIFT) & MAS1_TSIZE_MASK) + +#define MAS2_EPN 0xFFFFF000 +#define MAS2_X0 0x00000040 +#define MAS2_X1 0x00000020 +#define MAS2_W 0x00000010 +#define MAS2_I 0x00000008 +#define MAS2_M 0x00000004 +#define MAS2_G 0x00000002 +#define MAS2_E 0x00000001 #define MAS2_EPN_MASK(size) (~0 << (size + 10)) #define MAS2_VAL(addr, size, flags) ((addr) & MAS2_EPN_MASK(size) | (flags)) -#define MAS3_RPN 0xFFFFF000 -#define MAS3_U0 0x00000200 -#define MAS3_U1 0x00000100 -#define MAS3_U2 0x00000080 -#define MAS3_U3 0x00000040 -#define MAS3_UX 0x00000020 -#define MAS3_SX 0x00000010 -#define MAS3_UW 0x00000008 -#define MAS3_SW 0x00000004 -#define MAS3_UR 0x00000002 -#define MAS3_SR 0x00000001 - -#define MAS4_TLBSELD(x) MAS0_TLBSEL(x) -#define MAS4_INDD 0x00008000 -#define MAS4_TSIZED(x) MAS1_TSIZE(x) -#define MAS4_X0D 0x00000040 -#define MAS4_X1D 0x00000020 -#define MAS4_WD 0x00000010 -#define MAS4_ID 0x00000008 -#define MAS4_MD 0x00000004 -#define MAS4_GD 0x00000002 -#define MAS4_ED 0x00000001 - -#define MAS6_SPID0 0x3FFF0000 -#define MAS6_SPID1 0x00007FFE -#define MAS6_ISIZE(x) MAS1_TSIZE(x) -#define MAS6_SAS 0x00000001 -#define MAS6_SPID MAS6_SPID0 - -#define MAS7_RPN 0xFFFFFFFF +#define MAS3_RPN 0xFFFFF000 +#define MAS3_U0 0x00000200 +#define MAS3_U1 0x00000100 +#define MAS3_U2 0x00000080 +#define MAS3_U3 0x00000040 +#define MAS3_UX 0x00000020 +#define MAS3_SX 0x00000010 +#define MAS3_UW 0x00000008 +#define MAS3_SW 0x00000004 +#define MAS3_UR 0x00000002 +#define MAS3_SR 0x00000001 +#define MAS3_SPSIZE 0x0000003e +#define MAS3_SPSIZE_SHIFT 1 + +#define MAS4_TLBSELD(x) MAS0_TLBSEL(x) +#define MAS4_INDD 0x00008000 /* Default IND */ +#define MAS4_TSIZED(x) MAS1_TSIZE(x) +#define MAS4_X0D 0x00000040 +#define MAS4_X1D 0x00000020 +#define MAS4_WD 0x00000010 +#define MAS4_ID 0x00000008 +#define MAS4_MD 0x00000004 +#define MAS4_GD 0x00000002 +#define MAS4_ED 0x00000001 +#define MAS4_WIMGED_MASK 0x0000001f /* Default WIMGE */ +#define MAS4_WIMGED_SHIFT 0 +#define MAS4_VLED MAS4_X1D /* Default VLE */ +#define MAS4_ACMD 0x000000c0 /* Default ACM */ +#define MAS4_ACMD_SHIFT 6 +#define MAS4_TSIZED_MASK 0x00000f80 /* Default TSIZE */ +#define MAS4_TSIZED_SHIFT 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 +#define MAS6_SIND 0x00000002 /* Indirect page */ +#define MAS6_SIND_SHIFT 1 +#define MAS6_SPID_MASK 0x3fff0000 +#define MAS6_SPID_SHIFT 16 +#define MAS6_ISIZE_MASK 0x00000f80 +#define MAS6_ISIZE_SHIFT 7 + +#define MAS7_RPN 0xFFFFFFFF + +/* TLBnCFG encoding */ +#define TLBnCFG_N_ENTRY 0x00000fff /* number of entries */ +#define TLBnCFG_HES 0x00002000 /* HW select supported */ +#define TLBnCFG_IPROT 0x00008000 /* IPROT supported */ +#define TLBnCFG_GTWE 0x00010000 /* Guest can write */ +#define TLBnCFG_IND 0x00020000 /* IND entries supported */ +#define TLBnCFG_PT 0x00040000 /* Can load from page table */ +#define TLBnCFG_ASSOC 0xff000000 /* Associativity */ + +/* TLBnPS encoding */ +#define TLBnPS_4K 0x00000004 +#define TLBnPS_8K 0x00000008 +#define TLBnPS_16K 0x00000010 +#define TLBnPS_32K 0x00000020 +#define TLBnPS_64K 0x00000040 +#define TLBnPS_128K 0x00000080 +#define TLBnPS_256K 0x00000100 +#define TLBnPS_512K 0x00000200 +#define TLBnPS_1M 0x00000400 +#define TLBnPS_2M 0x00000800 +#define TLBnPS_4M 0x00001000 +#define TLBnPS_8M 0x00002000 +#define TLBnPS_16M 0x00004000 +#define TLBnPS_32M 0x00008000 +#define TLBnPS_64M 0x00010000 +#define TLBnPS_128M 0x00020000 +#define TLBnPS_256M 0x00040000 +#define TLBnPS_512M 0x00080000 +#define TLBnPS_1G 0x00100000 +#define TLBnPS_2G 0x00200000 +#define TLBnPS_4G 0x00400000 +#define TLBnPS_8G 0x00800000 +#define TLBnPS_16G 0x01000000 +#define TLBnPS_32G 0x02000000 +#define TLBnPS_64G 0x04000000 +#define TLBnPS_128G 0x08000000 +#define TLBnPS_256G 0x10000000 + +/* tlbilx action encoding */ +#define TLBILX_T_ALL 0 +#define TLBILX_T_TID 1 +#define TLBILX_T_FULLMATCH 3 +#define TLBILX_T_CLASS0 4 +#define TLBILX_T_CLASS1 5 +#define TLBILX_T_CLASS2 6 +#define TLBILX_T_CLASS3 7 #ifndef __ASSEMBLY__ @@ -100,6 +170,34 @@ typedef struct { unsigned int active; unsigned long vdso_base; } mm_context_t; + +/* Page size definitions, common between 32 and 64-bit + * + * shift : is the "PAGE_SHIFT" value for that page size + * penc : is the pte encoding mask + * + */ +struct mmu_psize_def +{ + unsigned int shift; /* number of bits */ + unsigned int enc; /* PTE encoding */ +}; +extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; + +/* The page sizes use the same names as 64-bit hash but are + * constants + */ +#if defined(CONFIG_PPC_4K_PAGES) +#define mmu_virtual_psize MMU_PAGE_4K +#elif defined(CONFIG_PPC_64K_PAGES) +#define mmu_virtual_psize MMU_PAGE_64K +#else +#error Unsupported page size +#endif + +extern int mmu_linear_psize; +extern int mmu_vmemmap_psize; + #endif /* !__ASSEMBLY__ */ #endif /* _ASM_POWERPC_MMU_BOOK3E_H_ */ diff --git a/arch/powerpc/include/asm/mmu-hash32.h b/arch/powerpc/include/asm/mmu-hash32.h index 16b1a1e77e64..382fc689f204 100644 --- a/arch/powerpc/include/asm/mmu-hash32.h +++ b/arch/powerpc/include/asm/mmu-hash32.h @@ -80,4 +80,10 @@ typedef struct { #endif /* !__ASSEMBLY__ */ +/* We happily ignore the smaller BATs on 601, we don't actually use + * those definitions on hash32 at the moment anyway + */ +#define mmu_virtual_psize MMU_PAGE_4K +#define mmu_linear_psize MMU_PAGE_256M + #endif /* _ASM_POWERPC_MMU_HASH32_H_ */ diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h index 98c104a09961..b537903b9fca 100644 --- a/arch/powerpc/include/asm/mmu-hash64.h +++ b/arch/powerpc/include/asm/mmu-hash64.h @@ -139,26 +139,6 @@ struct mmu_psize_def #endif /* __ASSEMBLY__ */ /* - * The kernel use the constants below to index in the page sizes array. - * The use of fixed constants for this purpose is better for performances - * of the low level hash refill handlers. - * - * A non supported page size has a "shift" field set to 0 - * - * Any new page size being implemented can get a new entry in here. Whether - * the kernel will use it or not is a different matter though. The actual page - * size used by hugetlbfs is not defined here and may be made variable - */ - -#define MMU_PAGE_4K 0 /* 4K */ -#define MMU_PAGE_64K 1 /* 64K */ -#define MMU_PAGE_64K_AP 2 /* 64K Admixed (in a 4K segment) */ -#define MMU_PAGE_1M 3 /* 1M */ -#define MMU_PAGE_16M 4 /* 16M */ -#define MMU_PAGE_16G 5 /* 16G */ -#define MMU_PAGE_COUNT 6 - -/* * Segment sizes. * These are the values used by hardware in the B field of * SLB entries and the first dword of MMU hashtable entries. diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h index fb57ded592f9..2fcfefc60894 100644 --- a/arch/powerpc/include/asm/mmu.h +++ b/arch/powerpc/include/asm/mmu.h @@ -17,6 +17,7 @@ #define MMU_FTR_TYPE_40x ASM_CONST(0x00000004) #define MMU_FTR_TYPE_44x ASM_CONST(0x00000008) #define MMU_FTR_TYPE_FSL_E ASM_CONST(0x00000010) +#define MMU_FTR_TYPE_3E ASM_CONST(0x00000020) /* * This is individual features @@ -73,6 +74,41 @@ extern void early_init_mmu_secondary(void); #endif /* !__ASSEMBLY__ */ +/* The kernel use the constants below to index in the page sizes array. + * The use of fixed constants for this purpose is better for performances + * of the low level hash refill handlers. + * + * A non supported page size has a "shift" field set to 0 + * + * Any new page size being implemented can get a new entry in here. Whether + * the kernel will use it or not is a different matter though. The actual page + * size used by hugetlbfs is not defined here and may be made variable + * + * Note: This array ended up being a false good idea as it's growing to the + * point where I wonder if we should replace it with something different, + * to think about, feedback welcome. --BenH. + */ + +/* There are #define as they have to be used in assembly + * + * WARNING: If you change this list, make sure to update the array of + * names currently in arch/powerpc/mm/hugetlbpage.c or bad things will + * happen + */ +#define MMU_PAGE_4K 0 +#define MMU_PAGE_16K 1 +#define MMU_PAGE_64K 2 +#define MMU_PAGE_64K_AP 3 /* "Admixed pages" (hash64 only) */ +#define MMU_PAGE_256K 4 +#define MMU_PAGE_1M 5 +#define MMU_PAGE_8M 6 +#define MMU_PAGE_16M 7 +#define MMU_PAGE_256M 8 +#define MMU_PAGE_1G 9 +#define MMU_PAGE_16G 10 +#define MMU_PAGE_64G 11 +#define MMU_PAGE_COUNT 12 + #if defined(CONFIG_PPC_STD_MMU_64) /* 64-bit classic hash table MMU */ @@ -94,5 +130,6 @@ extern void early_init_mmu_secondary(void); # include <asm/mmu-8xx.h> #endif + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_MMU_H_ */ diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h index b7063669f972..b34e94d94435 100644 --- a/arch/powerpc/include/asm/mmu_context.h +++ b/arch/powerpc/include/asm/mmu_context.h @@ -14,7 +14,6 @@ /* * Most if the context management is out of line */ -extern void mmu_context_init(void); extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm); extern void destroy_context(struct mm_struct *mm); @@ -23,6 +22,12 @@ extern void switch_stab(struct task_struct *tsk, struct mm_struct *mm); extern void switch_slb(struct task_struct *tsk, struct mm_struct *mm); extern void set_context(unsigned long id, pgd_t *pgd); +#ifdef CONFIG_PPC_BOOK3S_64 +static inline void mmu_context_init(void) { } +#else +extern void mmu_context_init(void); +#endif + /* * switch_mm is the entry point called from the architecture independent * code in kernel/sched.c @@ -38,6 +43,10 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, tsk->thread.pgdir = next->pgd; #endif /* CONFIG_PPC32 */ + /* 64-bit Book3E keeps track of current PGD in the PACA */ +#ifdef CONFIG_PPC_BOOK3E_64 + get_paca()->pgd = next->pgd; +#endif /* Nothing else to do if we aren't actually switching */ if (prev == next) return; @@ -84,6 +93,10 @@ static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next) static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) { + /* 64-bit Book3E keeps track of current PGD in the PACA */ +#ifdef CONFIG_PPC_BOOK3E_64 + get_paca()->pgd = NULL; +#endif } #endif /* __KERNEL__ */ diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index c8a3cbfe02ff..b634456ea893 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h @@ -14,9 +14,11 @@ #define _ASM_POWERPC_PACA_H #ifdef __KERNEL__ -#include <asm/types.h> -#include <asm/lppaca.h> -#include <asm/mmu.h> +#include <asm/types.h> +#include <asm/lppaca.h> +#include <asm/mmu.h> +#include <asm/page.h> +#include <asm/exception-64e.h> register struct paca_struct *local_paca asm("r13"); @@ -91,6 +93,21 @@ struct paca_struct { u16 slb_cache[SLB_CACHE_ENTRIES]; #endif /* CONFIG_PPC_STD_MMU_64 */ +#ifdef CONFIG_PPC_BOOK3E + pgd_t *pgd; /* Current PGD */ + pgd_t *kernel_pgd; /* Kernel PGD */ + u64 exgen[8] __attribute__((aligned(0x80))); + u64 extlb[EX_TLB_SIZE*3] __attribute__((aligned(0x80))); + u64 exmc[8]; /* used for machine checks */ + u64 excrit[8]; /* used for crit interrupts */ + u64 exdbg[8]; /* used for debug interrupts */ + + /* Kernel stack pointers for use by special exceptions */ + void *mc_kstack; + void *crit_kstack; + void *dbg_kstack; +#endif /* CONFIG_PPC_BOOK3E */ + mm_context_t context; /* diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h index 4940662ee87e..ff24254990e1 100644 --- a/arch/powerpc/include/asm/page.h +++ b/arch/powerpc/include/asm/page.h @@ -139,7 +139,11 @@ extern phys_addr_t kernstart_addr; * Don't compare things with KERNELBASE or PAGE_OFFSET to test for * "kernelness", use is_kernel_addr() - it should do what you want. */ +#ifdef CONFIG_PPC_BOOK3E_64 +#define is_kernel_addr(x) ((x) >= 0x8000000000000000ul) +#else #define is_kernel_addr(x) ((x) >= PAGE_OFFSET) +#endif #ifndef __ASSEMBLY__ diff --git a/arch/powerpc/include/asm/page_64.h b/arch/powerpc/include/asm/page_64.h index 5817a3b747e5..3f17b83f55a1 100644 --- a/arch/powerpc/include/asm/page_64.h +++ b/arch/powerpc/include/asm/page_64.h @@ -135,12 +135,22 @@ extern void slice_set_range_psize(struct mm_struct *mm, unsigned long start, #endif /* __ASSEMBLY__ */ #else #define slice_init() +#ifdef CONFIG_PPC_STD_MMU_64 #define get_slice_psize(mm, addr) ((mm)->context.user_psize) #define slice_set_user_psize(mm, psize) \ do { \ (mm)->context.user_psize = (psize); \ (mm)->context.sllp = SLB_VSID_USER | mmu_psize_defs[(psize)].sllp; \ } while (0) +#else /* CONFIG_PPC_STD_MMU_64 */ +#ifdef CONFIG_PPC_64K_PAGES +#define get_slice_psize(mm, addr) MMU_PAGE_64K +#else /* CONFIG_PPC_64K_PAGES */ +#define get_slice_psize(mm, addr) MMU_PAGE_4K +#endif /* !CONFIG_PPC_64K_PAGES */ +#define slice_set_user_psize(mm, psize) do { BUG(); } while(0) +#endif /* !CONFIG_PPC_STD_MMU_64 */ + #define slice_set_range_psize(mm, start, len, psize) \ slice_set_user_psize((mm), (psize)) #define slice_mm_new_context(mm) 1 diff --git a/arch/powerpc/include/asm/pgalloc.h b/arch/powerpc/include/asm/pgalloc.h index 1730e5e298d6..f2e812de7c3c 100644 --- a/arch/powerpc/include/asm/pgalloc.h +++ b/arch/powerpc/include/asm/pgalloc.h @@ -4,6 +4,15 @@ #include <linux/mm.h> +#ifdef CONFIG_PPC_BOOK3E +extern void tlb_flush_pgtable(struct mmu_gather *tlb, unsigned long address); +#else /* CONFIG_PPC_BOOK3E */ +static inline void tlb_flush_pgtable(struct mmu_gather *tlb, + unsigned long address) +{ +} +#endif /* !CONFIG_PPC_BOOK3E */ + static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) { free_page((unsigned long)pte); @@ -19,7 +28,12 @@ typedef struct pgtable_free { unsigned long val; } pgtable_free_t; -#define PGF_CACHENUM_MASK 0x7 +/* This needs to be big enough to allow for MMU_PAGE_COUNT + 2 to be stored + * and small enough to fit in the low bits of any naturally aligned page + * table cache entry. Arbitrarily set to 0x1f, that should give us some + * room to grow + */ +#define PGF_CACHENUM_MASK 0x1f static inline pgtable_free_t pgtable_free_cache(void *p, int cachenum, unsigned long mask) @@ -35,19 +49,27 @@ static inline pgtable_free_t pgtable_free_cache(void *p, int cachenum, #include <asm/pgalloc-32.h> #endif -extern void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf); - #ifdef CONFIG_SMP -#define __pte_free_tlb(tlb,ptepage,address) \ -do { \ - pgtable_page_dtor(ptepage); \ - pgtable_free_tlb(tlb, pgtable_free_cache(page_address(ptepage), \ - PTE_NONCACHE_NUM, PTE_TABLE_SIZE-1)); \ -} while (0) -#else -#define __pte_free_tlb(tlb, pte, address) pte_free((tlb)->mm, (pte)) -#endif +extern void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf); +extern void pte_free_finish(void); +#else /* CONFIG_SMP */ +static inline void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf) +{ + pgtable_free(pgf); +} +static inline void pte_free_finish(void) { } +#endif /* !CONFIG_SMP */ +static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage, + unsigned long address) +{ + pgtable_free_t pgf = pgtable_free_cache(page_address(ptepage), + PTE_NONCACHE_NUM, + PTE_TABLE_SIZE-1); + tlb_flush_pgtable(tlb, address); + pgtable_page_dtor(ptepage); + pgtable_free_tlb(tlb, pgf); +} #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_PGALLOC_H */ diff --git a/arch/powerpc/include/asm/pgtable-ppc64-64k.h b/arch/powerpc/include/asm/pgtable-ppc64-64k.h index 6cc085b945a5..90533ddcd703 100644 --- a/arch/powerpc/include/asm/pgtable-ppc64-64k.h +++ b/arch/powerpc/include/asm/pgtable-ppc64-64k.h @@ -10,10 +10,10 @@ #define PGD_INDEX_SIZE 4 #ifndef __ASSEMBLY__ - #define PTE_TABLE_SIZE (sizeof(real_pte_t) << PTE_INDEX_SIZE) #define PMD_TABLE_SIZE (sizeof(pmd_t) << PMD_INDEX_SIZE) #define PGD_TABLE_SIZE (sizeof(pgd_t) << PGD_INDEX_SIZE) +#endif /* __ASSEMBLY__ */ #define PTRS_PER_PTE (1 << PTE_INDEX_SIZE) #define PTRS_PER_PMD (1 << PMD_INDEX_SIZE) @@ -32,8 +32,6 @@ #define PGDIR_SIZE (1UL << PGDIR_SHIFT) #define PGDIR_MASK (~(PGDIR_SIZE-1)) -#endif /* __ASSEMBLY__ */ - /* Bits to mask out from a PMD to get to the PTE page */ #define PMD_MASKED_BITS 0x1ff /* Bits to mask out from a PGD/PUD to get to the PMD page */ diff --git a/arch/powerpc/include/asm/pgtable-ppc64.h b/arch/powerpc/include/asm/pgtable-ppc64.h index 8cd083c61503..200ec2dfa034 100644 --- a/arch/powerpc/include/asm/pgtable-ppc64.h +++ b/arch/powerpc/include/asm/pgtable-ppc64.h @@ -5,11 +5,6 @@ * the ppc64 hashed page table. */ -#ifndef __ASSEMBLY__ -#include <linux/stddef.h> -#include <asm/tlbflush.h> -#endif /* __ASSEMBLY__ */ - #ifdef CONFIG_PPC_64K_PAGES #include <asm/pgtable-ppc64-64k.h> #else @@ -38,26 +33,47 @@ #endif /* - * Define the address range of the vmalloc VM area. + * Define the address range of the kernel non-linear virtual area + */ + +#ifdef CONFIG_PPC_BOOK3E +#define KERN_VIRT_START ASM_CONST(0x8000000000000000) +#else +#define KERN_VIRT_START ASM_CONST(0xD000000000000000) +#endif +#define KERN_VIRT_SIZE PGTABLE_RANGE + +/* + * The vmalloc space starts at the beginning of that region, and + * occupies half of it on hash CPUs and a quarter of it on Book3E + * (we keep a quarter for the virtual memmap) */ -#define VMALLOC_START ASM_CONST(0xD000000000000000) -#define VMALLOC_SIZE (PGTABLE_RANGE >> 1) -#define VMALLOC_END (VMALLOC_START + VMALLOC_SIZE) +#define VMALLOC_START KERN_VIRT_START +#ifdef CONFIG_PPC_BOOK3E +#define VMALLOC_SIZE (KERN_VIRT_SIZE >> 2) +#else +#define VMALLOC_SIZE (KERN_VIRT_SIZE >> 1) +#endif +#define VMALLOC_END (VMALLOC_START + VMALLOC_SIZE) /* - * Define the address ranges for MMIO and IO space : + * The second half of the kernel virtual space is used for IO mappings, + * it's itself carved into the PIO region (ISA and PHB IO space) and + * the ioremap space * - * ISA_IO_BASE = VMALLOC_END, 64K reserved area + * ISA_IO_BASE = KERN_IO_START, 64K reserved area * PHB_IO_BASE = ISA_IO_BASE + 64K to ISA_IO_BASE + 2G, PHB IO spaces * IOREMAP_BASE = ISA_IO_BASE + 2G to VMALLOC_START + PGTABLE_RANGE */ +#define KERN_IO_START (KERN_VIRT_START + (KERN_VIRT_SIZE >> 1)) #define FULL_IO_SIZE 0x80000000ul -#define ISA_IO_BASE (VMALLOC_END) -#define ISA_IO_END (VMALLOC_END + 0x10000ul) +#define ISA_IO_BASE (KERN_IO_START) +#define ISA_IO_END (KERN_IO_START + 0x10000ul) #define PHB_IO_BASE (ISA_IO_END) -#define PHB_IO_END (VMALLOC_END + FULL_IO_SIZE) +#define PHB_IO_END (KERN_IO_START + FULL_IO_SIZE) #define IOREMAP_BASE (PHB_IO_END) -#define IOREMAP_END (VMALLOC_START + PGTABLE_RANGE) +#define IOREMAP_END (KERN_VIRT_START + KERN_VIRT_SIZE) + /* * Region IDs @@ -68,23 +84,32 @@ #define VMALLOC_REGION_ID (REGION_ID(VMALLOC_START)) #define KERNEL_REGION_ID (REGION_ID(PAGE_OFFSET)) -#define VMEMMAP_REGION_ID (0xfUL) +#define VMEMMAP_REGION_ID (0xfUL) /* Server only */ #define USER_REGION_ID (0UL) /* - * Defines the address of the vmemap area, in its own region + * Defines the address of the vmemap area, in its own region on + * hash table CPUs and after the vmalloc space on Book3E */ +#ifdef CONFIG_PPC_BOOK3E +#define VMEMMAP_BASE VMALLOC_END +#define VMEMMAP_END KERN_IO_START +#else #define VMEMMAP_BASE (VMEMMAP_REGION_ID << REGION_SHIFT) +#endif #define vmemmap ((struct page *)VMEMMAP_BASE) /* * Include the PTE bits definitions */ +#ifdef CONFIG_PPC_BOOK3S #include <asm/pte-hash64.h> +#else +#include <asm/pte-book3e.h> +#endif #include <asm/pte-common.h> - #ifdef CONFIG_PPC_MM_SLICES #define HAVE_ARCH_UNMAPPED_AREA #define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN @@ -92,6 +117,9 @@ #ifndef __ASSEMBLY__ +#include <linux/stddef.h> +#include <asm/tlbflush.h> + /* * This is the default implementation of various PTE accessors, it's * used in all cases except Book3S with 64K pages where we have a diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h index eb17da781128..2a5da069714e 100644 --- a/arch/powerpc/include/asm/pgtable.h +++ b/arch/powerpc/include/asm/pgtable.h @@ -104,8 +104,8 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr, 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 +#elif defined(CONFIG_PPC32) && defined(CONFIG_PTE_64BIT) + /* Second case is 32-bit with 64-bit PTE. 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, @@ -140,7 +140,7 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr, #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 + * cases, and 32-bit non-hash with 32-bit PTEs. */ *ptep = pte; #endif diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h index b74f16d45cb4..ef9aa84cac5a 100644 --- a/arch/powerpc/include/asm/ppc-opcode.h +++ b/arch/powerpc/include/asm/ppc-opcode.h @@ -48,6 +48,8 @@ #define PPC_INST_TLBIE 0x7c000264 #define PPC_INST_TLBILX 0x7c000024 #define PPC_INST_WAIT 0x7c00007c +#define PPC_INST_TLBIVAX 0x7c000624 +#define PPC_INST_TLBSRX_DOT 0x7c0006a5 /* macros to insert fields into opcodes */ #define __PPC_RA(a) (((a) & 0x1f) << 16) @@ -76,6 +78,10 @@ __PPC_WC(w)) #define PPC_TLBIE(lp,a) stringify_in_c(.long PPC_INST_TLBIE | \ __PPC_RB(a) | __PPC_RS(lp)) +#define PPC_TLBSRX_DOT(a,b) stringify_in_c(.long PPC_INST_TLBSRX_DOT | \ + __PPC_RA(a) | __PPC_RB(b)) +#define PPC_TLBIVAX(a,b) stringify_in_c(.long PPC_INST_TLBIVAX | \ + __PPC_RA(a) | __PPC_RB(b)) /* * Define what the VSX XX1 form instructions will look like, then add diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h index f9729529c20d..dfae6e916dfb 100644 --- a/arch/powerpc/include/asm/ppc_asm.h +++ b/arch/powerpc/include/asm/ppc_asm.h @@ -375,8 +375,15 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601) #define PPC440EP_ERR42 #endif - -#if defined(CONFIG_BOOKE) +/* + * toreal/fromreal/tophys/tovirt macros. 32-bit BookE makes them + * keep the address intact to be compatible with code shared with + * 32-bit classic. + * + * On the other hand, I find it useful to have them behave as expected + * by their name (ie always do the addition) on 64-bit BookE + */ +#if defined(CONFIG_BOOKE) && !defined(CONFIG_PPC64) #define toreal(rd) #define fromreal(rd) @@ -426,10 +433,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601) .previous #endif -#ifdef CONFIG_PPC64 +#ifdef CONFIG_PPC_BOOK3S_64 #define RFI rfid #define MTMSRD(r) mtmsrd r - #else #define FIX_SRR1(ra, rb) #ifndef CONFIG_40x diff --git a/arch/powerpc/include/asm/pte-book3e.h b/arch/powerpc/include/asm/pte-book3e.h new file mode 100644 index 000000000000..1d27c77d7704 --- /dev/null +++ b/arch/powerpc/include/asm/pte-book3e.h @@ -0,0 +1,70 @@ +#ifndef _ASM_POWERPC_PTE_BOOK3E_H +#define _ASM_POWERPC_PTE_BOOK3E_H +#ifdef __KERNEL__ + +/* PTE bit definitions for processors compliant to the Book3E + * architecture 2.06 or later. The position of the PTE bits + * matches the HW definition of the optional Embedded Page Table + * category. + */ + +/* Architected bits */ +#define _PAGE_PRESENT 0x000001 /* software: pte contains a translation */ +#define _PAGE_FILE 0x000002 /* (!present only) software: pte holds file offset */ +#define _PAGE_SW1 0x000002 +#define _PAGE_BAP_SR 0x000004 +#define _PAGE_BAP_UR 0x000008 +#define _PAGE_BAP_SW 0x000010 +#define _PAGE_BAP_UW 0x000020 +#define _PAGE_BAP_SX 0x000040 +#define _PAGE_BAP_UX 0x000080 +#define _PAGE_PSIZE_MSK 0x000f00 +#define _PAGE_PSIZE_4K 0x000200 +#define _PAGE_PSIZE_64K 0x000600 +#define _PAGE_PSIZE_1M 0x000a00 +#define _PAGE_PSIZE_16M 0x000e00 +#define _PAGE_DIRTY 0x001000 /* C: page changed */ +#define _PAGE_SW0 0x002000 +#define _PAGE_U3 0x004000 +#define _PAGE_U2 0x008000 +#define _PAGE_U1 0x010000 +#define _PAGE_U0 0x020000 +#define _PAGE_ACCESSED 0x040000 +#define _PAGE_LENDIAN 0x080000 +#define _PAGE_GUARDED 0x100000 +#define _PAGE_COHERENT 0x200000 /* M: enforce memory coherence */ +#define _PAGE_NO_CACHE 0x400000 /* I: cache inhibit */ +#define _PAGE_WRITETHRU 0x800000 /* W: cache write-through */ + +/* "Higher level" linux bit combinations */ +#define _PAGE_EXEC _PAGE_BAP_SX /* Can be executed from potentially */ +#define _PAGE_HWEXEC _PAGE_BAP_UX /* .. and was cache cleaned */ +#define _PAGE_RW (_PAGE_BAP_SW | _PAGE_BAP_UW) /* User write permission */ +#define _PAGE_KERNEL_RW (_PAGE_BAP_SW | _PAGE_BAP_SR | _PAGE_DIRTY) +#define _PAGE_KERNEL_RO (_PAGE_BAP_SR) +#define _PAGE_USER (_PAGE_BAP_UR | _PAGE_BAP_SR) /* Can be read */ + +#define _PAGE_HASHPTE 0 +#define _PAGE_BUSY 0 + +#define _PAGE_SPECIAL _PAGE_SW0 + +/* Flags to be preserved on PTE modifications */ +#define _PAGE_HPTEFLAGS _PAGE_BUSY + +/* Base page size */ +#ifdef CONFIG_PPC_64K_PAGES +#define _PAGE_PSIZE _PAGE_PSIZE_64K +#define PTE_RPN_SHIFT (28) +#else +#define _PAGE_PSIZE _PAGE_PSIZE_4K +#define PTE_RPN_SHIFT (24) +#endif + +/* On 32-bit, we never clear the top part of the PTE */ +#ifdef CONFIG_PPC32 +#define _PTE_NONE_MASK 0xffffffff00000000ULL +#endif + +#endif /* __KERNEL__ */ +#endif /* _ASM_POWERPC_PTE_FSL_BOOKE_H */ diff --git a/arch/powerpc/include/asm/pte-common.h b/arch/powerpc/include/asm/pte-common.h index a7e210b6b48c..8bb6464ba619 100644 --- a/arch/powerpc/include/asm/pte-common.h +++ b/arch/powerpc/include/asm/pte-common.h @@ -34,6 +34,9 @@ #ifndef _PAGE_4K_PFN #define _PAGE_4K_PFN 0 #endif +#ifndef _PAGE_SAO +#define _PAGE_SAO 0 +#endif #ifndef _PAGE_PSIZE #define _PAGE_PSIZE 0 #endif diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index 1170267736d3..6315edc205d8 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -98,19 +98,15 @@ #define MSR_RI __MASK(MSR_RI_LG) /* Recoverable Exception */ #define MSR_LE __MASK(MSR_LE_LG) /* Little Endian */ -#ifdef CONFIG_PPC64 +#if defined(CONFIG_PPC_BOOK3S_64) +/* Server variant */ #define MSR_ MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_ISF |MSR_HV #define MSR_KERNEL MSR_ | MSR_SF - #define MSR_USER32 MSR_ | MSR_PR | MSR_EE #define MSR_USER64 MSR_USER32 | MSR_SF - -#else /* 32-bit */ +#elif defined(CONFIG_PPC_BOOK3S_32) || defined(CONFIG_8xx) /* Default MSR for kernel mode. */ -#ifndef MSR_KERNEL /* reg_booke.h also defines this */ #define MSR_KERNEL (MSR_ME|MSR_RI|MSR_IR|MSR_DR) -#endif - #define MSR_USER (MSR_KERNEL|MSR_PR|MSR_EE) #endif @@ -646,6 +642,137 @@ #endif /* + * SPRG usage: + * + * All 64-bit: + * - SPRG1 stores PACA pointer + * + * 64-bit server: + * - SPRG0 unused (reserved for HV on Power4) + * - SPRG2 scratch for exception vectors + * - SPRG3 unused (user visible) + * + * 64-bit embedded + * - SPRG0 generic exception scratch + * - SPRG2 TLB exception stack + * - SPRG3 unused (user visible) + * - SPRG4 unused (user visible) + * - SPRG6 TLB miss scratch (user visible, sorry !) + * - SPRG7 critical exception scratch + * - SPRG8 machine check exception scratch + * - SPRG9 debug exception scratch + * + * All 32-bit: + * - SPRG3 current thread_info pointer + * (virtual on BookE, physical on others) + * + * 32-bit classic: + * - SPRG0 scratch for exception vectors + * - SPRG1 scratch for exception vectors + * - SPRG2 indicator that we are in RTAS + * - SPRG4 (603 only) pseudo TLB LRU data + * + * 32-bit 40x: + * - SPRG0 scratch for exception vectors + * - SPRG1 scratch for exception vectors + * - SPRG2 scratch for exception vectors + * - SPRG4 scratch for exception vectors (not 403) + * - SPRG5 scratch for exception vectors (not 403) + * - SPRG6 scratch for exception vectors (not 403) + * - SPRG7 scratch for exception vectors (not 403) + * + * 32-bit 440 and FSL BookE: + * - SPRG0 scratch for exception vectors + * - SPRG1 scratch for exception vectors (*) + * - SPRG2 scratch for crit interrupts handler + * - SPRG4 scratch for exception vectors + * - SPRG5 scratch for exception vectors + * - SPRG6 scratch for machine check handler + * - SPRG7 scratch for exception vectors + * - SPRG9 scratch for debug vectors (e500 only) + * + * Additionally, BookE separates "read" and "write" + * of those registers. That allows to use the userspace + * readable variant for reads, which can avoid a fault + * with KVM type virtualization. + * + * (*) Under KVM, the host SPRG1 is used to point to + * the current VCPU data structure + * + * 32-bit 8xx: + * - SPRG0 scratch for exception vectors + * - SPRG1 scratch for exception vectors + * - SPRG2 apparently unused but initialized + * + */ +#ifdef CONFIG_PPC64 +#define SPRN_SPRG_PACA SPRN_SPRG1 +#else +#define SPRN_SPRG_THREAD SPRN_SPRG3 +#endif + +#ifdef CONFIG_PPC_BOOK3S_64 +#define SPRN_SPRG_SCRATCH0 SPRN_SPRG2 +#endif + +#ifdef CONFIG_PPC_BOOK3E_64 +#define SPRN_SPRG_MC_SCRATCH SPRN_SPRG8 +#define SPRN_SPRG_CRIT_SCRATCH SPRN_SPRG7 +#define SPRN_SPRG_DBG_SCRATCH SPRN_SPRG9 +#define SPRN_SPRG_TLB_EXFRAME SPRN_SPRG2 +#define SPRN_SPRG_TLB_SCRATCH SPRN_SPRG6 +#define SPRN_SPRG_GEN_SCRATCH SPRN_SPRG0 +#endif + +#ifdef CONFIG_PPC_BOOK3S_32 +#define SPRN_SPRG_SCRATCH0 SPRN_SPRG0 +#define SPRN_SPRG_SCRATCH1 SPRN_SPRG1 +#define SPRN_SPRG_RTAS SPRN_SPRG2 +#define SPRN_SPRG_603_LRU SPRN_SPRG4 +#endif + +#ifdef CONFIG_40x +#define SPRN_SPRG_SCRATCH0 SPRN_SPRG0 +#define SPRN_SPRG_SCRATCH1 SPRN_SPRG1 +#define SPRN_SPRG_SCRATCH2 SPRN_SPRG2 +#define SPRN_SPRG_SCRATCH3 SPRN_SPRG4 +#define SPRN_SPRG_SCRATCH4 SPRN_SPRG5 +#define SPRN_SPRG_SCRATCH5 SPRN_SPRG6 +#define SPRN_SPRG_SCRATCH6 SPRN_SPRG7 +#endif + +#ifdef CONFIG_BOOKE +#define SPRN_SPRG_RSCRATCH0 SPRN_SPRG0 +#define SPRN_SPRG_WSCRATCH0 SPRN_SPRG0 +#define SPRN_SPRG_RSCRATCH1 SPRN_SPRG1 +#define SPRN_SPRG_WSCRATCH1 SPRN_SPRG1 +#define SPRN_SPRG_RSCRATCH_CRIT SPRN_SPRG2 +#define SPRN_SPRG_WSCRATCH_CRIT SPRN_SPRG2 +#define SPRN_SPRG_RSCRATCH2 SPRN_SPRG4R +#define SPRN_SPRG_WSCRATCH2 SPRN_SPRG4W +#define SPRN_SPRG_RSCRATCH3 SPRN_SPRG5R +#define SPRN_SPRG_WSCRATCH3 SPRN_SPRG5W +#define SPRN_SPRG_RSCRATCH_MC SPRN_SPRG6R +#define SPRN_SPRG_WSCRATCH_MC SPRN_SPRG6W +#define SPRN_SPRG_RSCRATCH4 SPRN_SPRG7R +#define SPRN_SPRG_WSCRATCH4 SPRN_SPRG7W +#ifdef CONFIG_E200 +#define SPRN_SPRG_RSCRATCH_DBG SPRN_SPRG6R +#define SPRN_SPRG_WSCRATCH_DBG SPRN_SPRG6W +#else +#define SPRN_SPRG_RSCRATCH_DBG SPRN_SPRG9 +#define SPRN_SPRG_WSCRATCH_DBG SPRN_SPRG9 +#endif +#define SPRN_SPRG_RVCPU SPRN_SPRG1 +#define SPRN_SPRG_WVCPU SPRN_SPRG1 +#endif + +#ifdef CONFIG_8xx +#define SPRN_SPRG_SCRATCH0 SPRN_SPRG0 +#define SPRN_SPRG_SCRATCH1 SPRN_SPRG1 +#endif + +/* * An mtfsf instruction with the L bit set. On CPUs that support this a * full 64bits of FPSCR is restored and on other CPUs the L bit is ignored. * diff --git a/arch/powerpc/include/asm/reg_booke.h b/arch/powerpc/include/asm/reg_booke.h index 6bcf364cbb2f..2c9c706e6448 100644 --- a/arch/powerpc/include/asm/reg_booke.h +++ b/arch/powerpc/include/asm/reg_booke.h @@ -18,18 +18,26 @@ #define MSR_IS MSR_IR /* Instruction Space */ #define MSR_DS MSR_DR /* Data Space */ #define MSR_PMM (1<<2) /* Performance monitor mark bit */ +#define MSR_CM (1<<31) /* Computation Mode (0=32-bit, 1=64-bit) */ -/* Default MSR for kernel mode. */ -#if defined (CONFIG_40x) +#if defined(CONFIG_PPC_BOOK3E_64) +#define MSR_ MSR_ME | MSR_CE +#define MSR_KERNEL MSR_ | MSR_CM +#define MSR_USER32 MSR_ | MSR_PR | MSR_EE +#define MSR_USER64 MSR_USER32 | MSR_CM +#elif defined (CONFIG_40x) #define MSR_KERNEL (MSR_ME|MSR_RI|MSR_IR|MSR_DR|MSR_CE) -#elif defined(CONFIG_BOOKE) +#define MSR_USER (MSR_KERNEL|MSR_PR|MSR_EE) +#else #define MSR_KERNEL (MSR_ME|MSR_RI|MSR_CE) +#define MSR_USER (MSR_KERNEL|MSR_PR|MSR_EE) #endif /* Special Purpose Registers (SPRNs)*/ #define SPRN_DECAR 0x036 /* Decrementer Auto Reload Register */ #define SPRN_IVPR 0x03F /* Interrupt Vector Prefix Register */ #define SPRN_USPRG0 0x100 /* User Special Purpose Register General 0 */ +#define SPRN_SPRG3R 0x103 /* Special Purpose Register General 3 Read */ #define SPRN_SPRG4R 0x104 /* Special Purpose Register General 4 Read */ #define SPRN_SPRG5R 0x105 /* Special Purpose Register General 5 Read */ #define SPRN_SPRG6R 0x106 /* Special Purpose Register General 6 Read */ @@ -38,11 +46,18 @@ #define SPRN_SPRG5W 0x115 /* Special Purpose Register General 5 Write */ #define SPRN_SPRG6W 0x116 /* Special Purpose Register General 6 Write */ #define SPRN_SPRG7W 0x117 /* Special Purpose Register General 7 Write */ +#define SPRN_EPCR 0x133 /* Embedded Processor Control Register */ #define SPRN_DBCR2 0x136 /* Debug Control Register 2 */ #define SPRN_IAC3 0x13A /* Instruction Address Compare 3 */ #define SPRN_IAC4 0x13B /* Instruction Address Compare 4 */ #define SPRN_DVC1 0x13E /* Data Value Compare Register 1 */ #define SPRN_DVC2 0x13F /* Data Value Compare Register 2 */ +#define SPRN_MAS8 0x155 /* MMU Assist Register 8 */ +#define SPRN_TLB0PS 0x158 /* TLB 0 Page Size Register */ +#define SPRN_MAS5_MAS6 0x15c /* MMU Assist Register 5 || 6 */ +#define SPRN_MAS8_MAS1 0x15d /* MMU Assist Register 8 || 1 */ +#define SPRN_MAS7_MAS3 0x174 /* MMU Assist Register 7 || 3 */ +#define SPRN_MAS0_MAS1 0x175 /* MMU Assist Register 0 || 1 */ #define SPRN_IVOR0 0x190 /* Interrupt Vector Offset Register 0 */ #define SPRN_IVOR1 0x191 /* Interrupt Vector Offset Register 1 */ #define SPRN_IVOR2 0x192 /* Interrupt Vector Offset Register 2 */ @@ -425,6 +440,27 @@ #define SGR_NORMAL 0 /* Speculative fetching allowed. */ #define SGR_GUARDED 1 /* Speculative fetching disallowed. */ +/* Bit definitions for EPCR */ +#define SPRN_EPCR_EXTGS 0x80000000 /* External Input interrupt + * directed to Guest state */ +#define SPRN_EPCR_DTLBGS 0x40000000 /* Data TLB Error interrupt + * directed to guest state */ +#define SPRN_EPCR_ITLBGS 0x20000000 /* Instr. TLB error interrupt + * directed to guest state */ +#define SPRN_EPCR_DSIGS 0x10000000 /* Data Storage interrupt + * directed to guest state */ +#define SPRN_EPCR_ISIGS 0x08000000 /* Instr. Storage interrupt + * directed to guest state */ +#define SPRN_EPCR_DUVD 0x04000000 /* Disable Hypervisor Debug */ +#define SPRN_EPCR_ICM 0x02000000 /* Interrupt computation mode + * (copied to MSR:CM on intr) */ +#define SPRN_EPCR_GICM 0x01000000 /* Guest Interrupt Comp. mode */ +#define SPRN_EPCR_DGTMI 0x00800000 /* Disable TLB Guest Management + * instructions */ +#define SPRN_EPCR_DMIUH 0x00400000 /* Disable MAS Interrupt updates + * for hypervisor */ + + /* * The IBM-403 is an even more odd special case, as it is much * older than the IBM-405 series. We put these down here incase someone diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h index c25f73d1d842..c0d3b8af9319 100644 --- a/arch/powerpc/include/asm/smp.h +++ b/arch/powerpc/include/asm/smp.h @@ -148,6 +148,16 @@ extern struct smp_ops_t *smp_ops; extern void arch_send_call_function_single_ipi(int cpu); extern void arch_send_call_function_ipi(cpumask_t mask); +/* Definitions relative to the secondary CPU spin loop + * and entry point. Not all of them exist on both 32 and + * 64-bit but defining them all here doesn't harm + */ +extern void generic_secondary_smp_init(void); +extern void generic_secondary_thread_init(void); +extern unsigned long __secondary_hold_spinloop; +extern unsigned long __secondary_hold_acknowledge; +extern char __secondary_hold; + #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h index 370600ca2765..ed24bd92fe49 100644 --- a/arch/powerpc/include/asm/systbl.h +++ b/arch/powerpc/include/asm/systbl.h @@ -95,8 +95,8 @@ SYSCALL(reboot) SYSX(sys_ni_syscall,compat_sys_old_readdir,sys_old_readdir) SYSCALL_SPU(mmap) SYSCALL_SPU(munmap) -SYSCALL_SPU(truncate) -SYSCALL_SPU(ftruncate) +COMPAT_SYS_SPU(truncate) +COMPAT_SYS_SPU(ftruncate) SYSCALL_SPU(fchmod) SYSCALL_SPU(fchown) COMPAT_SYS_SPU(getpriority) diff --git a/arch/powerpc/include/asm/tlb.h b/arch/powerpc/include/asm/tlb.h index e20ff7541f36..e2b428b0f7ba 100644 --- a/arch/powerpc/include/asm/tlb.h +++ b/arch/powerpc/include/asm/tlb.h @@ -25,57 +25,25 @@ #include <linux/pagemap.h> -struct mmu_gather; - #define tlb_start_vma(tlb, vma) do { } while (0) #define tlb_end_vma(tlb, vma) do { } while (0) -#if !defined(CONFIG_PPC_STD_MMU) - -#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm) - -#elif defined(__powerpc64__) - -extern void pte_free_finish(void); - -static inline void tlb_flush(struct mmu_gather *tlb) -{ - struct ppc64_tlb_batch *tlbbatch = &__get_cpu_var(ppc64_tlb_batch); - - /* If there's a TLB batch pending, then we must flush it because the - * pages are going to be freed and we really don't want to have a CPU - * access a freed page because it has a stale TLB - */ - if (tlbbatch->index) - __flush_tlb_pending(tlbbatch); - - pte_free_finish(); -} - -#else - extern void tlb_flush(struct mmu_gather *tlb); -#endif - /* Get the generic bits... */ #include <asm-generic/tlb.h> -#if !defined(CONFIG_PPC_STD_MMU) || defined(__powerpc64__) - -#define __tlb_remove_tlb_entry(tlb, pte, address) do { } while (0) - -#else extern void flush_hash_entry(struct mm_struct *mm, pte_t *ptep, unsigned long address); static inline void __tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, - unsigned long address) + unsigned long address) { +#ifdef CONFIG_PPC_STD_MMU_32 if (pte_val(*ptep) & _PAGE_HASHPTE) flush_hash_entry(tlb->mm, ptep, address); +#endif } -#endif #endif /* __KERNEL__ */ #endif /* __ASM_POWERPC_TLB_H */ diff --git a/arch/powerpc/include/asm/tlbflush.h b/arch/powerpc/include/asm/tlbflush.h index abbe3419d1dd..d50a380b2b6f 100644 --- a/arch/powerpc/include/asm/tlbflush.h +++ b/arch/powerpc/include/asm/tlbflush.h @@ -6,7 +6,7 @@ * * - flush_tlb_mm(mm) flushes the specified mm context TLB's * - flush_tlb_page(vma, vmaddr) flushes one page - * - local_flush_tlb_mm(mm) flushes the specified mm context on + * - local_flush_tlb_mm(mm, full) flushes the specified mm context on * the local processor * - local_flush_tlb_page(vma, vmaddr) flushes one page on the local processor * - flush_tlb_page_nohash(vma, vmaddr) flushes one page if SW loaded TLB @@ -29,7 +29,8 @@ * specific tlbie's */ -#include <linux/mm.h> +struct vm_area_struct; +struct mm_struct; #define MMU_NO_CONTEXT ((unsigned int)-1) @@ -40,12 +41,18 @@ extern void flush_tlb_kernel_range(unsigned long start, unsigned long end); extern void local_flush_tlb_mm(struct mm_struct *mm); extern void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); +extern void __local_flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr, + int tsize, int ind); + #ifdef CONFIG_SMP extern void flush_tlb_mm(struct mm_struct *mm); extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); +extern void __flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr, + int tsize, int ind); #else #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(mm,addr,p,i) __local_flush_tlb_page(mm,addr,p,i) #endif #define flush_tlb_page_nohash(vma,addr) flush_tlb_page(vma,addr) diff --git a/arch/powerpc/include/asm/vdso.h b/arch/powerpc/include/asm/vdso.h index 26fc449bd989..dc0419b66f17 100644 --- a/arch/powerpc/include/asm/vdso.h +++ b/arch/powerpc/include/asm/vdso.h @@ -7,9 +7,8 @@ #define VDSO32_LBASE 0x100000 #define VDSO64_LBASE 0x100000 -/* Default map addresses */ +/* Default map addresses for 32bit vDSO */ #define VDSO32_MBASE VDSO32_LBASE -#define VDSO64_MBASE VDSO64_LBASE #define VDSO_VERSION_STRING LINUX_2.6.15 |