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 | } |