From: Ian Campbell <ian.campbell@citrix.com>
To: xen-devel@lists.xen.org
Cc: julien.grall@citrix.com, tim@xen.org,
Ian Campbell <ian.campbell@citrix.com>,
stefano.stabellini@eu.citrix.com
Subject: [PATCH 14/17] xen: arm: handle 64-bit system register access traps.
Date: Mon, 29 Jul 2013 13:21:03 +0100 [thread overview]
Message-ID: <1375100466-7564-14-git-send-email-ian.campbell@citrix.com> (raw)
In-Reply-To: <1375100431.14896.95.camel@kazak.uk.xensource.com>
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@citrix.com>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
---
xen/arch/arm/traps.c | 39 ++++++++++++
xen/arch/arm/vtimer.c | 130 ++++++++++++++++++++++++++-------------
xen/include/asm-arm/processor.h | 32 ++++++++++
xen/include/asm-arm/sysregs.h | 56 +++++++++++++++++
4 files changed, 213 insertions(+), 44 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 32de87f..ac70984 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -1098,6 +1098,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);
@@ -1261,7 +1294,13 @@ asmlinkage void do_trap_hypervisor(struct cpu_user_regs *regs)
return do_trap_psci(regs);
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 aee762a..d58a630 100644
--- a/xen/arch/arm/vtimer.c
+++ b/xen/arch/arm/vtimer.c
@@ -112,57 +112,67 @@ 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
+ {
+ uint32_t ctl = *r & ~CNTx_CTL_PENDING;
+ if ( ctl & CNTx_CTL_ENABLE )
+ ctl |= v->arch.phys_timer.ctl & CNTx_CTL_PENDING;
+ v->arch.phys_timer.ctl = ctl;
+
+ 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->domain->arch.phys_timer_base.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->domain->arch.phys_timer_base.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 )
{
- uint32_t ctl = *r & ~CNTx_CTL_PENDING;
- if ( ctl & CNTx_CTL_ENABLE )
- ctl |= v->arch.phys_timer.ctl & CNTx_CTL_PENDING;
- v->arch.phys_timer.ctl = ctl;
-
- if ( v->arch.phys_timer.ctl & CNTx_CTL_ENABLE )
- {
- set_timer(&v->arch.phys_timer.timer,
- v->arch.phys_timer.cval +
- v->domain->arch.phys_timer_base.offset);
- }
- else
- stop_timer(&v->arch.phys_timer.timer);
+ v->arch.phys_timer.ctl &= ~CNTx_CTL_PENDING;
+ set_timer(&v->arch.phys_timer.timer,
+ v->arch.phys_timer.cval +
+ v->domain->arch.phys_timer_base.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->domain->arch.phys_timer_base.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 )
- {
- v->arch.phys_timer.ctl &= ~CNTx_CTL_PENDING;
- set_timer(&v->arch.phys_timer.timer,
- v->arch.phys_timer.cval +
- v->domain->arch.phys_timer_base.offset);
- }
- }
-
+ vtimer_cntp_tval(regs, r, cp32.read);
return 1;
default:
@@ -170,7 +180,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;
@@ -201,16 +211,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 d662f07..fa175d9 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
@@ -97,6 +98,7 @@
#define HSR_EC_SMC 0x13
#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
@@ -256,6 +258,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 */
@@ -298,6 +315,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.2.5
next prev parent reply other threads:[~2013-07-29 12:21 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-07-29 12:20 [PATCH v4 00/17] xen: arm: 64-bit dom0 kernel support Ian Campbell
2013-07-29 12:20 ` [PATCH 01/17] xen: arm: tweak arm64 stack frame layout Ian Campbell
2013-07-29 12:20 ` [PATCH 02/17] xen: arm: rename 32-bit specific zImage field offset constants Ian Campbell
2013-07-29 12:20 ` [PATCH 03/17] xen: arm: support for loading 64-bit zImage dom0 Ian Campbell
2013-07-29 12:20 ` [PATCH 04/17] xen: arm: support building a 64-bit dom0 domain Ian Campbell
2013-07-29 18:29 ` Julien Grall
2013-07-30 9:34 ` Ian Campbell
2013-07-30 9:43 ` Julien Grall
2013-08-02 16:07 ` Ian Campbell
2013-07-29 12:20 ` [PATCH 05/17] xen: arm: precalculate VTTBR_EL2 for a domain when setting up its p2m Ian Campbell
2013-07-29 12:20 ` [PATCH 06/17] xen: arm: improve register dump output for 64-bit guest (and more generally too) Ian Campbell
2013-07-29 12:53 ` Tim Deegan
2013-07-29 12:20 ` [PATCH 07/17] xen: arm: support dumping 64-bit guest stack Ian Campbell
2013-07-29 12:20 ` [PATCH 08/17] xen: arm: show less words in a line of a stack trace in 64-bit builds Ian Campbell
2013-07-29 12:20 ` [PATCH 09/17] xen: arm: Set EL1 register width in HCR_EL2 during context switch Ian Campbell
2013-07-29 12:20 ` [PATCH 10/17] xen: arm: some cleanups to hypervisor entry code Ian Campbell
2013-07-29 12:56 ` Tim Deegan
2013-07-29 12:21 ` [PATCH 11/17] xen: arm: refactor 64-bit return from trap path Ian Campbell
2013-07-29 13:01 ` Tim Deegan
2013-07-29 12:21 ` [PATCH 12/17] xen: arm: handle traps from 64-bit guests Ian Campbell
2013-07-29 13:49 ` Tim Deegan
2013-07-29 12:21 ` [PATCH 13/17] xen: arm: handle hypercalls " Ian Campbell
2013-07-29 12:21 ` Ian Campbell [this message]
2013-07-29 12:21 ` [PATCH 15/17] xen: arm: align some comments Ian Campbell
2013-07-29 12:21 ` [PATCH 16/17] xen: arm: document HCR bits Ian Campbell
2013-07-29 12:21 ` [PATCH 17/17] xen: arm: Handle SMC from 64-bit guests Ian Campbell
2013-07-29 13:53 ` Tim Deegan
2013-07-29 12:21 ` [PATCH v4 00/17] xen: arm: 64-bit dom0 kernel support Ian Campbell
2013-07-29 15:58 ` Ian Campbell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1375100466-7564-14-git-send-email-ian.campbell@citrix.com \
--to=ian.campbell@citrix.com \
--cc=julien.grall@citrix.com \
--cc=stefano.stabellini@eu.citrix.com \
--cc=tim@xen.org \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).