diff options
Diffstat (limited to 'arch/um/kernel/skas/tlb.c')
-rw-r--r-- | arch/um/kernel/skas/tlb.c | 66 |
1 files changed, 64 insertions, 2 deletions
diff --git a/arch/um/kernel/skas/tlb.c b/arch/um/kernel/skas/tlb.c index 304a5b0695a..c43901aa936 100644 --- a/arch/um/kernel/skas/tlb.c +++ b/arch/um/kernel/skas/tlb.c | |||
@@ -32,8 +32,7 @@ static int do_ops(union mm_context *mmu, struct host_vm_op *ops, int last, | |||
32 | op->u.mmap.offset, finished, flush); | 32 | op->u.mmap.offset, finished, flush); |
33 | break; | 33 | break; |
34 | case MUNMAP: | 34 | case MUNMAP: |
35 | ret = unmap(&mmu->skas.id, | 35 | ret = unmap(&mmu->skas.id, op->u.munmap.addr, |
36 | (void *) op->u.munmap.addr, | ||
37 | op->u.munmap.len, finished, flush); | 36 | op->u.munmap.len, finished, flush); |
38 | break; | 37 | break; |
39 | case MPROTECT: | 38 | case MPROTECT: |
@@ -94,3 +93,66 @@ void force_flush_all_skas(void) | |||
94 | unsigned long end = proc_mm ? task_size : CONFIG_STUB_START; | 93 | unsigned long end = proc_mm ? task_size : CONFIG_STUB_START; |
95 | fix_range(current->mm, 0, end, 1); | 94 | fix_range(current->mm, 0, end, 1); |
96 | } | 95 | } |
96 | |||
97 | void flush_tlb_page_skas(struct vm_area_struct *vma, unsigned long address) | ||
98 | { | ||
99 | pgd_t *pgd; | ||
100 | pud_t *pud; | ||
101 | pmd_t *pmd; | ||
102 | pte_t *pte; | ||
103 | struct mm_struct *mm = vma->vm_mm; | ||
104 | void *flush = NULL; | ||
105 | int r, w, x, err = 0; | ||
106 | struct mm_id *mm_id; | ||
107 | |||
108 | pgd = pgd_offset(vma->vm_mm, address); | ||
109 | if(!pgd_present(*pgd)) | ||
110 | goto kill; | ||
111 | |||
112 | pud = pud_offset(pgd, address); | ||
113 | if(!pud_present(*pud)) | ||
114 | goto kill; | ||
115 | |||
116 | pmd = pmd_offset(pud, address); | ||
117 | if(!pmd_present(*pmd)) | ||
118 | goto kill; | ||
119 | |||
120 | pte = pte_offset_kernel(pmd, address); | ||
121 | |||
122 | r = pte_read(*pte); | ||
123 | w = pte_write(*pte); | ||
124 | x = pte_exec(*pte); | ||
125 | if (!pte_young(*pte)) { | ||
126 | r = 0; | ||
127 | w = 0; | ||
128 | } else if (!pte_dirty(*pte)) { | ||
129 | w = 0; | ||
130 | } | ||
131 | |||
132 | mm_id = &mm->context.skas.id; | ||
133 | if(pte_newpage(*pte)){ | ||
134 | if(pte_present(*pte)){ | ||
135 | unsigned long long offset; | ||
136 | int fd; | ||
137 | |||
138 | fd = phys_mapping(pte_val(*pte) & PAGE_MASK, &offset); | ||
139 | err = map(mm_id, address, PAGE_SIZE, r, w, x, fd, | ||
140 | offset, 1, &flush); | ||
141 | } | ||
142 | else err = unmap(mm_id, address, PAGE_SIZE, 1, &flush); | ||
143 | } | ||
144 | else if(pte_newprot(*pte)) | ||
145 | err = protect(mm_id, address, PAGE_SIZE, r, w, x, 1, &flush); | ||
146 | |||
147 | if(err) | ||
148 | goto kill; | ||
149 | |||
150 | *pte = pte_mkuptodate(*pte); | ||
151 | |||
152 | return; | ||
153 | |||
154 | kill: | ||
155 | printk("Failed to flush page for address 0x%lx\n", address); | ||
156 | force_sig(SIGKILL, current); | ||
157 | } | ||
158 | |||