aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-s390
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2008-01-26 08:10:58 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2008-01-26 08:11:10 -0500
commit6f457e1a149eb39ee58d51913e8023fc27c52806 (patch)
treed702ec38780667a3305e45df05c4f7df3730e9f6 /include/asm-s390
parent4b28a8fe78bd593cdc4454cf28af71ca9556914d (diff)
[S390] Fix tlb flushing with idte.
The clear-by-asce operation of the idte instruction gets an asce (address-space-control-element) as argument to specify which TLBs need to get flushed. The current code passes a plain pointer to the start of the pgd without the additional bits which would make the pointer an asce. The current machines don't mind the difference but a future model might want to use the designation type control bits in the asce as a filter for the TLBs to flush. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'include/asm-s390')
-rw-r--r--include/asm-s390/mmu_context.h27
-rw-r--r--include/asm-s390/tlbflush.h12
2 files changed, 18 insertions, 21 deletions
diff --git a/include/asm-s390/mmu_context.h b/include/asm-s390/mmu_context.h
index 05b842126b99..a77d4ba3c8eb 100644
--- a/include/asm-s390/mmu_context.h
+++ b/include/asm-s390/mmu_context.h
@@ -12,10 +12,15 @@
12#include <asm/pgalloc.h> 12#include <asm/pgalloc.h>
13#include <asm-generic/mm_hooks.h> 13#include <asm-generic/mm_hooks.h>
14 14
15/* 15static inline int init_new_context(struct task_struct *tsk,
16 * get a new mmu context.. S390 don't know about contexts. 16 struct mm_struct *mm)
17 */ 17{
18#define init_new_context(tsk,mm) 0 18 mm->context = _ASCE_TABLE_LENGTH | _ASCE_USER_BITS;
19#ifdef CONFIG_64BIT
20 mm->context |= _ASCE_TYPE_REGION3;
21#endif
22 return 0;
23}
19 24
20#define destroy_context(mm) do { } while (0) 25#define destroy_context(mm) do { } while (0)
21 26
@@ -27,19 +32,11 @@
27 32
28static inline void update_mm(struct mm_struct *mm, struct task_struct *tsk) 33static inline void update_mm(struct mm_struct *mm, struct task_struct *tsk)
29{ 34{
30 pgd_t *pgd = mm->pgd; 35 S390_lowcore.user_asce = mm->context | __pa(mm->pgd);
31 unsigned long asce_bits;
32
33 /* Calculate asce bits from the first pgd table entry. */
34 asce_bits = _ASCE_TABLE_LENGTH | _ASCE_USER_BITS;
35#ifdef CONFIG_64BIT
36 asce_bits |= _ASCE_TYPE_REGION3;
37#endif
38 S390_lowcore.user_asce = asce_bits | __pa(pgd);
39 if (switch_amode) { 36 if (switch_amode) {
40 /* Load primary space page table origin. */ 37 /* Load primary space page table origin. */
41 pgd_t *shadow_pgd = get_shadow_table(pgd) ? : pgd; 38 pgd_t *shadow_pgd = get_shadow_table(mm->pgd) ? : mm->pgd;
42 S390_lowcore.user_exec_asce = asce_bits | __pa(shadow_pgd); 39 S390_lowcore.user_exec_asce = mm->context | __pa(shadow_pgd);
43 asm volatile(LCTL_OPCODE" 1,1,%0\n" 40 asm volatile(LCTL_OPCODE" 1,1,%0\n"
44 : : "m" (S390_lowcore.user_exec_asce) ); 41 : : "m" (S390_lowcore.user_exec_asce) );
45 } else 42 } else
diff --git a/include/asm-s390/tlbflush.h b/include/asm-s390/tlbflush.h
index a69bd2490d52..a5e876539ec6 100644
--- a/include/asm-s390/tlbflush.h
+++ b/include/asm-s390/tlbflush.h
@@ -42,11 +42,11 @@ static inline void __tlb_flush_global(void)
42/* 42/*
43 * Flush all tlb entries of a page table on all cpus. 43 * Flush all tlb entries of a page table on all cpus.
44 */ 44 */
45static inline void __tlb_flush_idte(pgd_t *pgd) 45static inline void __tlb_flush_idte(unsigned long asce)
46{ 46{
47 asm volatile( 47 asm volatile(
48 " .insn rrf,0xb98e0000,0,%0,%1,0" 48 " .insn rrf,0xb98e0000,0,%0,%1,0"
49 : : "a" (2048), "a" (__pa(pgd) & PAGE_MASK) : "cc" ); 49 : : "a" (2048), "a" (asce) : "cc" );
50} 50}
51 51
52static inline void __tlb_flush_mm(struct mm_struct * mm) 52static inline void __tlb_flush_mm(struct mm_struct * mm)
@@ -61,11 +61,11 @@ static inline void __tlb_flush_mm(struct mm_struct * mm)
61 * only ran on the local cpu. 61 * only ran on the local cpu.
62 */ 62 */
63 if (MACHINE_HAS_IDTE) { 63 if (MACHINE_HAS_IDTE) {
64 pgd_t *shadow_pgd = get_shadow_table(mm->pgd); 64 pgd_t *shadow = get_shadow_table(mm->pgd);
65 65
66 if (shadow_pgd) 66 if (shadow)
67 __tlb_flush_idte(shadow_pgd); 67 __tlb_flush_idte((unsigned long) shadow | mm->context);
68 __tlb_flush_idte(mm->pgd); 68 __tlb_flush_idte((unsigned long) mm->pgd | mm->context);
69 return; 69 return;
70 } 70 }
71 preempt_disable(); 71 preempt_disable();