1:
/* OK, we're in Secure state. */
PRINT("- Started in Secure state -\r\n- Entering Hyp mode -\r\n")
-
- /* Dance into Hyp mode */
- cpsid aif, #0x16 /* Enter Monitor mode */
- mrc CP32(r0, SCR)
- orr r0, r0, #0x100 /* Set HCE */
- orr r0, r0, #0xb1 /* Set SCD, AW, FW and NS */
- bic r0, r0, #0xe /* Clear EA, FIQ and IRQ */
- mcr CP32(r0, SCR)
- /* Ugly: the system timer's frequency register is only
- * programmable in Secure state. Since we don't know where its
- * memory-mapped control registers live, we can't find out the
- * right frequency. Use the VE model's default frequency here. */
- ldr r0, =0x5f5e100 /* 100 MHz */
- mcr CP32(r0, CNTFRQ)
- ldr r0, =0x40c00 /* SMP, c11, c10 in non-secure mode */
- mcr CP32(r0, NSACR)
- /* Continuing ugliness: Set up the GIC so NS state owns interrupts */
- mov r0, #GIC_BASE_ADDRESS
- add r0, r0, #GIC_DR_OFFSET
- mov r1, #0
- str r1, [r0] /* Disable delivery in the distributor */
- add r0, r0, #0x80 /* GICD_IGROUP0 */
- mov r2, #0xffffffff /* All interrupts to group 1 */
- str r2, [r0]
- str r2, [r0, #4]
- str r2, [r0, #8]
- /* Must drop priority mask below 0x80 before entering NS state */
- mov r0, #GIC_BASE_ADDRESS
- add r0, r0, #GIC_CR_OFFSET
- ldr r1, =0xff
- str r1, [r0, #0x4] /* -> GICC_PMR */
- /* Reset a few config registers */
- mov r0, #0
- mcr CP32(r0, FCSEIDR)
- mcr CP32(r0, CONTEXTIDR)
- /* FIXME: ought to reset some other NS control regs here */
- adr r1, 1f
- adr r0, hyp /* Store paddr (hyp entry point) */
- str r0, [r1] /* where we can use it for RFE */
- isb /* Ensure we see the stored target address */
- rfeia r1 /* Enter Hyp mode */
-
-1: .word 0 /* PC to enter Hyp mode at */
- .word 0x000001da /* CPSR: LE, Abort/IRQ/FIQ off, Hyp */
+ ldr r0, =enter_hyp_mode /* VA of function */
+ adr lr, hyp /* Set return address for call */
+ add pc, r0, r10 /* Call PA of function */
hyp:
PRINT("- Setting up control registers -\r\n")
--- /dev/null
+/*
+ * xen/arch/arm/mode_switch.S
+ *
+ * Start-of day code to take a CPU from Secure mode to Hyp mode.
+ *
+ * Tim Deegan <tim@xen.org>
+ * Copyright (c) 2011-2012 Citrix Systems.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <asm/config.h>
+#include <asm/page.h>
+#include <asm/asm_defns.h>
+
+/* Get up a CPU into Hyp mode. Clobbers r0-r3.
+ *
+ * This code is specific to the VE model, and not intended to be used
+ * on production systems. As such it's a bit hackier than the main
+ * boot code in head.S. In future it will be replaced by better
+ * integration with the bootloader/firmware so that Xen always starts
+ * in Hyp mode. */
+
+.globl enter_hyp_mode
+enter_hyp_mode:
+ mov r3, lr /* Put return address in non-banked reg */
+ cpsid aif, #0x16 /* Enter Monitor mode */
+ mrc CP32(r0, SCR)
+ orr r0, r0, #0x100 /* Set HCE */
+ orr r0, r0, #0xb1 /* Set SCD, AW, FW and NS */
+ bic r0, r0, #0xe /* Clear EA, FIQ and IRQ */
+ mcr CP32(r0, SCR)
+ /* Ugly: the system timer's frequency register is only
+ * programmable in Secure state. Since we don't know where its
+ * memory-mapped control registers live, we can't find out the
+ * right frequency. Use the VE model's default frequency here. */
+ ldr r0, =0x5f5e100 /* 100 MHz */
+ mcr CP32(r0, CNTFRQ)
+ ldr r0, =0x40c00 /* SMP, c11, c10 in non-secure mode */
+ mcr CP32(r0, NSACR)
+ /* Continuing ugliness: Set up the GIC so NS state owns interrupts */
+ mov r0, #GIC_BASE_ADDRESS
+ add r0, r0, #GIC_DR_OFFSET
+ mov r1, #0
+ str r1, [r0] /* Disable delivery in the distributor */
+ add r0, r0, #0x80 /* GICD_IGROUP0 */
+ mov r2, #0xffffffff /* All interrupts to group 1 */
+ str r2, [r0]
+ str r2, [r0, #4]
+ str r2, [r0, #8]
+ /* Must drop priority mask below 0x80 before entering NS state */
+ mov r0, #GIC_BASE_ADDRESS
+ add r0, r0, #GIC_CR_OFFSET
+ ldr r1, =0xff
+ str r1, [r0, #0x4] /* -> GICC_PMR */
+ /* Reset a few config registers */
+ mov r0, #0
+ mcr CP32(r0, FCSEIDR)
+ mcr CP32(r0, CONTEXTIDR)
+ /* FIXME: ought to reset some other NS control regs here */
+ adr r1, 1f /* Store return address */
+ str r3, [r1] /* where we can use it for RFE */
+ isb /* Ensure we see the stored address */
+ rfeia r1 /* Enter Hyp mode */
+
+1: .word 0 /* PC to enter Hyp mode at */
+ .word 0x000001da /* CPSR: LE, Abort/IRQ/FIQ off, Hyp */
+