[Xen-devel,v2,4/7] xen/arm: Move sysreg emulation outside of traps.c

Message ID 20170912103622.18562-5-julien.grall@arm.com
State Superseded
Headers show
Series
  • xen/arm: Clean-up traps.c
Related show

Commit Message

Julien Grall Sept. 12, 2017, 10:36 a.m.
The sysreg emulation is 64-bit specific and surrounded by #ifdef. Move
them in a separate file arm/arm64/vsysreg.c to shrink down a bit traps.c

No functional change.

Signed-off-by: Julien Grall <julien.grall@arm.com>
---
 xen/arch/arm/arm64/Makefile       |   1 +
 xen/arch/arm/arm64/vsysreg.c      | 229 ++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/traps.c              | 198 --------------------------------
 xen/include/asm-arm/arm64/traps.h |   3 +
 4 files changed, 233 insertions(+), 198 deletions(-)
 create mode 100644 xen/arch/arm/arm64/vsysreg.c

Comments

Stefano Stabellini Sept. 12, 2017, 9:40 p.m. | #1
On Tue, 12 Sep 2017, Julien Grall wrote:
> The sysreg emulation is 64-bit specific and surrounded by #ifdef. Move
> them in a separate file arm/arm64/vsysreg.c to shrink down a bit traps.c
> 
> No functional change.
> 
> Signed-off-by: Julien Grall <julien.grall@arm.com>

Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>

> ---
>  xen/arch/arm/arm64/Makefile       |   1 +
>  xen/arch/arm/arm64/vsysreg.c      | 229 ++++++++++++++++++++++++++++++++++++++
>  xen/arch/arm/traps.c              | 198 --------------------------------
>  xen/include/asm-arm/arm64/traps.h |   3 +
>  4 files changed, 233 insertions(+), 198 deletions(-)
>  create mode 100644 xen/arch/arm/arm64/vsysreg.c
> 
> diff --git a/xen/arch/arm/arm64/Makefile b/xen/arch/arm/arm64/Makefile
> index 149b6b3901..718fe44455 100644
> --- a/xen/arch/arm/arm64/Makefile
> +++ b/xen/arch/arm/arm64/Makefile
> @@ -10,3 +10,4 @@ obj-$(CONFIG_LIVEPATCH) += livepatch.o
>  obj-y += smpboot.o
>  obj-y += traps.o
>  obj-y += vfp.o
> +obj-y += vsysreg.o
> diff --git a/xen/arch/arm/arm64/vsysreg.c b/xen/arch/arm/arm64/vsysreg.c
> new file mode 100644
> index 0000000000..c57ac12503
> --- /dev/null
> +++ b/xen/arch/arm/arm64/vsysreg.c
> @@ -0,0 +1,229 @@
> +/*
> + * xen/arch/arm/arm64/sysreg.c
> + *
> + * Emulate system registers trapped.
> + *
> + * Copyright (c) 2011 Citrix Systems.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <xen/sched.h>
> +
> +#include <asm/current.h>
> +#include <asm/regs.h>
> +#include <asm/traps.h>
> +#include <asm/vtimer.h>
> +
> +void do_sysreg(struct cpu_user_regs *regs,
> +               const union hsr hsr)
> +{
> +    int regidx = hsr.sysreg.reg;
> +    struct vcpu *v = current;
> +
> +    switch ( hsr.bits & HSR_SYSREG_REGS_MASK )
> +    {
> +    /*
> +     * HCR_EL2.TACR
> +     *
> +     * ARMv8 (DDI 0487A.d): D7.2.1
> +     */
> +    case HSR_SYSREG_ACTLR_EL1:
> +        if ( psr_mode_is_user(regs) )
> +            return inject_undef_exception(regs, hsr);
> +        if ( hsr.sysreg.read )
> +            set_user_reg(regs, regidx, v->arch.actlr);
> +        break;
> +
> +    /*
> +     * MDCR_EL2.TDRA
> +     *
> +     * ARMv8 (DDI 0487A.d): D1-1508 Table D1-57
> +     */
> +    case HSR_SYSREG_MDRAR_EL1:
> +        return handle_ro_raz(regs, regidx, hsr.sysreg.read, hsr, 1);
> +
> +    /*
> +     * MDCR_EL2.TDOSA
> +     *
> +     * ARMv8 (DDI 0487A.d): D1-1509 Table D1-58
> +     *
> +     * Unhandled:
> +     *    OSLSR_EL1
> +     *    DBGPRCR_EL1
> +     */
> +    case HSR_SYSREG_OSLAR_EL1:
> +        return handle_wo_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
> +    case HSR_SYSREG_OSDLR_EL1:
> +        return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
> +
> +    /*
> +     * MDCR_EL2.TDA
> +     *
> +     * ARMv8 (DDI 0487A.d): D1-1510 Table D1-59
> +     *
> +     * Unhandled:
> +     *    MDCCINT_EL1
> +     *    DBGDTR_EL0
> +     *    DBGDTRRX_EL0
> +     *    DBGDTRTX_EL0
> +     *    OSDTRRX_EL1
> +     *    OSDTRTX_EL1
> +     *    OSECCR_EL1
> +     *    DBGCLAIMSET_EL1
> +     *    DBGCLAIMCLR_EL1
> +     *    DBGAUTHSTATUS_EL1
> +     */
> +    case HSR_SYSREG_MDSCR_EL1:
> +        return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
> +    case HSR_SYSREG_MDCCSR_EL0:
> +        /*
> +         * Accessible at EL0 only if MDSCR_EL1.TDCC is set to 0. We emulate that
> +         * register as RAZ/WI above. So RO at both EL0 and EL1.
> +         */
> +        return handle_ro_raz(regs, regidx, hsr.sysreg.read, hsr, 0);
> +    HSR_SYSREG_DBG_CASES(DBGBVR):
> +    HSR_SYSREG_DBG_CASES(DBGBCR):
> +    HSR_SYSREG_DBG_CASES(DBGWVR):
> +    HSR_SYSREG_DBG_CASES(DBGWCR):
> +        return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
> +
> +    /*
> +     * MDCR_EL2.TPM
> +     *
> +     * ARMv8 (DDI 0487A.d): D1-1511 Table D1-61
> +     *
> +     * Unhandled:
> +     *    PMEVCNTR<n>_EL0
> +     *    PMEVTYPER<n>_EL0
> +     *    PMCCFILTR_EL0
> +     * MDCR_EL2.TPMCR
> +     *
> +     * ARMv7 (DDI 0406C.b): B1.14.17
> +     * ARMv8 (DDI 0487A.d): D1-1511 Table D1-62
> +     *
> +     * NB: Both MDCR_EL2.TPM and MDCR_EL2.TPMCR cause trapping of PMCR.
> +     */
> +    case HSR_SYSREG_PMINTENSET_EL1:
> +    case HSR_SYSREG_PMINTENCLR_EL1:
> +        /*
> +         * Accessible from EL1 only, but if EL0 trap happens handle as
> +         * undef.
> +         */
> +        return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
> +    case HSR_SYSREG_PMUSERENR_EL0:
> +        /* RO at EL0. RAZ/WI at EL1 */
> +        if ( psr_mode_is_user(regs) )
> +            return handle_ro_raz(regs, regidx, hsr.sysreg.read, hsr, 0);
> +        else
> +            return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
> +    case HSR_SYSREG_PMCR_EL0:
> +    case HSR_SYSREG_PMCNTENSET_EL0:
> +    case HSR_SYSREG_PMCNTENCLR_EL0:
> +    case HSR_SYSREG_PMOVSCLR_EL0:
> +    case HSR_SYSREG_PMSWINC_EL0:
> +    case HSR_SYSREG_PMSELR_EL0:
> +    case HSR_SYSREG_PMCEID0_EL0:
> +    case HSR_SYSREG_PMCEID1_EL0:
> +    case HSR_SYSREG_PMCCNTR_EL0:
> +    case HSR_SYSREG_PMXEVTYPER_EL0:
> +    case HSR_SYSREG_PMXEVCNTR_EL0:
> +    case HSR_SYSREG_PMOVSSET_EL0:
> +        /*
> +         * Accessible at EL0 only if PMUSERENR_EL0.EN is set. We
> +         * emulate that register as 0 above.
> +         */
> +        return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
> +
> +    /*
> +     * !CNTHCTL_EL2.EL1PCEN
> +     *
> +     * ARMv8 (DDI 0487A.d): D1-1510 Table D1-60
> +     */
> +    case HSR_SYSREG_CNTP_CTL_EL0:
> +    case HSR_SYSREG_CNTP_TVAL_EL0:
> +    case HSR_SYSREG_CNTP_CVAL_EL0:
> +        if ( !vtimer_emulate(regs, hsr) )
> +            return inject_undef_exception(regs, hsr);
> +        break;
> +
> +    /*
> +     * HCR_EL2.FMO or HCR_EL2.IMO
> +     *
> +     * GIC Architecture Specification (IHI 0069C): Section 4.6.3
> +     */
> +    case HSR_SYSREG_ICC_SGI1R_EL1:
> +    case HSR_SYSREG_ICC_ASGI1R_EL1:
> +    case HSR_SYSREG_ICC_SGI0R_EL1:
> +
> +        if ( !vgic_emulate(regs, hsr) )
> +            return inject_undef64_exception(regs, hsr.len);
> +        break;
> +
> +    /*
> +     *  ICC_SRE_EL2.Enable = 0
> +     *
> +     *  GIC Architecture Specification (IHI 0069C): Section 8.1.9
> +     */
> +    case HSR_SYSREG_ICC_SRE_EL1:
> +        /*
> +         * Trapped when the guest is using GICv2 whilst the platform
> +         * interrupt controller is GICv3. In this case, the register
> +         * should be emulate as RAZ/WI to tell the guest to use the GIC
> +         * memory mapped interface (i.e GICv2 compatibility).
> +         */
> +        return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
> +
> +    /*
> +     * HCR_EL2.TIDCP
> +     *
> +     * ARMv8 (DDI 0487A.d): D1-1501 Table D1-43
> +     *
> +     *  - Reserved control space for IMPLEMENTATION DEFINED functionality.
> +     *
> +     * CPTR_EL2.TTA
> +     *
> +     * ARMv8 (DDI 0487A.d): D1-1507 Table D1-54
> +     *
> +     *  - All implemented trace registers.
> +     *
> +     * And all other unknown registers.
> +     */
> +    default:
> +        {
> +            const struct hsr_sysreg sysreg = hsr.sysreg;
> +
> +            gdprintk(XENLOG_ERR,
> +                     "%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);
> +            gdprintk(XENLOG_ERR, "unhandled 64-bit sysreg access %#x\n",
> +                     hsr.bits & HSR_SYSREG_REGS_MASK);
> +            inject_undef_exception(regs, hsr);
> +            return;
> +        }
> +    }
> +
> +    regs->pc += 4;
> +}
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
> index 1c334a7b99..f00aa48892 100644
> --- a/xen/arch/arm/traps.c
> +++ b/xen/arch/arm/traps.c
> @@ -2295,204 +2295,6 @@ static void do_cp(struct cpu_user_regs *regs, const union hsr hsr)
>      inject_undef_exception(regs, hsr);
>  }
>  
> -#ifdef CONFIG_ARM_64
> -static void do_sysreg(struct cpu_user_regs *regs,
> -                      const union hsr hsr)
> -{
> -    int regidx = hsr.sysreg.reg;
> -    struct vcpu *v = current;
> -
> -    switch ( hsr.bits & HSR_SYSREG_REGS_MASK )
> -    {
> -    /*
> -     * HCR_EL2.TACR
> -     *
> -     * ARMv8 (DDI 0487A.d): D7.2.1
> -     */
> -    case HSR_SYSREG_ACTLR_EL1:
> -        if ( psr_mode_is_user(regs) )
> -            return inject_undef_exception(regs, hsr);
> -        if ( hsr.sysreg.read )
> -            set_user_reg(regs, regidx, v->arch.actlr);
> -        break;
> -
> -    /*
> -     * MDCR_EL2.TDRA
> -     *
> -     * ARMv8 (DDI 0487A.d): D1-1508 Table D1-57
> -     */
> -    case HSR_SYSREG_MDRAR_EL1:
> -        return handle_ro_raz(regs, regidx, hsr.sysreg.read, hsr, 1);
> -
> -    /*
> -     * MDCR_EL2.TDOSA
> -     *
> -     * ARMv8 (DDI 0487A.d): D1-1509 Table D1-58
> -     *
> -     * Unhandled:
> -     *    OSLSR_EL1
> -     *    DBGPRCR_EL1
> -     */
> -    case HSR_SYSREG_OSLAR_EL1:
> -        return handle_wo_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
> -    case HSR_SYSREG_OSDLR_EL1:
> -        return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
> -
> -    /*
> -     * MDCR_EL2.TDA
> -     *
> -     * ARMv8 (DDI 0487A.d): D1-1510 Table D1-59
> -     *
> -     * Unhandled:
> -     *    MDCCINT_EL1
> -     *    DBGDTR_EL0
> -     *    DBGDTRRX_EL0
> -     *    DBGDTRTX_EL0
> -     *    OSDTRRX_EL1
> -     *    OSDTRTX_EL1
> -     *    OSECCR_EL1
> -     *    DBGCLAIMSET_EL1
> -     *    DBGCLAIMCLR_EL1
> -     *    DBGAUTHSTATUS_EL1
> -     */
> -    case HSR_SYSREG_MDSCR_EL1:
> -        return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
> -    case HSR_SYSREG_MDCCSR_EL0:
> -        /*
> -         * Accessible at EL0 only if MDSCR_EL1.TDCC is set to 0. We emulate that
> -         * register as RAZ/WI above. So RO at both EL0 and EL1.
> -         */
> -        return handle_ro_raz(regs, regidx, hsr.sysreg.read, hsr, 0);
> -    HSR_SYSREG_DBG_CASES(DBGBVR):
> -    HSR_SYSREG_DBG_CASES(DBGBCR):
> -    HSR_SYSREG_DBG_CASES(DBGWVR):
> -    HSR_SYSREG_DBG_CASES(DBGWCR):
> -        return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
> -
> -    /*
> -     * MDCR_EL2.TPM
> -     *
> -     * ARMv8 (DDI 0487A.d): D1-1511 Table D1-61
> -     *
> -     * Unhandled:
> -     *    PMEVCNTR<n>_EL0
> -     *    PMEVTYPER<n>_EL0
> -     *    PMCCFILTR_EL0
> -     * MDCR_EL2.TPMCR
> -     *
> -     * ARMv7 (DDI 0406C.b): B1.14.17
> -     * ARMv8 (DDI 0487A.d): D1-1511 Table D1-62
> -     *
> -     * NB: Both MDCR_EL2.TPM and MDCR_EL2.TPMCR cause trapping of PMCR.
> -     */
> -    case HSR_SYSREG_PMINTENSET_EL1:
> -    case HSR_SYSREG_PMINTENCLR_EL1:
> -        /*
> -         * Accessible from EL1 only, but if EL0 trap happens handle as
> -         * undef.
> -         */
> -        return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
> -    case HSR_SYSREG_PMUSERENR_EL0:
> -        /* RO at EL0. RAZ/WI at EL1 */
> -        if ( psr_mode_is_user(regs) )
> -            return handle_ro_raz(regs, regidx, hsr.sysreg.read, hsr, 0);
> -        else
> -            return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
> -    case HSR_SYSREG_PMCR_EL0:
> -    case HSR_SYSREG_PMCNTENSET_EL0:
> -    case HSR_SYSREG_PMCNTENCLR_EL0:
> -    case HSR_SYSREG_PMOVSCLR_EL0:
> -    case HSR_SYSREG_PMSWINC_EL0:
> -    case HSR_SYSREG_PMSELR_EL0:
> -    case HSR_SYSREG_PMCEID0_EL0:
> -    case HSR_SYSREG_PMCEID1_EL0:
> -    case HSR_SYSREG_PMCCNTR_EL0:
> -    case HSR_SYSREG_PMXEVTYPER_EL0:
> -    case HSR_SYSREG_PMXEVCNTR_EL0:
> -    case HSR_SYSREG_PMOVSSET_EL0:
> -        /*
> -         * Accessible at EL0 only if PMUSERENR_EL0.EN is set. We
> -         * emulate that register as 0 above.
> -         */
> -        return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
> -
> -    /*
> -     * !CNTHCTL_EL2.EL1PCEN
> -     *
> -     * ARMv8 (DDI 0487A.d): D1-1510 Table D1-60
> -     */
> -    case HSR_SYSREG_CNTP_CTL_EL0:
> -    case HSR_SYSREG_CNTP_TVAL_EL0:
> -    case HSR_SYSREG_CNTP_CVAL_EL0:
> -        if ( !vtimer_emulate(regs, hsr) )
> -            return inject_undef_exception(regs, hsr);
> -        break;
> -
> -    /*
> -     * HCR_EL2.FMO or HCR_EL2.IMO
> -     *
> -     * GIC Architecture Specification (IHI 0069C): Section 4.6.3
> -     */
> -    case HSR_SYSREG_ICC_SGI1R_EL1:
> -    case HSR_SYSREG_ICC_ASGI1R_EL1:
> -    case HSR_SYSREG_ICC_SGI0R_EL1:
> -
> -        if ( !vgic_emulate(regs, hsr) )
> -            return inject_undef64_exception(regs, hsr.len);
> -        break;
> -
> -    /*
> -     *  ICC_SRE_EL2.Enable = 0
> -     *
> -     *  GIC Architecture Specification (IHI 0069C): Section 8.1.9
> -     */
> -    case HSR_SYSREG_ICC_SRE_EL1:
> -        /*
> -         * Trapped when the guest is using GICv2 whilst the platform
> -         * interrupt controller is GICv3. In this case, the register
> -         * should be emulate as RAZ/WI to tell the guest to use the GIC
> -         * memory mapped interface (i.e GICv2 compatibility).
> -         */
> -        return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
> -
> -    /*
> -     * HCR_EL2.TIDCP
> -     *
> -     * ARMv8 (DDI 0487A.d): D1-1501 Table D1-43
> -     *
> -     *  - Reserved control space for IMPLEMENTATION DEFINED functionality.
> -     *
> -     * CPTR_EL2.TTA
> -     *
> -     * ARMv8 (DDI 0487A.d): D1-1507 Table D1-54
> -     *
> -     *  - All implemented trace registers.
> -     *
> -     * And all other unknown registers.
> -     */
> -    default:
> -        {
> -            const struct hsr_sysreg sysreg = hsr.sysreg;
> -
> -            gdprintk(XENLOG_ERR,
> -                     "%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);
> -            gdprintk(XENLOG_ERR, "unhandled 64-bit sysreg access %#x\n",
> -                     hsr.bits & HSR_SYSREG_REGS_MASK);
> -            inject_undef_exception(regs, hsr);
> -            return;
> -        }
> -    }
> -
> -    regs->pc += 4;
> -}
> -#endif
> -
>  void dump_guest_s1_walk(struct domain *d, vaddr_t addr)
>  {
>      register_t ttbcr = READ_SYSREG(TCR_EL1);
> diff --git a/xen/include/asm-arm/arm64/traps.h b/xen/include/asm-arm/arm64/traps.h
> index e5e5a4a036..2379b578cb 100644
> --- a/xen/include/asm-arm/arm64/traps.h
> +++ b/xen/include/asm-arm/arm64/traps.h
> @@ -3,6 +3,9 @@
>  
>  void inject_undef64_exception(struct cpu_user_regs *regs, int instr_len);
>  
> +void do_sysreg(struct cpu_user_regs *regs,
> +               const union hsr hsr);
> +
>  #endif /* __ASM_ARM64_TRAPS__ */
>  /*
>   * Local variables:
> -- 
> 2.11.0
>

Patch

diff --git a/xen/arch/arm/arm64/Makefile b/xen/arch/arm/arm64/Makefile
index 149b6b3901..718fe44455 100644
--- a/xen/arch/arm/arm64/Makefile
+++ b/xen/arch/arm/arm64/Makefile
@@ -10,3 +10,4 @@  obj-$(CONFIG_LIVEPATCH) += livepatch.o
 obj-y += smpboot.o
 obj-y += traps.o
 obj-y += vfp.o
+obj-y += vsysreg.o
diff --git a/xen/arch/arm/arm64/vsysreg.c b/xen/arch/arm/arm64/vsysreg.c
new file mode 100644
index 0000000000..c57ac12503
--- /dev/null
+++ b/xen/arch/arm/arm64/vsysreg.c
@@ -0,0 +1,229 @@ 
+/*
+ * xen/arch/arm/arm64/sysreg.c
+ *
+ * Emulate system registers trapped.
+ *
+ * Copyright (c) 2011 Citrix Systems.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <xen/sched.h>
+
+#include <asm/current.h>
+#include <asm/regs.h>
+#include <asm/traps.h>
+#include <asm/vtimer.h>
+
+void do_sysreg(struct cpu_user_regs *regs,
+               const union hsr hsr)
+{
+    int regidx = hsr.sysreg.reg;
+    struct vcpu *v = current;
+
+    switch ( hsr.bits & HSR_SYSREG_REGS_MASK )
+    {
+    /*
+     * HCR_EL2.TACR
+     *
+     * ARMv8 (DDI 0487A.d): D7.2.1
+     */
+    case HSR_SYSREG_ACTLR_EL1:
+        if ( psr_mode_is_user(regs) )
+            return inject_undef_exception(regs, hsr);
+        if ( hsr.sysreg.read )
+            set_user_reg(regs, regidx, v->arch.actlr);
+        break;
+
+    /*
+     * MDCR_EL2.TDRA
+     *
+     * ARMv8 (DDI 0487A.d): D1-1508 Table D1-57
+     */
+    case HSR_SYSREG_MDRAR_EL1:
+        return handle_ro_raz(regs, regidx, hsr.sysreg.read, hsr, 1);
+
+    /*
+     * MDCR_EL2.TDOSA
+     *
+     * ARMv8 (DDI 0487A.d): D1-1509 Table D1-58
+     *
+     * Unhandled:
+     *    OSLSR_EL1
+     *    DBGPRCR_EL1
+     */
+    case HSR_SYSREG_OSLAR_EL1:
+        return handle_wo_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
+    case HSR_SYSREG_OSDLR_EL1:
+        return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
+
+    /*
+     * MDCR_EL2.TDA
+     *
+     * ARMv8 (DDI 0487A.d): D1-1510 Table D1-59
+     *
+     * Unhandled:
+     *    MDCCINT_EL1
+     *    DBGDTR_EL0
+     *    DBGDTRRX_EL0
+     *    DBGDTRTX_EL0
+     *    OSDTRRX_EL1
+     *    OSDTRTX_EL1
+     *    OSECCR_EL1
+     *    DBGCLAIMSET_EL1
+     *    DBGCLAIMCLR_EL1
+     *    DBGAUTHSTATUS_EL1
+     */
+    case HSR_SYSREG_MDSCR_EL1:
+        return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
+    case HSR_SYSREG_MDCCSR_EL0:
+        /*
+         * Accessible at EL0 only if MDSCR_EL1.TDCC is set to 0. We emulate that
+         * register as RAZ/WI above. So RO at both EL0 and EL1.
+         */
+        return handle_ro_raz(regs, regidx, hsr.sysreg.read, hsr, 0);
+    HSR_SYSREG_DBG_CASES(DBGBVR):
+    HSR_SYSREG_DBG_CASES(DBGBCR):
+    HSR_SYSREG_DBG_CASES(DBGWVR):
+    HSR_SYSREG_DBG_CASES(DBGWCR):
+        return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
+
+    /*
+     * MDCR_EL2.TPM
+     *
+     * ARMv8 (DDI 0487A.d): D1-1511 Table D1-61
+     *
+     * Unhandled:
+     *    PMEVCNTR<n>_EL0
+     *    PMEVTYPER<n>_EL0
+     *    PMCCFILTR_EL0
+     * MDCR_EL2.TPMCR
+     *
+     * ARMv7 (DDI 0406C.b): B1.14.17
+     * ARMv8 (DDI 0487A.d): D1-1511 Table D1-62
+     *
+     * NB: Both MDCR_EL2.TPM and MDCR_EL2.TPMCR cause trapping of PMCR.
+     */
+    case HSR_SYSREG_PMINTENSET_EL1:
+    case HSR_SYSREG_PMINTENCLR_EL1:
+        /*
+         * Accessible from EL1 only, but if EL0 trap happens handle as
+         * undef.
+         */
+        return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
+    case HSR_SYSREG_PMUSERENR_EL0:
+        /* RO at EL0. RAZ/WI at EL1 */
+        if ( psr_mode_is_user(regs) )
+            return handle_ro_raz(regs, regidx, hsr.sysreg.read, hsr, 0);
+        else
+            return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
+    case HSR_SYSREG_PMCR_EL0:
+    case HSR_SYSREG_PMCNTENSET_EL0:
+    case HSR_SYSREG_PMCNTENCLR_EL0:
+    case HSR_SYSREG_PMOVSCLR_EL0:
+    case HSR_SYSREG_PMSWINC_EL0:
+    case HSR_SYSREG_PMSELR_EL0:
+    case HSR_SYSREG_PMCEID0_EL0:
+    case HSR_SYSREG_PMCEID1_EL0:
+    case HSR_SYSREG_PMCCNTR_EL0:
+    case HSR_SYSREG_PMXEVTYPER_EL0:
+    case HSR_SYSREG_PMXEVCNTR_EL0:
+    case HSR_SYSREG_PMOVSSET_EL0:
+        /*
+         * Accessible at EL0 only if PMUSERENR_EL0.EN is set. We
+         * emulate that register as 0 above.
+         */
+        return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
+
+    /*
+     * !CNTHCTL_EL2.EL1PCEN
+     *
+     * ARMv8 (DDI 0487A.d): D1-1510 Table D1-60
+     */
+    case HSR_SYSREG_CNTP_CTL_EL0:
+    case HSR_SYSREG_CNTP_TVAL_EL0:
+    case HSR_SYSREG_CNTP_CVAL_EL0:
+        if ( !vtimer_emulate(regs, hsr) )
+            return inject_undef_exception(regs, hsr);
+        break;
+
+    /*
+     * HCR_EL2.FMO or HCR_EL2.IMO
+     *
+     * GIC Architecture Specification (IHI 0069C): Section 4.6.3
+     */
+    case HSR_SYSREG_ICC_SGI1R_EL1:
+    case HSR_SYSREG_ICC_ASGI1R_EL1:
+    case HSR_SYSREG_ICC_SGI0R_EL1:
+
+        if ( !vgic_emulate(regs, hsr) )
+            return inject_undef64_exception(regs, hsr.len);
+        break;
+
+    /*
+     *  ICC_SRE_EL2.Enable = 0
+     *
+     *  GIC Architecture Specification (IHI 0069C): Section 8.1.9
+     */
+    case HSR_SYSREG_ICC_SRE_EL1:
+        /*
+         * Trapped when the guest is using GICv2 whilst the platform
+         * interrupt controller is GICv3. In this case, the register
+         * should be emulate as RAZ/WI to tell the guest to use the GIC
+         * memory mapped interface (i.e GICv2 compatibility).
+         */
+        return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
+
+    /*
+     * HCR_EL2.TIDCP
+     *
+     * ARMv8 (DDI 0487A.d): D1-1501 Table D1-43
+     *
+     *  - Reserved control space for IMPLEMENTATION DEFINED functionality.
+     *
+     * CPTR_EL2.TTA
+     *
+     * ARMv8 (DDI 0487A.d): D1-1507 Table D1-54
+     *
+     *  - All implemented trace registers.
+     *
+     * And all other unknown registers.
+     */
+    default:
+        {
+            const struct hsr_sysreg sysreg = hsr.sysreg;
+
+            gdprintk(XENLOG_ERR,
+                     "%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);
+            gdprintk(XENLOG_ERR, "unhandled 64-bit sysreg access %#x\n",
+                     hsr.bits & HSR_SYSREG_REGS_MASK);
+            inject_undef_exception(regs, hsr);
+            return;
+        }
+    }
+
+    regs->pc += 4;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index 1c334a7b99..f00aa48892 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -2295,204 +2295,6 @@  static void do_cp(struct cpu_user_regs *regs, const union hsr hsr)
     inject_undef_exception(regs, hsr);
 }
 
-#ifdef CONFIG_ARM_64
-static void do_sysreg(struct cpu_user_regs *regs,
-                      const union hsr hsr)
-{
-    int regidx = hsr.sysreg.reg;
-    struct vcpu *v = current;
-
-    switch ( hsr.bits & HSR_SYSREG_REGS_MASK )
-    {
-    /*
-     * HCR_EL2.TACR
-     *
-     * ARMv8 (DDI 0487A.d): D7.2.1
-     */
-    case HSR_SYSREG_ACTLR_EL1:
-        if ( psr_mode_is_user(regs) )
-            return inject_undef_exception(regs, hsr);
-        if ( hsr.sysreg.read )
-            set_user_reg(regs, regidx, v->arch.actlr);
-        break;
-
-    /*
-     * MDCR_EL2.TDRA
-     *
-     * ARMv8 (DDI 0487A.d): D1-1508 Table D1-57
-     */
-    case HSR_SYSREG_MDRAR_EL1:
-        return handle_ro_raz(regs, regidx, hsr.sysreg.read, hsr, 1);
-
-    /*
-     * MDCR_EL2.TDOSA
-     *
-     * ARMv8 (DDI 0487A.d): D1-1509 Table D1-58
-     *
-     * Unhandled:
-     *    OSLSR_EL1
-     *    DBGPRCR_EL1
-     */
-    case HSR_SYSREG_OSLAR_EL1:
-        return handle_wo_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
-    case HSR_SYSREG_OSDLR_EL1:
-        return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
-
-    /*
-     * MDCR_EL2.TDA
-     *
-     * ARMv8 (DDI 0487A.d): D1-1510 Table D1-59
-     *
-     * Unhandled:
-     *    MDCCINT_EL1
-     *    DBGDTR_EL0
-     *    DBGDTRRX_EL0
-     *    DBGDTRTX_EL0
-     *    OSDTRRX_EL1
-     *    OSDTRTX_EL1
-     *    OSECCR_EL1
-     *    DBGCLAIMSET_EL1
-     *    DBGCLAIMCLR_EL1
-     *    DBGAUTHSTATUS_EL1
-     */
-    case HSR_SYSREG_MDSCR_EL1:
-        return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
-    case HSR_SYSREG_MDCCSR_EL0:
-        /*
-         * Accessible at EL0 only if MDSCR_EL1.TDCC is set to 0. We emulate that
-         * register as RAZ/WI above. So RO at both EL0 and EL1.
-         */
-        return handle_ro_raz(regs, regidx, hsr.sysreg.read, hsr, 0);
-    HSR_SYSREG_DBG_CASES(DBGBVR):
-    HSR_SYSREG_DBG_CASES(DBGBCR):
-    HSR_SYSREG_DBG_CASES(DBGWVR):
-    HSR_SYSREG_DBG_CASES(DBGWCR):
-        return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
-
-    /*
-     * MDCR_EL2.TPM
-     *
-     * ARMv8 (DDI 0487A.d): D1-1511 Table D1-61
-     *
-     * Unhandled:
-     *    PMEVCNTR<n>_EL0
-     *    PMEVTYPER<n>_EL0
-     *    PMCCFILTR_EL0
-     * MDCR_EL2.TPMCR
-     *
-     * ARMv7 (DDI 0406C.b): B1.14.17
-     * ARMv8 (DDI 0487A.d): D1-1511 Table D1-62
-     *
-     * NB: Both MDCR_EL2.TPM and MDCR_EL2.TPMCR cause trapping of PMCR.
-     */
-    case HSR_SYSREG_PMINTENSET_EL1:
-    case HSR_SYSREG_PMINTENCLR_EL1:
-        /*
-         * Accessible from EL1 only, but if EL0 trap happens handle as
-         * undef.
-         */
-        return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
-    case HSR_SYSREG_PMUSERENR_EL0:
-        /* RO at EL0. RAZ/WI at EL1 */
-        if ( psr_mode_is_user(regs) )
-            return handle_ro_raz(regs, regidx, hsr.sysreg.read, hsr, 0);
-        else
-            return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
-    case HSR_SYSREG_PMCR_EL0:
-    case HSR_SYSREG_PMCNTENSET_EL0:
-    case HSR_SYSREG_PMCNTENCLR_EL0:
-    case HSR_SYSREG_PMOVSCLR_EL0:
-    case HSR_SYSREG_PMSWINC_EL0:
-    case HSR_SYSREG_PMSELR_EL0:
-    case HSR_SYSREG_PMCEID0_EL0:
-    case HSR_SYSREG_PMCEID1_EL0:
-    case HSR_SYSREG_PMCCNTR_EL0:
-    case HSR_SYSREG_PMXEVTYPER_EL0:
-    case HSR_SYSREG_PMXEVCNTR_EL0:
-    case HSR_SYSREG_PMOVSSET_EL0:
-        /*
-         * Accessible at EL0 only if PMUSERENR_EL0.EN is set. We
-         * emulate that register as 0 above.
-         */
-        return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
-
-    /*
-     * !CNTHCTL_EL2.EL1PCEN
-     *
-     * ARMv8 (DDI 0487A.d): D1-1510 Table D1-60
-     */
-    case HSR_SYSREG_CNTP_CTL_EL0:
-    case HSR_SYSREG_CNTP_TVAL_EL0:
-    case HSR_SYSREG_CNTP_CVAL_EL0:
-        if ( !vtimer_emulate(regs, hsr) )
-            return inject_undef_exception(regs, hsr);
-        break;
-
-    /*
-     * HCR_EL2.FMO or HCR_EL2.IMO
-     *
-     * GIC Architecture Specification (IHI 0069C): Section 4.6.3
-     */
-    case HSR_SYSREG_ICC_SGI1R_EL1:
-    case HSR_SYSREG_ICC_ASGI1R_EL1:
-    case HSR_SYSREG_ICC_SGI0R_EL1:
-
-        if ( !vgic_emulate(regs, hsr) )
-            return inject_undef64_exception(regs, hsr.len);
-        break;
-
-    /*
-     *  ICC_SRE_EL2.Enable = 0
-     *
-     *  GIC Architecture Specification (IHI 0069C): Section 8.1.9
-     */
-    case HSR_SYSREG_ICC_SRE_EL1:
-        /*
-         * Trapped when the guest is using GICv2 whilst the platform
-         * interrupt controller is GICv3. In this case, the register
-         * should be emulate as RAZ/WI to tell the guest to use the GIC
-         * memory mapped interface (i.e GICv2 compatibility).
-         */
-        return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
-
-    /*
-     * HCR_EL2.TIDCP
-     *
-     * ARMv8 (DDI 0487A.d): D1-1501 Table D1-43
-     *
-     *  - Reserved control space for IMPLEMENTATION DEFINED functionality.
-     *
-     * CPTR_EL2.TTA
-     *
-     * ARMv8 (DDI 0487A.d): D1-1507 Table D1-54
-     *
-     *  - All implemented trace registers.
-     *
-     * And all other unknown registers.
-     */
-    default:
-        {
-            const struct hsr_sysreg sysreg = hsr.sysreg;
-
-            gdprintk(XENLOG_ERR,
-                     "%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);
-            gdprintk(XENLOG_ERR, "unhandled 64-bit sysreg access %#x\n",
-                     hsr.bits & HSR_SYSREG_REGS_MASK);
-            inject_undef_exception(regs, hsr);
-            return;
-        }
-    }
-
-    regs->pc += 4;
-}
-#endif
-
 void dump_guest_s1_walk(struct domain *d, vaddr_t addr)
 {
     register_t ttbcr = READ_SYSREG(TCR_EL1);
diff --git a/xen/include/asm-arm/arm64/traps.h b/xen/include/asm-arm/arm64/traps.h
index e5e5a4a036..2379b578cb 100644
--- a/xen/include/asm-arm/arm64/traps.h
+++ b/xen/include/asm-arm/arm64/traps.h
@@ -3,6 +3,9 @@ 
 
 void inject_undef64_exception(struct cpu_user_regs *regs, int instr_len);
 
+void do_sysreg(struct cpu_user_regs *regs,
+               const union hsr hsr);
+
 #endif /* __ASM_ARM64_TRAPS__ */
 /*
  * Local variables: