Commit 786c02f1acb73ca68ecdc4fa93911495dc1147c6

Authored by edgar_igl
1 parent e62b5b13

Model more parts of the ETRAX mmu (still alot missing).


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4056 c046a42c-6fe2-441c-8c8c-71466251a162
target-cris/cpu.h
... ... @@ -35,7 +35,7 @@
35 35 #define EXCP_MMU_READ 1
36 36 #define EXCP_MMU_WRITE 2
37 37 #define EXCP_MMU_FLUSH 3
38   -#define EXCP_MMU_MISS 4
  38 +#define EXCP_MMU_FAULT 4
39 39 #define EXCP_BREAK 16 /* trap. */
40 40  
41 41 /* CPU flags. */
... ... @@ -110,9 +110,6 @@ typedef struct CPUCRISState {
110 110 uint32_t btarget;
111 111 int btaken;
112 112  
113   - /* for traps. */
114   - int trapnr;
115   -
116 113 /* Condition flag tracking. */
117 114 uint32_t cc_op;
118 115 uint32_t cc_mask;
... ... @@ -129,9 +126,12 @@ typedef struct CPUCRISState {
129 126  
130 127 int features;
131 128  
132   - uint64_t pending_interrupts;
133   - int interrupt_request;
134 129 int exception_index;
  130 + int interrupt_request;
  131 + int interrupt_vector;
  132 + int fault_vector;
  133 + int trap_vector;
  134 +
135 135 int user_mode_only;
136 136 int halted;
137 137  
... ... @@ -245,9 +245,13 @@ static inline int cpu_mmu_index (CPUState *env)
245 245 #define R_ACR 15
246 246  
247 247 /* Support regs, P0 - P15 */
  248 +#define PR_BZ 0
  249 +#define PR_VR 1
248 250 #define PR_PID 2
249 251 #define PR_SRS 3
  252 +#define PR_WZ 4
250 253 #define PR_MOF 7
  254 +#define PR_DZ 8
251 255 #define PR_EBP 9
252 256 #define PR_ERP 10
253 257 #define PR_SRP 11
... ... @@ -255,12 +259,12 @@ static inline int cpu_mmu_index (CPUState *env)
255 259  
256 260 /* Support function regs. */
257 261 #define SFR_RW_GC_CFG 0][0
258   -#define SFR_RW_MM_CFG 1][0
259   -#define SFR_RW_MM_KBASE_LO 1][1
260   -#define SFR_RW_MM_KBASE_HI 1][2
261   -#define SFR_R_MM_CAUSE 1][3
262   -#define SFR_RW_MM_TLB_SEL 1][4
263   -#define SFR_RW_MM_TLB_LO 1][5
264   -#define SFR_RW_MM_TLB_HI 1][6
  262 +#define SFR_RW_MM_CFG 2][0
  263 +#define SFR_RW_MM_KBASE_LO 2][1
  264 +#define SFR_RW_MM_KBASE_HI 2][2
  265 +#define SFR_R_MM_CAUSE 2][3
  266 +#define SFR_RW_MM_TLB_SEL 2][4
  267 +#define SFR_RW_MM_TLB_LO 2][5
  268 +#define SFR_RW_MM_TLB_HI 2][6
265 269  
266 270 #endif
... ...
target-cris/helper.h 0 → 100644
  1 +#define TCG_HELPER_PROTO
  2 +void TCG_HELPER_PROTO helper_tlb_update(uint32_t T0);
  3 +
... ...
target-cris/mmu.c
... ... @@ -30,6 +30,7 @@
30 30 #include "mmu.h"
31 31 #include "exec-all.h"
32 32  
  33 +#define D(x)
33 34  
34 35 static int cris_mmu_enabled(uint32_t rw_gc_cfg)
35 36 {
... ... @@ -60,7 +61,22 @@ static uint32_t cris_mmu_translate_seg(CPUState *env, int seg)
60 61 }
61 62 /* Used by the tlb decoder. */
62 63 #define EXTRACT_FIELD(src, start, end) \
63   - (((src) >> start) & ((1 << (end - start + 1)) - 1))
  64 + (((src) >> start) & ((1 << (end - start + 1)) - 1))
  65 +
  66 +static inline void set_field(uint32_t *dst, unsigned int val,
  67 + unsigned int offset, unsigned int width)
  68 +{
  69 + uint32_t mask;
  70 +
  71 + mask = (1 << width) - 1;
  72 + mask <<= offset;
  73 + val <<= offset;
  74 +
  75 + val &= mask;
  76 + D(printf ("val=%x mask=%x dst=%x\n", val, mask, *dst));
  77 + *dst &= ~(mask);
  78 + *dst |= val;
  79 +}
64 80  
65 81 static int cris_mmu_translate_page(struct cris_mmu_result_t *res,
66 82 CPUState *env, uint32_t vaddr,
... ... @@ -69,46 +85,149 @@ static int cris_mmu_translate_page(struct cris_mmu_result_t *res,
69 85 unsigned int vpage;
70 86 unsigned int idx;
71 87 uint32_t lo, hi;
72   - uint32_t vpn, pfn = 0, pid, fg, fv, fk, fw, fx;
  88 + uint32_t tlb_vpn, tlb_pfn = 0;
  89 + int tlb_pid, tlb_g, tlb_v, tlb_k, tlb_w, tlb_x;
  90 + int cfg_v, cfg_k, cfg_w, cfg_x;
73 91 int i, match = 0;
  92 + uint32_t r_cause;
  93 + uint32_t r_cfg;
  94 + int rwcause;
  95 + int update_sel = 0;
  96 +
  97 + r_cause = env->sregs[SFR_R_MM_CAUSE];
  98 + r_cfg = env->sregs[SFR_RW_MM_CFG];
  99 + rwcause = rw ? CRIS_MMU_ERR_WRITE : CRIS_MMU_ERR_READ;
74 100  
75 101 vpage = vaddr >> 13;
76   - idx = vpage & 31;
77   - vpage >>= 4;
  102 + idx = vpage & 15;
78 103  
79 104 /* We know the index which to check on each set.
80 105 Scan both I and D. */
  106 +#if 0
  107 + for (i = 0; i < 4; i++) {
  108 + int j;
  109 + for (j = 0; j < 16; j++) {
  110 + lo = env->tlbsets[1][i][j].lo;
  111 + hi = env->tlbsets[1][i][j].hi;
  112 + tlb_vpn = EXTRACT_FIELD(hi, 13, 31);
  113 + tlb_pfn = EXTRACT_FIELD(lo, 13, 31);
  114 +
  115 + printf ("TLB: [%d][%d] hi=%x lo=%x v=%x p=%x\n",
  116 + i, j, hi, lo, tlb_vpn, tlb_pfn);
  117 + }
  118 + }
  119 +#endif
81 120 for (i = 0; i < 4; i++)
82 121 {
83   - lo = env->tlbsets[0][i][idx].lo;
84   - hi = env->tlbsets[0][i][idx].hi;
  122 + lo = env->tlbsets[1][i][idx].lo;
  123 + hi = env->tlbsets[1][i][idx].hi;
85 124  
86   - vpn = EXTRACT_FIELD(hi, 13, 31);
87   - pid = EXTRACT_FIELD(hi, 0, 7);
  125 + tlb_vpn = EXTRACT_FIELD(hi, 13, 31);
  126 + tlb_pfn = EXTRACT_FIELD(lo, 13, 31);
88 127  
89   - if (vpn == vpage
90   - && pid == env->pregs[PR_PID]) {
  128 + D(printf ("TLB[%d][%d] tlbv=%x vpage=%x -> pfn=%x\n",
  129 + i, idx, tlb_vpn, vpage, tlb_pfn));
  130 + if (tlb_vpn == vpage) {
91 131 match = 1;
92 132 break;
93 133 }
94 134 }
95 135  
96 136 if (match) {
97   - pfn = EXTRACT_FIELD(lo, 13, 31);
98   - fg = EXTRACT_FIELD(lo, 4, 4);
99   - fv = EXTRACT_FIELD(lo, 3, 3);
100   - fk = EXTRACT_FIELD(lo, 2, 2);
101   - fw = EXTRACT_FIELD(lo, 1, 1);
102   - fx = EXTRACT_FIELD(lo, 0, 0);
  137 +
  138 + cfg_w = EXTRACT_FIELD(r_cfg, 19, 19);
  139 + cfg_k = EXTRACT_FIELD(r_cfg, 18, 18);
  140 + cfg_x = EXTRACT_FIELD(r_cfg, 17, 17);
  141 + cfg_v = EXTRACT_FIELD(r_cfg, 16, 16);
  142 +
  143 + tlb_pid = EXTRACT_FIELD(hi, 0, 7);
  144 + tlb_pfn = EXTRACT_FIELD(lo, 13, 31);
  145 + tlb_g = EXTRACT_FIELD(lo, 4, 4);
  146 + tlb_v = EXTRACT_FIELD(lo, 3, 3);
  147 + tlb_k = EXTRACT_FIELD(lo, 2, 2);
  148 + tlb_w = EXTRACT_FIELD(lo, 1, 1);
  149 + tlb_x = EXTRACT_FIELD(lo, 0, 0);
  150 +
  151 + /*
  152 + set_exception_vector(0x04, i_mmu_refill);
  153 + set_exception_vector(0x05, i_mmu_invalid);
  154 + set_exception_vector(0x06, i_mmu_access);
  155 + set_exception_vector(0x07, i_mmu_execute);
  156 + set_exception_vector(0x08, d_mmu_refill);
  157 + set_exception_vector(0x09, d_mmu_invalid);
  158 + set_exception_vector(0x0a, d_mmu_access);
  159 + set_exception_vector(0x0b, d_mmu_write);
  160 + */
  161 + if (cfg_v && !tlb_v) {
  162 + printf ("tlb: invalid\n");
  163 + set_field(&r_cause, rwcause, 8, 9);
  164 + match = 0;
  165 + res->bf_vec = 0x9;
  166 + update_sel = 1;
  167 + }
  168 + else if (!tlb_g
  169 + && tlb_pid != 0xff
  170 + && tlb_pid != env->pregs[PR_PID]
  171 + && cfg_w && !tlb_w) {
  172 + printf ("tlb: wrong pid\n");
  173 + match = 0;
  174 + res->bf_vec = 0xa;
  175 + }
  176 + else if (rw && cfg_w && !tlb_w) {
  177 + printf ("tlb: write protected\n");
  178 + match = 0;
  179 + res->bf_vec = 0xb;
  180 + }
  181 + } else
  182 + update_sel = 1;
  183 +
  184 + if (update_sel) {
  185 + /* miss. */
  186 + env->sregs[SFR_RW_MM_TLB_SEL] = 0;
  187 + D(printf ("tlb: miss %x vp=%x\n",
  188 + env->sregs[SFR_RW_MM_TLB_SEL], vpage & 15));
  189 + set_field(&env->sregs[SFR_RW_MM_TLB_SEL], vpage & 15, 0, 4);
  190 + set_field(&env->sregs[SFR_RW_MM_TLB_SEL], 0, 4, 5);
  191 + res->bf_vec = 0x8;
  192 + }
  193 +
  194 + if (!match) {
  195 + set_field(&r_cause, rwcause, 8, 9);
  196 + set_field(&r_cause, vpage, 13, 19);
  197 + set_field(&r_cause, env->pregs[PR_PID], 0, 8);
  198 + env->sregs[SFR_R_MM_CAUSE] = r_cause;
103 199 }
104   - printf ("%s match=%d vaddr=%x vpage=%x vpn=%x pfn=%x pid=%x %x\n",
105   - __func__, match,
106   - vaddr, vpage,
107   - vpn, pfn, pid, env->pregs[PR_PID]);
108   - res->pfn = pfn;
  200 + D(printf ("%s mtch=%d pc=%x va=%x vpn=%x tlbvpn=%x pfn=%x pid=%x"
  201 + " %x cause=%x sel=%x r13=%x\n",
  202 + __func__, match, env->pc,
  203 + vaddr, vpage,
  204 + tlb_vpn, tlb_pfn, tlb_pid,
  205 + env->pregs[PR_PID],
  206 + r_cause,
  207 + env->sregs[SFR_RW_MM_TLB_SEL],
  208 + env->regs[13]));
  209 +
  210 + res->pfn = tlb_pfn;
109 211 return !match;
110 212 }
111 213  
  214 +/* Give us the vaddr corresponding to the latest TLB update. */
  215 +target_ulong cris_mmu_tlb_latest_update(CPUState *env, uint32_t new_lo)
  216 +{
  217 + uint32_t sel = env->sregs[SFR_RW_MM_TLB_SEL];
  218 + uint32_t vaddr;
  219 + uint32_t hi;
  220 + int set;
  221 + int idx;
  222 +
  223 + idx = EXTRACT_FIELD(sel, 0, 4);
  224 + set = EXTRACT_FIELD(sel, 4, 5);
  225 +
  226 + hi = env->tlbsets[1][set][idx].hi;
  227 + vaddr = EXTRACT_FIELD(hi, 13, 31);
  228 + return vaddr << TARGET_PAGE_BITS;
  229 +}
  230 +
112 231 int cris_mmu_translate(struct cris_mmu_result_t *res,
113 232 CPUState *env, uint32_t vaddr,
114 233 int rw, int mmu_idx)
... ... @@ -116,7 +235,7 @@ int cris_mmu_translate(struct cris_mmu_result_t *res,
116 235 uint32_t phy = vaddr;
117 236 int seg;
118 237 int miss = 0;
119   - int is_user = mmu_idx == MMU_USER_IDX;
  238 + int is_user = mmu_idx == MMU_USER_IDX;
120 239  
121 240 if (!cris_mmu_enabled(env->sregs[SFR_RW_GC_CFG])) {
122 241 res->phy = vaddr;
... ... @@ -142,7 +261,7 @@ int cris_mmu_translate(struct cris_mmu_result_t *res,
142 261 res->phy = phy;
143 262 }
144 263 }
145   -// printf ("miss=%d v=%x -> p=%x\n", miss, vaddr, phy);
  264 + D(printf ("miss=%d v=%x -> p=%x\n", miss, vaddr, phy));
146 265 return miss;
147 266 }
148 267 #endif
... ...
target-cris/mmu.h
... ... @@ -7,14 +7,10 @@ struct cris_mmu_result_t
7 7 {
8 8 uint32_t phy;
9 9 uint32_t pfn;
10   - int g:1;
11   - int v:1;
12   - int k:1;
13   - int w:1;
14   - int e:1;
15   - int cause_op;
  10 + int bf_vec;
16 11 };
17 12  
  13 +target_ulong cris_mmu_tlb_latest_update(CPUState *env, uint32_t new_lo);
18 14 int cris_mmu_translate(struct cris_mmu_result_t *res,
19 15 CPUState *env, uint32_t vaddr,
20 16 int rw, int mmu_idx);
... ...
target-cris/op.c
... ... @@ -153,7 +153,7 @@
153 153  
154 154 void OPPROTO op_break_im(void)
155 155 {
156   - env->trapnr = PARAM1;
  156 + env->trap_vector = PARAM1;
157 157 env->exception_index = EXCP_BREAK;
158 158 cpu_loop_exit();
159 159 }
... ... @@ -196,7 +196,7 @@ void OPPROTO op_ccs_rshift (void)
196 196  
197 197 /* Apply the ccs shift. */
198 198 ccs = env->pregs[PR_CCS];
199   - ccs = (ccs & 0xc0000000) | (ccs >> 10);
  199 + ccs = (ccs & 0xc0000000) | ((ccs & 0x0fffffff) >> 10);
200 200 env->pregs[PR_CCS] = ccs;
201 201 RETURN();
202 202 }
... ... @@ -269,28 +269,41 @@ void OPPROTO op_movl_sreg_T0 (void)
269 269 RETURN();
270 270 }
271 271  
  272 +void OPPROTO op_movl_tlb_hi_T0 (void)
  273 +{
  274 + uint32_t srs;
  275 + srs = env->pregs[PR_SRS];
  276 + if (srs == 1 || srs == 2)
  277 + {
  278 + /* Writes to tlb-hi write to mm_cause as a side effect. */
  279 + env->sregs[SFR_RW_MM_TLB_HI] = T0;
  280 + env->sregs[SFR_R_MM_CAUSE] = T0;
  281 + }
  282 + RETURN();
  283 +}
  284 +
272 285 void OPPROTO op_movl_tlb_lo_T0 (void)
273 286 {
274   - int srs;
  287 + uint32_t srs;
275 288 srs = env->pregs[PR_SRS];
276 289 if (srs == 1 || srs == 2)
277 290 {
278   - int set;
279   - int idx;
  291 + uint32_t set;
  292 + uint32_t idx;
280 293 uint32_t lo, hi;
281 294  
282 295 idx = set = env->sregs[SFR_RW_MM_TLB_SEL];
283 296 set >>= 4;
284 297 set &= 3;
285 298  
286   - idx &= 31;
  299 + idx &= 15;
287 300 /* We've just made a write to tlb_lo. */
288 301 lo = env->sregs[SFR_RW_MM_TLB_LO];
289   - hi = env->sregs[SFR_RW_MM_TLB_HI];
  302 + /* Writes are done via r_mm_cause. */
  303 + hi = env->sregs[SFR_R_MM_CAUSE];
290 304 env->tlbsets[srs - 1][set][idx].lo = lo;
291 305 env->tlbsets[srs - 1][set][idx].hi = hi;
292 306 }
293   -
294 307 RETURN();
295 308 }
296 309  
... ...
target-cris/op_helper.c
... ... @@ -21,6 +21,7 @@
21 21  
22 22 #include <assert.h>
23 23 #include "exec.h"
  24 +#include "mmu.h"
24 25  
25 26 #define MMUSUFFIX _mmu
26 27 #ifdef __s390__
... ... @@ -41,6 +42,8 @@
41 42 #define SHIFT 3
42 43 #include "softmmu_template.h"
43 44  
  45 +#define D(x)
  46 +
44 47 /* Try to fill the TLB and return an exception if error. If retaddr is
45 48 NULL, it means that the function was called in C code (i.e. not
46 49 from generated code or from helper.c) */
... ... @@ -73,8 +76,20 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
73 76 env = saved_env;
74 77 }
75 78  
  79 +void helper_tlb_update(uint32_t T0)
  80 +{
  81 +#if !defined(CONFIG_USER_ONLY)
  82 + uint32_t vaddr;
  83 +
  84 + vaddr = cris_mmu_tlb_latest_update(env, T0);
  85 + D(printf("flush vaddr %x\n", vaddr));
  86 + tlb_flush_page(env, vaddr);
  87 +#endif
  88 +}
  89 +
76 90 void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
77 91 int is_asi)
78 92 {
79   -
  93 + D(printf("%s addr=%x w=%d ex=%d asi=%d\n",
  94 + __func__, addr, is_write, is_exec, is_asi));
80 95 }
... ...