aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/kernel/skas/tlb.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/kernel/skas/tlb.c')
-rw-r--r--arch/um/kernel/skas/tlb.c87
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
93void force_flush_all_skas(void) 90void 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
101void 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
160kill:
161 printk("Failed to flush page for address 0x%lx\n", address);
162 force_sig(SIGKILL, current);
97} 163}
164