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,8 +77,13 @@ static int get_physical_address (CPUState *env, target_ulong *physical, | ||
77 | int *prot, target_ulong address, | 77 | int *prot, target_ulong address, |
78 | int rw, int access_type) | 78 | int rw, int access_type) |
79 | { | 79 | { |
80 | - /* User mode can only access useg */ | 80 | + /* User mode can only access useg/xuseg */ |
81 | int user_mode = (env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM; | 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 | int ret = TLBRET_MATCH; | 87 | int ret = TLBRET_MATCH; |
83 | 88 | ||
84 | #if 0 | 89 | #if 0 |
@@ -87,10 +92,18 @@ static int get_physical_address (CPUState *env, target_ulong *physical, | @@ -87,10 +92,18 @@ static int get_physical_address (CPUState *env, target_ulong *physical, | ||
87 | user_mode, env->hflags); | 92 | user_mode, env->hflags); |
88 | } | 93 | } |
89 | #endif | 94 | #endif |
95 | + | ||
96 | +#ifdef TARGET_MIPS64 | ||
97 | + if (user_mode && address > 0x3FFFFFFFFFFFFFFFULL) | ||
98 | + return TLBRET_BADADDR; | ||
99 | +#else | ||
90 | if (user_mode && address > 0x7FFFFFFFUL) | 100 | if (user_mode && address > 0x7FFFFFFFUL) |
91 | return TLBRET_BADADDR; | 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 | #ifdef MIPS_USES_R4K_TLB | 107 | #ifdef MIPS_USES_R4K_TLB |
95 | ret = map_address(env, physical, prot, address, rw, access_type); | 108 | ret = map_address(env, physical, prot, address, rw, access_type); |
96 | #else | 109 | #else |
@@ -101,6 +114,45 @@ static int get_physical_address (CPUState *env, target_ulong *physical, | @@ -101,6 +114,45 @@ static int get_physical_address (CPUState *env, target_ulong *physical, | ||
101 | *physical = address; | 114 | *physical = address; |
102 | *prot = PAGE_READ | PAGE_WRITE; | 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 | } else if (address < (int32_t)0xA0000000UL) { | 156 | } else if (address < (int32_t)0xA0000000UL) { |
105 | /* kseg0 */ | 157 | /* kseg0 */ |
106 | /* XXX: check supervisor mode */ | 158 | /* XXX: check supervisor mode */ |
@@ -116,7 +168,7 @@ static int get_physical_address (CPUState *env, target_ulong *physical, | @@ -116,7 +168,7 @@ static int get_physical_address (CPUState *env, target_ulong *physical, | ||
116 | #ifdef MIPS_USES_R4K_TLB | 168 | #ifdef MIPS_USES_R4K_TLB |
117 | ret = map_address(env, physical, prot, address, rw, access_type); | 169 | ret = map_address(env, physical, prot, address, rw, access_type); |
118 | #else | 170 | #else |
119 | - *physical = address; | 171 | + *physical = address & 0xFFFFFFFF; |
120 | *prot = PAGE_READ | PAGE_WRITE; | 172 | *prot = PAGE_READ | PAGE_WRITE; |
121 | #endif | 173 | #endif |
122 | } else { | 174 | } else { |
@@ -126,7 +178,7 @@ static int get_physical_address (CPUState *env, target_ulong *physical, | @@ -126,7 +178,7 @@ static int get_physical_address (CPUState *env, target_ulong *physical, | ||
126 | #ifdef MIPS_USES_R4K_TLB | 178 | #ifdef MIPS_USES_R4K_TLB |
127 | ret = map_address(env, physical, prot, address, rw, access_type); | 179 | ret = map_address(env, physical, prot, address, rw, access_type); |
128 | #else | 180 | #else |
129 | - *physical = address; | 181 | + *physical = address & 0xFFFFFFFF; |
130 | *prot = PAGE_READ | PAGE_WRITE; | 182 | *prot = PAGE_READ | PAGE_WRITE; |
131 | #endif | 183 | #endif |
132 | } | 184 | } |