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,7 +35,7 @@
35 #define EXCP_MMU_READ 1 35 #define EXCP_MMU_READ 1
36 #define EXCP_MMU_WRITE 2 36 #define EXCP_MMU_WRITE 2
37 #define EXCP_MMU_FLUSH 3 37 #define EXCP_MMU_FLUSH 3
38 -#define EXCP_MMU_MISS 4 38 +#define EXCP_MMU_FAULT 4
39 #define EXCP_BREAK 16 /* trap. */ 39 #define EXCP_BREAK 16 /* trap. */
40 40
41 /* CPU flags. */ 41 /* CPU flags. */
@@ -110,9 +110,6 @@ typedef struct CPUCRISState { @@ -110,9 +110,6 @@ typedef struct CPUCRISState {
110 uint32_t btarget; 110 uint32_t btarget;
111 int btaken; 111 int btaken;
112 112
113 - /* for traps. */  
114 - int trapnr;  
115 -  
116 /* Condition flag tracking. */ 113 /* Condition flag tracking. */
117 uint32_t cc_op; 114 uint32_t cc_op;
118 uint32_t cc_mask; 115 uint32_t cc_mask;
@@ -129,9 +126,12 @@ typedef struct CPUCRISState { @@ -129,9 +126,12 @@ typedef struct CPUCRISState {
129 126
130 int features; 127 int features;
131 128
132 - uint64_t pending_interrupts;  
133 - int interrupt_request;  
134 int exception_index; 129 int exception_index;
  130 + int interrupt_request;
  131 + int interrupt_vector;
  132 + int fault_vector;
  133 + int trap_vector;
  134 +
135 int user_mode_only; 135 int user_mode_only;
136 int halted; 136 int halted;
137 137
@@ -245,9 +245,13 @@ static inline int cpu_mmu_index (CPUState *env) @@ -245,9 +245,13 @@ static inline int cpu_mmu_index (CPUState *env)
245 #define R_ACR 15 245 #define R_ACR 15
246 246
247 /* Support regs, P0 - P15 */ 247 /* Support regs, P0 - P15 */
  248 +#define PR_BZ 0
  249 +#define PR_VR 1
248 #define PR_PID 2 250 #define PR_PID 2
249 #define PR_SRS 3 251 #define PR_SRS 3
  252 +#define PR_WZ 4
250 #define PR_MOF 7 253 #define PR_MOF 7
  254 +#define PR_DZ 8
251 #define PR_EBP 9 255 #define PR_EBP 9
252 #define PR_ERP 10 256 #define PR_ERP 10
253 #define PR_SRP 11 257 #define PR_SRP 11
@@ -255,12 +259,12 @@ static inline int cpu_mmu_index (CPUState *env) @@ -255,12 +259,12 @@ static inline int cpu_mmu_index (CPUState *env)
255 259
256 /* Support function regs. */ 260 /* Support function regs. */
257 #define SFR_RW_GC_CFG 0][0 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 #endif 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,6 +30,7 @@
30 #include "mmu.h" 30 #include "mmu.h"
31 #include "exec-all.h" 31 #include "exec-all.h"
32 32
  33 +#define D(x)
33 34
34 static int cris_mmu_enabled(uint32_t rw_gc_cfg) 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,7 +61,22 @@ static uint32_t cris_mmu_translate_seg(CPUState *env, int seg)
60 } 61 }
61 /* Used by the tlb decoder. */ 62 /* Used by the tlb decoder. */
62 #define EXTRACT_FIELD(src, start, end) \ 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 static int cris_mmu_translate_page(struct cris_mmu_result_t *res, 81 static int cris_mmu_translate_page(struct cris_mmu_result_t *res,
66 CPUState *env, uint32_t vaddr, 82 CPUState *env, uint32_t vaddr,
@@ -69,46 +85,149 @@ static int cris_mmu_translate_page(struct cris_mmu_result_t *res, @@ -69,46 +85,149 @@ static int cris_mmu_translate_page(struct cris_mmu_result_t *res,
69 unsigned int vpage; 85 unsigned int vpage;
70 unsigned int idx; 86 unsigned int idx;
71 uint32_t lo, hi; 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 int i, match = 0; 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 vpage = vaddr >> 13; 101 vpage = vaddr >> 13;
76 - idx = vpage & 31;  
77 - vpage >>= 4; 102 + idx = vpage & 15;
78 103
79 /* We know the index which to check on each set. 104 /* We know the index which to check on each set.
80 Scan both I and D. */ 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 for (i = 0; i < 4; i++) 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 match = 1; 131 match = 1;
92 break; 132 break;
93 } 133 }
94 } 134 }
95 135
96 if (match) { 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 return !match; 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 int cris_mmu_translate(struct cris_mmu_result_t *res, 231 int cris_mmu_translate(struct cris_mmu_result_t *res,
113 CPUState *env, uint32_t vaddr, 232 CPUState *env, uint32_t vaddr,
114 int rw, int mmu_idx) 233 int rw, int mmu_idx)
@@ -116,7 +235,7 @@ int cris_mmu_translate(struct cris_mmu_result_t *res, @@ -116,7 +235,7 @@ int cris_mmu_translate(struct cris_mmu_result_t *res,
116 uint32_t phy = vaddr; 235 uint32_t phy = vaddr;
117 int seg; 236 int seg;
118 int miss = 0; 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 if (!cris_mmu_enabled(env->sregs[SFR_RW_GC_CFG])) { 240 if (!cris_mmu_enabled(env->sregs[SFR_RW_GC_CFG])) {
122 res->phy = vaddr; 241 res->phy = vaddr;
@@ -142,7 +261,7 @@ int cris_mmu_translate(struct cris_mmu_result_t *res, @@ -142,7 +261,7 @@ int cris_mmu_translate(struct cris_mmu_result_t *res,
142 res->phy = phy; 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 return miss; 265 return miss;
147 } 266 }
148 #endif 267 #endif
target-cris/mmu.h
@@ -7,14 +7,10 @@ struct cris_mmu_result_t @@ -7,14 +7,10 @@ struct cris_mmu_result_t
7 { 7 {
8 uint32_t phy; 8 uint32_t phy;
9 uint32_t pfn; 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 int cris_mmu_translate(struct cris_mmu_result_t *res, 14 int cris_mmu_translate(struct cris_mmu_result_t *res,
19 CPUState *env, uint32_t vaddr, 15 CPUState *env, uint32_t vaddr,
20 int rw, int mmu_idx); 16 int rw, int mmu_idx);
target-cris/op.c
@@ -153,7 +153,7 @@ @@ -153,7 +153,7 @@
153 153
154 void OPPROTO op_break_im(void) 154 void OPPROTO op_break_im(void)
155 { 155 {
156 - env->trapnr = PARAM1; 156 + env->trap_vector = PARAM1;
157 env->exception_index = EXCP_BREAK; 157 env->exception_index = EXCP_BREAK;
158 cpu_loop_exit(); 158 cpu_loop_exit();
159 } 159 }
@@ -196,7 +196,7 @@ void OPPROTO op_ccs_rshift (void) @@ -196,7 +196,7 @@ void OPPROTO op_ccs_rshift (void)
196 196
197 /* Apply the ccs shift. */ 197 /* Apply the ccs shift. */
198 ccs = env->pregs[PR_CCS]; 198 ccs = env->pregs[PR_CCS];
199 - ccs = (ccs & 0xc0000000) | (ccs >> 10); 199 + ccs = (ccs & 0xc0000000) | ((ccs & 0x0fffffff) >> 10);
200 env->pregs[PR_CCS] = ccs; 200 env->pregs[PR_CCS] = ccs;
201 RETURN(); 201 RETURN();
202 } 202 }
@@ -269,28 +269,41 @@ void OPPROTO op_movl_sreg_T0 (void) @@ -269,28 +269,41 @@ void OPPROTO op_movl_sreg_T0 (void)
269 RETURN(); 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 void OPPROTO op_movl_tlb_lo_T0 (void) 285 void OPPROTO op_movl_tlb_lo_T0 (void)
273 { 286 {
274 - int srs; 287 + uint32_t srs;
275 srs = env->pregs[PR_SRS]; 288 srs = env->pregs[PR_SRS];
276 if (srs == 1 || srs == 2) 289 if (srs == 1 || srs == 2)
277 { 290 {
278 - int set;  
279 - int idx; 291 + uint32_t set;
  292 + uint32_t idx;
280 uint32_t lo, hi; 293 uint32_t lo, hi;
281 294
282 idx = set = env->sregs[SFR_RW_MM_TLB_SEL]; 295 idx = set = env->sregs[SFR_RW_MM_TLB_SEL];
283 set >>= 4; 296 set >>= 4;
284 set &= 3; 297 set &= 3;
285 298
286 - idx &= 31; 299 + idx &= 15;
287 /* We've just made a write to tlb_lo. */ 300 /* We've just made a write to tlb_lo. */
288 lo = env->sregs[SFR_RW_MM_TLB_LO]; 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 env->tlbsets[srs - 1][set][idx].lo = lo; 304 env->tlbsets[srs - 1][set][idx].lo = lo;
291 env->tlbsets[srs - 1][set][idx].hi = hi; 305 env->tlbsets[srs - 1][set][idx].hi = hi;
292 } 306 }
293 -  
294 RETURN(); 307 RETURN();
295 } 308 }
296 309
target-cris/op_helper.c
@@ -21,6 +21,7 @@ @@ -21,6 +21,7 @@
21 21
22 #include <assert.h> 22 #include <assert.h>
23 #include "exec.h" 23 #include "exec.h"
  24 +#include "mmu.h"
24 25
25 #define MMUSUFFIX _mmu 26 #define MMUSUFFIX _mmu
26 #ifdef __s390__ 27 #ifdef __s390__
@@ -41,6 +42,8 @@ @@ -41,6 +42,8 @@
41 #define SHIFT 3 42 #define SHIFT 3
42 #include "softmmu_template.h" 43 #include "softmmu_template.h"
43 44
  45 +#define D(x)
  46 +
44 /* Try to fill the TLB and return an exception if error. If retaddr is 47 /* Try to fill the TLB and return an exception if error. If retaddr is
45 NULL, it means that the function was called in C code (i.e. not 48 NULL, it means that the function was called in C code (i.e. not
46 from generated code or from helper.c) */ 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,8 +76,20 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
73 env = saved_env; 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 void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, 90 void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
77 int is_asi) 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 }