Subversion Repositories HelenOS

Rev

Rev 4341 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4341 Rev 4346
1
/*
1
/*
2
 * Copyright (c) 2006 Martin Decky
2
 * Copyright (c) 2006 Martin Decky
3
 * All rights reserved.
3
 * All rights reserved.
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
6
 * modification, are permitted provided that the following conditions
7
 * are met:
7
 * are met:
8
 *
8
 *
9
 * - Redistributions of source code must retain the above copyright
9
 * - Redistributions of source code must retain the above copyright
10
 *   notice, this list of conditions and the following disclaimer.
10
 *   notice, this list of conditions and the following disclaimer.
11
 * - Redistributions in binary form must reproduce the above copyright
11
 * - Redistributions in binary form must reproduce the above copyright
12
 *   notice, this list of conditions and the following disclaimer in the
12
 *   notice, this list of conditions and the following disclaimer in the
13
 *   documentation and/or other materials provided with the distribution.
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
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.
15
 *   derived from this software without specific prior written permission.
16
 *
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
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
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
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
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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
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.
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
27
 */
28
 
28
 
29
/** @addtogroup ppc32mm
29
/** @addtogroup ppc32mm
30
 * @{
30
 * @{
31
 */
31
 */
32
/** @file
32
/** @file
33
 */
33
 */
34
 
34
 
35
#include <mm/tlb.h>
35
#include <mm/tlb.h>
36
#include <arch/mm/tlb.h>
36
#include <arch/mm/tlb.h>
37
#include <arch/interrupt.h>
37
#include <arch/interrupt.h>
38
#include <interrupt.h>
38
#include <interrupt.h>
39
#include <mm/as.h>
39
#include <mm/as.h>
40
#include <arch.h>
40
#include <arch.h>
41
#include <print.h>
41
#include <print.h>
42
#include <symtab.h>
-
 
43
#include <macros.h>
42
#include <macros.h>
44
 
-
 
-
 
43
#include <symtab.h>
45
 
44
 
46
static unsigned int seed = 10;
45
static unsigned int seed = 10;
47
static unsigned int seed_real __attribute__ ((section("K_UNMAPPED_DATA_START"))) = 42;
46
static unsigned int seed_real __attribute__ ((section("K_UNMAPPED_DATA_START"))) = 42;
48
 
47
 
49
 
48
 
50
#define TLB_FLUSH \
49
#define TLB_FLUSH \
51
    "tlbie %0\n" \
50
    "tlbie %0\n" \
52
    "addi %0, %0, 0x1000\n"
51
    "addi %0, %0, 0x1000\n"
53
 
52
 
54
 
53
 
55
/** Try to find PTE for faulting address
54
/** Try to find PTE for faulting address
56
 *
55
 *
57
 * Try to find PTE for faulting address.
56
 * Try to find PTE for faulting address.
58
 * The as->lock must be held on entry to this function
57
 * The as->lock must be held on entry to this function
59
 * if lock is true.
58
 * if lock is true.
60
 *
59
 *
61
 * @param as        Address space.
60
 * @param as        Address space.
62
 * @param lock      Lock/unlock the address space.
61
 * @param lock      Lock/unlock the address space.
63
 * @param badvaddr  Faulting virtual address.
62
 * @param badvaddr  Faulting virtual address.
64
 * @param access    Access mode that caused the fault.
63
 * @param access    Access mode that caused the fault.
65
 * @param istate    Pointer to interrupted state.
64
 * @param istate    Pointer to interrupted state.
66
 * @param pfrc      Pointer to variable where as_page_fault() return code
65
 * @param pfrc      Pointer to variable where as_page_fault() return code
67
 *          will be stored.
66
 *          will be stored.
68
 * @return      PTE on success, NULL otherwise.
67
 * @return      PTE on success, NULL otherwise.
69
 *
68
 *
70
 */
69
 */
71
static pte_t *
70
static pte_t *
72
find_mapping_and_check(as_t *as, bool lock, uintptr_t badvaddr, int access,
71
find_mapping_and_check(as_t *as, bool lock, uintptr_t badvaddr, int access,
73
    istate_t *istate, int *pfrc)
72
    istate_t *istate, int *pfrc)
74
{
73
{
75
    /*
74
    /*
76
     * Check if the mapping exists in page tables.
75
     * Check if the mapping exists in page tables.
77
     */
76
     */
78
    pte_t *pte = page_mapping_find(as, badvaddr);
77
    pte_t *pte = page_mapping_find(as, badvaddr);
79
    if ((pte) && (pte->present)) {
78
    if ((pte) && (pte->present)) {
80
        /*
79
        /*
81
         * Mapping found in page tables.
80
         * Mapping found in page tables.
82
         * Immediately succeed.
81
         * Immediately succeed.
83
         */
82
         */
84
        return pte;
83
        return pte;
85
    } else {
84
    } else {
86
        int rc;
85
        int rc;
87
   
86
   
88
        /*
87
        /*
89
         * Mapping not found in page tables.
88
         * Mapping not found in page tables.
90
         * Resort to higher-level page fault handler.
89
         * Resort to higher-level page fault handler.
91
         */
90
         */
92
        page_table_unlock(as, lock);
91
        page_table_unlock(as, lock);
93
        switch (rc = as_page_fault(badvaddr, access, istate)) {
92
        switch (rc = as_page_fault(badvaddr, access, istate)) {
94
        case AS_PF_OK:
93
        case AS_PF_OK:
95
            /*
94
            /*
96
             * The higher-level page fault handler succeeded,
95
             * The higher-level page fault handler succeeded,
97
             * The mapping ought to be in place.
96
             * The mapping ought to be in place.
98
             */
97
             */
99
            page_table_lock(as, lock);
98
            page_table_lock(as, lock);
100
            pte = page_mapping_find(as, badvaddr);
99
            pte = page_mapping_find(as, badvaddr);
101
            ASSERT((pte) && (pte->present));
100
            ASSERT((pte) && (pte->present));
102
            *pfrc = 0;
101
            *pfrc = 0;
103
            return pte;
102
            return pte;
104
        case AS_PF_DEFER:
103
        case AS_PF_DEFER:
105
            page_table_lock(as, lock);
104
            page_table_lock(as, lock);
106
            *pfrc = rc;
105
            *pfrc = rc;
107
            return NULL;
106
            return NULL;
108
        case AS_PF_FAULT:
107
        case AS_PF_FAULT:
109
            page_table_lock(as, lock);
108
            page_table_lock(as, lock);
110
            *pfrc = rc;
109
            *pfrc = rc;
111
            return NULL;
110
            return NULL;
112
        default:
111
        default:
113
            panic("Unexpected rc (%d).", rc);
112
            panic("Unexpected rc (%d).", rc);
114
        }  
113
        }  
115
    }
114
    }
116
}
115
}
117
 
116
 
118
 
117
 
119
static void pht_refill_fail(uintptr_t badvaddr, istate_t *istate)
118
static void pht_refill_fail(uintptr_t badvaddr, istate_t *istate)
120
{
119
{
121
    char *symbol = "";
120
    char *symbol;
122
    char *sym2 = "";
121
    char *sym2;
123
 
122
 
124
    char *str = get_symtab_entry(istate->pc);
123
    symbol = symtab_fmt_name_lookup(istate->pc);
125
    if (str)
-
 
126
        symbol = str;
-
 
127
    str = get_symtab_entry(istate->lr);
124
    sym2 = symtab_fmt_name_lookup(istate->lr);
128
    if (str)
-
 
129
        sym2 = str;
-
 
130
 
125
 
131
    fault_if_from_uspace(istate,
126
    fault_if_from_uspace(istate,
132
        "PHT Refill Exception on %p.", badvaddr);
127
        "PHT Refill Exception on %p.", badvaddr);
133
    panic("%p: PHT Refill Exception at %p (%s<-%s).", badvaddr,
128
    panic("%p: PHT Refill Exception at %p (%s<-%s).", badvaddr,
134
        istate->pc, symbol, sym2);
129
        istate->pc, symbol, sym2);
135
}
130
}
136
 
131
 
137
 
132
 
138
static void pht_insert(const uintptr_t vaddr, const pte_t *pte)
133
static void pht_insert(const uintptr_t vaddr, const pte_t *pte)
139
{
134
{
140
    uint32_t page = (vaddr >> 12) & 0xffff;
135
    uint32_t page = (vaddr >> 12) & 0xffff;
141
    uint32_t api = (vaddr >> 22) & 0x3f;
136
    uint32_t api = (vaddr >> 22) & 0x3f;
142
   
137
   
143
    uint32_t vsid;
138
    uint32_t vsid;
144
    asm volatile (
139
    asm volatile (
145
        "mfsrin %0, %1\n"
140
        "mfsrin %0, %1\n"
146
        : "=r" (vsid)
141
        : "=r" (vsid)
147
        : "r" (vaddr)
142
        : "r" (vaddr)
148
    );
143
    );
149
   
144
   
150
    uint32_t sdr1;
145
    uint32_t sdr1;
151
    asm volatile (
146
    asm volatile (
152
        "mfsdr1 %0\n"
147
        "mfsdr1 %0\n"
153
        : "=r" (sdr1)
148
        : "=r" (sdr1)
154
    );
149
    );
155
    phte_t *phte = (phte_t *) PA2KA(sdr1 & 0xffff0000);
150
    phte_t *phte = (phte_t *) PA2KA(sdr1 & 0xffff0000);
156
   
151
   
157
    /* Primary hash (xor) */
152
    /* Primary hash (xor) */
158
    uint32_t h = 0;
153
    uint32_t h = 0;
159
    uint32_t hash = vsid ^ page;
154
    uint32_t hash = vsid ^ page;
160
    uint32_t base = (hash & 0x3ff) << 3;
155
    uint32_t base = (hash & 0x3ff) << 3;
161
    uint32_t i;
156
    uint32_t i;
162
    bool found = false;
157
    bool found = false;
163
   
158
   
164
    /* Find colliding PTE in PTEG */
159
    /* Find colliding PTE in PTEG */
165
    for (i = 0; i < 8; i++) {
160
    for (i = 0; i < 8; i++) {
166
        if ((phte[base + i].v)
161
        if ((phte[base + i].v)
167
            && (phte[base + i].vsid == vsid)
162
            && (phte[base + i].vsid == vsid)
168
            && (phte[base + i].api == api)
163
            && (phte[base + i].api == api)
169
            && (phte[base + i].h == 0)) {
164
            && (phte[base + i].h == 0)) {
170
            found = true;
165
            found = true;
171
            break;
166
            break;
172
        }
167
        }
173
    }
168
    }
174
   
169
   
175
    if (!found) {
170
    if (!found) {
176
        /* Find unused PTE in PTEG */
171
        /* Find unused PTE in PTEG */
177
        for (i = 0; i < 8; i++) {
172
        for (i = 0; i < 8; i++) {
178
            if (!phte[base + i].v) {
173
            if (!phte[base + i].v) {
179
                found = true;
174
                found = true;
180
                break;
175
                break;
181
            }
176
            }
182
        }
177
        }
183
    }
178
    }
184
   
179
   
185
    if (!found) {
180
    if (!found) {
186
        /* Secondary hash (not) */
181
        /* Secondary hash (not) */
187
        uint32_t base2 = (~hash & 0x3ff) << 3;
182
        uint32_t base2 = (~hash & 0x3ff) << 3;
188
       
183
       
189
        /* Find colliding PTE in PTEG */
184
        /* Find colliding PTE in PTEG */
190
        for (i = 0; i < 8; i++) {
185
        for (i = 0; i < 8; i++) {
191
            if ((phte[base2 + i].v)
186
            if ((phte[base2 + i].v)
192
                && (phte[base2 + i].vsid == vsid)
187
                && (phte[base2 + i].vsid == vsid)
193
                && (phte[base2 + i].api == api)
188
                && (phte[base2 + i].api == api)
194
                && (phte[base2 + i].h == 1)) {
189
                && (phte[base2 + i].h == 1)) {
195
                found = true;
190
                found = true;
196
                base = base2;
191
                base = base2;
197
                h = 1;
192
                h = 1;
198
                break;
193
                break;
199
            }
194
            }
200
        }
195
        }
201
       
196
       
202
        if (!found) {
197
        if (!found) {
203
            /* Find unused PTE in PTEG */
198
            /* Find unused PTE in PTEG */
204
            for (i = 0; i < 8; i++) {
199
            for (i = 0; i < 8; i++) {
205
                if (!phte[base2 + i].v) {
200
                if (!phte[base2 + i].v) {
206
                    found = true;
201
                    found = true;
207
                    base = base2;
202
                    base = base2;
208
                    h = 1;
203
                    h = 1;
209
                    break;
204
                    break;
210
                }
205
                }
211
            }
206
            }
212
        }
207
        }
213
       
208
       
214
        if (!found)
209
        if (!found)
215
            i = RANDI(seed) % 8;
210
            i = RANDI(seed) % 8;
216
    }
211
    }
217
   
212
   
218
    phte[base + i].v = 1;
213
    phte[base + i].v = 1;
219
    phte[base + i].vsid = vsid;
214
    phte[base + i].vsid = vsid;
220
    phte[base + i].h = h;
215
    phte[base + i].h = h;
221
    phte[base + i].api = api;
216
    phte[base + i].api = api;
222
    phte[base + i].rpn = pte->pfn;
217
    phte[base + i].rpn = pte->pfn;
223
    phte[base + i].r = 0;
218
    phte[base + i].r = 0;
224
    phte[base + i].c = 0;
219
    phte[base + i].c = 0;
225
    phte[base + i].wimg = (pte->page_cache_disable ? WIMG_NO_CACHE : 0);
220
    phte[base + i].wimg = (pte->page_cache_disable ? WIMG_NO_CACHE : 0);
226
    phte[base + i].pp = 2; // FIXME
221
    phte[base + i].pp = 2; // FIXME
227
}
222
}
228
 
223
 
229
 
224
 
230
/** Process Instruction/Data Storage Exception
225
/** Process Instruction/Data Storage Exception
231
 *
226
 *
232
 * @param n      Exception vector number.
227
 * @param n      Exception vector number.
233
 * @param istate Interrupted register context.
228
 * @param istate Interrupted register context.
234
 *
229
 *
235
 */
230
 */
236
void pht_refill(int n, istate_t *istate)
231
void pht_refill(int n, istate_t *istate)
237
{
232
{
238
    uintptr_t badvaddr;
233
    uintptr_t badvaddr;
239
    pte_t *pte;
234
    pte_t *pte;
240
    int pfrc;
235
    int pfrc;
241
    as_t *as;
236
    as_t *as;
242
    bool lock;
237
    bool lock;
243
   
238
   
244
    if (AS == NULL) {
239
    if (AS == NULL) {
245
        as = AS_KERNEL;
240
        as = AS_KERNEL;
246
        lock = false;
241
        lock = false;
247
    } else {
242
    } else {
248
        as = AS;
243
        as = AS;
249
        lock = true;
244
        lock = true;
250
    }
245
    }
251
   
246
   
252
    if (n == VECTOR_DATA_STORAGE)
247
    if (n == VECTOR_DATA_STORAGE)
253
        badvaddr = istate->dar;
248
        badvaddr = istate->dar;
254
    else
249
    else
255
        badvaddr = istate->pc;
250
        badvaddr = istate->pc;
256
       
251
       
257
    page_table_lock(as, lock);
252
    page_table_lock(as, lock);
258
   
253
   
259
    pte = find_mapping_and_check(as, lock, badvaddr,
254
    pte = find_mapping_and_check(as, lock, badvaddr,
260
        PF_ACCESS_READ /* FIXME */, istate, &pfrc);
255
        PF_ACCESS_READ /* FIXME */, istate, &pfrc);
261
    if (!pte) {
256
    if (!pte) {
262
        switch (pfrc) {
257
        switch (pfrc) {
263
        case AS_PF_FAULT:
258
        case AS_PF_FAULT:
264
            goto fail;
259
            goto fail;
265
            break;
260
            break;
266
        case AS_PF_DEFER:
261
        case AS_PF_DEFER:
267
            /*
262
            /*
268
             * The page fault came during copy_from_uspace()
263
             * The page fault came during copy_from_uspace()
269
             * or copy_to_uspace().
264
             * or copy_to_uspace().
270
             */
265
             */
271
            page_table_unlock(as, lock);
266
            page_table_unlock(as, lock);
272
            return;
267
            return;
273
        default:
268
        default:
274
            panic("Unexpected pfrc (%d).", pfrc);
269
            panic("Unexpected pfrc (%d).", pfrc);
275
        }
270
        }
276
    }
271
    }
277
   
272
   
278
    pte->accessed = 1; /* Record access to PTE */
273
    pte->accessed = 1; /* Record access to PTE */
279
    pht_insert(badvaddr, pte);
274
    pht_insert(badvaddr, pte);
280
   
275
   
281
    page_table_unlock(as, lock);
276
    page_table_unlock(as, lock);
282
    return;
277
    return;
283
   
278
   
284
fail:
279
fail:
285
    page_table_unlock(as, lock);
280
    page_table_unlock(as, lock);
286
    pht_refill_fail(badvaddr, istate);
281
    pht_refill_fail(badvaddr, istate);
287
}
282
}
288
 
283
 
289
 
284
 
290
/** Process Instruction/Data Storage Exception in Real Mode
285
/** Process Instruction/Data Storage Exception in Real Mode
291
 *
286
 *
292
 * @param n      Exception vector number.
287
 * @param n      Exception vector number.
293
 * @param istate Interrupted register context.
288
 * @param istate Interrupted register context.
294
 *
289
 *
295
 */
290
 */
296
bool pht_refill_real(int n, istate_t *istate)
291
bool pht_refill_real(int n, istate_t *istate)
297
{
292
{
298
    uintptr_t badvaddr;
293
    uintptr_t badvaddr;
299
   
294
   
300
    if (n == VECTOR_DATA_STORAGE)
295
    if (n == VECTOR_DATA_STORAGE)
301
        badvaddr = istate->dar;
296
        badvaddr = istate->dar;
302
    else
297
    else
303
        badvaddr = istate->pc;
298
        badvaddr = istate->pc;
304
   
299
   
305
    uint32_t physmem;
300
    uint32_t physmem;
306
    asm volatile (
301
    asm volatile (
307
        "mfsprg3 %0\n"
302
        "mfsprg3 %0\n"
308
        : "=r" (physmem)
303
        : "=r" (physmem)
309
    );
304
    );
310
   
305
   
311
    if ((badvaddr < PA2KA(0)) || (badvaddr >= PA2KA(physmem)))
306
    if ((badvaddr < PA2KA(0)) || (badvaddr >= PA2KA(physmem)))
312
        return false;
307
        return false;
313
   
308
   
314
    uint32_t page = (badvaddr >> 12) & 0xffff;
309
    uint32_t page = (badvaddr >> 12) & 0xffff;
315
    uint32_t api = (badvaddr >> 22) & 0x3f;
310
    uint32_t api = (badvaddr >> 22) & 0x3f;
316
   
311
   
317
    uint32_t vsid;
312
    uint32_t vsid;
318
    asm volatile (
313
    asm volatile (
319
        "mfsrin %0, %1\n"
314
        "mfsrin %0, %1\n"
320
        : "=r" (vsid)
315
        : "=r" (vsid)
321
        : "r" (badvaddr)
316
        : "r" (badvaddr)
322
    );
317
    );
323
   
318
   
324
    uint32_t sdr1;
319
    uint32_t sdr1;
325
    asm volatile (
320
    asm volatile (
326
        "mfsdr1 %0\n"
321
        "mfsdr1 %0\n"
327
        : "=r" (sdr1)
322
        : "=r" (sdr1)
328
    );
323
    );
329
    phte_t *phte_real = (phte_t *) (sdr1 & 0xffff0000);
324
    phte_t *phte_real = (phte_t *) (sdr1 & 0xffff0000);
330
   
325
   
331
    /* Primary hash (xor) */
326
    /* Primary hash (xor) */
332
    uint32_t h = 0;
327
    uint32_t h = 0;
333
    uint32_t hash = vsid ^ page;
328
    uint32_t hash = vsid ^ page;
334
    uint32_t base = (hash & 0x3ff) << 3;
329
    uint32_t base = (hash & 0x3ff) << 3;
335
    uint32_t i;
330
    uint32_t i;
336
    bool found = false;
331
    bool found = false;
337
   
332
   
338
    /* Find colliding PTE in PTEG */
333
    /* Find colliding PTE in PTEG */
339
    for (i = 0; i < 8; i++) {
334
    for (i = 0; i < 8; i++) {
340
        if ((phte_real[base + i].v)
335
        if ((phte_real[base + i].v)
341
            && (phte_real[base + i].vsid == vsid)
336
            && (phte_real[base + i].vsid == vsid)
342
            && (phte_real[base + i].api == api)
337
            && (phte_real[base + i].api == api)
343
            && (phte_real[base + i].h == 0)) {
338
            && (phte_real[base + i].h == 0)) {
344
            found = true;
339
            found = true;
345
            break;
340
            break;
346
        }
341
        }
347
    }
342
    }
348
   
343
   
349
    if (!found) {
344
    if (!found) {
350
        /* Find unused PTE in PTEG */
345
        /* Find unused PTE in PTEG */
351
        for (i = 0; i < 8; i++) {
346
        for (i = 0; i < 8; i++) {
352
            if (!phte_real[base + i].v) {
347
            if (!phte_real[base + i].v) {
353
                found = true;
348
                found = true;
354
                break;
349
                break;
355
            }
350
            }
356
        }
351
        }
357
    }
352
    }
358
   
353
   
359
    if (!found) {
354
    if (!found) {
360
        /* Secondary hash (not) */
355
        /* Secondary hash (not) */
361
        uint32_t base2 = (~hash & 0x3ff) << 3;
356
        uint32_t base2 = (~hash & 0x3ff) << 3;
362
       
357
       
363
        /* Find colliding PTE in PTEG */
358
        /* Find colliding PTE in PTEG */
364
        for (i = 0; i < 8; i++) {
359
        for (i = 0; i < 8; i++) {
365
            if ((phte_real[base2 + i].v)
360
            if ((phte_real[base2 + i].v)
366
                && (phte_real[base2 + i].vsid == vsid)
361
                && (phte_real[base2 + i].vsid == vsid)
367
                && (phte_real[base2 + i].api == api)
362
                && (phte_real[base2 + i].api == api)
368
                && (phte_real[base2 + i].h == 1)) {
363
                && (phte_real[base2 + i].h == 1)) {
369
                found = true;
364
                found = true;
370
                base = base2;
365
                base = base2;
371
                h = 1;
366
                h = 1;
372
                break;
367
                break;
373
            }
368
            }
374
        }
369
        }
375
       
370
       
376
        if (!found) {
371
        if (!found) {
377
            /* Find unused PTE in PTEG */
372
            /* Find unused PTE in PTEG */
378
            for (i = 0; i < 8; i++) {
373
            for (i = 0; i < 8; i++) {
379
                if (!phte_real[base2 + i].v) {
374
                if (!phte_real[base2 + i].v) {
380
                    found = true;
375
                    found = true;
381
                    base = base2;
376
                    base = base2;
382
                    h = 1;
377
                    h = 1;
383
                    break;
378
                    break;
384
                }
379
                }
385
            }
380
            }
386
        }
381
        }
387
       
382
       
388
        if (!found) {
383
        if (!found) {
389
            /* Use secondary hash to avoid collisions
384
            /* Use secondary hash to avoid collisions
390
               with usual PHT refill handler. */
385
               with usual PHT refill handler. */
391
            i = RANDI(seed_real) % 8;
386
            i = RANDI(seed_real) % 8;
392
            base = base2;
387
            base = base2;
393
            h = 1;
388
            h = 1;
394
        }
389
        }
395
    }
390
    }
396
   
391
   
397
    phte_real[base + i].v = 1;
392
    phte_real[base + i].v = 1;
398
    phte_real[base + i].vsid = vsid;
393
    phte_real[base + i].vsid = vsid;
399
    phte_real[base + i].h = h;
394
    phte_real[base + i].h = h;
400
    phte_real[base + i].api = api;
395
    phte_real[base + i].api = api;
401
    phte_real[base + i].rpn = KA2PA(badvaddr) >> 12;
396
    phte_real[base + i].rpn = KA2PA(badvaddr) >> 12;
402
    phte_real[base + i].r = 0;
397
    phte_real[base + i].r = 0;
403
    phte_real[base + i].c = 0;
398
    phte_real[base + i].c = 0;
404
    phte_real[base + i].wimg = 0;
399
    phte_real[base + i].wimg = 0;
405
    phte_real[base + i].pp = 2; // FIXME
400
    phte_real[base + i].pp = 2; // FIXME
406
   
401
   
407
    return true;
402
    return true;
408
}
403
}
409
 
404
 
410
 
405
 
411
/** Process ITLB/DTLB Miss Exception in Real Mode
406
/** Process ITLB/DTLB Miss Exception in Real Mode
412
 *
407
 *
413
 *
408
 *
414
 */
409
 */
415
void tlb_refill_real(int n, uint32_t tlbmiss, ptehi_t ptehi, ptelo_t ptelo, istate_t *istate)
410
void tlb_refill_real(int n, uint32_t tlbmiss, ptehi_t ptehi, ptelo_t ptelo, istate_t *istate)
416
{
411
{
417
    uint32_t badvaddr = tlbmiss & 0xfffffffc;
412
    uint32_t badvaddr = tlbmiss & 0xfffffffc;
418
   
413
   
419
    uint32_t physmem;
414
    uint32_t physmem;
420
    asm volatile (
415
    asm volatile (
421
        "mfsprg3 %0\n"
416
        "mfsprg3 %0\n"
422
        : "=r" (physmem)
417
        : "=r" (physmem)
423
    );
418
    );
424
   
419
   
425
    if ((badvaddr < PA2KA(0)) || (badvaddr >= PA2KA(physmem)))
420
    if ((badvaddr < PA2KA(0)) || (badvaddr >= PA2KA(physmem)))
426
        return; // FIXME
421
        return; // FIXME
427
   
422
   
428
    ptelo.rpn = KA2PA(badvaddr) >> 12;
423
    ptelo.rpn = KA2PA(badvaddr) >> 12;
429
    ptelo.wimg = 0;
424
    ptelo.wimg = 0;
430
    ptelo.pp = 2; // FIXME
425
    ptelo.pp = 2; // FIXME
431
   
426
   
432
    uint32_t index = 0;
427
    uint32_t index = 0;
433
    asm volatile (
428
    asm volatile (
434
        "mtspr 981, %0\n"
429
        "mtspr 981, %0\n"
435
        "mtspr 982, %1\n"
430
        "mtspr 982, %1\n"
436
        "tlbld %2\n"
431
        "tlbld %2\n"
437
        "tlbli %2\n"
432
        "tlbli %2\n"
438
        : "=r" (index)
433
        : "=r" (index)
439
        : "r" (ptehi),
434
        : "r" (ptehi),
440
          "r" (ptelo)
435
          "r" (ptelo)
441
    );
436
    );
442
}
437
}
443
 
438
 
444
 
439
 
445
void tlb_arch_init(void)
440
void tlb_arch_init(void)
446
{
441
{
447
    tlb_invalidate_all();
442
    tlb_invalidate_all();
448
}
443
}
449
 
444
 
450
 
445
 
451
void tlb_invalidate_all(void)
446
void tlb_invalidate_all(void)
452
{
447
{
453
    uint32_t index;
448
    uint32_t index;
454
    asm volatile (
449
    asm volatile (
455
        "li %0, 0\n"
450
        "li %0, 0\n"
456
        "sync\n"
451
        "sync\n"
457
       
452
       
458
        TLB_FLUSH
453
        TLB_FLUSH
459
        TLB_FLUSH
454
        TLB_FLUSH
460
        TLB_FLUSH
455
        TLB_FLUSH
461
        TLB_FLUSH
456
        TLB_FLUSH
462
        TLB_FLUSH
457
        TLB_FLUSH
463
        TLB_FLUSH
458
        TLB_FLUSH
464
        TLB_FLUSH
459
        TLB_FLUSH
465
        TLB_FLUSH
460
        TLB_FLUSH
466
       
461
       
467
        TLB_FLUSH
462
        TLB_FLUSH
468
        TLB_FLUSH
463
        TLB_FLUSH
469
        TLB_FLUSH
464
        TLB_FLUSH
470
        TLB_FLUSH
465
        TLB_FLUSH
471
        TLB_FLUSH
466
        TLB_FLUSH
472
        TLB_FLUSH
467
        TLB_FLUSH
473
        TLB_FLUSH
468
        TLB_FLUSH
474
        TLB_FLUSH
469
        TLB_FLUSH
475
       
470
       
476
        TLB_FLUSH
471
        TLB_FLUSH
477
        TLB_FLUSH
472
        TLB_FLUSH
478
        TLB_FLUSH
473
        TLB_FLUSH
479
        TLB_FLUSH
474
        TLB_FLUSH
480
        TLB_FLUSH
475
        TLB_FLUSH
481
        TLB_FLUSH
476
        TLB_FLUSH
482
        TLB_FLUSH
477
        TLB_FLUSH
483
        TLB_FLUSH
478
        TLB_FLUSH
484
       
479
       
485
        TLB_FLUSH
480
        TLB_FLUSH
486
        TLB_FLUSH
481
        TLB_FLUSH
487
        TLB_FLUSH
482
        TLB_FLUSH
488
        TLB_FLUSH
483
        TLB_FLUSH
489
        TLB_FLUSH
484
        TLB_FLUSH
490
        TLB_FLUSH
485
        TLB_FLUSH
491
        TLB_FLUSH
486
        TLB_FLUSH
492
        TLB_FLUSH
487
        TLB_FLUSH
493
       
488
       
494
        TLB_FLUSH
489
        TLB_FLUSH
495
        TLB_FLUSH
490
        TLB_FLUSH
496
        TLB_FLUSH
491
        TLB_FLUSH
497
        TLB_FLUSH
492
        TLB_FLUSH
498
        TLB_FLUSH
493
        TLB_FLUSH
499
        TLB_FLUSH
494
        TLB_FLUSH
500
        TLB_FLUSH
495
        TLB_FLUSH
501
        TLB_FLUSH
496
        TLB_FLUSH
502
       
497
       
503
        TLB_FLUSH
498
        TLB_FLUSH
504
        TLB_FLUSH
499
        TLB_FLUSH
505
        TLB_FLUSH
500
        TLB_FLUSH
506
        TLB_FLUSH
501
        TLB_FLUSH
507
        TLB_FLUSH
502
        TLB_FLUSH
508
        TLB_FLUSH
503
        TLB_FLUSH
509
        TLB_FLUSH
504
        TLB_FLUSH
510
        TLB_FLUSH
505
        TLB_FLUSH
511
       
506
       
512
        TLB_FLUSH
507
        TLB_FLUSH
513
        TLB_FLUSH
508
        TLB_FLUSH
514
        TLB_FLUSH
509
        TLB_FLUSH
515
        TLB_FLUSH
510
        TLB_FLUSH
516
        TLB_FLUSH
511
        TLB_FLUSH
517
        TLB_FLUSH
512
        TLB_FLUSH
518
        TLB_FLUSH
513
        TLB_FLUSH
519
        TLB_FLUSH
514
        TLB_FLUSH
520
       
515
       
521
        TLB_FLUSH
516
        TLB_FLUSH
522
        TLB_FLUSH
517
        TLB_FLUSH
523
        TLB_FLUSH
518
        TLB_FLUSH
524
        TLB_FLUSH
519
        TLB_FLUSH
525
        TLB_FLUSH
520
        TLB_FLUSH
526
        TLB_FLUSH
521
        TLB_FLUSH
527
        TLB_FLUSH
522
        TLB_FLUSH
528
        TLB_FLUSH
523
        TLB_FLUSH
529
       
524
       
530
        "eieio\n"
525
        "eieio\n"
531
        "tlbsync\n"
526
        "tlbsync\n"
532
        "sync\n"
527
        "sync\n"
533
        : "=r" (index)
528
        : "=r" (index)
534
    );
529
    );
535
}
530
}
536
 
531
 
537
 
532
 
538
void tlb_invalidate_asid(asid_t asid)
533
void tlb_invalidate_asid(asid_t asid)
539
{
534
{
540
    uint32_t sdr1;
535
    uint32_t sdr1;
541
    asm volatile (
536
    asm volatile (
542
        "mfsdr1 %0\n"
537
        "mfsdr1 %0\n"
543
        : "=r" (sdr1)
538
        : "=r" (sdr1)
544
    );
539
    );
545
    phte_t *phte = (phte_t *) PA2KA(sdr1 & 0xffff0000);
540
    phte_t *phte = (phte_t *) PA2KA(sdr1 & 0xffff0000);
546
   
541
   
547
    uint32_t i;
542
    uint32_t i;
548
    for (i = 0; i < 8192; i++) {
543
    for (i = 0; i < 8192; i++) {
549
        if ((phte[i].v) && (phte[i].vsid >= (asid << 4)) &&
544
        if ((phte[i].v) && (phte[i].vsid >= (asid << 4)) &&
550
            (phte[i].vsid < ((asid << 4) + 16)))
545
            (phte[i].vsid < ((asid << 4) + 16)))
551
            phte[i].v = 0;
546
            phte[i].v = 0;
552
    }
547
    }
553
    tlb_invalidate_all();
548
    tlb_invalidate_all();
554
}
549
}
555
 
550
 
556
 
551
 
557
void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt)
552
void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt)
558
{
553
{
559
    // TODO
554
    // TODO
560
    tlb_invalidate_all();
555
    tlb_invalidate_all();
561
}
556
}
562
 
557
 
563
 
558
 
564
#define PRINT_BAT(name, ureg, lreg) \
559
#define PRINT_BAT(name, ureg, lreg) \
565
    asm volatile ( \
560
    asm volatile ( \
566
        "mfspr %0," #ureg "\n" \
561
        "mfspr %0," #ureg "\n" \
567
        "mfspr %1," #lreg "\n" \
562
        "mfspr %1," #lreg "\n" \
568
        : "=r" (upper), "=r" (lower) \
563
        : "=r" (upper), "=r" (lower) \
569
    ); \
564
    ); \
570
    mask = (upper & 0x1ffc) >> 2; \
565
    mask = (upper & 0x1ffc) >> 2; \
571
    if (upper & 3) { \
566
    if (upper & 3) { \
572
        uint32_t tmp = mask; \
567
        uint32_t tmp = mask; \
573
        length = 128; \
568
        length = 128; \
574
        while (tmp) { \
569
        while (tmp) { \
575
            if ((tmp & 1) == 0) { \
570
            if ((tmp & 1) == 0) { \
576
                printf("ibat[0]: error in mask\n"); \
571
                printf("ibat[0]: error in mask\n"); \
577
                break; \
572
                break; \
578
            } \
573
            } \
579
            length <<= 1; \
574
            length <<= 1; \
580
            tmp >>= 1; \
575
            tmp >>= 1; \
581
        } \
576
        } \
582
    } else \
577
    } else \
583
        length = 0; \
578
        length = 0; \
584
    printf(name ": page=%.*p frame=%.*p length=%d KB (mask=%#x)%s%s\n", \
579
    printf(name ": page=%.*p frame=%.*p length=%d KB (mask=%#x)%s%s\n", \
585
        sizeof(upper) * 2, upper & 0xffff0000, sizeof(lower) * 2, \
580
        sizeof(upper) * 2, upper & 0xffff0000, sizeof(lower) * 2, \
586
        lower & 0xffff0000, length, mask, \
581
        lower & 0xffff0000, length, mask, \
587
        ((upper >> 1) & 1) ? " supervisor" : "", \
582
        ((upper >> 1) & 1) ? " supervisor" : "", \
588
        (upper & 1) ? " user" : "");
583
        (upper & 1) ? " user" : "");
589
 
584
 
590
 
585
 
591
void tlb_print(void)
586
void tlb_print(void)
592
{
587
{
593
    uint32_t sr;
588
    uint32_t sr;
594
   
589
   
595
    for (sr = 0; sr < 16; sr++) {
590
    for (sr = 0; sr < 16; sr++) {
596
        uint32_t vsid;
591
        uint32_t vsid;
597
        asm volatile (
592
        asm volatile (
598
            "mfsrin %0, %1\n"
593
            "mfsrin %0, %1\n"
599
            : "=r" (vsid)
594
            : "=r" (vsid)
600
            : "r" (sr << 28)
595
            : "r" (sr << 28)
601
        );
596
        );
602
        printf("sr[%02u]: vsid=%.*p (asid=%u)%s%s\n", sr,
597
        printf("sr[%02u]: vsid=%.*p (asid=%u)%s%s\n", sr,
603
            sizeof(vsid) * 2, vsid & 0xffffff, (vsid & 0xffffff) >> 4,
598
            sizeof(vsid) * 2, vsid & 0xffffff, (vsid & 0xffffff) >> 4,
604
            ((vsid >> 30) & 1) ? " supervisor" : "",
599
            ((vsid >> 30) & 1) ? " supervisor" : "",
605
            ((vsid >> 29) & 1) ? " user" : "");
600
            ((vsid >> 29) & 1) ? " user" : "");
606
    }
601
    }
607
   
602
   
608
    uint32_t upper;
603
    uint32_t upper;
609
    uint32_t lower;
604
    uint32_t lower;
610
    uint32_t mask;
605
    uint32_t mask;
611
    uint32_t length;
606
    uint32_t length;
612
   
607
   
613
    PRINT_BAT("ibat[0]", 528, 529);
608
    PRINT_BAT("ibat[0]", 528, 529);
614
    PRINT_BAT("ibat[1]", 530, 531);
609
    PRINT_BAT("ibat[1]", 530, 531);
615
    PRINT_BAT("ibat[2]", 532, 533);
610
    PRINT_BAT("ibat[2]", 532, 533);
616
    PRINT_BAT("ibat[3]", 534, 535);
611
    PRINT_BAT("ibat[3]", 534, 535);
617
   
612
   
618
    PRINT_BAT("dbat[0]", 536, 537);
613
    PRINT_BAT("dbat[0]", 536, 537);
619
    PRINT_BAT("dbat[1]", 538, 539);
614
    PRINT_BAT("dbat[1]", 538, 539);
620
    PRINT_BAT("dbat[2]", 540, 541);
615
    PRINT_BAT("dbat[2]", 540, 541);
621
    PRINT_BAT("dbat[3]", 542, 543);
616
    PRINT_BAT("dbat[3]", 542, 543);
622
}
617
}
623
 
618
 
624
/** @}
619
/** @}
625
 */
620
 */
626
 
621