mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
arch: arm64: always set IL=1 when injecting undefined exception
ARM Architecture Reference Manual states that IL field of ESR_EL1 register should be 1 when EC is 0b000000 aka HSR_EC_UNKNOWN. Section D24.2.40, page D24-7337 of ARM DDI 0487L: IL, bit [25] Instruction Length for synchronous exceptions. Possible values of this bit are: [...] 0b1 - 32-bit instruction trapped. This value is also used when the exception is one of the following: [...] - An exception reported using EC value 0b000000. To align code with the specification, set .len field to 1 in inject_undef64_exception() and remove unneeded second parameter. Signed-off-by: Volodymyr Babchuk <volodymyr_babchuk@epam.com> Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
This commit is contained in:
1 parent
0207fee58d
commit
9480d48437
8 files changed
+37
-41
No files matched your search
@@ -95,7 +95,7 @@ void do_sysreg(struct cpu_user_regs *regs,
|
||||
*/
|
||||
case HSR_SYSREG_ACTLR_EL1:
|
||||
if ( regs_mode_is_user(regs) )
|
||||
return inject_undef_exception(regs, hsr);
|
||||
return inject_undef_exception(regs);
|
||||
if ( hsr.sysreg.read )
|
||||
set_user_reg(regs, regidx, v->arch.actlr);
|
||||
break;
|
||||
@@ -109,7 +109,7 @@ void do_sysreg(struct cpu_user_regs *regs,
|
||||
case HSR_SYSREG_DCCSW:
|
||||
case HSR_SYSREG_DCCISW:
|
||||
if ( !hsr.sysreg.read )
|
||||
p2m_set_way_flush(current, regs, hsr);
|
||||
p2m_set_way_flush(current, regs);
|
||||
break;
|
||||
|
||||
/*
|
||||
@@ -267,7 +267,7 @@ void do_sysreg(struct cpu_user_regs *regs,
|
||||
case HSR_SYSREG_CNTP_TVAL_EL0:
|
||||
case HSR_SYSREG_CNTP_CVAL_EL0:
|
||||
if ( !vtimer_emulate(regs, hsr) )
|
||||
return inject_undef_exception(regs, hsr);
|
||||
return inject_undef_exception(regs);
|
||||
break;
|
||||
|
||||
/*
|
||||
@@ -280,7 +280,7 @@ void do_sysreg(struct cpu_user_regs *regs,
|
||||
case HSR_SYSREG_ICC_SGI0R_EL1:
|
||||
|
||||
if ( !vgic_emulate(regs, hsr) )
|
||||
return inject_undef64_exception(regs, hsr.len);
|
||||
return inject_undef64_exception(regs);
|
||||
break;
|
||||
|
||||
/*
|
||||
@@ -440,7 +440,7 @@ void do_sysreg(struct cpu_user_regs *regs,
|
||||
gdprintk(XENLOG_ERR,
|
||||
"unhandled 64-bit sysreg access %#"PRIregister"\n",
|
||||
hsr.bits & HSR_SYSREG_REGS_MASK);
|
||||
inject_undef_exception(regs, hsr);
|
||||
inject_undef_exception(regs);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __ASM_ARM64_TRAPS__
|
||||
#define __ASM_ARM64_TRAPS__
|
||||
|
||||
void inject_undef64_exception(struct cpu_user_regs *regs, int instr_len);
|
||||
void inject_undef64_exception(struct cpu_user_regs *regs);
|
||||
|
||||
void do_sysreg(struct cpu_user_regs *regs,
|
||||
const union hsr hsr);
|
||||
|
||||
@@ -298,8 +298,7 @@ void p2m_domain_creation_finished(struct domain *d);
|
||||
*/
|
||||
int p2m_cache_flush_range(struct domain *d, gfn_t *pstart, gfn_t end);
|
||||
|
||||
void p2m_set_way_flush(struct vcpu *v, struct cpu_user_regs *regs,
|
||||
const union hsr hsr);
|
||||
void p2m_set_way_flush(struct vcpu *v, struct cpu_user_regs *regs);
|
||||
|
||||
void p2m_toggle_cache(struct vcpu *v, bool was_enabled);
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ int check_conditional_instr(struct cpu_user_regs *regs, const union hsr hsr);
|
||||
|
||||
void advance_pc(struct cpu_user_regs *regs, const union hsr hsr);
|
||||
|
||||
void inject_undef_exception(struct cpu_user_regs *regs, const union hsr hsr);
|
||||
void inject_undef_exception(struct cpu_user_regs *regs);
|
||||
|
||||
/* read as zero and write ignore */
|
||||
void handle_raz_wi(struct cpu_user_regs *regs, int regidx, bool read,
|
||||
|
||||
+2
-3
@@ -428,8 +428,7 @@ int p2m_cache_flush_range(struct domain *d, gfn_t *pstart, gfn_t end)
|
||||
*
|
||||
* - Once the caches are enabled, we stop trapping VM ops.
|
||||
*/
|
||||
void p2m_set_way_flush(struct vcpu *v, struct cpu_user_regs *regs,
|
||||
const union hsr hsr)
|
||||
void p2m_set_way_flush(struct vcpu *v, struct cpu_user_regs *regs)
|
||||
{
|
||||
/* This function can only work with the current vCPU. */
|
||||
ASSERT(v == current);
|
||||
@@ -438,7 +437,7 @@ void p2m_set_way_flush(struct vcpu *v, struct cpu_user_regs *regs,
|
||||
{
|
||||
gprintk(XENLOG_ERR,
|
||||
"The cache should be flushed by VA rather than by set/way.\n");
|
||||
inject_undef_exception(regs, hsr);
|
||||
inject_undef_exception(regs);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+12
-12
@@ -533,12 +533,12 @@ static vaddr_t exception_handler64(struct cpu_user_regs *regs, vaddr_t offset)
|
||||
}
|
||||
|
||||
/* Inject an undefined exception into a 64 bit guest */
|
||||
void inject_undef64_exception(struct cpu_user_regs *regs, int instr_len)
|
||||
void inject_undef64_exception(struct cpu_user_regs *regs)
|
||||
{
|
||||
vaddr_t handler;
|
||||
const union hsr esr = {
|
||||
.iss = 0,
|
||||
.len = instr_len,
|
||||
.len = 1,
|
||||
.ec = HSR_EC_UNKNOWN,
|
||||
};
|
||||
|
||||
@@ -606,13 +606,13 @@ static void inject_iabt64_exception(struct cpu_user_regs *regs,
|
||||
|
||||
#endif
|
||||
|
||||
void inject_undef_exception(struct cpu_user_regs *regs, const union hsr hsr)
|
||||
void inject_undef_exception(struct cpu_user_regs *regs)
|
||||
{
|
||||
if ( is_32bit_domain(current->domain) )
|
||||
inject_undef32_exception(regs);
|
||||
#ifdef CONFIG_ARM_64
|
||||
else
|
||||
inject_undef64_exception(regs, hsr.len);
|
||||
inject_undef64_exception(regs);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1418,7 +1418,7 @@ static void do_trap_hypercall(struct cpu_user_regs *regs, register_t *nr,
|
||||
if ( hsr.iss != XEN_HYPERCALL_TAG )
|
||||
{
|
||||
gprintk(XENLOG_WARNING, "Invalid HVC imm 0x%x\n", hsr.iss);
|
||||
return inject_undef_exception(regs, hsr);
|
||||
return inject_undef_exception(regs);
|
||||
}
|
||||
|
||||
curr->hcall_preempted = false;
|
||||
@@ -1655,7 +1655,7 @@ void handle_raz_wi(struct cpu_user_regs *regs,
|
||||
ASSERT((min_el == 0) || (min_el == 1));
|
||||
|
||||
if ( min_el > 0 && regs_mode_is_user(regs) )
|
||||
return inject_undef_exception(regs, hsr);
|
||||
return inject_undef_exception(regs);
|
||||
|
||||
if ( read )
|
||||
set_user_reg(regs, regidx, 0);
|
||||
@@ -1674,10 +1674,10 @@ void handle_wo_wi(struct cpu_user_regs *regs,
|
||||
ASSERT((min_el == 0) || (min_el == 1));
|
||||
|
||||
if ( min_el > 0 && regs_mode_is_user(regs) )
|
||||
return inject_undef_exception(regs, hsr);
|
||||
return inject_undef_exception(regs);
|
||||
|
||||
if ( read )
|
||||
return inject_undef_exception(regs, hsr);
|
||||
return inject_undef_exception(regs);
|
||||
/* else: ignore */
|
||||
|
||||
advance_pc(regs, hsr);
|
||||
@@ -1694,10 +1694,10 @@ void handle_ro_read_val(struct cpu_user_regs *regs,
|
||||
ASSERT((min_el == 0) || (min_el == 1));
|
||||
|
||||
if ( min_el > 0 && regs_mode_is_user(regs) )
|
||||
return inject_undef_exception(regs, hsr);
|
||||
return inject_undef_exception(regs);
|
||||
|
||||
if ( !read )
|
||||
return inject_undef_exception(regs, hsr);
|
||||
return inject_undef_exception(regs);
|
||||
|
||||
set_user_reg(regs, regidx, val);
|
||||
|
||||
@@ -2147,7 +2147,7 @@ void asmlinkage do_trap_guest_sync(struct cpu_user_regs *regs)
|
||||
case HSR_EC_SVE:
|
||||
GUEST_BUG_ON(regs_mode_is_32bit(regs));
|
||||
gprintk(XENLOG_WARNING, "Domain tried to use SVE while not allowed\n");
|
||||
inject_undef_exception(regs, hsr);
|
||||
inject_undef_exception(regs);
|
||||
break;
|
||||
#endif
|
||||
|
||||
@@ -2164,7 +2164,7 @@ void asmlinkage do_trap_guest_sync(struct cpu_user_regs *regs)
|
||||
gprintk(XENLOG_WARNING,
|
||||
"Unknown Guest Trap. HSR=%#"PRIregister" EC=0x%x IL=%x Syndrome=0x%"PRIx32"\n",
|
||||
hsr.bits, hsr.ec, hsr.len, hsr.iss);
|
||||
inject_undef_exception(regs, hsr);
|
||||
inject_undef_exception(regs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+13
-13
@@ -206,7 +206,7 @@ void do_cp15_32(struct cpu_user_regs *regs, const union hsr hsr)
|
||||
case HSR_CPREG32(CNTP_CTL):
|
||||
case HSR_CPREG32(CNTP_TVAL):
|
||||
if ( !vtimer_emulate(regs, hsr) )
|
||||
return inject_undef_exception(regs, hsr);
|
||||
return inject_undef_exception(regs);
|
||||
break;
|
||||
|
||||
/*
|
||||
@@ -217,7 +217,7 @@ void do_cp15_32(struct cpu_user_regs *regs, const union hsr hsr)
|
||||
*/
|
||||
case HSR_CPREG32(ACTLR):
|
||||
if ( regs_mode_is_user(regs) )
|
||||
return inject_undef_exception(regs, hsr);
|
||||
return inject_undef_exception(regs);
|
||||
if ( cp32.read )
|
||||
set_user_reg(regs, regidx, v->arch.actlr);
|
||||
break;
|
||||
@@ -232,7 +232,7 @@ void do_cp15_32(struct cpu_user_regs *regs, const union hsr hsr)
|
||||
case HSR_CPREG32(DCCSW):
|
||||
case HSR_CPREG32(DCCISW):
|
||||
if ( !cp32.read )
|
||||
p2m_set_way_flush(current, regs, hsr);
|
||||
p2m_set_way_flush(current, regs);
|
||||
break;
|
||||
|
||||
/*
|
||||
@@ -397,7 +397,7 @@ void do_cp15_32(struct cpu_user_regs *regs, const union hsr hsr)
|
||||
cp32.op1, cp32.reg, cp32.crn, cp32.crm, cp32.op2, regs->pc);
|
||||
gdprintk(XENLOG_ERR, "unhandled 32-bit CP15 access %#"PRIregister"\n",
|
||||
hsr.bits & HSR_CP32_REGS_MASK);
|
||||
inject_undef_exception(regs, hsr);
|
||||
inject_undef_exception(regs);
|
||||
return;
|
||||
}
|
||||
advance_pc(regs, hsr);
|
||||
@@ -421,7 +421,7 @@ void do_cp15_64(struct cpu_user_regs *regs, const union hsr hsr)
|
||||
*/
|
||||
case HSR_CPREG64(CNTP_CVAL):
|
||||
if ( !vtimer_emulate(regs, hsr) )
|
||||
return inject_undef_exception(regs, hsr);
|
||||
return inject_undef_exception(regs);
|
||||
break;
|
||||
|
||||
/*
|
||||
@@ -433,7 +433,7 @@ void do_cp15_64(struct cpu_user_regs *regs, const union hsr hsr)
|
||||
case HSR_CPREG64(ICC_ASGI1R):
|
||||
case HSR_CPREG64(ICC_SGI0R):
|
||||
if ( !vgic_emulate(regs, hsr) )
|
||||
return inject_undef_exception(regs, hsr);
|
||||
return inject_undef_exception(regs);
|
||||
break;
|
||||
|
||||
GENERATE_CASE(TTBR0, 64)
|
||||
@@ -467,7 +467,7 @@ void do_cp15_64(struct cpu_user_regs *regs, const union hsr hsr)
|
||||
gdprintk(XENLOG_ERR,
|
||||
"unhandled 64-bit CP15 access %#"PRIregister"\n",
|
||||
hsr.bits & HSR_CP64_REGS_MASK);
|
||||
inject_undef_exception(regs, hsr);
|
||||
inject_undef_exception(regs);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -532,7 +532,7 @@ void do_cp14_32(struct cpu_user_regs *regs, const union hsr hsr)
|
||||
* is set to 0, which we emulated below.
|
||||
*/
|
||||
if ( !cp32.read )
|
||||
return inject_undef_exception(regs, hsr);
|
||||
return inject_undef_exception(regs);
|
||||
|
||||
/* Implement the minimum requirements:
|
||||
* - Number of watchpoints: 1
|
||||
@@ -631,7 +631,7 @@ void do_cp14_32(struct cpu_user_regs *regs, const union hsr hsr)
|
||||
cp32.op1, cp32.reg, cp32.crn, cp32.crm, cp32.op2, regs->pc);
|
||||
gdprintk(XENLOG_ERR, "unhandled 32-bit cp14 access %#"PRIregister"\n",
|
||||
hsr.bits & HSR_CP32_REGS_MASK);
|
||||
inject_undef_exception(regs, hsr);
|
||||
inject_undef_exception(regs);
|
||||
}
|
||||
|
||||
void do_cp14_64(struct cpu_user_regs *regs, const union hsr hsr)
|
||||
@@ -669,7 +669,7 @@ void do_cp14_64(struct cpu_user_regs *regs, const union hsr hsr)
|
||||
cp64.op1, cp64.reg1, cp64.reg2, cp64.crm, regs->pc);
|
||||
gdprintk(XENLOG_ERR, "unhandled 64-bit CP14 access %#"PRIregister"\n",
|
||||
hsr.bits & HSR_CP64_REGS_MASK);
|
||||
inject_undef_exception(regs, hsr);
|
||||
inject_undef_exception(regs);
|
||||
}
|
||||
|
||||
void do_cp14_dbg(struct cpu_user_regs *regs, const union hsr hsr)
|
||||
@@ -698,7 +698,7 @@ void do_cp14_dbg(struct cpu_user_regs *regs, const union hsr hsr)
|
||||
gdprintk(XENLOG_ERR, "unhandled 64-bit CP14 DBG access %#"PRIregister"\n",
|
||||
hsr.bits & HSR_CP64_REGS_MASK);
|
||||
|
||||
inject_undef_exception(regs, hsr);
|
||||
inject_undef_exception(regs);
|
||||
}
|
||||
|
||||
void do_cp10(struct cpu_user_regs *regs, const union hsr hsr)
|
||||
@@ -731,7 +731,7 @@ void do_cp10(struct cpu_user_regs *regs, const union hsr hsr)
|
||||
cp32.op1, cp32.reg, cp32.crn, cp32.crm, cp32.op2, regs->pc);
|
||||
gdprintk(XENLOG_ERR, "unhandled 32-bit CP10 access %#"PRIregister"\n",
|
||||
hsr.bits & HSR_CP32_REGS_MASK);
|
||||
inject_undef_exception(regs, hsr);
|
||||
inject_undef_exception(regs);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -756,7 +756,7 @@ void do_cp(struct cpu_user_regs *regs, const union hsr hsr)
|
||||
|
||||
ASSERT(!cp.tas); /* We don't trap SIMD instruction */
|
||||
gdprintk(XENLOG_ERR, "unhandled CP%d access\n", cp.coproc);
|
||||
inject_undef_exception(regs, hsr);
|
||||
inject_undef_exception(regs);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+2
-4
@@ -346,13 +346,11 @@ void do_trap_smc(struct cpu_user_regs *regs, const union hsr hsr)
|
||||
if ( vsmccc_handle_call(regs) )
|
||||
advance_pc(regs, hsr);
|
||||
else
|
||||
inject_undef_exception(regs, hsr);
|
||||
inject_undef_exception(regs);
|
||||
}
|
||||
|
||||
void do_trap_hvc_smccc(struct cpu_user_regs *regs)
|
||||
{
|
||||
const union hsr hsr = { .bits = regs->hsr };
|
||||
|
||||
/*
|
||||
* vsmccc_handle_call() will return false if this call is not
|
||||
* SMCCC compatible (e.g. immediate value != 0). As it is not
|
||||
@@ -360,7 +358,7 @@ void do_trap_hvc_smccc(struct cpu_user_regs *regs)
|
||||
* ARM_SMCCC_ERR_UNKNOWN_FUNCTION.
|
||||
*/
|
||||
if ( !vsmccc_handle_call(regs) )
|
||||
inject_undef_exception(regs, hsr);
|
||||
inject_undef_exception(regs);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||