1 /*
2  * xen/arch/arm/arm64/traps.c
3  *
4  * ARM AArch64 Specific Trap handlers
5  *
6  * Copyright (c) 2012 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/lib.h>
20 #include <xen/sched.h>
21 
22 #include <asm/hsr.h>
23 #include <asm/system.h>
24 #include <asm/processor.h>
25 #include <asm/traps.h>
26 
27 #include <public/xen.h>
28 
29 static const char *handler[]= {
30         "Synchronous Abort",
31         "IRQ",
32         "FIQ",
33         "Error"
34 };
35 
do_bad_mode(struct cpu_user_regs * regs,int reason)36 void do_bad_mode(struct cpu_user_regs *regs, int reason)
37 {
38     union hsr hsr = { .bits = regs->hsr };
39 
40     printk("Bad mode in %s handler detected\n", handler[reason]);
41     printk("ESR=%#"PRIregister":  EC=%"PRIx32", IL=%"PRIx32", ISS=%"PRIx32"\n",
42            hsr.bits, hsr.ec, hsr.len, hsr.iss);
43 
44     local_irq_disable();
45     show_execution_state(regs);
46     panic("bad mode\n");
47 }
48 
finalize_instr_emulation(const struct instr_details * instr)49 void finalize_instr_emulation(const struct instr_details *instr)
50 {
51     struct cpu_user_regs *regs = guest_cpu_user_regs();
52     register_t val = 0;
53     uint8_t psr_mode = (regs->cpsr & PSR_MODE_MASK);
54 
55     /* Currently, we handle only ldr/str post indexing instructions */
56     if ( instr->state != INSTR_LDR_STR_POSTINDEXING )
57         return;
58 
59     /*
60      * Handle when rn = SP
61      * Refer ArmV8 ARM DDI 0487G.b, Page - D1-2463 "Stack pointer register
62      * selection"
63      * t = SP_EL0
64      * h = SP_ELx
65      * and M[3:0] (Page - C5-474 "When exception taken from AArch64 state:")
66      */
67     if ( instr->rn == 31 )
68     {
69         switch ( psr_mode )
70         {
71         case PSR_MODE_EL1h:
72             val = regs->sp_el1;
73             break;
74         case PSR_MODE_EL1t:
75         case PSR_MODE_EL0t:
76             val = regs->sp_el0;
77             break;
78 
79         default:
80             domain_crash(current->domain);
81             return;
82         }
83     }
84     else
85         val = get_user_reg(regs, instr->rn);
86 
87     val += instr->imm9;
88 
89     if ( instr->rn == 31 )
90     {
91         if ( (regs->cpsr & PSR_MODE_MASK) == PSR_MODE_EL1h )
92             regs->sp_el1 = val;
93         else
94             regs->sp_el0 = val;
95     }
96     else
97         set_user_reg(regs, instr->rn, val);
98 }
99 
100 /*
101  * Local variables:
102  * mode: C
103  * c-file-style: "BSD"
104  * c-basic-offset: 4
105  * indent-tabs-mode: nil
106  * End:
107  */
108