root / target-cris / mmu.c @ 89fc88da
History | View | Annotate | Download (3.3 kB)
1 | 94cff60a | ths | /*
|
---|---|---|---|
2 | 94cff60a | ths | * CRIS mmu emulation.
|
3 | 94cff60a | ths | *
|
4 | 94cff60a | ths | * Copyright (c) 2007 AXIS Communications AB
|
5 | 94cff60a | ths | * Written by Edgar E. Iglesias.
|
6 | 94cff60a | ths | *
|
7 | 94cff60a | ths | * This library is free software; you can redistribute it and/or
|
8 | 94cff60a | ths | * modify it under the terms of the GNU Lesser General Public
|
9 | 94cff60a | ths | * License as published by the Free Software Foundation; either
|
10 | 94cff60a | ths | * version 2 of the License, or (at your option) any later version.
|
11 | 94cff60a | ths | *
|
12 | 94cff60a | ths | * This library is distributed in the hope that it will be useful,
|
13 | 94cff60a | ths | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14 | 94cff60a | ths | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15 | 94cff60a | ths | * Lesser General Public License for more details.
|
16 | 94cff60a | ths | *
|
17 | 94cff60a | ths | * You should have received a copy of the GNU Lesser General Public
|
18 | 94cff60a | ths | * License along with this library; if not, write to the Free Software
|
19 | 94cff60a | ths | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
20 | 94cff60a | ths | */
|
21 | 94cff60a | ths | |
22 | 94cff60a | ths | #ifndef CONFIG_USER_ONLY
|
23 | 94cff60a | ths | |
24 | 94cff60a | ths | #include <stdio.h> |
25 | 94cff60a | ths | #include <string.h> |
26 | 94cff60a | ths | #include <stdlib.h> |
27 | 94cff60a | ths | |
28 | 94cff60a | ths | #include "config.h" |
29 | 94cff60a | ths | #include "cpu.h" |
30 | 94cff60a | ths | #include "mmu.h" |
31 | 94cff60a | ths | #include "exec-all.h" |
32 | 94cff60a | ths | |
33 | 94cff60a | ths | |
34 | 94cff60a | ths | static int cris_mmu_enabled(uint32_t rw_gc_cfg) |
35 | 94cff60a | ths | { |
36 | 94cff60a | ths | return (rw_gc_cfg & 12) != 0; |
37 | 94cff60a | ths | } |
38 | 94cff60a | ths | |
39 | 94cff60a | ths | static int cris_mmu_segmented_addr(int seg, uint32_t rw_mm_cfg) |
40 | 94cff60a | ths | { |
41 | 94cff60a | ths | return (1 << seg) & rw_mm_cfg; |
42 | 94cff60a | ths | } |
43 | 94cff60a | ths | |
44 | 94cff60a | ths | static uint32_t cris_mmu_translate_seg(CPUState *env, int seg) |
45 | 94cff60a | ths | { |
46 | 94cff60a | ths | uint32_t base; |
47 | 94cff60a | ths | int i;
|
48 | 94cff60a | ths | |
49 | 94cff60a | ths | if (seg < 8) |
50 | 94cff60a | ths | base = env->sregs[SFR_RW_MM_KBASE_LO]; |
51 | 94cff60a | ths | else
|
52 | 94cff60a | ths | base = env->sregs[SFR_RW_MM_KBASE_HI]; |
53 | 94cff60a | ths | |
54 | 94cff60a | ths | i = seg & 7;
|
55 | 94cff60a | ths | base >>= i * 4;
|
56 | 94cff60a | ths | base &= 15;
|
57 | 94cff60a | ths | |
58 | 94cff60a | ths | base <<= 28;
|
59 | 94cff60a | ths | return base;
|
60 | 94cff60a | ths | } |
61 | 94cff60a | ths | /* Used by the tlb decoder. */
|
62 | 94cff60a | ths | #define EXTRACT_FIELD(src, start, end) \
|
63 | 94cff60a | ths | (((src) >> start) & ((1 << (end - start + 1)) - 1)) |
64 | 94cff60a | ths | |
65 | 94cff60a | ths | static int cris_mmu_translate_page(struct cris_mmu_result_t *res, |
66 | 94cff60a | ths | CPUState *env, uint32_t vaddr, |
67 | 94cff60a | ths | int rw, int usermode) |
68 | 94cff60a | ths | { |
69 | 94cff60a | ths | unsigned int vpage; |
70 | 94cff60a | ths | unsigned int idx; |
71 | 94cff60a | ths | uint32_t lo, hi; |
72 | 94cff60a | ths | uint32_t vpn, pfn = 0, pid, fg, fv, fk, fw, fx;
|
73 | 94cff60a | ths | int i, match = 0; |
74 | 94cff60a | ths | |
75 | 94cff60a | ths | vpage = vaddr >> 13;
|
76 | 94cff60a | ths | idx = vpage & 31;
|
77 | 94cff60a | ths | vpage >>= 4;
|
78 | 94cff60a | ths | |
79 | 94cff60a | ths | /* We know the index which to check on each set.
|
80 | 94cff60a | ths | Scan both I and D. */
|
81 | 94cff60a | ths | for (i = 0; i < 4; i++) |
82 | 94cff60a | ths | { |
83 | 94cff60a | ths | lo = env->tlbsets[0][i][idx].lo;
|
84 | 94cff60a | ths | hi = env->tlbsets[0][i][idx].hi;
|
85 | 94cff60a | ths | |
86 | 94cff60a | ths | vpn = EXTRACT_FIELD(hi, 13, 31); |
87 | 94cff60a | ths | pid = EXTRACT_FIELD(hi, 0, 7); |
88 | 94cff60a | ths | |
89 | 94cff60a | ths | if (vpn == vpage
|
90 | 94cff60a | ths | && pid == env->pregs[SR_PID]) { |
91 | 94cff60a | ths | match = 1;
|
92 | 94cff60a | ths | break;
|
93 | 94cff60a | ths | } |
94 | 94cff60a | ths | } |
95 | 94cff60a | ths | |
96 | 94cff60a | ths | if (match) {
|
97 | 94cff60a | ths | pfn = EXTRACT_FIELD(lo, 13, 31); |
98 | 94cff60a | ths | fg = EXTRACT_FIELD(lo, 4, 4); |
99 | 94cff60a | ths | fv = EXTRACT_FIELD(lo, 3, 3); |
100 | 94cff60a | ths | fk = EXTRACT_FIELD(lo, 2, 2); |
101 | 94cff60a | ths | fw = EXTRACT_FIELD(lo, 1, 1); |
102 | 94cff60a | ths | fx = EXTRACT_FIELD(lo, 0, 0); |
103 | 94cff60a | ths | } |
104 | 94cff60a | ths | printf ("%s match=%d vaddr=%x vpage=%x vpn=%x pfn=%x pid=%x %x\n",
|
105 | 94cff60a | ths | __func__, match, |
106 | 94cff60a | ths | vaddr, vpage, |
107 | 94cff60a | ths | vpn, pfn, pid, env->pregs[SR_PID]); |
108 | 94cff60a | ths | res->pfn = pfn; |
109 | 94cff60a | ths | return !match;
|
110 | 94cff60a | ths | } |
111 | 94cff60a | ths | |
112 | 94cff60a | ths | int cris_mmu_translate(struct cris_mmu_result_t *res, |
113 | 94cff60a | ths | CPUState *env, uint32_t vaddr, |
114 | 94cff60a | ths | int rw, int is_user) |
115 | 94cff60a | ths | { |
116 | 94cff60a | ths | uint32_t phy = vaddr; |
117 | 94cff60a | ths | int seg;
|
118 | 94cff60a | ths | int miss = 0; |
119 | 94cff60a | ths | |
120 | 94cff60a | ths | if (!cris_mmu_enabled(env->sregs[SFR_RW_GC_CFG])) {
|
121 | 94cff60a | ths | res->phy = vaddr; |
122 | 94cff60a | ths | return 0; |
123 | 94cff60a | ths | } |
124 | 94cff60a | ths | |
125 | 94cff60a | ths | seg = vaddr >> 28;
|
126 | 94cff60a | ths | if (cris_mmu_segmented_addr(seg, env->sregs[SFR_RW_MM_CFG]))
|
127 | 94cff60a | ths | { |
128 | 94cff60a | ths | uint32_t base; |
129 | 94cff60a | ths | |
130 | 94cff60a | ths | miss = 0;
|
131 | 94cff60a | ths | base = cris_mmu_translate_seg(env, seg); |
132 | 94cff60a | ths | phy = base | (0x0fffffff & vaddr);
|
133 | 94cff60a | ths | res->phy = phy; |
134 | 94cff60a | ths | } |
135 | 94cff60a | ths | else
|
136 | 94cff60a | ths | { |
137 | 94cff60a | ths | miss = cris_mmu_translate_page(res, env, vaddr, rw, is_user); |
138 | 94cff60a | ths | if (!miss) {
|
139 | 94cff60a | ths | phy &= 8191;
|
140 | 94cff60a | ths | phy |= (res->pfn << 13);
|
141 | 94cff60a | ths | res->phy = phy; |
142 | 94cff60a | ths | } |
143 | 94cff60a | ths | } |
144 | 94cff60a | ths | // printf ("miss=%d v=%x -> p=%x\n", miss, vaddr, phy);
|
145 | 94cff60a | ths | return miss;
|
146 | 94cff60a | ths | } |
147 | 94cff60a | ths | #endif |