1 /*
2  * xen/arch/arm/arm64/sysreg.c
3  *
4  * Emulate system registers trapped.
5  *
6  * Copyright (c) 2011 Citrix Systems.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  */
18 
19 #include <xen/sched.h>
20 
21 #include <asm/current.h>
22 #include <asm/regs.h>
23 #include <asm/traps.h>
24 #include <asm/vtimer.h>
25 
do_sysreg(struct cpu_user_regs * regs,const union hsr hsr)26 void do_sysreg(struct cpu_user_regs *regs,
27                const union hsr hsr)
28 {
29     int regidx = hsr.sysreg.reg;
30     struct vcpu *v = current;
31 
32     switch ( hsr.bits & HSR_SYSREG_REGS_MASK )
33     {
34     /*
35      * HCR_EL2.TACR
36      *
37      * ARMv8 (DDI 0487A.d): D7.2.1
38      */
39     case HSR_SYSREG_ACTLR_EL1:
40         if ( psr_mode_is_user(regs) )
41             return inject_undef_exception(regs, hsr);
42         if ( hsr.sysreg.read )
43             set_user_reg(regs, regidx, v->arch.actlr);
44         break;
45 
46     /*
47      * MDCR_EL2.TDRA
48      *
49      * ARMv8 (DDI 0487A.d): D1-1508 Table D1-57
50      */
51     case HSR_SYSREG_MDRAR_EL1:
52         return handle_ro_raz(regs, regidx, hsr.sysreg.read, hsr, 1);
53 
54     /*
55      * MDCR_EL2.TDOSA
56      *
57      * ARMv8 (DDI 0487A.d): D1-1509 Table D1-58
58      *
59      * Unhandled:
60      *    OSLSR_EL1
61      *    DBGPRCR_EL1
62      */
63     case HSR_SYSREG_OSLAR_EL1:
64         return handle_wo_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
65     case HSR_SYSREG_OSDLR_EL1:
66         return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
67 
68     /*
69      * MDCR_EL2.TDA
70      *
71      * ARMv8 (DDI 0487A.d): D1-1510 Table D1-59
72      *
73      * Unhandled:
74      *    MDCCINT_EL1
75      *    DBGDTR_EL0
76      *    DBGDTRRX_EL0
77      *    DBGDTRTX_EL0
78      *    OSDTRRX_EL1
79      *    OSDTRTX_EL1
80      *    OSECCR_EL1
81      *    DBGCLAIMSET_EL1
82      *    DBGCLAIMCLR_EL1
83      *    DBGAUTHSTATUS_EL1
84      */
85     case HSR_SYSREG_MDSCR_EL1:
86         return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
87     case HSR_SYSREG_MDCCSR_EL0:
88         /*
89          * Accessible at EL0 only if MDSCR_EL1.TDCC is set to 0. We emulate that
90          * register as RAZ/WI above. So RO at both EL0 and EL1.
91          */
92         return handle_ro_raz(regs, regidx, hsr.sysreg.read, hsr, 0);
93     HSR_SYSREG_DBG_CASES(DBGBVR):
94     HSR_SYSREG_DBG_CASES(DBGBCR):
95     HSR_SYSREG_DBG_CASES(DBGWVR):
96     HSR_SYSREG_DBG_CASES(DBGWCR):
97         return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
98 
99     /*
100      * MDCR_EL2.TPM
101      *
102      * ARMv8 (DDI 0487A.d): D1-1511 Table D1-61
103      *
104      * Unhandled:
105      *    PMEVCNTR<n>_EL0
106      *    PMEVTYPER<n>_EL0
107      *    PMCCFILTR_EL0
108      * MDCR_EL2.TPMCR
109      *
110      * ARMv7 (DDI 0406C.b): B1.14.17
111      * ARMv8 (DDI 0487A.d): D1-1511 Table D1-62
112      *
113      * NB: Both MDCR_EL2.TPM and MDCR_EL2.TPMCR cause trapping of PMCR.
114      */
115     case HSR_SYSREG_PMINTENSET_EL1:
116     case HSR_SYSREG_PMINTENCLR_EL1:
117         /*
118          * Accessible from EL1 only, but if EL0 trap happens handle as
119          * undef.
120          */
121         return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
122     case HSR_SYSREG_PMUSERENR_EL0:
123         /* RO at EL0. RAZ/WI at EL1 */
124         if ( psr_mode_is_user(regs) )
125             return handle_ro_raz(regs, regidx, hsr.sysreg.read, hsr, 0);
126         else
127             return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
128     case HSR_SYSREG_PMCR_EL0:
129     case HSR_SYSREG_PMCNTENSET_EL0:
130     case HSR_SYSREG_PMCNTENCLR_EL0:
131     case HSR_SYSREG_PMOVSCLR_EL0:
132     case HSR_SYSREG_PMSWINC_EL0:
133     case HSR_SYSREG_PMSELR_EL0:
134     case HSR_SYSREG_PMCEID0_EL0:
135     case HSR_SYSREG_PMCEID1_EL0:
136     case HSR_SYSREG_PMCCNTR_EL0:
137     case HSR_SYSREG_PMXEVTYPER_EL0:
138     case HSR_SYSREG_PMXEVCNTR_EL0:
139     case HSR_SYSREG_PMOVSSET_EL0:
140         /*
141          * Accessible at EL0 only if PMUSERENR_EL0.EN is set. We
142          * emulate that register as 0 above.
143          */
144         return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
145 
146     /*
147      * !CNTHCTL_EL2.EL1PCEN
148      *
149      * ARMv8 (DDI 0487A.d): D1-1510 Table D1-60
150      */
151     case HSR_SYSREG_CNTP_CTL_EL0:
152     case HSR_SYSREG_CNTP_TVAL_EL0:
153     case HSR_SYSREG_CNTP_CVAL_EL0:
154         if ( !vtimer_emulate(regs, hsr) )
155             return inject_undef_exception(regs, hsr);
156         break;
157 
158     /*
159      * HCR_EL2.FMO or HCR_EL2.IMO
160      *
161      * GIC Architecture Specification (IHI 0069C): Section 4.6.3
162      */
163     case HSR_SYSREG_ICC_SGI1R_EL1:
164     case HSR_SYSREG_ICC_ASGI1R_EL1:
165     case HSR_SYSREG_ICC_SGI0R_EL1:
166 
167         if ( !vgic_emulate(regs, hsr) )
168             return inject_undef64_exception(regs, hsr.len);
169         break;
170 
171     /*
172      *  ICC_SRE_EL2.Enable = 0
173      *
174      *  GIC Architecture Specification (IHI 0069C): Section 8.1.9
175      */
176     case HSR_SYSREG_ICC_SRE_EL1:
177         /*
178          * Trapped when the guest is using GICv2 whilst the platform
179          * interrupt controller is GICv3. In this case, the register
180          * should be emulate as RAZ/WI to tell the guest to use the GIC
181          * memory mapped interface (i.e GICv2 compatibility).
182          */
183         return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
184 
185     /*
186      * HCR_EL2.TIDCP
187      *
188      * ARMv8 (DDI 0487A.d): D1-1501 Table D1-43
189      *
190      *  - Reserved control space for IMPLEMENTATION DEFINED functionality.
191      *
192      * CPTR_EL2.TTA
193      *
194      * ARMv8 (DDI 0487A.d): D1-1507 Table D1-54
195      *
196      *  - All implemented trace registers.
197      *
198      * And all other unknown registers.
199      */
200     default:
201         {
202             const struct hsr_sysreg sysreg = hsr.sysreg;
203 
204             gdprintk(XENLOG_ERR,
205                      "%s %d, %d, c%d, c%d, %d %s x%d @ 0x%"PRIregister"\n",
206                      sysreg.read ? "mrs" : "msr",
207                      sysreg.op0, sysreg.op1,
208                      sysreg.crn, sysreg.crm,
209                      sysreg.op2,
210                      sysreg.read ? "=>" : "<=",
211                      sysreg.reg, regs->pc);
212             gdprintk(XENLOG_ERR, "unhandled 64-bit sysreg access %#x\n",
213                      hsr.bits & HSR_SYSREG_REGS_MASK);
214             inject_undef_exception(regs, hsr);
215             return;
216         }
217     }
218 
219     regs->pc += 4;
220 }
221 
222 /*
223  * Local variables:
224  * mode: C
225  * c-file-style: "BSD"
226  * c-basic-offset: 4
227  * indent-tabs-mode: nil
228  * End:
229  */
230