Commit 6f27aba62e90b382d3d8e35e6d72046470c270a8
1 parent
952a328f
Sparc64 hypervisor mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3398 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
121 additions
and
48 deletions
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; | ... | ... |