Commit b4ab4b4e1b8119ac1d9b28510d90682e30259c38
1 parent
a6763a58
Preliminary MIPS 64-bit MMU implementation, by Aurelien Jarno.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2794 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
57 additions
and
5 deletions
target-mips/helper.c
... | ... | @@ -77,8 +77,13 @@ static int get_physical_address (CPUState *env, target_ulong *physical, |
77 | 77 | int *prot, target_ulong address, |
78 | 78 | int rw, int access_type) |
79 | 79 | { |
80 | - /* User mode can only access useg */ | |
80 | + /* User mode can only access useg/xuseg */ | |
81 | 81 | int user_mode = (env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM; |
82 | +#ifdef TARGET_MIPS64 | |
83 | + int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0; | |
84 | + int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0; | |
85 | + int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0; | |
86 | +#endif | |
82 | 87 | int ret = TLBRET_MATCH; |
83 | 88 | |
84 | 89 | #if 0 |
... | ... | @@ -87,10 +92,18 @@ static int get_physical_address (CPUState *env, target_ulong *physical, |
87 | 92 | user_mode, env->hflags); |
88 | 93 | } |
89 | 94 | #endif |
95 | + | |
96 | +#ifdef TARGET_MIPS64 | |
97 | + if (user_mode && address > 0x3FFFFFFFFFFFFFFFULL) | |
98 | + return TLBRET_BADADDR; | |
99 | +#else | |
90 | 100 | if (user_mode && address > 0x7FFFFFFFUL) |
91 | 101 | return TLBRET_BADADDR; |
92 | - if (address < (int32_t)0x80000000UL) { | |
93 | - if (!(env->CP0_Status & (1 << CP0St_ERL))) { | |
102 | +#endif | |
103 | + | |
104 | + if (address <= (int32_t)0x7FFFFFFFUL) { | |
105 | + /* useg */ | |
106 | + if (!(env->CP0_Status & (1 << CP0St_ERL) && user_mode)) { | |
94 | 107 | #ifdef MIPS_USES_R4K_TLB |
95 | 108 | ret = map_address(env, physical, prot, address, rw, access_type); |
96 | 109 | #else |
... | ... | @@ -101,6 +114,45 @@ static int get_physical_address (CPUState *env, target_ulong *physical, |
101 | 114 | *physical = address; |
102 | 115 | *prot = PAGE_READ | PAGE_WRITE; |
103 | 116 | } |
117 | +#ifdef TARGET_MIPS64 | |
118 | +/* | |
119 | + XXX: Assuming : | |
120 | + - PABITS = 36 (correct for MIPS64R1) | |
121 | + - SEGBITS = 40 | |
122 | +*/ | |
123 | + } else if (address < 0x3FFFFFFFFFFFFFFFULL) { | |
124 | + /* xuseg */ | |
125 | + if (UX && address < 0x000000FFFFFFFFFFULL) { | |
126 | + ret = map_address(env, physical, prot, address, rw, access_type); | |
127 | + } else { | |
128 | + ret = TLBRET_BADADDR; | |
129 | + } | |
130 | + } else if (address < 0x7FFFFFFFFFFFFFFFULL) { | |
131 | + /* xsseg */ | |
132 | + if (SX && address < 0x400000FFFFFFFFFFULL) { | |
133 | + ret = map_address(env, physical, prot, address, rw, access_type); | |
134 | + } else { | |
135 | + ret = TLBRET_BADADDR; | |
136 | + } | |
137 | + } else if (address < 0xBFFFFFFFFFFFFFFFULL) { | |
138 | + /* xkphys */ | |
139 | + /* XXX: check supervisor mode */ | |
140 | + if (KX && (address & 0x03FFFFFFFFFFFFFFULL) < 0X0000000FFFFFFFFFULL) | |
141 | + { | |
142 | + *physical = address & 0X000000FFFFFFFFFFULL; | |
143 | + *prot = PAGE_READ | PAGE_WRITE; | |
144 | + } else { | |
145 | + ret = TLBRET_BADADDR; | |
146 | + } | |
147 | + } else if (address < 0xFFFFFFFF7FFFFFFFULL) { | |
148 | + /* xkseg */ | |
149 | + /* XXX: check supervisor mode */ | |
150 | + if (KX && address < 0xC00000FF7FFFFFFFULL) { | |
151 | + ret = map_address(env, physical, prot, address, rw, access_type); | |
152 | + } else { | |
153 | + ret = TLBRET_BADADDR; | |
154 | + } | |
155 | +#endif | |
104 | 156 | } else if (address < (int32_t)0xA0000000UL) { |
105 | 157 | /* kseg0 */ |
106 | 158 | /* XXX: check supervisor mode */ |
... | ... | @@ -116,7 +168,7 @@ static int get_physical_address (CPUState *env, target_ulong *physical, |
116 | 168 | #ifdef MIPS_USES_R4K_TLB |
117 | 169 | ret = map_address(env, physical, prot, address, rw, access_type); |
118 | 170 | #else |
119 | - *physical = address; | |
171 | + *physical = address & 0xFFFFFFFF; | |
120 | 172 | *prot = PAGE_READ | PAGE_WRITE; |
121 | 173 | #endif |
122 | 174 | } else { |
... | ... | @@ -126,7 +178,7 @@ static int get_physical_address (CPUState *env, target_ulong *physical, |
126 | 178 | #ifdef MIPS_USES_R4K_TLB |
127 | 179 | ret = map_address(env, physical, prot, address, rw, access_type); |
128 | 180 | #else |
129 | - *physical = address; | |
181 | + *physical = address & 0xFFFFFFFF; | |
130 | 182 | *prot = PAGE_READ | PAGE_WRITE; |
131 | 183 | #endif |
132 | 184 | } | ... | ... |