Sparc64 hypervisor mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3398 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
952a328ff5
commit
6f27aba62e
@ -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"
|
||||
|
@ -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)
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user