[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 13/14] xen: arm: handle 64-bit system register access traps.
On Tue, 12 Mar 2013, Ian Campbell wrote: > From: Ian Campbell <ian.campbell@xxxxxxxxxx> > > Wire up the vtimer handling to it. > > Use a simplified version of the 32-bit cp-register macros to have convenient > decoding of HSR register values. (simplified because we don't need them for > passing to the assembler on 64-bit) > > Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx> Acked-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx> assuming that you didn't make any mistakes in writing down thw new SYSREG #define > xen/arch/arm/traps.c | 39 +++++++++++++ > xen/arch/arm/vtimer.c | 119 > ++++++++++++++++++++++++++------------- > xen/include/asm-arm/processor.h | 32 +++++++++++ > xen/include/asm-arm/sysregs.h | 56 ++++++++++++++++++ > 4 files changed, 208 insertions(+), 38 deletions(-) > create mode 100644 xen/include/asm-arm/sysregs.h > > diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c > index 190d1e8..67d9072 100644 > --- a/xen/arch/arm/traps.c > +++ b/xen/arch/arm/traps.c > @@ -973,6 +973,39 @@ static void do_cp15_64(struct cpu_user_regs *regs, > > } > > +#ifdef CONFIG_ARM_64 > +static void do_sysreg(struct cpu_user_regs *regs, > + union hsr hsr) > +{ > + struct hsr_sysreg sysreg = hsr.sysreg; > + > + switch ( hsr.bits & HSR_SYSREG_REGS_MASK ) > + { > + case CNTP_CTL_EL0: > + case CNTP_TVAL_EL0: > + if ( !vtimer_emulate(regs, hsr) ) > + { > + dprintk(XENLOG_ERR, > + "failed emulation of 64-bit vtimer sysreg access\n"); > + domain_crash_synchronous(); > + } > + break; > + default: > + printk("%s %d, %d, c%d, c%d, %d %s x%d @ 0x%"PRIregister"\n", > + sysreg.read ? "mrs" : "msr", > + sysreg.op0, sysreg.op1, > + sysreg.crn, sysreg.crm, > + sysreg.op2, > + sysreg.read ? "=>" : "<=", > + sysreg.reg, regs->pc); > + panic("unhandled 64-bit sysreg access %#x\n", > + hsr.bits & HSR_SYSREG_REGS_MASK); > + } > + > + regs->pc += 4; > +} > +#endif > + > void dump_guest_s1_walk(struct domain *d, vaddr_t addr) > { > uint32_t ttbcr = READ_SYSREG32(TCR_EL1); > @@ -1114,7 +1147,13 @@ asmlinkage void do_trap_hypervisor(struct > cpu_user_regs *regs) > #endif > do_trap_hypercall(regs, ®s->x16, hsr.iss); > break; > + case HSR_EC_SYSREG: > + if ( is_pv32_domain(current->domain) ) > + goto bad_trap; > + do_sysreg(regs, hsr); > + break; > #endif > + > case HSR_EC_DATA_ABORT_GUEST: > do_trap_data_abort_guest(regs, hsr.dabt); > break; > diff --git a/xen/arch/arm/vtimer.c b/xen/arch/arm/vtimer.c > index a68f662..f9fc045 100644 > --- a/xen/arch/arm/vtimer.c > +++ b/xen/arch/arm/vtimer.c > @@ -102,51 +102,62 @@ int virt_timer_restore(struct vcpu *v) > return 0; > } > > -static int vtimer_emulate_32(struct cpu_user_regs *regs, union hsr hsr) > +static void vtimer_cntp_ctl(struct cpu_user_regs *regs, uint32_t *r, int > read) > { > struct vcpu *v = current; > - struct hsr_cp32 cp32 = hsr.cp32; > - uint32_t *r = (uint32_t *)select_user_reg(regs, cp32.reg); > - s_time_t now; > - > - switch ( hsr.bits & HSR_CP32_REGS_MASK ) > + if ( read ) > { > - case HSR_CPREG32(CNTP_CTL): > - if ( cp32.read ) > + *r = v->arch.phys_timer.ctl; > + } > + else > + { > + v->arch.phys_timer.ctl = *r; > + > + if ( v->arch.phys_timer.ctl & CNTx_CTL_ENABLE ) > { > - *r = v->arch.phys_timer.ctl; > + set_timer(&v->arch.phys_timer.timer, > + v->arch.phys_timer.cval + v->arch.phys_timer.offset); > } > else > + stop_timer(&v->arch.phys_timer.timer); > + } > +} > + > +static void vtimer_cntp_tval(struct cpu_user_regs *regs, uint32_t *r, int > read) > +{ > + struct vcpu *v = current; > + s_time_t now; > + > + now = NOW() - v->arch.phys_timer.offset; > + > + if ( read ) > + { > + *r = (uint32_t)(ns_to_ticks(v->arch.phys_timer.cval - now) & > 0xffffffffull); > + } > + else > + { > + v->arch.phys_timer.cval = now + ticks_to_ns(*r); > + if ( v->arch.phys_timer.ctl & CNTx_CTL_ENABLE ) > { > - v->arch.phys_timer.ctl = *r; > - > - if ( v->arch.phys_timer.ctl & CNTx_CTL_ENABLE ) > - { > - set_timer(&v->arch.phys_timer.timer, > - v->arch.phys_timer.cval + > v->arch.phys_timer.offset); > - } > - else > - stop_timer(&v->arch.phys_timer.timer); > + set_timer(&v->arch.phys_timer.timer, > + v->arch.phys_timer.cval + v->arch.phys_timer.offset); > } > + } > +} > > +static int vtimer_emulate_cp32(struct cpu_user_regs *regs, union hsr hsr) > +{ > + struct hsr_cp32 cp32 = hsr.cp32; > + uint32_t *r = (uint32_t *)select_user_reg(regs, cp32.reg); > + > + switch ( hsr.bits & HSR_CP32_REGS_MASK ) > + { > + case HSR_CPREG32(CNTP_CTL): > + vtimer_cntp_ctl(regs, r, cp32.read); > return 1; > > case HSR_CPREG32(CNTP_TVAL): > - now = NOW() - v->arch.phys_timer.offset; > - if ( cp32.read ) > - { > - *r = (uint32_t)(ns_to_ticks(v->arch.phys_timer.cval - now) & > 0xffffffffull); > - } > - else > - { > - v->arch.phys_timer.cval = now + ticks_to_ns(*r); > - if ( v->arch.phys_timer.ctl & CNTx_CTL_ENABLE ) > - { > - set_timer(&v->arch.phys_timer.timer, > - v->arch.phys_timer.cval + > v->arch.phys_timer.offset); > - } > - } > - > + vtimer_cntp_tval(regs, r, cp32.read); > return 1; > > default: > @@ -154,7 +165,7 @@ static int vtimer_emulate_32(struct cpu_user_regs *regs, > union hsr hsr) > } > } > > -static int vtimer_emulate_64(struct cpu_user_regs *regs, union hsr hsr) > +static int vtimer_emulate_cp64(struct cpu_user_regs *regs, union hsr hsr) > { > struct vcpu *v = current; > struct hsr_cp64 cp64 = hsr.cp64; > @@ -185,16 +196,48 @@ static int vtimer_emulate_64(struct cpu_user_regs > *regs, union hsr hsr) > } > } > > +#ifdef CONFIG_ARM_64 > +static int vtimer_emulate_sysreg(struct cpu_user_regs *regs, union hsr hsr) > +{ > + struct hsr_sysreg sysreg = hsr.sysreg; > + register_t *x = select_user_reg(regs, sysreg.reg); > + uint32_t r = (uint32_t)*x; > + > + switch ( hsr.bits & HSR_SYSREG_REGS_MASK ) > + { > + case CNTP_CTL_EL0: > + vtimer_cntp_ctl(regs, &r, sysreg.read); > + *x = r; > + return 1; > + case CNTP_TVAL_EL0: > + vtimer_cntp_tval(regs, &r, sysreg.read); > + *x = r; > + return 1; > + default: > + return 0; > + } > + > +} > +#endif > + > int vtimer_emulate(struct cpu_user_regs *regs, union hsr hsr) > { > - if ( !is_pv32_domain(current->domain) ) > - return -EINVAL; > > switch (hsr.ec) { > case HSR_EC_CP15_32: > - return vtimer_emulate_32(regs, hsr); > + if ( !is_pv32_domain(current->domain) ) > + return 0; > + return vtimer_emulate_cp32(regs, hsr); > case HSR_EC_CP15_64: > - return vtimer_emulate_64(regs, hsr); > + if ( !is_pv32_domain(current->domain) ) > + return 0; > + return vtimer_emulate_cp64(regs, hsr); > +#ifdef CONFIG_ARM_64 > + case HSR_EC_SYSREG: > + if ( is_pv32_domain(current->domain) ) > + return 0; > + return vtimer_emulate_sysreg(regs, hsr); > +#endif > default: > return 0; > } > diff --git a/xen/include/asm-arm/processor.h b/xen/include/asm-arm/processor.h > index 17f5465..d75530d 100644 > --- a/xen/include/asm-arm/processor.h > +++ b/xen/include/asm-arm/processor.h > @@ -2,6 +2,7 @@ > #define __ASM_ARM_PROCESSOR_H > > #include <asm/cpregs.h> > +#include <asm/sysregs.h> > > /* MIDR Main ID Register */ > #define MIDR_MASK 0xff0ffff0 > @@ -90,6 +91,7 @@ > #define HSR_EC_HVC32 0x12 > #ifdef CONFIG_ARM_64 > #define HSR_EC_HVC64 0x16 > +#define HSR_EC_SYSREG 0x18 > #endif > #define HSR_EC_INSTR_ABORT_GUEST 0x20 > #define HSR_EC_INSTR_ABORT_HYP 0x21 > @@ -249,6 +251,21 @@ union hsr { > unsigned long ec:6; /* Exception Class */ > } cp64; /* HSR_EC_CP15_64, HSR_EC_CP14_64 */ > > +#ifdef CONFIG_ARM_64 > + struct hsr_sysreg { > + unsigned long read:1; /* Direction */ > + unsigned long crm:4; /* CRm */ > + unsigned long reg:5; /* Rt */ > + unsigned long crn:4; /* CRn */ > + unsigned long op1:3; /* Op1 */ > + unsigned long op2:3; /* Op2 */ > + unsigned long op0:2; /* Op0 */ > + unsigned long res0:3; > + unsigned long len:1; /* Instruction length */ > + unsigned long ec:6; > + } sysreg; /* HSR_EC_SYSREG */ > +#endif > + > struct hsr_dabt { > unsigned long dfsc:6; /* Data Fault Status Code */ > unsigned long write:1; /* Write / not Read */ > @@ -291,6 +308,21 @@ union hsr { > #define HSR_CP64_CRM_SHIFT (1) > #define HSR_CP64_REGS_MASK (HSR_CP64_OP1_MASK|HSR_CP64_CRM_MASK) > > +/* HSR.EC == HSR_SYSREG */ > +#define HSR_SYSREG_OP0_MASK (0x00300000) > +#define HSR_SYSREG_OP0_SHIFT (20) > +#define HSR_SYSREG_OP1_MASK (0x0001c000) > +#define HSR_SYSREG_OP1_SHIFT (14) > +#define HSR_SYSREG_CRN_MASK (0x00003800) > +#define HSR_SYSREG_CRN_SHIFT (10) > +#define HSR_SYSREG_CRM_MASK (0x0000001e) > +#define HSR_SYSREG_CRM_SHIFT (1) > +#define HSR_SYSREG_OP2_MASK (0x000e0000) > +#define HSR_SYSREG_OP2_SHIFT (17) > +#define HSR_SYSREG_REGS_MASK (HSR_SYSREG_OP0_MASK|HSR_SYSREG_OP1_MASK|\ > + HSR_SYSREG_CRN_MASK|HSR_SYSREG_CRM_MASK|\ > + HSR_SYSREG_OP2_MASK) > + > /* Physical Address Register */ > #define PAR_F (1<<0) > > diff --git a/xen/include/asm-arm/sysregs.h b/xen/include/asm-arm/sysregs.h > new file mode 100644 > index 0000000..9c64777 > --- /dev/null > +++ b/xen/include/asm-arm/sysregs.h > @@ -0,0 +1,56 @@ > +#ifndef __ASM_ARM_SYSREGS_H > +#define __ASM_ARM_SYSREGS_H > + > +#ifdef CONFIG_ARM_64 > + > +#include <xen/stringify.h> > + > +/* AArch 64 System Register Encodings */ > +#define __HSR_SYSREG_c0 0 > +#define __HSR_SYSREG_c1 1 > +#define __HSR_SYSREG_c2 2 > +#define __HSR_SYSREG_c3 3 > +#define __HSR_SYSREG_c4 4 > +#define __HSR_SYSREG_c5 5 > +#define __HSR_SYSREG_c6 6 > +#define __HSR_SYSREG_c7 7 > +#define __HSR_SYSREG_c8 8 > +#define __HSR_SYSREG_c9 9 > +#define __HSR_SYSREG_c10 10 > +#define __HSR_SYSREG_c11 11 > +#define __HSR_SYSREG_c12 12 > +#define __HSR_SYSREG_c13 13 > +#define __HSR_SYSREG_c14 14 > +#define __HSR_SYSREG_c15 15 > + > +#define __HSR_SYSREG_0 0 > +#define __HSR_SYSREG_1 1 > +#define __HSR_SYSREG_2 2 > +#define __HSR_SYSREG_3 3 > +#define __HSR_SYSREG_4 4 > +#define __HSR_SYSREG_5 5 > +#define __HSR_SYSREG_6 6 > +#define __HSR_SYSREG_7 7 > + > +/* These are used to decode traps with HSR.EC==HSR_EC_SYSREG */ > +#define HSR_SYSREG(op0,op1,crn,crm,op2) \ > + ((__HSR_SYSREG_##op0) << HSR_SYSREG_OP0_SHIFT) | \ > + ((__HSR_SYSREG_##op1) << HSR_SYSREG_OP1_SHIFT) | \ > + ((__HSR_SYSREG_##crn) << HSR_SYSREG_CRN_SHIFT) | \ > + ((__HSR_SYSREG_##crm) << HSR_SYSREG_CRM_SHIFT) | \ > + ((__HSR_SYSREG_##op2) << HSR_SYSREG_OP2_SHIFT) > + > +#define CNTP_CTL_EL0 HSR_SYSREG(3,3,c14,c2,1) > +#define CNTP_TVAL_EL0 HSR_SYSREG(3,3,c14,c2,0) > +#endif > + > +#endif > + > +/* > + * Local variables: > + * mode: C > + * c-set-style: "BSD" > + * c-basic-offset: 4 > + * indent-tabs-mode: nil > + * End: > + */ > -- > 1.7.10.4 > _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |