diff options
Diffstat (limited to 'arch/s390/include/asm')
-rw-r--r-- | arch/s390/include/asm/lowcore.h | 2 | ||||
-rw-r--r-- | arch/s390/include/asm/mmu.h | 4 | ||||
-rw-r--r-- | arch/s390/include/asm/pgalloc.h | 7 | ||||
-rw-r--r-- | arch/s390/include/asm/pgtable.h | 42 | ||||
-rw-r--r-- | arch/s390/include/asm/processor.h | 1 | ||||
-rw-r--r-- | arch/s390/include/asm/tlbflush.h | 2 |
6 files changed, 52 insertions, 6 deletions
diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index 228cf0b295db..f26280d9e88d 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h | |||
@@ -268,7 +268,7 @@ struct _lowcore { | |||
268 | __u64 vdso_per_cpu_data; /* 0x0358 */ | 268 | __u64 vdso_per_cpu_data; /* 0x0358 */ |
269 | __u64 machine_flags; /* 0x0360 */ | 269 | __u64 machine_flags; /* 0x0360 */ |
270 | __u64 ftrace_func; /* 0x0368 */ | 270 | __u64 ftrace_func; /* 0x0368 */ |
271 | __u64 sie_hook; /* 0x0370 */ | 271 | __u64 gmap; /* 0x0370 */ |
272 | __u64 cmf_hpp; /* 0x0378 */ | 272 | __u64 cmf_hpp; /* 0x0378 */ |
273 | 273 | ||
274 | /* Interrupt response block. */ | 274 | /* Interrupt response block. */ |
diff --git a/arch/s390/include/asm/mmu.h b/arch/s390/include/asm/mmu.h index 82d0847896a0..4506791adcd5 100644 --- a/arch/s390/include/asm/mmu.h +++ b/arch/s390/include/asm/mmu.h | |||
@@ -6,6 +6,7 @@ typedef struct { | |||
6 | unsigned int flush_mm; | 6 | unsigned int flush_mm; |
7 | spinlock_t list_lock; | 7 | spinlock_t list_lock; |
8 | struct list_head pgtable_list; | 8 | struct list_head pgtable_list; |
9 | struct list_head gmap_list; | ||
9 | unsigned long asce_bits; | 10 | unsigned long asce_bits; |
10 | unsigned long asce_limit; | 11 | unsigned long asce_limit; |
11 | unsigned long vdso_base; | 12 | unsigned long vdso_base; |
@@ -17,6 +18,7 @@ typedef struct { | |||
17 | 18 | ||
18 | #define INIT_MM_CONTEXT(name) \ | 19 | #define INIT_MM_CONTEXT(name) \ |
19 | .context.list_lock = __SPIN_LOCK_UNLOCKED(name.context.list_lock), \ | 20 | .context.list_lock = __SPIN_LOCK_UNLOCKED(name.context.list_lock), \ |
20 | .context.pgtable_list = LIST_HEAD_INIT(name.context.pgtable_list), | 21 | .context.pgtable_list = LIST_HEAD_INIT(name.context.pgtable_list), \ |
22 | .context.gmap_list = LIST_HEAD_INIT(name.context.gmap_list), | ||
21 | 23 | ||
22 | #endif | 24 | #endif |
diff --git a/arch/s390/include/asm/pgalloc.h b/arch/s390/include/asm/pgalloc.h index 38e71ebcd3c2..8eef9b5b3cf4 100644 --- a/arch/s390/include/asm/pgalloc.h +++ b/arch/s390/include/asm/pgalloc.h | |||
@@ -20,7 +20,7 @@ | |||
20 | unsigned long *crst_table_alloc(struct mm_struct *); | 20 | unsigned long *crst_table_alloc(struct mm_struct *); |
21 | void crst_table_free(struct mm_struct *, unsigned long *); | 21 | void crst_table_free(struct mm_struct *, unsigned long *); |
22 | 22 | ||
23 | unsigned long *page_table_alloc(struct mm_struct *); | 23 | unsigned long *page_table_alloc(struct mm_struct *, unsigned long); |
24 | void page_table_free(struct mm_struct *, unsigned long *); | 24 | void page_table_free(struct mm_struct *, unsigned long *); |
25 | #ifdef CONFIG_HAVE_RCU_TABLE_FREE | 25 | #ifdef CONFIG_HAVE_RCU_TABLE_FREE |
26 | void page_table_free_rcu(struct mmu_gather *, unsigned long *); | 26 | void page_table_free_rcu(struct mmu_gather *, unsigned long *); |
@@ -115,6 +115,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm) | |||
115 | { | 115 | { |
116 | spin_lock_init(&mm->context.list_lock); | 116 | spin_lock_init(&mm->context.list_lock); |
117 | INIT_LIST_HEAD(&mm->context.pgtable_list); | 117 | INIT_LIST_HEAD(&mm->context.pgtable_list); |
118 | INIT_LIST_HEAD(&mm->context.gmap_list); | ||
118 | return (pgd_t *) crst_table_alloc(mm); | 119 | return (pgd_t *) crst_table_alloc(mm); |
119 | } | 120 | } |
120 | #define pgd_free(mm, pgd) crst_table_free(mm, (unsigned long *) pgd) | 121 | #define pgd_free(mm, pgd) crst_table_free(mm, (unsigned long *) pgd) |
@@ -133,8 +134,8 @@ static inline void pmd_populate(struct mm_struct *mm, | |||
133 | /* | 134 | /* |
134 | * page table entry allocation/free routines. | 135 | * page table entry allocation/free routines. |
135 | */ | 136 | */ |
136 | #define pte_alloc_one_kernel(mm, vmaddr) ((pte_t *) page_table_alloc(mm)) | 137 | #define pte_alloc_one_kernel(mm, vmaddr) ((pte_t *) page_table_alloc(mm, vmaddr)) |
137 | #define pte_alloc_one(mm, vmaddr) ((pte_t *) page_table_alloc(mm)) | 138 | #define pte_alloc_one(mm, vmaddr) ((pte_t *) page_table_alloc(mm, vmaddr)) |
138 | 139 | ||
139 | #define pte_free_kernel(mm, pte) page_table_free(mm, (unsigned long *) pte) | 140 | #define pte_free_kernel(mm, pte) page_table_free(mm, (unsigned long *) pte) |
140 | #define pte_free(mm, pte) page_table_free(mm, (unsigned long *) pte) | 141 | #define pte_free(mm, pte) page_table_free(mm, (unsigned long *) pte) |
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 801fbe1d837d..519eb5f187ef 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h | |||
@@ -654,6 +654,48 @@ static inline void pgste_set_pte(pte_t *ptep, pgste_t pgste) | |||
654 | #endif | 654 | #endif |
655 | } | 655 | } |
656 | 656 | ||
657 | /** | ||
658 | * struct gmap_struct - guest address space | ||
659 | * @mm: pointer to the parent mm_struct | ||
660 | * @table: pointer to the page directory | ||
661 | * @crst_list: list of all crst tables used in the guest address space | ||
662 | */ | ||
663 | struct gmap { | ||
664 | struct list_head list; | ||
665 | struct mm_struct *mm; | ||
666 | unsigned long *table; | ||
667 | struct list_head crst_list; | ||
668 | }; | ||
669 | |||
670 | /** | ||
671 | * struct gmap_rmap - reverse mapping for segment table entries | ||
672 | * @next: pointer to the next gmap_rmap structure in the list | ||
673 | * @entry: pointer to a segment table entry | ||
674 | */ | ||
675 | struct gmap_rmap { | ||
676 | struct list_head list; | ||
677 | unsigned long *entry; | ||
678 | }; | ||
679 | |||
680 | /** | ||
681 | * struct gmap_pgtable - gmap information attached to a page table | ||
682 | * @vmaddr: address of the 1MB segment in the process virtual memory | ||
683 | * @mapper: list of segment table entries maping a page table | ||
684 | */ | ||
685 | struct gmap_pgtable { | ||
686 | unsigned long vmaddr; | ||
687 | struct list_head mapper; | ||
688 | }; | ||
689 | |||
690 | struct gmap *gmap_alloc(struct mm_struct *mm); | ||
691 | void gmap_free(struct gmap *gmap); | ||
692 | void gmap_enable(struct gmap *gmap); | ||
693 | void gmap_disable(struct gmap *gmap); | ||
694 | int gmap_map_segment(struct gmap *gmap, unsigned long from, | ||
695 | unsigned long to, unsigned long length); | ||
696 | int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len); | ||
697 | unsigned long gmap_fault(unsigned long address, struct gmap *); | ||
698 | |||
657 | /* | 699 | /* |
658 | * Certain architectures need to do special things when PTEs | 700 | * Certain architectures need to do special things when PTEs |
659 | * within a page table are directly modified. Thus, the following | 701 | * within a page table are directly modified. Thus, the following |
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index 1300c3025334..55dfcc8bdc0d 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h | |||
@@ -80,6 +80,7 @@ struct thread_struct { | |||
80 | mm_segment_t mm_segment; | 80 | mm_segment_t mm_segment; |
81 | unsigned long prot_addr; /* address of protection-excep. */ | 81 | unsigned long prot_addr; /* address of protection-excep. */ |
82 | unsigned int trap_no; | 82 | unsigned int trap_no; |
83 | unsigned long gmap_addr; /* address of last gmap fault. */ | ||
83 | struct per_regs per_user; /* User specified PER registers */ | 84 | struct per_regs per_user; /* User specified PER registers */ |
84 | struct per_event per_event; /* Cause of the last PER trap */ | 85 | struct per_event per_event; /* Cause of the last PER trap */ |
85 | /* pfault_wait is used to block the process on a pfault event */ | 86 | /* pfault_wait is used to block the process on a pfault event */ |
diff --git a/arch/s390/include/asm/tlbflush.h b/arch/s390/include/asm/tlbflush.h index b7a4f2eb0057..304445382382 100644 --- a/arch/s390/include/asm/tlbflush.h +++ b/arch/s390/include/asm/tlbflush.h | |||
@@ -80,7 +80,7 @@ static inline void __tlb_flush_mm(struct mm_struct * mm) | |||
80 | * on all cpus instead of doing a local flush if the mm | 80 | * on all cpus instead of doing a local flush if the mm |
81 | * only ran on the local cpu. | 81 | * only ran on the local cpu. |
82 | */ | 82 | */ |
83 | if (MACHINE_HAS_IDTE) | 83 | if (MACHINE_HAS_IDTE && list_empty(&mm->context.gmap_list)) |
84 | __tlb_flush_idte((unsigned long) mm->pgd | | 84 | __tlb_flush_idte((unsigned long) mm->pgd | |
85 | mm->context.asce_bits); | 85 | mm->context.asce_bits); |
86 | else | 86 | else |