* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include <uk/arch/lcpu.h>
+#include <uk/arch/ctx.h>
+#include <uk/plat/config.h>
#include <uk/plat/common/bootinfo.h>
#include <uk/plat/common/acpi.h>
#include <uk/plat/lcpu.h>
#define CPU_ID_MASK 0xff00ffffffUL
+/*
+ * STACK_SIZE STACK_SIZE
+ * <---------------------><--------------------->
+ * |============================================|
+ * | | |
+ * | trap stack | IRQ stack |
+ * | | |
+ * |=============================================
+ * ^
+ * SP_EL0
+ */
+static __align(UKARCH_SP_ALIGN)
+UKPLAT_PER_LCPU_ARRAY_DEFINE(__u8, lcpu_irqntrap_sp, STACK_SIZE * 2);
+
__lcpuid lcpu_arch_id(void)
{
__u64 mpidr_reg;
int lcpu_arch_init(struct lcpu *this_lcpu)
{
+ __uptr irqntrap_sp;
int ret = 0;
/* Initialize the interrupt controller for non-bsp cores */
SYSREG_WRITE64(tpidr_el1, (__uptr)this_lcpu);
+ irqntrap_sp = (__uptr)&ukplat_per_lcpu_array_current(lcpu_irqntrap_sp,
+ STACK_SIZE / 2);
+ SYSREG_WRITE64(sp_el0, irqntrap_sp);
+
return ret;
}
*/
#include <uk/arch/lcpu.h>
#include <uk/asm.h>
+#include <uk/plat/common/lcpu.h>
+#include <uk/plat/config.h>
.macro EXCHANGE_SP_WITH_X0
add sp, sp, x0 // new_sp = sp + x0
EXCHANGE_SP_WITH_X0
.endm
-.macro SAVE_REGS
- sub sp, sp, #__TRAP_STACK_SIZE
+.macro SAVE_REGS, is_irq
+ /* Use TPIDRRO_EL0 as scratch register. It is fine to do so because
+ * it will always hold a value the application can't modify and we will
+ * always be able to restore it to its desired known value anytime we
+ * want. Thus, temporarily store x0.
+ */
+ msr tpidrro_el0, x0
+
+ /* Fetch middle of `lcpu_irqntrap_sp`:
+ * STACK_SIZE STACK_SIZE
+ * <---------------------><--------------------->
+ * |============================================|
+ * | | |
+ * | trap stack | IRQ stack |
+ * | | |
+ * |=============================================
+ * ^
+ * SP_EL0
+ */
+ mrs x0, sp_el0
+
+ /* Make it so that SP contains SP_EL0 and x0 contains old SP */
+ EXCHANGE_SP_WITH_X0
+
+.if \is_irq != 0
+ /* If we are an IRQ, use the IRQ stack instead. */
+ add sp, sp, #STACK_SIZE
+.endif
+
+ /* Store old SP previously saved into x0 */
+ str x0, [sp, #-16]
+
+ /* Restore x0 */
+ mrs x0, tpidrro_el0
+
+ /* Begin saving registers */
+ sub sp, sp, #__TRAP_STACK_SIZE
/* Save general purpose registers */
- stp x0, x1, [sp, #16 * 0]
- stp x2, x3, [sp, #16 * 1]
- stp x4, x5, [sp, #16 * 2]
- stp x6, x7, [sp, #16 * 3]
- stp x8, x9, [sp, #16 * 4]
- stp x10, x11, [sp, #16 * 5]
- stp x12, x13, [sp, #16 * 6]
- stp x14, x15, [sp, #16 * 7]
- stp x16, x17, [sp, #16 * 8]
- stp x18, x19, [sp, #16 * 9]
- stp x20, x21, [sp, #16 * 10]
- stp x22, x23, [sp, #16 * 11]
- stp x24, x25, [sp, #16 * 12]
- stp x26, x27, [sp, #16 * 13]
- stp x28, x29, [sp, #16 * 14]
+ stp x0, x1, [sp, #16 * 0]
+ stp x2, x3, [sp, #16 * 1]
+ stp x4, x5, [sp, #16 * 2]
+ stp x6, x7, [sp, #16 * 3]
+ stp x8, x9, [sp, #16 * 4]
+ stp x10, x11, [sp, #16 * 5]
+ stp x12, x13, [sp, #16 * 6]
+ stp x14, x15, [sp, #16 * 7]
+ stp x16, x17, [sp, #16 * 8]
+ stp x18, x19, [sp, #16 * 9]
+ stp x20, x21, [sp, #16 * 10]
+ stp x22, x23, [sp, #16 * 11]
+ stp x24, x25, [sp, #16 * 12]
+ stp x26, x27, [sp, #16 * 13]
+ stp x28, x29, [sp, #16 * 14]
/* Save LR and exception PC */
- mrs x21, elr_el1
- stp x30, x21, [sp, #16 * 15]
+ mrs x21, elr_el1
+ stp x30, x21, [sp, #16 * 15]
/* Save pstate and exception status register */
- mrs x22, spsr_el1
- mrs x23, esr_el1
- stp x22, x23, [sp, #16 * 16]
+ mrs x22, spsr_el1
+ mrs x23, esr_el1
+ stp x22, x23, [sp, #16 * 16]
.endm
.macro RESTORE_REGS
/* Restore x18, x19 */
ldp x18, x19, [x19, #16 * 9]
- add sp, sp, #__TRAP_STACK_SIZE
-
eret
.endm
*/
.align 6
el1_sync:
- SAVE_REGS
+ SAVE_REGS 0
mov x0, sp
mrs x1, far_el1
bl trap_el1_sync
.align 6
el1_irq:
- SAVE_REGS
+ SAVE_REGS 1
msr daifclr, #(8 | 4 | 1)
mov x0, sp
bl trap_el1_irq
#define el_invalid(name, reason, el) \
.align 6; \
name##_invalid: \
- SAVE_REGS; \
+ SAVE_REGS 0; \
mov x0, sp; \
mov x1, el; \
mov x2, #(reason); \