Subversion Repositories HelenOS

Rev

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

Rev 3836 Rev 3837
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>
42
#include <symtab.h>
43
 
43
 
44
 
44
 
-
 
45
static unsigned int seed = 10;
-
 
46
static unsigned int seed_real __attribute__ ((section("K_UNMAPPED_DATA_START"))) = 42;
-
 
47
 
-
 
48
 
45
/** Try to find PTE for faulting address
49
/** Try to find PTE for faulting address
46
 *
50
 *
47
 * Try to find PTE for faulting address.
51
 * Try to find PTE for faulting address.
48
 * The as->lock must be held on entry to this function
52
 * The as->lock must be held on entry to this function
49
 * if lock is true.
53
 * if lock is true.
50
 *
54
 *
51
 * @param as        Address space.
55
 * @param as        Address space.
52
 * @param lock      Lock/unlock the address space.
56
 * @param lock      Lock/unlock the address space.
53
 * @param badvaddr  Faulting virtual address.
57
 * @param badvaddr  Faulting virtual address.
54
 * @param access    Access mode that caused the fault.
58
 * @param access    Access mode that caused the fault.
55
 * @param istate    Pointer to interrupted state.
59
 * @param istate    Pointer to interrupted state.
56
 * @param pfrc      Pointer to variable where as_page_fault() return code
60
 * @param pfrc      Pointer to variable where as_page_fault() return code
57
 *          will be stored.
61
 *          will be stored.
58
 * @return      PTE on success, NULL otherwise.
62
 * @return      PTE on success, NULL otherwise.
59
 *
63
 *
60
 */
64
 */
61
static pte_t *
65
static pte_t *
62
find_mapping_and_check(as_t *as, bool lock, uintptr_t badvaddr, int access,
66
find_mapping_and_check(as_t *as, bool lock, uintptr_t badvaddr, int access,
63
    istate_t *istate, int *pfrc)
67
    istate_t *istate, int *pfrc)
64
{
68
{
65
    /*
69
    /*
66
     * Check if the mapping exists in page tables.
70
     * Check if the mapping exists in page tables.
67
     */
71
     */
68
    pte_t *pte = page_mapping_find(as, badvaddr);
72
    pte_t *pte = page_mapping_find(as, badvaddr);
69
    if ((pte) && (pte->present)) {
73
    if ((pte) && (pte->present)) {
70
        /*
74
        /*
71
         * Mapping found in page tables.
75
         * Mapping found in page tables.
72
         * Immediately succeed.
76
         * Immediately succeed.
73
         */
77
         */
74
        return pte;
78
        return pte;
75
    } else {
79
    } else {
76
        int rc;
80
        int rc;
77
   
81
   
78
        /*
82
        /*
79
         * Mapping not found in page tables.
83
         * Mapping not found in page tables.
80
         * Resort to higher-level page fault handler.
84
         * Resort to higher-level page fault handler.
81
         */
85
         */
82
        page_table_unlock(as, lock);
86
        page_table_unlock(as, lock);
83
        switch (rc = as_page_fault(badvaddr, access, istate)) {
87
        switch (rc = as_page_fault(badvaddr, access, istate)) {
84
        case AS_PF_OK:
88
        case AS_PF_OK:
85
            /*
89
            /*
86
             * The higher-level page fault handler succeeded,
90
             * The higher-level page fault handler succeeded,
87
             * The mapping ought to be in place.
91
             * The mapping ought to be in place.
88
             */
92
             */
89
            page_table_lock(as, lock);
93
            page_table_lock(as, lock);
90
            pte = page_mapping_find(as, badvaddr);
94
            pte = page_mapping_find(as, badvaddr);
91
            ASSERT((pte) && (pte->present));
95
            ASSERT((pte) && (pte->present));
92
            *pfrc = 0;
96
            *pfrc = 0;
93
            return pte;
97
            return pte;
94
        case AS_PF_DEFER:
98
        case AS_PF_DEFER:
95
            page_table_lock(as, lock);
99
            page_table_lock(as, lock);
96
            *pfrc = rc;
100
            *pfrc = rc;
97
            return NULL;
101
            return NULL;
98
        case AS_PF_FAULT:
102
        case AS_PF_FAULT:
99
            page_table_lock(as, lock);
103
            page_table_lock(as, lock);
100
            *pfrc = rc;
104
            *pfrc = rc;
101
            return NULL;
105
            return NULL;
102
        default:
106
        default:
103
            panic("Unexpected rc (%d).", rc);
107
            panic("Unexpected rc (%d).", rc);
104
        }  
108
        }  
105
    }
109
    }
106
}
110
}
107
 
111
 
108
 
112
 
109
static void pht_refill_fail(uintptr_t badvaddr, istate_t *istate)
113
static void pht_refill_fail(uintptr_t badvaddr, istate_t *istate)
110
{
114
{
111
    char *symbol = "";
115
    char *symbol = "";
112
    char *sym2 = "";
116
    char *sym2 = "";
113
 
117
 
114
    char *str = get_symtab_entry(istate->pc);
118
    char *str = get_symtab_entry(istate->pc);
115
    if (str)
119
    if (str)
116
        symbol = str;
120
        symbol = str;
117
    str = get_symtab_entry(istate->lr);
121
    str = get_symtab_entry(istate->lr);
118
    if (str)
122
    if (str)
119
        sym2 = str;
123
        sym2 = str;
120
 
124
 
121
    fault_if_from_uspace(istate,
125
    fault_if_from_uspace(istate,
122
        "PHT Refill Exception on %p.", badvaddr);
126
        "PHT Refill Exception on %p.", badvaddr);
123
    panic("%p: PHT Refill Exception at %p (%s<-%s).", badvaddr,
127
    panic("%p: PHT Refill Exception at %p (%s<-%s).", badvaddr,
124
        istate->pc, symbol, sym2);
128
        istate->pc, symbol, sym2);
125
}
129
}
126
 
130
 
127
 
131
 
-
 
132
/** Pseudorandom generator
-
 
133
 *
-
 
134
 * A pretty standard linear congruential pseudorandom
-
 
135
 * number generator (m = 2^32).
-
 
136
 *
-
 
137
 */
-
 
138
#define RANDI(seed) \
-
 
139
    ({ \
-
 
140
        (seed) = 1103515245 * (seed) + 12345; \
-
 
141
        (seed); \
-
 
142
    })
-
 
143
 
-
 
144
 
128
static void pht_insert(const uintptr_t vaddr, const pte_t *pte)
145
static void pht_insert(const uintptr_t vaddr, const pte_t *pte)
129
{
146
{
130
    uint32_t page = (vaddr >> 12) & 0xffff;
147
    uint32_t page = (vaddr >> 12) & 0xffff;
131
    uint32_t api = (vaddr >> 22) & 0x3f;
148
    uint32_t api = (vaddr >> 22) & 0x3f;
132
   
149
   
133
    uint32_t vsid;
150
    uint32_t vsid;
134
    asm volatile (
151
    asm volatile (
135
        "mfsrin %0, %1\n"
152
        "mfsrin %0, %1\n"
136
        : "=r" (vsid)
153
        : "=r" (vsid)
137
        : "r" (vaddr)
154
        : "r" (vaddr)
138
    );
155
    );
139
   
156
   
140
    uint32_t sdr1;
157
    uint32_t sdr1;
141
    asm volatile (
158
    asm volatile (
142
        "mfsdr1 %0\n"
159
        "mfsdr1 %0\n"
143
        : "=r" (sdr1)
160
        : "=r" (sdr1)
144
    );
161
    );
145
    phte_t *phte = (phte_t *) PA2KA(sdr1 & 0xffff0000);
162
    phte_t *phte = (phte_t *) PA2KA(sdr1 & 0xffff0000);
146
   
163
   
147
    /* Primary hash (xor) */
164
    /* Primary hash (xor) */
148
    uint32_t h = 0;
165
    uint32_t h = 0;
149
    uint32_t hash = vsid ^ page;
166
    uint32_t hash = vsid ^ page;
150
    uint32_t base = (hash & 0x3ff) << 3;
167
    uint32_t base = (hash & 0x3ff) << 3;
151
    uint32_t i;
168
    uint32_t i;
152
    bool found = false;
169
    bool found = false;
153
   
170
   
154
    /* Find unused or colliding PTE in PTEG */
171
    /* Find unused or colliding PTE in PTEG */
155
    for (i = 0; i < 8; i++) {
172
    for (i = 0; i < 8; i++) {
156
        if ((!phte[base + i].v) ||
173
        if ((!phte[base + i].v) ||
157
            ((phte[base + i].vsid == vsid)
174
            ((phte[base + i].vsid == vsid)
158
            && (phte[base + i].api == api)
175
            && (phte[base + i].api == api)
159
            && (phte[base + i].h == 0))) {
176
            && (phte[base + i].h == 0))) {
160
            found = true;
177
            found = true;
161
            break;
178
            break;
162
        }
179
        }
163
    }
180
    }
164
   
181
   
165
    if (!found) {
182
    if (!found) {
166
        /* Secondary hash (not) */
183
        /* Secondary hash (not) */
167
        uint32_t base2 = (~hash & 0x3ff) << 3;
184
        uint32_t base2 = (~hash & 0x3ff) << 3;
168
       
185
       
169
        /* Find unused or colliding PTE in PTEG */
186
        /* Find unused or colliding PTE in PTEG */
170
        for (i = 0; i < 8; i++) {
187
        for (i = 0; i < 8; i++) {
171
            if ((!phte[base2 + i].v) ||
188
            if ((!phte[base2 + i].v) ||
172
                ((phte[base2 + i].vsid == vsid)
189
                ((phte[base2 + i].vsid == vsid)
173
                && (phte[base2 + i].api == api)
190
                && (phte[base2 + i].api == api)
174
                && (phte[base2 + i].h == 1))) {
191
                && (phte[base2 + i].h == 1))) {
175
                found = true;
192
                found = true;
176
                base = base2;
193
                base = base2;
177
                h = 1;
194
                h = 1;
178
                break;
195
                break;
179
            }
196
            }
180
        }
197
        }
181
       
198
       
182
        if (!found)
199
        if (!found)
183
            i = page % 8;
200
            i = RANDI(seed) % 8;
184
    }
201
    }
185
   
202
   
186
   
-
 
187
   
-
 
188
    phte[base + i].v = 1;
203
    phte[base + i].v = 1;
189
    phte[base + i].vsid = vsid;
204
    phte[base + i].vsid = vsid;
190
    phte[base + i].h = h;
205
    phte[base + i].h = h;
191
    phte[base + i].api = api;
206
    phte[base + i].api = api;
192
    phte[base + i].rpn = pte->pfn;
207
    phte[base + i].rpn = pte->pfn;
193
    phte[base + i].r = 0;
208
    phte[base + i].r = 0;
194
    phte[base + i].c = 0;
209
    phte[base + i].c = 0;
195
    phte[base + i].wimg = (pte->page_cache_disable ? WIMG_NO_CACHE : 0);
210
    phte[base + i].wimg = (pte->page_cache_disable ? WIMG_NO_CACHE : 0);
196
    phte[base + i].pp = 2; // FIXME
211
    phte[base + i].pp = 2; // FIXME
197
}
212
}
198
 
213
 
199
 
214
 
200
static void pht_real_insert(const uintptr_t vaddr, const pfn_t pfn)
-
 
201
{
-
 
202
    uint32_t page = (vaddr >> 12) & 0xffff;
-
 
203
    uint32_t api = (vaddr >> 22) & 0x3f;
-
 
204
   
-
 
205
    uint32_t vsid;
-
 
206
    asm volatile (
-
 
207
        "mfsrin %0, %1\n"
-
 
208
        : "=r" (vsid)
-
 
209
        : "r" (vaddr)
-
 
210
    );
-
 
211
   
-
 
212
    uint32_t sdr1;
-
 
213
    asm volatile (
-
 
214
        "mfsdr1 %0\n"
-
 
215
        : "=r" (sdr1)
-
 
216
    );
-
 
217
    phte_t *phte_physical = (phte_t *) (sdr1 & 0xffff0000);
-
 
218
   
-
 
219
    /* Primary hash (xor) */
-
 
220
    uint32_t h = 0;
-
 
221
    uint32_t hash = vsid ^ page;
-
 
222
    uint32_t base = (hash & 0x3ff) << 3;
-
 
223
    uint32_t i;
-
 
224
    bool found = false;
-
 
225
   
-
 
226
    /* Find unused or colliding PTE in PTEG */
-
 
227
    for (i = 0; i < 8; i++) {
-
 
228
        if ((!phte_physical[base + i].v) ||
-
 
229
            ((phte_physical[base + i].vsid == vsid)
-
 
230
            && (phte_physical[base + i].api == api)
-
 
231
            && (phte_physical[base + i].h == 0))) {
-
 
232
            found = true;
-
 
233
            break;
-
 
234
        }
-
 
235
    }
-
 
236
   
-
 
237
    if (!found) {
-
 
238
        /* Secondary hash (not) */
-
 
239
        uint32_t base2 = (~hash & 0x3ff) << 3;
-
 
240
       
-
 
241
        /* Find unused or colliding PTE in PTEG */
-
 
242
        for (i = 0; i < 8; i++) {
-
 
243
            if ((!phte_physical[base2 + i].v) ||
-
 
244
                ((phte_physical[base2 + i].vsid == vsid)
-
 
245
                && (phte_physical[base2 + i].api == api)
-
 
246
                && (phte_physical[base2 + i].h == 1))) {
-
 
247
                found = true;
-
 
248
                base = base2;
-
 
249
                h = 1;
-
 
250
                break;
-
 
251
            }
-
 
252
        }
-
 
253
       
-
 
254
        if (!found) {
-
 
255
            i = page % 8;
-
 
256
            base = base2;
-
 
257
            h = 1;
-
 
258
        }
-
 
259
    }
-
 
260
   
-
 
261
    phte_physical[base + i].v = 1;
-
 
262
    phte_physical[base + i].vsid = vsid;
-
 
263
    phte_physical[base + i].h = h;
-
 
264
    phte_physical[base + i].api = api;
-
 
265
    phte_physical[base + i].rpn = pfn;
-
 
266
    phte_physical[base + i].r = 0;
-
 
267
    phte_physical[base + i].c = 0;
-
 
268
    phte_physical[base + i].wimg = 0;
-
 
269
    phte_physical[base + i].pp = 2; // FIXME
-
 
270
}
-
 
271
 
-
 
272
 
-
 
273
/** Process Instruction/Data Storage Interrupt
215
/** Process Instruction/Data Storage Interrupt
274
 *
216
 *
275
 * @param n     Interrupt vector number.
217
 * @param n     Interrupt vector number.
276
 * @param istate    Interrupted register context.
218
 * @param istate    Interrupted register context.
277
 *
219
 *
278
 */
220
 */
279
void pht_refill(int n, istate_t *istate)
221
void pht_refill(int n, istate_t *istate)
280
{
222
{
281
    uintptr_t badvaddr;
223
    uintptr_t badvaddr;
282
    pte_t *pte;
224
    pte_t *pte;
283
    int pfrc;
225
    int pfrc;
284
    as_t *as;
226
    as_t *as;
285
    bool lock;
227
    bool lock;
286
   
228
   
287
    if (AS == NULL) {
229
    if (AS == NULL) {
288
        as = AS_KERNEL;
230
        as = AS_KERNEL;
289
        lock = false;
231
        lock = false;
290
    } else {
232
    } else {
291
        as = AS;
233
        as = AS;
292
        lock = true;
234
        lock = true;
293
    }
235
    }
294
   
236
   
295
    if (n == VECTOR_DATA_STORAGE)
237
    if (n == VECTOR_DATA_STORAGE)
296
        badvaddr = istate->dar;
238
        badvaddr = istate->dar;
297
    else
239
    else
298
        badvaddr = istate->pc;
240
        badvaddr = istate->pc;
299
       
241
       
300
    page_table_lock(as, lock);
242
    page_table_lock(as, lock);
301
   
243
   
302
    pte = find_mapping_and_check(as, lock, badvaddr,
244
    pte = find_mapping_and_check(as, lock, badvaddr,
303
        PF_ACCESS_READ /* FIXME */, istate, &pfrc);
245
        PF_ACCESS_READ /* FIXME */, istate, &pfrc);
304
    if (!pte) {
246
    if (!pte) {
305
        switch (pfrc) {
247
        switch (pfrc) {
306
        case AS_PF_FAULT:
248
        case AS_PF_FAULT:
307
            goto fail;
249
            goto fail;
308
            break;
250
            break;
309
        case AS_PF_DEFER:
251
        case AS_PF_DEFER:
310
            /*
252
            /*
311
             * The page fault came during copy_from_uspace()
253
             * The page fault came during copy_from_uspace()
312
             * or copy_to_uspace().
254
             * or copy_to_uspace().
313
             */
255
             */
314
            page_table_unlock(as, lock);
256
            page_table_unlock(as, lock);
315
            return;
257
            return;
316
        default:
258
        default:
317
            panic("Unexpected pfrc (%d).", pfrc);
259
            panic("Unexpected pfrc (%d).", pfrc);
318
        }
260
        }
319
    }
261
    }
320
   
262
   
321
    pte->accessed = 1; /* Record access to PTE */
263
    pte->accessed = 1; /* Record access to PTE */
322
    pht_insert(badvaddr, pte);
264
    pht_insert(badvaddr, pte);
323
   
265
   
324
    page_table_unlock(as, lock);
266
    page_table_unlock(as, lock);
325
    return;
267
    return;
326
   
268
   
327
fail:
269
fail:
328
    page_table_unlock(as, lock);
270
    page_table_unlock(as, lock);
329
    pht_refill_fail(badvaddr, istate);
271
    pht_refill_fail(badvaddr, istate);
330
}
272
}
331
 
273
 
332
 
274
 
333
/** Process Instruction/Data Storage Interrupt in Real Mode
275
/** Process Instruction/Data Storage Interrupt in Real Mode
334
 *
276
 *
335
 * @param n     Interrupt vector number.
277
 * @param n     Interrupt vector number.
336
 * @param istate    Interrupted register context.
278
 * @param istate    Interrupted register context.
337
 *
279
 *
338
 */
280
 */
339
bool pht_real_refill(int n, istate_t *istate)
281
bool pht_refill_real(int n, istate_t *istate)
340
{
282
{
341
    uintptr_t badvaddr;
283
    uintptr_t badvaddr;
342
   
284
   
343
    if (n == VECTOR_DATA_STORAGE)
285
    if (n == VECTOR_DATA_STORAGE)
344
        badvaddr = istate->dar;
286
        badvaddr = istate->dar;
345
    else
287
    else
346
        badvaddr = istate->pc;
288
        badvaddr = istate->pc;
347
   
289
   
348
    uint32_t physmem;
290
    uint32_t physmem;
349
    asm volatile (
291
    asm volatile (
350
        "mfsprg3 %0\n"
292
        "mfsprg3 %0\n"
351
        : "=r" (physmem)
293
        : "=r" (physmem)
352
    );
294
    );
353
   
295
   
354
    if ((badvaddr >= PA2KA(0)) && (badvaddr < PA2KA(physmem))) {
296
    if ((badvaddr < PA2KA(0)) || (badvaddr >= PA2KA(physmem)))
-
 
297
        return false;
-
 
298
   
-
 
299
    uint32_t page = (badvaddr >> 12) & 0xffff;
355
        pht_real_insert(badvaddr, KA2PA(badvaddr) >> 12);
300
    uint32_t api = (badvaddr >> 22) & 0x3f;
-
 
301
   
-
 
302
    uint32_t vsid;
-
 
303
    asm volatile (
-
 
304
        "mfsrin %0, %1\n"
-
 
305
        : "=r" (vsid)
-
 
306
        : "r" (badvaddr)
-
 
307
    );
-
 
308
   
-
 
309
    uint32_t sdr1;
-
 
310
    asm volatile (
-
 
311
        "mfsdr1 %0\n"
-
 
312
        : "=r" (sdr1)
-
 
313
    );
-
 
314
    phte_t *phte_real = (phte_t *) (sdr1 & 0xffff0000);
-
 
315
   
-
 
316
    /* Primary hash (xor) */
-
 
317
    uint32_t h = 0;
-
 
318
    uint32_t hash = vsid ^ page;
-
 
319
    uint32_t base = (hash & 0x3ff) << 3;
-
 
320
    uint32_t i;
-
 
321
    bool found = false;
-
 
322
   
-
 
323
    /* Find unused or colliding PTE in PTEG */
-
 
324
    for (i = 0; i < 8; i++) {
-
 
325
        if ((!phte_real[base + i].v) ||
-
 
326
            ((phte_real[base + i].vsid == vsid)
-
 
327
            && (phte_real[base + i].api == api)
-
 
328
            && (phte_real[base + i].h == 0))) {
356
        return true;
329
            found = true;
-
 
330
            break;
-
 
331
        }
357
    }
332
    }
358
   
333
   
-
 
334
    if (!found) {
-
 
335
        /* Secondary hash (not) */
-
 
336
        uint32_t base2 = (~hash & 0x3ff) << 3;
-
 
337
       
-
 
338
        /* Find unused or colliding PTE in PTEG */
-
 
339
        for (i = 0; i < 8; i++) {
-
 
340
            if ((!phte_real[base2 + i].v) ||
-
 
341
                ((phte_real[base2 + i].vsid == vsid)
-
 
342
                && (phte_real[base2 + i].api == api)
-
 
343
                && (phte_real[base2 + i].h == 1))) {
-
 
344
                found = true;
-
 
345
                base = base2;
-
 
346
                h = 1;
-
 
347
                break;
-
 
348
            }
-
 
349
        }
-
 
350
       
-
 
351
        if (!found) {
-
 
352
            /* Use secondary hash to avoid collisions
-
 
353
               with usual PHT refill handler. */
-
 
354
            i = RANDI(seed_real) % 8;
-
 
355
            base = base2;
-
 
356
            h = 1;
-
 
357
        }
-
 
358
    }
-
 
359
   
-
 
360
    phte_real[base + i].v = 1;
-
 
361
    phte_real[base + i].vsid = vsid;
-
 
362
    phte_real[base + i].h = h;
-
 
363
    phte_real[base + i].api = api;
-
 
364
    phte_real[base + i].rpn = KA2PA(badvaddr) >> 12;
-
 
365
    phte_real[base + i].r = 0;
-
 
366
    phte_real[base + i].c = 0;
-
 
367
    phte_real[base + i].wimg = 0;
-
 
368
    phte_real[base + i].pp = 2; // FIXME
-
 
369
   
359
    return false;
370
    return true;
360
}
371
}
361
 
372
 
362
 
373
 
363
void tlb_arch_init(void)
374
void tlb_arch_init(void)
364
{
375
{
365
    tlb_invalidate_all();
376
    tlb_invalidate_all();
366
}
377
}
367
 
378
 
368
 
379
 
369
void tlb_invalidate_all(void)
380
void tlb_invalidate_all(void)
370
{
381
{
371
    asm volatile (
382
    asm volatile (
372
        "tlbsync\n"
383
        "tlbsync\n"
373
    );
384
    );
374
}
385
}
375
 
386
 
376
 
387
 
377
void tlb_invalidate_asid(asid_t asid)
388
void tlb_invalidate_asid(asid_t asid)
378
{
389
{
379
    uint32_t sdr1;
390
    uint32_t sdr1;
380
    asm volatile (
391
    asm volatile (
381
        "mfsdr1 %0\n"
392
        "mfsdr1 %0\n"
382
        : "=r" (sdr1)
393
        : "=r" (sdr1)
383
    );
394
    );
384
    phte_t *phte = (phte_t *) PA2KA(sdr1 & 0xffff0000);
395
    phte_t *phte = (phte_t *) PA2KA(sdr1 & 0xffff0000);
385
   
396
   
386
    uint32_t i;
397
    uint32_t i;
387
    for (i = 0; i < 8192; i++) {
398
    for (i = 0; i < 8192; i++) {
388
        if ((phte[i].v) && (phte[i].vsid >= (asid << 4)) &&
399
        if ((phte[i].v) && (phte[i].vsid >= (asid << 4)) &&
389
            (phte[i].vsid < ((asid << 4) + 16)))
400
            (phte[i].vsid < ((asid << 4) + 16)))
390
            phte[i].v = 0;
401
            phte[i].v = 0;
391
    }
402
    }
392
    tlb_invalidate_all();
403
    tlb_invalidate_all();
393
}
404
}
394
 
405
 
395
 
406
 
396
void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt)
407
void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt)
397
{
408
{
398
    // TODO
409
    // TODO
399
    tlb_invalidate_all();
410
    tlb_invalidate_all();
400
}
411
}
401
 
412
 
402
 
413
 
403
#define PRINT_BAT(name, ureg, lreg) \
414
#define PRINT_BAT(name, ureg, lreg) \
404
    asm volatile ( \
415
    asm volatile ( \
405
        "mfspr %0," #ureg "\n" \
416
        "mfspr %0," #ureg "\n" \
406
        "mfspr %1," #lreg "\n" \
417
        "mfspr %1," #lreg "\n" \
407
        : "=r" (upper), "=r" (lower) \
418
        : "=r" (upper), "=r" (lower) \
408
    ); \
419
    ); \
409
    mask = (upper & 0x1ffc) >> 2; \
420
    mask = (upper & 0x1ffc) >> 2; \
410
    if (upper & 3) { \
421
    if (upper & 3) { \
411
        uint32_t tmp = mask; \
422
        uint32_t tmp = mask; \
412
        length = 128; \
423
        length = 128; \
413
        while (tmp) { \
424
        while (tmp) { \
414
            if ((tmp & 1) == 0) { \
425
            if ((tmp & 1) == 0) { \
415
                printf("ibat[0]: error in mask\n"); \
426
                printf("ibat[0]: error in mask\n"); \
416
                break; \
427
                break; \
417
            } \
428
            } \
418
            length <<= 1; \
429
            length <<= 1; \
419
            tmp >>= 1; \
430
            tmp >>= 1; \
420
        } \
431
        } \
421
    } else \
432
    } else \
422
        length = 0; \
433
        length = 0; \
423
    printf(name ": page=%.*p frame=%.*p length=%d KB (mask=%#x)%s%s\n", \
434
    printf(name ": page=%.*p frame=%.*p length=%d KB (mask=%#x)%s%s\n", \
424
        sizeof(upper) * 2, upper & 0xffff0000, sizeof(lower) * 2, \
435
        sizeof(upper) * 2, upper & 0xffff0000, sizeof(lower) * 2, \
425
        lower & 0xffff0000, length, mask, \
436
        lower & 0xffff0000, length, mask, \
426
        ((upper >> 1) & 1) ? " supervisor" : "", \
437
        ((upper >> 1) & 1) ? " supervisor" : "", \
427
        (upper & 1) ? " user" : "");
438
        (upper & 1) ? " user" : "");
428
 
439
 
429
 
440
 
430
void tlb_print(void)
441
void tlb_print(void)
431
{
442
{
432
    uint32_t sr;
443
    uint32_t sr;
433
   
444
   
434
    for (sr = 0; sr < 16; sr++) {
445
    for (sr = 0; sr < 16; sr++) {
435
        uint32_t vsid;
446
        uint32_t vsid;
436
        asm volatile (
447
        asm volatile (
437
            "mfsrin %0, %1\n"
448
            "mfsrin %0, %1\n"
438
            : "=r" (vsid)
449
            : "=r" (vsid)
439
            : "r" (sr << 28)
450
            : "r" (sr << 28)
440
        );
451
        );
441
        printf("vsid[%d]: VSID=%.*p (ASID=%d)%s%s\n", sr,
452
        printf("sr[%02u]: vsid=%.*p (asid=%u)%s%s\n", sr,
442
            sizeof(vsid) * 2, vsid & 0xffffff, (vsid & 0xffffff) >> 4,
453
            sizeof(vsid) * 2, vsid & 0xffffff, (vsid & 0xffffff) >> 4,
443
            ((vsid >> 30) & 1) ? " supervisor" : "",
454
            ((vsid >> 30) & 1) ? " supervisor" : "",
444
            ((vsid >> 29) & 1) ? " user" : "");
455
            ((vsid >> 29) & 1) ? " user" : "");
445
    }
456
    }
446
   
457
   
447
    uint32_t upper;
458
    uint32_t upper;
448
    uint32_t lower;
459
    uint32_t lower;
449
    uint32_t mask;
460
    uint32_t mask;
450
    uint32_t length;
461
    uint32_t length;
451
   
462
   
452
    PRINT_BAT("ibat[0]", 528, 529);
463
    PRINT_BAT("ibat[0]", 528, 529);
453
    PRINT_BAT("ibat[1]", 530, 531);
464
    PRINT_BAT("ibat[1]", 530, 531);
454
    PRINT_BAT("ibat[2]", 532, 533);
465
    PRINT_BAT("ibat[2]", 532, 533);
455
    PRINT_BAT("ibat[3]", 534, 535);
466
    PRINT_BAT("ibat[3]", 534, 535);
456
   
467
   
457
    PRINT_BAT("dbat[0]", 536, 537);
468
    PRINT_BAT("dbat[0]", 536, 537);
458
    PRINT_BAT("dbat[1]", 538, 539);
469
    PRINT_BAT("dbat[1]", 538, 539);
459
    PRINT_BAT("dbat[2]", 540, 541);
470
    PRINT_BAT("dbat[2]", 540, 541);
460
    PRINT_BAT("dbat[3]", 542, 543);
471
    PRINT_BAT("dbat[3]", 542, 543);
461
}
472
}
462
 
473
 
463
/** @}
474
/** @}
464
 */
475
 */
465
 
476