Commit b4ab4b4e1b8119ac1d9b28510d90682e30259c38

Authored by ths
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 }