source: mainline/arch/ppc32/src/mm/tlb.c@ 8424198

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 8424198 was 68965ec5, checked in by Martin Decky <martin@…>, 19 years ago

ppc32: TLB manipulation stub

  • Property mode set to 100644
File size: 5.6 KB
Line 
1/*
2 * Copyright (C) 2006 Martin Decky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <arch/mm/tlb.h>
30#include <arch/types.h>
31#include <mm/tlb.h>
32#include <mm/frame.h>
33#include <mm/page.h>
34#include <mm/as.h>
35#include <arch.h>
36#include <print.h>
37#include <symtab.h>
38
39
40static phte_t *phte;
41
42
43/** Initialize Page Hash Table.
44 *
45 * Setup the Page Hash Table with no entries.
46 *
47 */
48void tlb_arch_init(void)
49{
50 phte_t *physical_phte = (phte_t *) PFN2ADDR(frame_alloc(PHT_ORDER, FRAME_KA | FRAME_PANIC));
51 phte =(phte_t *) PA2KA((__address) physical_phte);
52
53 ASSERT((__address) physical_phte % (1 << PHT_BITS) == 0);
54
55 memsetb((__address) phte, 1 << PHT_BITS, 0);
56
57 asm volatile (
58 "mtsdr1 %0\n"
59 :
60 : "r" ((__address) physical_phte)
61 );
62}
63
64
65/** Try to find PTE for faulting address
66 *
67 * Try to find PTE for faulting address.
68 * The AS->lock must be held on entry to this function.
69 *
70 * @param badvaddr Faulting virtual address.
71 * @param istate Pointer to interrupted state.
72 * @param pfrc Pointer to variable where as_page_fault() return code will be stored.
73 * @return PTE on success, NULL otherwise.
74 *
75 */
76static pte_t *find_mapping_and_check(__address badvaddr, istate_t *istate, int *pfcr)
77{
78 /*
79 * Check if the mapping exists in page tables.
80 */
81 pte_t *pte = page_mapping_find(AS, badvaddr);
82 if ((pte) && (pte->p)) {
83 /*
84 * Mapping found in page tables.
85 * Immediately succeed.
86 */
87 return pte;
88 } else {
89 int rc;
90
91 /*
92 * Mapping not found in page tables.
93 * Resort to higher-level page fault handler.
94 */
95 page_table_unlock(AS, true);
96 switch (rc = as_page_fault(badvaddr, istate)) {
97 case AS_PF_OK:
98 /*
99 * The higher-level page fault handler succeeded,
100 * The mapping ought to be in place.
101 */
102 page_table_lock(AS, true);
103 pte = page_mapping_find(AS, badvaddr);
104 ASSERT((pte) && (pte->p));
105 return pte;
106 break;
107 case AS_PF_DEFER:
108 page_table_lock(AS, true);
109 *pfcr = rc;
110 return NULL;
111 break;
112 case AS_PF_FAULT:
113 page_table_lock(AS, true);
114 printf("Page fault.\n");
115 *pfcr = rc;
116 return NULL;
117 break;
118 default:
119 panic("unexpected rc (%d)\n", rc);
120 break;
121 }
122 }
123}
124
125
126static void pht_refill_fail(__address badvaddr, istate_t *istate)
127{
128 char *symbol = "";
129 char *sym2 = "";
130
131 char *s = get_symtab_entry(istate->pc);
132 if (s)
133 symbol = s;
134 s = get_symtab_entry(istate->lr);
135 if (s)
136 sym2 = s;
137 panic("%p: PHT Refill Exception at %p (%s<-%s)\n", badvaddr, istate->pc, symbol, sym2);
138}
139
140
141/** Process Instruction/Data Storage Interrupt
142 *
143 * @param data True if Data Storage Interrupt.
144 * @param istate Interrupted register context.
145 *
146 */
147void pht_refill(bool data, istate_t *istate)
148{
149 asid_t asid;
150 __address badvaddr;
151 pte_t *pte;
152 __u32 page;
153 __u32 api;
154 __u32 vsid;
155 __u32 hash;
156 __u32 i;
157 int pfcr;
158
159 if (data) {
160 asm volatile (
161 "mfdar %0\n"
162 : "=r" (badvaddr)
163 );
164 } else
165 badvaddr = istate->pc;
166
167 spinlock_lock(&AS->lock);
168 asid = AS->asid;
169 spinlock_unlock(&AS->lock);
170
171 page_table_lock(AS, true);
172
173 pte = find_mapping_and_check(badvaddr, istate, &pfcr);
174 if (!pte) {
175 switch (pfcr) {
176 case AS_PF_FAULT:
177 goto fail;
178 break;
179 case AS_PF_DEFER:
180 /*
181 * The page fault came during copy_from_uspace()
182 * or copy_to_uspace().
183 */
184 page_table_unlock(AS, true);
185 return;
186 default:
187 panic("Unexpected pfrc (%d)\n", pfcr);
188 break;
189 }
190 }
191
192 /* Record access to PTE */
193 pte->a = 1;
194
195 page = (badvaddr >> 12) & 0xffff;
196 api = (badvaddr >> 22) & 0x3f;
197 asm volatile (
198 "mfsrin %0, %1\n"
199 : "=r" (vsid)
200 : "r" (badvaddr)
201 );
202
203 /* Primary hash (xor) */
204 hash = ((vsid ^ page) & 0x3ff) << 3;
205
206 /* Find invalid PTE in PTEG */
207 for (i = 0; i < 8; i++) {
208 if (!phte[hash + i].v)
209 break;
210 }
211
212 // TODO: Check access/change bits, secondary hash
213
214 if (i == 8)
215 i = page % 8;
216
217 phte[hash + i].v = 1;
218 phte[hash + i].vsid = vsid;
219 phte[hash + i].h = 0;
220 phte[hash + i].api = api;
221 phte[hash + i].rpn = pte->pfn;
222 phte[hash + i].r = 0;
223 phte[hash + i].c = 0;
224 phte[hash + i].pp = 2; // FIXME
225
226 page_table_unlock(AS, true);
227 return;
228
229fail:
230 page_table_unlock(AS, true);
231 pht_refill_fail(badvaddr, istate);
232}
233
234
235void tlb_invalidate_all(void)
236{
237 ipl_t ipl;
238
239 ipl = interrupts_disable();
240 memsetb((__address) phte, 1 << PHT_BITS, 0);
241 interrupts_restore(ipl);
242}
243
244
245/** Print contents of Page Hash Table. */
246void tlb_print(void)
247{
248}
Note: See TracBrowser for help on using the repository browser.