Sparc64 hypervisor mode

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3398 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
blueswir1 2007-10-14 17:07:21 +00:00
parent 952a328ff5
commit 6f27aba62e
4 changed files with 121 additions and 48 deletions

View File

@ -98,6 +98,8 @@
#define PS_AG (1<<0)
#define FPRS_FEF (1<<2)
#define HS_PRIV (1<<2)
#endif
/* Fcc */
@ -166,7 +168,11 @@
typedef struct sparc_def_t sparc_def_t;
#if !defined(TARGET_SPARC64)
#define NB_MMU_MODES 2
#else
#define NB_MMU_MODES 3
#endif
typedef struct CPUSPARCState {
target_ulong gregs[8]; /* general registers */
@ -323,12 +329,37 @@ void cpu_check_irqs(CPUSPARCState *env);
#define cpu_list sparc_cpu_list
/* MMU modes definitions */
#define MMU_MODE0_SUFFIX _kernel
#define MMU_MODE1_SUFFIX _user
#define MMU_USER_IDX 1
#define MMU_MODE0_SUFFIX _user
#define MMU_MODE1_SUFFIX _kernel
#ifdef TARGET_SPARC64
#define MMU_MODE2_SUFFIX _hypv
#endif
#define MMU_USER_IDX 0
static inline int cpu_mmu_index (CPUState *env)
{
return env->psrs == 0 ? 1 : 0;
#if defined(CONFIG_USER_ONLY)
return 0;
#elif !defined(TARGET_SPARC64)
return env->psrs;
#else
if (!env->psrs)
return 0;
else if ((env->hpstate & HS_PRIV) == 0)
return 1;
else
return 2;
#endif
}
static inline int cpu_fpu_enabled(CPUState *env)
{
#if defined(CONFIG_USER_ONLY)
return 1;
#elif !defined(TARGET_SPARC64)
return env->psref;
#else
return ((env->pstate & PS_PEF) != 0) && ((env->fprs & FPRS_FEF) != 0);
#endif
}
#include "cpu-all.h"

View File

@ -1023,6 +1023,11 @@ void OPPROTO op_sra(void)
#define MEMSUFFIX _kernel
#include "op_mem.h"
#ifdef TARGET_SPARC64
#define MEMSUFFIX _hypv
#include "op_mem.h"
#endif
#endif
void OPPROTO op_ldfsr(void)

View File

@ -789,7 +789,8 @@ void helper_ld_asi(int asi, int size, int sign)
{
uint64_t ret = 0;
if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
|| (asi >= 0x30 && asi < 0x80) && !(env->hpstate & HS_PRIV))
raise_exception(TT_PRIV_ACT);
switch (asi) {
@ -800,20 +801,38 @@ void helper_ld_asi(int asi, int size, int sign)
case 0x88: // Primary LE
case 0x8a: // Primary no-fault LE
if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
switch(size) {
case 1:
ret = ldub_kernel(T0);
break;
case 2:
ret = lduw_kernel(T0 & ~1);
break;
case 4:
ret = ldl_kernel(T0 & ~3);
break;
default:
case 8:
ret = ldq_kernel(T0 & ~7);
break;
if (env->hpstate & HS_PRIV) {
switch(size) {
case 1:
ret = ldub_hypv(T0);
break;
case 2:
ret = lduw_hypv(T0 & ~1);
break;
case 4:
ret = ldl_hypv(T0 & ~3);
break;
default:
case 8:
ret = ldq_hypv(T0 & ~7);
break;
}
} else {
switch(size) {
case 1:
ret = ldub_kernel(T0);
break;
case 2:
ret = lduw_kernel(T0 & ~1);
break;
case 4:
ret = ldl_kernel(T0 & ~3);
break;
default:
case 8:
ret = ldq_kernel(T0 & ~7);
break;
}
}
} else {
switch(size) {
@ -987,7 +1006,8 @@ void helper_ld_asi(int asi, int size, int sign)
void helper_st_asi(int asi, int size)
{
if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
|| (asi >= 0x30 && asi < 0x80) && !(env->hpstate & HS_PRIV))
raise_exception(TT_PRIV_ACT);
/* Convert to little endian */
@ -1022,20 +1042,38 @@ void helper_st_asi(int asi, int size)
case 0x80: // Primary
case 0x88: // Primary LE
if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
switch(size) {
case 1:
stb_kernel(T0, T1);
break;
case 2:
stw_kernel(T0 & ~1, T1);
break;
case 4:
stl_kernel(T0 & ~3, T1);
break;
case 8:
default:
stq_kernel(T0 & ~7, T1);
break;
if (env->hpstate & HS_PRIV) {
switch(size) {
case 1:
stb_hypv(T0, T1);
break;
case 2:
stw_hypv(T0 & ~1, T1);
break;
case 4:
stl_hypv(T0 & ~3, T1);
break;
case 8:
default:
stq_hypv(T0 & ~7, T1);
break;
}
} else {
switch(size) {
case 1:
stb_kernel(T0, T1);
break;
case 2:
stw_kernel(T0 & ~1, T1);
break;
case 4:
stl_kernel(T0 & ~3, T1);
break;
case 8:
default:
stq_kernel(T0 & ~7, T1);
break;
}
}
} else {
switch(size) {

View File

@ -361,17 +361,24 @@ GEN32(gen_op_store_DT1_fpr, gen_op_store_DT1_fpr_fprf);
#endif
#define gen_op_ldst(name) gen_op_##name##_raw()
#else
#define supervisor(dc) (dc->mem_idx == 1)
#define supervisor(dc) (dc->mem_idx >= 1)
#ifdef TARGET_SPARC64
#define hypervisor(dc) (dc->mem_idx == 2)
#endif
#define gen_op_ldst(name) (*gen_op_##name[dc->mem_idx])()
#define OP_LD_TABLE(width) \
static GenOpFunc * const gen_op_##width[] = { \
&gen_op_##width##_user, \
&gen_op_##width##_kernel, \
&gen_op_##width##_hypv, \
};
#else
#define OP_LD_TABLE(width) \
static GenOpFunc * const gen_op_##width[] = { \
&gen_op_##width##_user, \
&gen_op_##width##_kernel, \
};
#endif
#define gen_op_ldst(name) (*gen_op_##name[dc->mem_idx])()
#endif
#ifndef CONFIG_USER_ONLY
OP_LD_TABLE(ld);
@ -3378,17 +3385,8 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
dc->pc = pc_start;
last_pc = dc->pc;
dc->npc = (target_ulong) tb->cs_base;
#if defined(CONFIG_USER_ONLY)
dc->mem_idx = 0;
dc->fpu_enabled = 1;
#else
dc->mem_idx = ((env->psrs) != 0);
#ifdef TARGET_SPARC64
dc->fpu_enabled = (((env->pstate & PS_PEF) != 0) && ((env->fprs & FPRS_FEF) != 0));
#else
dc->fpu_enabled = ((env->psref) != 0);
#endif
#endif
dc->mem_idx = cpu_mmu_index(env);
dc->fpu_enabled = cpu_fpu_enabled(env);
gen_opc_ptr = gen_opc_buf;
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
gen_opparam_ptr = gen_opparam_buf;
@ -3522,6 +3520,7 @@ void cpu_reset(CPUSPARCState *env)
env->psrps = 1;
#ifdef TARGET_SPARC64
env->pstate = PS_PRIV;
env->hpstate = HS_PRIV;
env->pc = 0x1fff0000000ULL;
#else
env->pc = 0;