Commit 6f27aba62e90b382d3d8e35e6d72046470c270a8

Authored by blueswir1
1 parent 952a328f

Sparc64 hypervisor mode


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3398 c046a42c-6fe2-441c-8c8c-71466251a162
target-sparc/cpu.h
@@ -98,6 +98,8 @@ @@ -98,6 +98,8 @@
98 #define PS_AG (1<<0) 98 #define PS_AG (1<<0)
99 99
100 #define FPRS_FEF (1<<2) 100 #define FPRS_FEF (1<<2)
  101 +
  102 +#define HS_PRIV (1<<2)
101 #endif 103 #endif
102 104
103 /* Fcc */ 105 /* Fcc */
@@ -166,7 +168,11 @@ @@ -166,7 +168,11 @@
166 168
167 typedef struct sparc_def_t sparc_def_t; 169 typedef struct sparc_def_t sparc_def_t;
168 170
  171 +#if !defined(TARGET_SPARC64)
169 #define NB_MMU_MODES 2 172 #define NB_MMU_MODES 2
  173 +#else
  174 +#define NB_MMU_MODES 3
  175 +#endif
170 176
171 typedef struct CPUSPARCState { 177 typedef struct CPUSPARCState {
172 target_ulong gregs[8]; /* general registers */ 178 target_ulong gregs[8]; /* general registers */
@@ -323,12 +329,37 @@ void cpu_check_irqs(CPUSPARCState *env); @@ -323,12 +329,37 @@ void cpu_check_irqs(CPUSPARCState *env);
323 #define cpu_list sparc_cpu_list 329 #define cpu_list sparc_cpu_list
324 330
325 /* MMU modes definitions */ 331 /* MMU modes definitions */
326 -#define MMU_MODE0_SUFFIX _kernel  
327 -#define MMU_MODE1_SUFFIX _user  
328 -#define MMU_USER_IDX 1 332 +#define MMU_MODE0_SUFFIX _user
  333 +#define MMU_MODE1_SUFFIX _kernel
  334 +#ifdef TARGET_SPARC64
  335 +#define MMU_MODE2_SUFFIX _hypv
  336 +#endif
  337 +#define MMU_USER_IDX 0
329 static inline int cpu_mmu_index (CPUState *env) 338 static inline int cpu_mmu_index (CPUState *env)
330 { 339 {
331 - return env->psrs == 0 ? 1 : 0; 340 +#if defined(CONFIG_USER_ONLY)
  341 + return 0;
  342 +#elif !defined(TARGET_SPARC64)
  343 + return env->psrs;
  344 +#else
  345 + if (!env->psrs)
  346 + return 0;
  347 + else if ((env->hpstate & HS_PRIV) == 0)
  348 + return 1;
  349 + else
  350 + return 2;
  351 +#endif
  352 +}
  353 +
  354 +static inline int cpu_fpu_enabled(CPUState *env)
  355 +{
  356 +#if defined(CONFIG_USER_ONLY)
  357 + return 1;
  358 +#elif !defined(TARGET_SPARC64)
  359 + return env->psref;
  360 +#else
  361 + return ((env->pstate & PS_PEF) != 0) && ((env->fprs & FPRS_FEF) != 0);
  362 +#endif
332 } 363 }
333 364
334 #include "cpu-all.h" 365 #include "cpu-all.h"
target-sparc/op.c
@@ -1023,6 +1023,11 @@ void OPPROTO op_sra(void) @@ -1023,6 +1023,11 @@ void OPPROTO op_sra(void)
1023 1023
1024 #define MEMSUFFIX _kernel 1024 #define MEMSUFFIX _kernel
1025 #include "op_mem.h" 1025 #include "op_mem.h"
  1026 +
  1027 +#ifdef TARGET_SPARC64
  1028 +#define MEMSUFFIX _hypv
  1029 +#include "op_mem.h"
  1030 +#endif
1026 #endif 1031 #endif
1027 1032
1028 void OPPROTO op_ldfsr(void) 1033 void OPPROTO op_ldfsr(void)
target-sparc/op_helper.c
@@ -789,7 +789,8 @@ void helper_ld_asi(int asi, int size, int sign) @@ -789,7 +789,8 @@ void helper_ld_asi(int asi, int size, int sign)
789 { 789 {
790 uint64_t ret = 0; 790 uint64_t ret = 0;
791 791
792 - if (asi < 0x80 && (env->pstate & PS_PRIV) == 0) 792 + if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
  793 + || (asi >= 0x30 && asi < 0x80) && !(env->hpstate & HS_PRIV))
793 raise_exception(TT_PRIV_ACT); 794 raise_exception(TT_PRIV_ACT);
794 795
795 switch (asi) { 796 switch (asi) {
@@ -800,20 +801,38 @@ void helper_ld_asi(int asi, int size, int sign) @@ -800,20 +801,38 @@ void helper_ld_asi(int asi, int size, int sign)
800 case 0x88: // Primary LE 801 case 0x88: // Primary LE
801 case 0x8a: // Primary no-fault LE 802 case 0x8a: // Primary no-fault LE
802 if ((asi & 0x80) && (env->pstate & PS_PRIV)) { 803 if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
803 - switch(size) {  
804 - case 1:  
805 - ret = ldub_kernel(T0);  
806 - break;  
807 - case 2:  
808 - ret = lduw_kernel(T0 & ~1);  
809 - break;  
810 - case 4:  
811 - ret = ldl_kernel(T0 & ~3);  
812 - break;  
813 - default:  
814 - case 8:  
815 - ret = ldq_kernel(T0 & ~7);  
816 - break; 804 + if (env->hpstate & HS_PRIV) {
  805 + switch(size) {
  806 + case 1:
  807 + ret = ldub_hypv(T0);
  808 + break;
  809 + case 2:
  810 + ret = lduw_hypv(T0 & ~1);
  811 + break;
  812 + case 4:
  813 + ret = ldl_hypv(T0 & ~3);
  814 + break;
  815 + default:
  816 + case 8:
  817 + ret = ldq_hypv(T0 & ~7);
  818 + break;
  819 + }
  820 + } else {
  821 + switch(size) {
  822 + case 1:
  823 + ret = ldub_kernel(T0);
  824 + break;
  825 + case 2:
  826 + ret = lduw_kernel(T0 & ~1);
  827 + break;
  828 + case 4:
  829 + ret = ldl_kernel(T0 & ~3);
  830 + break;
  831 + default:
  832 + case 8:
  833 + ret = ldq_kernel(T0 & ~7);
  834 + break;
  835 + }
817 } 836 }
818 } else { 837 } else {
819 switch(size) { 838 switch(size) {
@@ -987,7 +1006,8 @@ void helper_ld_asi(int asi, int size, int sign) @@ -987,7 +1006,8 @@ void helper_ld_asi(int asi, int size, int sign)
987 1006
988 void helper_st_asi(int asi, int size) 1007 void helper_st_asi(int asi, int size)
989 { 1008 {
990 - if (asi < 0x80 && (env->pstate & PS_PRIV) == 0) 1009 + if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
  1010 + || (asi >= 0x30 && asi < 0x80) && !(env->hpstate & HS_PRIV))
991 raise_exception(TT_PRIV_ACT); 1011 raise_exception(TT_PRIV_ACT);
992 1012
993 /* Convert to little endian */ 1013 /* Convert to little endian */
@@ -1022,20 +1042,38 @@ void helper_st_asi(int asi, int size) @@ -1022,20 +1042,38 @@ void helper_st_asi(int asi, int size)
1022 case 0x80: // Primary 1042 case 0x80: // Primary
1023 case 0x88: // Primary LE 1043 case 0x88: // Primary LE
1024 if ((asi & 0x80) && (env->pstate & PS_PRIV)) { 1044 if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
1025 - switch(size) {  
1026 - case 1:  
1027 - stb_kernel(T0, T1);  
1028 - break;  
1029 - case 2:  
1030 - stw_kernel(T0 & ~1, T1);  
1031 - break;  
1032 - case 4:  
1033 - stl_kernel(T0 & ~3, T1);  
1034 - break;  
1035 - case 8:  
1036 - default:  
1037 - stq_kernel(T0 & ~7, T1);  
1038 - break; 1045 + if (env->hpstate & HS_PRIV) {
  1046 + switch(size) {
  1047 + case 1:
  1048 + stb_hypv(T0, T1);
  1049 + break;
  1050 + case 2:
  1051 + stw_hypv(T0 & ~1, T1);
  1052 + break;
  1053 + case 4:
  1054 + stl_hypv(T0 & ~3, T1);
  1055 + break;
  1056 + case 8:
  1057 + default:
  1058 + stq_hypv(T0 & ~7, T1);
  1059 + break;
  1060 + }
  1061 + } else {
  1062 + switch(size) {
  1063 + case 1:
  1064 + stb_kernel(T0, T1);
  1065 + break;
  1066 + case 2:
  1067 + stw_kernel(T0 & ~1, T1);
  1068 + break;
  1069 + case 4:
  1070 + stl_kernel(T0 & ~3, T1);
  1071 + break;
  1072 + case 8:
  1073 + default:
  1074 + stq_kernel(T0 & ~7, T1);
  1075 + break;
  1076 + }
1039 } 1077 }
1040 } else { 1078 } else {
1041 switch(size) { 1079 switch(size) {
target-sparc/translate.c
@@ -361,17 +361,24 @@ GEN32(gen_op_store_DT1_fpr, gen_op_store_DT1_fpr_fprf); @@ -361,17 +361,24 @@ GEN32(gen_op_store_DT1_fpr, gen_op_store_DT1_fpr_fprf);
361 #endif 361 #endif
362 #define gen_op_ldst(name) gen_op_##name##_raw() 362 #define gen_op_ldst(name) gen_op_##name##_raw()
363 #else 363 #else
364 -#define supervisor(dc) (dc->mem_idx == 1) 364 +#define supervisor(dc) (dc->mem_idx >= 1)
365 #ifdef TARGET_SPARC64 365 #ifdef TARGET_SPARC64
366 #define hypervisor(dc) (dc->mem_idx == 2) 366 #define hypervisor(dc) (dc->mem_idx == 2)
367 -#endif  
368 -#define gen_op_ldst(name) (*gen_op_##name[dc->mem_idx])() 367 +#define OP_LD_TABLE(width) \
  368 + static GenOpFunc * const gen_op_##width[] = { \
  369 + &gen_op_##width##_user, \
  370 + &gen_op_##width##_kernel, \
  371 + &gen_op_##width##_hypv, \
  372 + };
  373 +#else
369 #define OP_LD_TABLE(width) \ 374 #define OP_LD_TABLE(width) \
370 static GenOpFunc * const gen_op_##width[] = { \ 375 static GenOpFunc * const gen_op_##width[] = { \
371 &gen_op_##width##_user, \ 376 &gen_op_##width##_user, \
372 &gen_op_##width##_kernel, \ 377 &gen_op_##width##_kernel, \
373 }; 378 };
374 #endif 379 #endif
  380 +#define gen_op_ldst(name) (*gen_op_##name[dc->mem_idx])()
  381 +#endif
375 382
376 #ifndef CONFIG_USER_ONLY 383 #ifndef CONFIG_USER_ONLY
377 OP_LD_TABLE(ld); 384 OP_LD_TABLE(ld);
@@ -3378,17 +3385,8 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb, @@ -3378,17 +3385,8 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
3378 dc->pc = pc_start; 3385 dc->pc = pc_start;
3379 last_pc = dc->pc; 3386 last_pc = dc->pc;
3380 dc->npc = (target_ulong) tb->cs_base; 3387 dc->npc = (target_ulong) tb->cs_base;
3381 -#if defined(CONFIG_USER_ONLY)  
3382 - dc->mem_idx = 0;  
3383 - dc->fpu_enabled = 1;  
3384 -#else  
3385 - dc->mem_idx = ((env->psrs) != 0);  
3386 -#ifdef TARGET_SPARC64  
3387 - dc->fpu_enabled = (((env->pstate & PS_PEF) != 0) && ((env->fprs & FPRS_FEF) != 0));  
3388 -#else  
3389 - dc->fpu_enabled = ((env->psref) != 0);  
3390 -#endif  
3391 -#endif 3388 + dc->mem_idx = cpu_mmu_index(env);
  3389 + dc->fpu_enabled = cpu_fpu_enabled(env);
3392 gen_opc_ptr = gen_opc_buf; 3390 gen_opc_ptr = gen_opc_buf;
3393 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; 3391 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
3394 gen_opparam_ptr = gen_opparam_buf; 3392 gen_opparam_ptr = gen_opparam_buf;
@@ -3522,6 +3520,7 @@ void cpu_reset(CPUSPARCState *env) @@ -3522,6 +3520,7 @@ void cpu_reset(CPUSPARCState *env)
3522 env->psrps = 1; 3520 env->psrps = 1;
3523 #ifdef TARGET_SPARC64 3521 #ifdef TARGET_SPARC64
3524 env->pstate = PS_PRIV; 3522 env->pstate = PS_PRIV;
  3523 + env->hpstate = HS_PRIV;
3525 env->pc = 0x1fff0000000ULL; 3524 env->pc = 0x1fff0000000ULL;
3526 #else 3525 #else
3527 env->pc = 0; 3526 env->pc = 0;