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 98 #define PS_AG (1<<0)
99 99  
100 100 #define FPRS_FEF (1<<2)
  101 +
  102 +#define HS_PRIV (1<<2)
101 103 #endif
102 104  
103 105 /* Fcc */
... ... @@ -166,7 +168,11 @@
166 168  
167 169 typedef struct sparc_def_t sparc_def_t;
168 170  
  171 +#if !defined(TARGET_SPARC64)
169 172 #define NB_MMU_MODES 2
  173 +#else
  174 +#define NB_MMU_MODES 3
  175 +#endif
170 176  
171 177 typedef struct CPUSPARCState {
172 178 target_ulong gregs[8]; /* general registers */
... ... @@ -323,12 +329,37 @@ void cpu_check_irqs(CPUSPARCState *env);
323 329 #define cpu_list sparc_cpu_list
324 330  
325 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 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 365 #include "cpu-all.h"
... ...
target-sparc/op.c
... ... @@ -1023,6 +1023,11 @@ void OPPROTO op_sra(void)
1023 1023  
1024 1024 #define MEMSUFFIX _kernel
1025 1025 #include "op_mem.h"
  1026 +
  1027 +#ifdef TARGET_SPARC64
  1028 +#define MEMSUFFIX _hypv
  1029 +#include "op_mem.h"
  1030 +#endif
1026 1031 #endif
1027 1032  
1028 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 789 {
790 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 794 raise_exception(TT_PRIV_ACT);
794 795  
795 796 switch (asi) {
... ... @@ -800,20 +801,38 @@ void helper_ld_asi(int asi, int size, int sign)
800 801 case 0x88: // Primary LE
801 802 case 0x8a: // Primary no-fault LE
802 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 837 } else {
819 838 switch(size) {
... ... @@ -987,7 +1006,8 @@ void helper_ld_asi(int asi, int size, int sign)
987 1006  
988 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 1011 raise_exception(TT_PRIV_ACT);
992 1012  
993 1013 /* Convert to little endian */
... ... @@ -1022,20 +1042,38 @@ void helper_st_asi(int asi, int size)
1022 1042 case 0x80: // Primary
1023 1043 case 0x88: // Primary LE
1024 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 1078 } else {
1041 1079 switch(size) {
... ...
target-sparc/translate.c
... ... @@ -361,17 +361,24 @@ GEN32(gen_op_store_DT1_fpr, gen_op_store_DT1_fpr_fprf);
361 361 #endif
362 362 #define gen_op_ldst(name) gen_op_##name##_raw()
363 363 #else
364   -#define supervisor(dc) (dc->mem_idx == 1)
  364 +#define supervisor(dc) (dc->mem_idx >= 1)
365 365 #ifdef TARGET_SPARC64
366 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 374 #define OP_LD_TABLE(width) \
370 375 static GenOpFunc * const gen_op_##width[] = { \
371 376 &gen_op_##width##_user, \
372 377 &gen_op_##width##_kernel, \
373 378 };
374 379 #endif
  380 +#define gen_op_ldst(name) (*gen_op_##name[dc->mem_idx])()
  381 +#endif
375 382  
376 383 #ifndef CONFIG_USER_ONLY
377 384 OP_LD_TABLE(ld);
... ... @@ -3378,17 +3385,8 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
3378 3385 dc->pc = pc_start;
3379 3386 last_pc = dc->pc;
3380 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 3390 gen_opc_ptr = gen_opc_buf;
3393 3391 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
3394 3392 gen_opparam_ptr = gen_opparam_buf;
... ... @@ -3522,6 +3520,7 @@ void cpu_reset(CPUSPARCState *env)
3522 3520 env->psrps = 1;
3523 3521 #ifdef TARGET_SPARC64
3524 3522 env->pstate = PS_PRIV;
  3523 + env->hpstate = HS_PRIV;
3525 3524 env->pc = 0x1fff0000000ULL;
3526 3525 #else
3527 3526 env->pc = 0;
... ...