diff options
Diffstat (limited to 'arch/um/kernel/skas/tlb.c')
-rw-r--r-- | arch/um/kernel/skas/tlb.c | 87 |
1 files changed, 77 insertions, 10 deletions
diff --git a/arch/um/kernel/skas/tlb.c b/arch/um/kernel/skas/tlb.c index 27eb29ce666b..c0f0693743ba 100644 --- a/arch/um/kernel/skas/tlb.c +++ b/arch/um/kernel/skas/tlb.c | |||
@@ -10,7 +10,6 @@ | |||
10 | #include "asm/page.h" | 10 | #include "asm/page.h" |
11 | #include "asm/pgtable.h" | 11 | #include "asm/pgtable.h" |
12 | #include "asm/mmu.h" | 12 | #include "asm/mmu.h" |
13 | #include "user_util.h" | ||
14 | #include "mem_user.h" | 13 | #include "mem_user.h" |
15 | #include "mem.h" | 14 | #include "mem.h" |
16 | #include "skas.h" | 15 | #include "skas.h" |
@@ -28,19 +27,17 @@ static int do_ops(union mm_context *mmu, struct host_vm_op *ops, int last, | |||
28 | switch(op->type){ | 27 | switch(op->type){ |
29 | case MMAP: | 28 | case MMAP: |
30 | ret = map(&mmu->skas.id, op->u.mmap.addr, | 29 | ret = map(&mmu->skas.id, op->u.mmap.addr, |
31 | op->u.mmap.len, op->u.mmap.r, op->u.mmap.w, | 30 | op->u.mmap.len, op->u.mmap.prot, |
32 | op->u.mmap.x, op->u.mmap.fd, | 31 | op->u.mmap.fd, op->u.mmap.offset, finished, |
33 | op->u.mmap.offset, finished, flush); | 32 | flush); |
34 | break; | 33 | break; |
35 | case MUNMAP: | 34 | case MUNMAP: |
36 | ret = unmap(&mmu->skas.id, | 35 | ret = unmap(&mmu->skas.id, op->u.munmap.addr, |
37 | (void *) op->u.munmap.addr, | ||
38 | op->u.munmap.len, finished, flush); | 36 | op->u.munmap.len, finished, flush); |
39 | break; | 37 | break; |
40 | case MPROTECT: | 38 | case MPROTECT: |
41 | ret = protect(&mmu->skas.id, op->u.mprotect.addr, | 39 | ret = protect(&mmu->skas.id, op->u.mprotect.addr, |
42 | op->u.mprotect.len, op->u.mprotect.r, | 40 | op->u.mprotect.len, op->u.mprotect.prot, |
43 | op->u.mprotect.w, op->u.mprotect.x, | ||
44 | finished, flush); | 41 | finished, flush); |
45 | break; | 42 | break; |
46 | default: | 43 | default: |
@@ -92,6 +89,76 @@ void flush_tlb_mm_skas(struct mm_struct *mm) | |||
92 | 89 | ||
93 | void force_flush_all_skas(void) | 90 | void force_flush_all_skas(void) |
94 | { | 91 | { |
95 | unsigned long end = proc_mm ? task_size : CONFIG_STUB_START; | 92 | struct mm_struct *mm = current->mm; |
96 | fix_range(current->mm, 0, end, 1); | 93 | struct vm_area_struct *vma = mm->mmap; |
94 | |||
95 | while(vma != NULL) { | ||
96 | fix_range(mm, vma->vm_start, vma->vm_end, 1); | ||
97 | vma = vma->vm_next; | ||
98 | } | ||
99 | } | ||
100 | |||
101 | void flush_tlb_page_skas(struct vm_area_struct *vma, unsigned long address) | ||
102 | { | ||
103 | pgd_t *pgd; | ||
104 | pud_t *pud; | ||
105 | pmd_t *pmd; | ||
106 | pte_t *pte; | ||
107 | struct mm_struct *mm = vma->vm_mm; | ||
108 | void *flush = NULL; | ||
109 | int r, w, x, prot, err = 0; | ||
110 | struct mm_id *mm_id; | ||
111 | |||
112 | pgd = pgd_offset(mm, address); | ||
113 | if(!pgd_present(*pgd)) | ||
114 | goto kill; | ||
115 | |||
116 | pud = pud_offset(pgd, address); | ||
117 | if(!pud_present(*pud)) | ||
118 | goto kill; | ||
119 | |||
120 | pmd = pmd_offset(pud, address); | ||
121 | if(!pmd_present(*pmd)) | ||
122 | goto kill; | ||
123 | |||
124 | pte = pte_offset_kernel(pmd, address); | ||
125 | |||
126 | r = pte_read(*pte); | ||
127 | w = pte_write(*pte); | ||
128 | x = pte_exec(*pte); | ||
129 | if (!pte_young(*pte)) { | ||
130 | r = 0; | ||
131 | w = 0; | ||
132 | } else if (!pte_dirty(*pte)) { | ||
133 | w = 0; | ||
134 | } | ||
135 | |||
136 | mm_id = &mm->context.skas.id; | ||
137 | prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) | | ||
138 | (x ? UM_PROT_EXEC : 0)); | ||
139 | if(pte_newpage(*pte)){ | ||
140 | if(pte_present(*pte)){ | ||
141 | unsigned long long offset; | ||
142 | int fd; | ||
143 | |||
144 | fd = phys_mapping(pte_val(*pte) & PAGE_MASK, &offset); | ||
145 | err = map(mm_id, address, PAGE_SIZE, prot, fd, offset, | ||
146 | 1, &flush); | ||
147 | } | ||
148 | else err = unmap(mm_id, address, PAGE_SIZE, 1, &flush); | ||
149 | } | ||
150 | else if(pte_newprot(*pte)) | ||
151 | err = protect(mm_id, address, PAGE_SIZE, prot, 1, &flush); | ||
152 | |||
153 | if(err) | ||
154 | goto kill; | ||
155 | |||
156 | *pte = pte_mkuptodate(*pte); | ||
157 | |||
158 | return; | ||
159 | |||
160 | kill: | ||
161 | printk("Failed to flush page for address 0x%lx\n", address); | ||
162 | force_sig(SIGKILL, current); | ||
97 | } | 163 | } |
164 | |||