target-arm: A64: Emulate the HVC insn
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> Message-id: 1411718914-6608-8-git-send-email-edgar.iglesias@gmail.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
		
							parent
							
								
									2dd081ae76
								
							
						
					
					
						commit
						35979d71c4
					
				@ -51,6 +51,7 @@
 | 
			
		||||
#define EXCP_EXCEPTION_EXIT  8   /* Return from v7M exception.  */
 | 
			
		||||
#define EXCP_KERNEL_TRAP     9   /* Jumped to kernel code page.  */
 | 
			
		||||
#define EXCP_STREX          10
 | 
			
		||||
#define EXCP_HVC            11   /* HyperVisor Call */
 | 
			
		||||
 | 
			
		||||
#define ARMV7M_EXCP_RESET   1
 | 
			
		||||
#define ARMV7M_EXCP_NMI     2
 | 
			
		||||
 | 
			
		||||
@ -476,6 +476,7 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
 | 
			
		||||
    case EXCP_BKPT:
 | 
			
		||||
    case EXCP_UDEF:
 | 
			
		||||
    case EXCP_SWI:
 | 
			
		||||
    case EXCP_HVC:
 | 
			
		||||
        env->cp15.esr_el[new_el] = env->exception.syndrome;
 | 
			
		||||
        break;
 | 
			
		||||
    case EXCP_IRQ:
 | 
			
		||||
 | 
			
		||||
@ -3769,9 +3769,27 @@ void switch_mode(CPUARMState *env, int mode)
 | 
			
		||||
 */
 | 
			
		||||
unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx)
 | 
			
		||||
{
 | 
			
		||||
    ARMCPU *cpu = ARM_CPU(cs);
 | 
			
		||||
    CPUARMState *env = &cpu->env;
 | 
			
		||||
    unsigned int cur_el = arm_current_pl(env);
 | 
			
		||||
    unsigned int target_el;
 | 
			
		||||
 | 
			
		||||
    if (!env->aarch64) {
 | 
			
		||||
        /* TODO: Add EL2 and 3 exception handling for AArch32.  */
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    switch (excp_idx) {
 | 
			
		||||
    case EXCP_HVC:
 | 
			
		||||
        target_el = 2;
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        target_el = MAX(cur_el, 1);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    return target_el;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void v7m_push(CPUARMState *env, uint32_t val)
 | 
			
		||||
{
 | 
			
		||||
    CPUState *cs = CPU(arm_env_get_cpu(env));
 | 
			
		||||
 | 
			
		||||
@ -50,6 +50,7 @@ DEF_HELPER_2(exception_internal, void, env, i32)
 | 
			
		||||
DEF_HELPER_3(exception_with_syndrome, void, env, i32, i32)
 | 
			
		||||
DEF_HELPER_1(wfi, void, env)
 | 
			
		||||
DEF_HELPER_1(wfe, void, env)
 | 
			
		||||
DEF_HELPER_1(pre_hvc, void, env)
 | 
			
		||||
 | 
			
		||||
DEF_HELPER_3(cpsr_write, void, env, i32, i32)
 | 
			
		||||
DEF_HELPER_1(cpsr_read, i32, env)
 | 
			
		||||
 | 
			
		||||
@ -53,6 +53,7 @@ static const char * const excnames[] = {
 | 
			
		||||
    [EXCP_EXCEPTION_EXIT] = "QEMU v7M exception exit",
 | 
			
		||||
    [EXCP_KERNEL_TRAP] = "QEMU intercept of kernel commpage",
 | 
			
		||||
    [EXCP_STREX] = "QEMU intercept of STREX",
 | 
			
		||||
    [EXCP_HVC] = "Hypervisor Call",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static inline void arm_log_exception(int idx)
 | 
			
		||||
@ -215,6 +216,11 @@ static inline uint32_t syn_aa64_svc(uint32_t imm16)
 | 
			
		||||
    return (EC_AA64_SVC << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline uint32_t syn_aa64_hvc(uint32_t imm16)
 | 
			
		||||
{
 | 
			
		||||
    return (EC_AA64_HVC << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline uint32_t syn_aa32_svc(uint32_t imm16, bool is_thumb)
 | 
			
		||||
{
 | 
			
		||||
    return (EC_AA32_SVC << ARM_EL_EC_SHIFT) | (imm16 & 0xffff)
 | 
			
		||||
 | 
			
		||||
@ -385,6 +385,37 @@ void HELPER(clear_pstate_ss)(CPUARMState *env)
 | 
			
		||||
    env->pstate &= ~PSTATE_SS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HELPER(pre_hvc)(CPUARMState *env)
 | 
			
		||||
{
 | 
			
		||||
    int cur_el = arm_current_pl(env);
 | 
			
		||||
    /* FIXME: Use actual secure state.  */
 | 
			
		||||
    bool secure = false;
 | 
			
		||||
    bool undef;
 | 
			
		||||
 | 
			
		||||
    /* We've already checked that EL2 exists at translation time.
 | 
			
		||||
     * EL3.HCE has priority over EL2.HCD.
 | 
			
		||||
     */
 | 
			
		||||
    if (arm_feature(env, ARM_FEATURE_EL3)) {
 | 
			
		||||
        undef = !(env->cp15.scr_el3 & SCR_HCE);
 | 
			
		||||
    } else {
 | 
			
		||||
        undef = env->cp15.hcr_el2 & HCR_HCD;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* In ARMv7 and ARMv8/AArch32, HVC is undef in secure state.
 | 
			
		||||
     * For ARMv8/AArch64, HVC is allowed in EL3.
 | 
			
		||||
     * Note that we've already trapped HVC from EL0 at translation
 | 
			
		||||
     * time.
 | 
			
		||||
     */
 | 
			
		||||
    if (secure && (!is_a64(env) || cur_el == 1)) {
 | 
			
		||||
        undef = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (undef) {
 | 
			
		||||
        env->exception.syndrome = syn_uncategorized();
 | 
			
		||||
        raise_exception(env, EXCP_UDEF);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HELPER(exception_return)(CPUARMState *env)
 | 
			
		||||
{
 | 
			
		||||
    int cur_el = arm_current_pl(env);
 | 
			
		||||
 | 
			
		||||
@ -1473,21 +1473,34 @@ static void disas_exc(DisasContext *s, uint32_t insn)
 | 
			
		||||
 | 
			
		||||
    switch (opc) {
 | 
			
		||||
    case 0:
 | 
			
		||||
        /* SVC, HVC, SMC; since we don't support the Virtualization
 | 
			
		||||
         * or TrustZone extensions these all UNDEF except SVC.
 | 
			
		||||
         */
 | 
			
		||||
        if (op2_ll != 1) {
 | 
			
		||||
            unallocated_encoding(s);
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        /* For SVC, HVC and SMC we advance the single-step state
 | 
			
		||||
         * machine before taking the exception. This is architecturally
 | 
			
		||||
         * mandated, to ensure that single-stepping a system call
 | 
			
		||||
         * instruction works properly.
 | 
			
		||||
         */
 | 
			
		||||
        switch (op2_ll) {
 | 
			
		||||
        case 1:
 | 
			
		||||
            gen_ss_advance(s);
 | 
			
		||||
            gen_exception_insn(s, 0, EXCP_SWI, syn_aa64_svc(imm16));
 | 
			
		||||
            break;
 | 
			
		||||
        case 2:
 | 
			
		||||
            if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_pl == 0) {
 | 
			
		||||
                unallocated_encoding(s);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            /* The pre HVC helper handles cases when HVC gets trapped
 | 
			
		||||
             * as an undefined insn by runtime configuration.
 | 
			
		||||
             */
 | 
			
		||||
            gen_a64_set_pc_im(s->pc - 4);
 | 
			
		||||
            gen_helper_pre_hvc(cpu_env);
 | 
			
		||||
            gen_ss_advance(s);
 | 
			
		||||
            gen_exception_insn(s, 0, EXCP_HVC, syn_aa64_hvc(imm16));
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            unallocated_encoding(s);
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case 1:
 | 
			
		||||
        if (op2_ll != 0) {
 | 
			
		||||
            unallocated_encoding(s);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user