blob: 3151294cee66ddc7870e68cdfeb1c1d851daefa4 [file] [log] [blame]
Achin Gupta4f6ad662013-10-25 09:08:21 +01001/*
Dan Handleye83b0ca2014-01-14 18:17:09 +00002 * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
Achin Gupta4f6ad662013-10-25 09:08:21 +01003 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * Neither the name of ARM nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific
16 * prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <arch_helpers.h>
32#include <platform.h>
33#include <bl_common.h>
34#include <bl31.h>
35#include <psci.h>
36#include <assert.h>
37#include <runtime_svc.h>
38
39/*******************************************************************************
40 * This function checks whether this is a valid smc e.g.
41 * the function id is correct, top word of args are zeroed
42 * when aarch64 makes an aarch32 call etc.
43 ******************************************************************************/
44int validate_smc(gp_regs *regs)
45{
46 unsigned int rw = GET_RW(regs->spsr);
47 unsigned int cc = GET_SMC_CC(regs->x0);
48
49 /* Check if there is a difference in the caller RW and SMC CC */
50 if (rw == cc) {
51
52 /* Check whether the caller has chosen the right func. id */
53 if (cc == SMC_64) {
54 regs->x0 = SMC_UNK;
55 return SMC_UNK;
56 }
57
58 /*
59 * Paranoid check to zero the top word of passed args
60 * irrespective of caller's register width.
61 *
62 * TODO: Check if this needed if the caller is aarch32
63 */
64 regs->x0 &= (unsigned int) 0xFFFFFFFF;
65 regs->x1 &= (unsigned int) 0xFFFFFFFF;
66 regs->x2 &= (unsigned int) 0xFFFFFFFF;
67 regs->x3 &= (unsigned int) 0xFFFFFFFF;
68 regs->x4 &= (unsigned int) 0xFFFFFFFF;
69 regs->x5 &= (unsigned int) 0xFFFFFFFF;
70 regs->x6 &= (unsigned int) 0xFFFFFFFF;
71 }
72
73 return 0;
74}
75
76/* TODO: Break down the SMC handler into fast and standard SMC handlers. */
77void smc_handler(unsigned type, unsigned long esr, gp_regs *regs)
78{
79 /* Check if the SMC has been correctly called */
80 if (validate_smc(regs) != 0)
81 return;
82
83 switch (regs->x0) {
84 case PSCI_VERSION:
85 regs->x0 = psci_version();
86 break;
87
88 case PSCI_CPU_OFF:
89 regs->x0 = __psci_cpu_off();
90 break;
91
92 case PSCI_CPU_SUSPEND_AARCH64:
93 case PSCI_CPU_SUSPEND_AARCH32:
94 regs->x0 = __psci_cpu_suspend(regs->x1, regs->x2, regs->x3);
95 break;
96
97 case PSCI_CPU_ON_AARCH64:
98 case PSCI_CPU_ON_AARCH32:
99 regs->x0 = psci_cpu_on(regs->x1, regs->x2, regs->x3);
100 break;
101
102 case PSCI_AFFINITY_INFO_AARCH32:
103 case PSCI_AFFINITY_INFO_AARCH64:
104 regs->x0 = psci_affinity_info(regs->x1, regs->x2);
105 break;
106
107 default:
108 regs->x0 = SMC_UNK;
109 }
110
111 return;
112}
113
114void irq_handler(unsigned type, unsigned long esr, gp_regs *regs)
115{
116 plat_report_exception(type);
117 assert(0);
118}
119
120void fiq_handler(unsigned type, unsigned long esr, gp_regs *regs)
121{
122 plat_report_exception(type);
123 assert(0);
124}
125
126void serror_handler(unsigned type, unsigned long esr, gp_regs *regs)
127{
128 plat_report_exception(type);
129 assert(0);
130}
131
132void sync_exception_handler(unsigned type, gp_regs *regs)
133{
134 unsigned long esr = read_esr();
135 unsigned int ec = EC_BITS(esr);
136
137 switch (ec) {
138
139 case EC_AARCH32_SMC:
140 case EC_AARCH64_SMC:
141 smc_handler(type, esr, regs);
142 break;
143
144 default:
145 plat_report_exception(type);
146 assert(0);
147 }
148 return;
149}
150
151void async_exception_handler(unsigned type, gp_regs *regs)
152{
153 unsigned long esr = read_esr();
154
155 switch (type) {
156
157 case IRQ_SP_EL0:
158 case IRQ_SP_ELX:
159 case IRQ_AARCH64:
160 case IRQ_AARCH32:
161 irq_handler(type, esr, regs);
162 break;
163
164 case FIQ_SP_EL0:
165 case FIQ_SP_ELX:
166 case FIQ_AARCH64:
167 case FIQ_AARCH32:
168 fiq_handler(type, esr, regs);
169 break;
170
171 case SERROR_SP_EL0:
172 case SERROR_SP_ELX:
173 case SERROR_AARCH64:
174 case SERROR_AARCH32:
175 serror_handler(type, esr, regs);
176 break;
177
178 default:
179 plat_report_exception(type);
180 assert(0);
181 }
182
183 return;
184}