1 #ifndef __ASM_ARM_TRAPS__
2 #define __ASM_ARM_TRAPS__
3 
4 #include <asm/hsr.h>
5 #include <asm/processor.h>
6 
7 #if defined(CONFIG_ARM_32)
8 # include <asm/arm32/traps.h>
9 #elif defined(CONFIG_ARM_64)
10 # include <asm/arm64/traps.h>
11 #endif
12 
13 #ifdef CONFIG_PARTIAL_EMULATION
14 extern bool partial_emulation;
15 #else
16 #define partial_emulation false
17 #endif
18 
19 /*
20  * GUEST_BUG_ON is intended for checking that the guest state has not been
21  * corrupted in hardware and/or that the hardware behaves as we
22  * believe it should (i.e. that certain traps can only occur when the
23  * guest is in a particular mode).
24  *
25  * The intention is to limit the damage such h/w bugs (or spec
26  * misunderstandings) can do by turning them into Denial of Service
27  * attacks instead of e.g. information leaks or privilege escalations.
28  *
29  * GUEST_BUG_ON *MUST* *NOT* be used to check for guest controllable state!
30  *
31  * Compared with regular BUG_ON it dumps the guest vcpu state instead
32  * of Xen's state.
33  */
34 #define guest_bug_on_failed(p)                          \
35 do {                                                    \
36     show_execution_state(guest_cpu_user_regs());        \
37     panic("Guest Bug: %pv: '%s', line %d, file %s\n",   \
38           current, p, __LINE__, __FILE__);              \
39 } while (0)
40 #define GUEST_BUG_ON(p) \
41     do { if ( unlikely(p) ) guest_bug_on_failed(#p); } while (0)
42 
43 int check_conditional_instr(struct cpu_user_regs *regs, const union hsr hsr);
44 
45 void advance_pc(struct cpu_user_regs *regs, const union hsr hsr);
46 
47 void inject_undef_exception(struct cpu_user_regs *regs);
48 
49 /* read as zero and write ignore */
50 void handle_raz_wi(struct cpu_user_regs *regs, int regidx, bool read,
51                    const union hsr hsr, int min_el);
52 
53 /* write only as write ignore */
54 void handle_wo_wi(struct cpu_user_regs *regs, int regidx, bool read,
55                   const union hsr hsr, int min_el);
56 
57 /* read only as read as zero */
58 void handle_ro_raz(struct cpu_user_regs *regs, int regidx, bool read,
59                    const union hsr hsr, int min_el);
60 
61 /* Read only as value provided with 'val' argument */
62 void handle_ro_read_val(struct cpu_user_regs *regs, int regidx, bool read,
63                         const union hsr hsr, int min_el, register_t val);
64 
65 /* Co-processor registers emulation (see arch/arm/vcpreg.c). */
66 void do_cp15_32(struct cpu_user_regs *regs, const union hsr hsr);
67 void do_cp15_64(struct cpu_user_regs *regs, const union hsr hsr);
68 void do_cp14_32(struct cpu_user_regs *regs, const union hsr hsr);
69 void do_cp14_64(struct cpu_user_regs *regs, const union hsr hsr);
70 void do_cp14_dbg(struct cpu_user_regs *regs, const union hsr hsr);
71 void do_cp10(struct cpu_user_regs *regs, const union hsr hsr);
72 void do_cp(struct cpu_user_regs *regs, const union hsr hsr);
73 
74 /* SMCCC handling */
75 void do_trap_smc(struct cpu_user_regs *regs, const union hsr hsr);
76 void do_trap_hvc_smccc(struct cpu_user_regs *regs);
77 
78 int do_bug_frame(const struct cpu_user_regs *regs, vaddr_t pc);
79 
80 void noreturn do_unexpected_trap(const char *msg,
81                                  const struct cpu_user_regs *regs);
82 void do_trap_hyp_sync(struct cpu_user_regs *regs);
83 
84 /* Functions for pending virtual abort checking window. */
85 void abort_guest_exit_start(void);
86 void abort_guest_exit_end(void);
87 
VABORT_GEN_BY_GUEST(const struct cpu_user_regs * regs)88 static inline bool VABORT_GEN_BY_GUEST(const struct cpu_user_regs *regs)
89 {
90     return ((unsigned long)abort_guest_exit_start == regs->pc) ||
91         (unsigned long)abort_guest_exit_end == regs->pc;
92 }
93 
94 /* Check whether the sign extension is required and perform it */
sign_extend(const struct hsr_dabt dabt,register_t r)95 static inline register_t sign_extend(const struct hsr_dabt dabt, register_t r)
96 {
97     uint8_t size = (1 << dabt.size) * 8;
98 
99     /*
100      * Sign extend if required.
101      * Note that we expect the read handler to have zeroed the bits
102      * outside the requested access size.
103      */
104     if ( dabt.sign && (size < sizeof(register_t) * 8) &&
105          (r & (1UL << (size - 1))) )
106     {
107         /*
108          * We are relying on register_t using the same as
109          * an unsigned long in order to keep the 32-bit assembly
110          * code smaller.
111          */
112         BUILD_BUG_ON(sizeof(register_t) != sizeof(unsigned long));
113         r |= (~0UL) << size;
114     }
115 
116     return r;
117 }
118 
119 void finalize_instr_emulation(const struct instr_details *instr);
120 
121 #endif /* __ASM_ARM_TRAPS__ */
122 /*
123  * Local variables:
124  * mode: C
125  * c-file-style: "BSD"
126  * c-basic-offset: 4
127  * indent-tabs-mode: nil
128  * End:
129  */
130 
131