[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>
This commit is contained in:

committed by
Martin Schwidefsky

parent
2c78091405
commit
250cf776f7
@@ -20,12 +20,25 @@ static inline int init_new_context(struct task_struct *tsk,
|
||||
#ifdef CONFIG_64BIT
|
||||
mm->context.asce_bits |= _ASCE_TYPE_REGION3;
|
||||
#endif
|
||||
if (current->mm->context.pgstes) {
|
||||
if (current->mm->context.alloc_pgste) {
|
||||
/*
|
||||
* alloc_pgste indicates, that any NEW context will be created
|
||||
* with extended page tables. The old context is unchanged. The
|
||||
* page table allocation and the page table operations will
|
||||
* look at has_pgste to distinguish normal and extended page
|
||||
* tables. The only way to create extended page tables is to
|
||||
* set alloc_pgste and then create a new context (e.g. dup_mm).
|
||||
* The page table allocation is called after init_new_context
|
||||
* and if has_pgste is set, it will create extended page
|
||||
* tables.
|
||||
*/
|
||||
mm->context.noexec = 0;
|
||||
mm->context.pgstes = 1;
|
||||
mm->context.has_pgste = 1;
|
||||
mm->context.alloc_pgste = 1;
|
||||
} else {
|
||||
mm->context.noexec = s390_noexec;
|
||||
mm->context.pgstes = 0;
|
||||
mm->context.has_pgste = 0;
|
||||
mm->context.alloc_pgste = 0;
|
||||
}
|
||||
mm->context.asce_limit = STACK_TOP_MAX;
|
||||
crst_table_init((unsigned long *) mm->pgd, pgd_entry_type(mm));
|
||||
|
Reference in New Issue
Block a user