diff options
author | Christian Borntraeger <borntraeger@de.ibm.com> | 2008-10-28 06:10:15 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2008-10-28 06:12:03 -0400 |
commit | 250cf776f74b5932a1977d0489cae9206e2351dd (patch) | |
tree | 71bb6778e65e8efbdd0cac09a64e4e1194b98c3f /arch/s390/include/asm/mmu_context.h | |
parent | 2c78091405d6f54748b1fac78c45f2a799e3073a (diff) |
[S390] pgtables: Fix race in enable_sie vs. page table ops
The current enable_sie code sets the mm->context.pgstes bit to tell
dup_mm that the new mm should have extended page tables. This bit is also
used by the s390 specific page table primitives to decide about the page
table layout - which means context.pgstes has two meanings. This can cause
any kind of bugs. For example - e.g. shrink_zone can call
ptep_clear_flush_young while enable_sie is running. ptep_clear_flush_young
will test for context.pgstes. Since enable_sie changed that value of the old
struct mm without changing the page table layout ptep_clear_flush_young will
do the wrong thing.
The solution is to split pgstes into two bits
- one for the allocation
- one for the current state
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/include/asm/mmu_context.h')
-rw-r--r-- | arch/s390/include/asm/mmu_context.h | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/arch/s390/include/asm/mmu_context.h b/arch/s390/include/asm/mmu_context.h index 4c2fbf48c9c4..28ec870655af 100644 --- a/arch/s390/include/asm/mmu_context.h +++ b/arch/s390/include/asm/mmu_context.h | |||
@@ -20,12 +20,25 @@ static inline int init_new_context(struct task_struct *tsk, | |||
20 | #ifdef CONFIG_64BIT | 20 | #ifdef CONFIG_64BIT |
21 | mm->context.asce_bits |= _ASCE_TYPE_REGION3; | 21 | mm->context.asce_bits |= _ASCE_TYPE_REGION3; |
22 | #endif | 22 | #endif |
23 | if (current->mm->context.pgstes) { | 23 | if (current->mm->context.alloc_pgste) { |
24 | /* | ||
25 | * alloc_pgste indicates, that any NEW context will be created | ||
26 | * with extended page tables. The old context is unchanged. The | ||
27 | * page table allocation and the page table operations will | ||
28 | * look at has_pgste to distinguish normal and extended page | ||
29 | * tables. The only way to create extended page tables is to | ||
30 | * set alloc_pgste and then create a new context (e.g. dup_mm). | ||
31 | * The page table allocation is called after init_new_context | ||
32 | * and if has_pgste is set, it will create extended page | ||
33 | * tables. | ||
34 | */ | ||
24 | mm->context.noexec = 0; | 35 | mm->context.noexec = 0; |
25 | mm->context.pgstes = 1; | 36 | mm->context.has_pgste = 1; |
37 | mm->context.alloc_pgste = 1; | ||
26 | } else { | 38 | } else { |
27 | mm->context.noexec = s390_noexec; | 39 | mm->context.noexec = s390_noexec; |
28 | mm->context.pgstes = 0; | 40 | mm->context.has_pgste = 0; |
41 | mm->context.alloc_pgste = 0; | ||
29 | } | 42 | } |
30 | mm->context.asce_limit = STACK_TOP_MAX; | 43 | mm->context.asce_limit = STACK_TOP_MAX; |
31 | crst_table_init((unsigned long *) mm->pgd, pgd_entry_type(mm)); | 44 | crst_table_init((unsigned long *) mm->pgd, pgd_entry_type(mm)); |