firmware: rockchip: update sip interface
authorchenjh <chenjh@rock-chips.com>
Fri, 17 Mar 2017 08:36:34 +0000 (16:36 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Thu, 6 Apr 2017 02:39:22 +0000 (10:39 +0800)
clean up code and add support for fiq debugger

Change-Id: I6dc0e4306a8554c49342207191005e55fb662b38
Signed-off-by: chenjh <chenjh@rock-chips.com>
drivers/firmware/rockchip_sip.c
drivers/soc/rockchip/rockchip_pm_config.c
include/linux/rockchip/rockchip_sip.h

index 2dadfaa8c80bffcb7e7dbcccc79666fc2251b21c..4d12d2d65856b4057e07c546b72813266b7eb300 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/cputype.h>
 #include <asm/smp_plat.h>
 #include <uapi/linux/psci.h>
+#include <linux/ptrace.h>
 
 #ifdef CONFIG_64BIT
 #define PSCI_FN_NATIVE(version, name)  PSCI_##version##_FN64_##name
@@ -37,40 +38,34 @@ static struct arm_smccc_res __invoke_sip_fn_smc(unsigned long function_id,
        return res;
 }
 
-struct arm_smccc_res sip_smc_ddr_cfg(u32 arg0, u32 arg1,
-                                    u32 arg2)
+struct arm_smccc_res sip_smc_ddr_cfg(u32 arg0, u32 arg1, u32 arg2)
 {
-       return __invoke_sip_fn_smc(SIP_DDR_CFG32, arg0, arg1, arg2);
+       return __invoke_sip_fn_smc(SIP_DDR_CFG, arg0, arg1, arg2);
 }
 
 struct arm_smccc_res sip_smc_get_atf_version(void)
 {
-       return __invoke_sip_fn_smc(SIP_ATF_VERSION32, 0, 0, 0);
+       return __invoke_sip_fn_smc(SIP_ATF_VERSION, 0, 0, 0);
 }
 
 struct arm_smccc_res sip_smc_get_sip_version(void)
 {
-       return __invoke_sip_fn_smc(SIP_SIP_VERSION32, 0, 0, 0);
+       return __invoke_sip_fn_smc(SIP_SIP_VERSION, 0, 0, 0);
 }
 
-int sip_smc_set_suspend_mode(u32 ctrl,
-                            u32 config1,
-                            u32 config2)
+int sip_smc_set_suspend_mode(u32 ctrl, u32 config1, u32 config2)
 {
        struct arm_smccc_res res;
 
-       res = __invoke_sip_fn_smc(SIP_SUSPEND_MODE32, ctrl,
-                                 config1, config2);
-
+       res = __invoke_sip_fn_smc(SIP_SUSPEND_MODE, ctrl, config1, config2);
        return res.a0;
 }
 
-int rk_psci_virtual_poweroff(void)
+int sip_smc_virtual_poweroff(void)
 {
        struct arm_smccc_res res;
 
-       res = __invoke_sip_fn_smc(PSCI_FN_NATIVE(1_0, SYSTEM_SUSPEND),
-                                 0, 0, 0);
+       res = __invoke_sip_fn_smc(PSCI_FN_NATIVE(1_0, SYSTEM_SUSPEND), 0, 0, 0);
        return res.a0;
 }
 
@@ -98,101 +93,195 @@ int sip_smc_secure_reg_write(u32 addr_phy, u32 val)
        return res.a0;
 }
 
-/************************** fiq debugger **************************************/
-static u64 ft_fiq_mem_phy;
-static void __iomem *ft_fiq_mem_base;
-static void (*psci_fiq_debugger_uart_irq_tf)(void *reg_base, u64 sp_el1);
-static u32 fig_init_flag;
-
-u32 rockchip_psci_smc_get_tf_ver(void)
+struct arm_smccc_res sip_smc_request_share_mem(u32 page_num,
+                                              share_page_type_t page_type)
 {
        struct arm_smccc_res res;
+       unsigned long share_mem_phy;
+
+       res = __invoke_sip_fn_smc(SIP_SHARE_MEM, page_num, page_type, 0);
+       if (IS_SIP_ERROR(res.a0))
+               goto error;
+
+       share_mem_phy = res.a1;
+       res.a1 = (unsigned long)ioremap(share_mem_phy, SIZE_PAGE(page_num));
 
-       arm_smccc_smc(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0, 0, 0, 0, 0, &res);
-       return 0x00010005;
+error:
+       return res;
 }
 
-void psci_fiq_debugger_uart_irq_tf_cb(u64 sp_el1, u64 offset)
+struct arm_smccc_res sip_smc_mcu_el3fiq(u32 arg0, u32 arg1, u32 arg2)
 {
-       psci_fiq_debugger_uart_irq_tf((char *)ft_fiq_mem_base + offset, sp_el1);
-       __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64, 0, 0,
-                           UARTDBG_CFG_OSHDL_TO_OS);
+       return __invoke_sip_fn_smc(SIP_MCU_EL3FIQ_CFG, arg0, arg1, arg2);
 }
 
-void psci_fiq_debugger_uart_irq_tf_init(u32 irq_id, void *callback)
+/************************** fiq debugger **************************************/
+#ifdef CONFIG_ARM64
+#define SIP_UARTDBG_FN         SIP_UARTDBG_CFG64
+#else
+#define SIP_UARTDBG_FN         SIP_UARTDBG_CFG
+#endif
+
+static int fiq_sip_enabled;
+static int fiq_target_cpu;
+static phys_addr_t ft_fiq_mem_phy;
+static void __iomem *ft_fiq_mem_base;
+static void (*sip_fiq_debugger_uart_irq_tf)(struct pt_regs _pt_regs,
+                                           unsigned long cpu);
+int sip_fiq_debugger_is_enabled(void)
 {
-       struct arm_smccc_res sip_smmc;
+       return fiq_sip_enabled;
+}
+
+static struct pt_regs sip_fiq_debugger_get_pt_regs(void *reg_base,
+                                                  unsigned long sp_el1)
+{
+       struct pt_regs fiq_pt_regs;
+
+#ifdef CONFIG_ARM64
+       /* copy cpu context */
+       memcpy(&fiq_pt_regs, reg_base, 8 * 31);
+
+       /* copy pstate */
+       memcpy(&fiq_pt_regs.pstate, reg_base + 0x110, 8);
+
+       /* EL1 mode */
+       if (fiq_pt_regs.pstate & 0x10)
+               memcpy(&fiq_pt_regs.sp, reg_base + 0xf8, 8);
+       /* EL0 mode */
+       else
+               fiq_pt_regs.sp = sp_el1;
+
+       /* copy pc */
+       memcpy(&fiq_pt_regs.pc, reg_base + 0x118, 8);
+#else
+       struct sm_nsec_ctx *nsec_ctx = reg_base;
+
+       fiq_pt_regs.ARM_r0 = nsec_ctx->r0;
+       fiq_pt_regs.ARM_r1 = nsec_ctx->r1;
+       fiq_pt_regs.ARM_r2 = nsec_ctx->r2;
+       fiq_pt_regs.ARM_r3 = nsec_ctx->r3;
+       fiq_pt_regs.ARM_r4 = nsec_ctx->r4;
+       fiq_pt_regs.ARM_r5 = nsec_ctx->r5;
+       fiq_pt_regs.ARM_r6 = nsec_ctx->r6;
+       fiq_pt_regs.ARM_r7 = nsec_ctx->r7;
+       fiq_pt_regs.ARM_r8 = nsec_ctx->r8;
+       fiq_pt_regs.ARM_r9 = nsec_ctx->r9;
+       fiq_pt_regs.ARM_r10 = nsec_ctx->r10;
+       fiq_pt_regs.ARM_fp = nsec_ctx->r11;
+       fiq_pt_regs.ARM_ip = nsec_ctx->r12;
+       fiq_pt_regs.ARM_sp = nsec_ctx->svc_sp;
+       fiq_pt_regs.ARM_lr = nsec_ctx->svc_lr;
+       fiq_pt_regs.ARM_pc = nsec_ctx->mon_lr;
+       fiq_pt_regs.ARM_cpsr = nsec_ctx->mon_spsr;
+#endif
 
-       psci_fiq_debugger_uart_irq_tf = callback;
-       sip_smmc = __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64, irq_id,
-                                      (unsigned long)psci_fiq_debugger_uart_irq_tf_cb,
-                                      UARTDBG_CFG_INIT);
-       ft_fiq_mem_phy = sip_smmc.a0;
-       ft_fiq_mem_base = ioremap(ft_fiq_mem_phy, 8 * 1024);
-       fig_init_flag = 1;
+       return fiq_pt_regs;
 }
 
-void psci_enable_fiq(void)
+static void sip_fiq_debugger_uart_irq_tf_cb(unsigned long sp_el1,
+                                           unsigned long offset,
+                                           unsigned long cpu)
 {
-       int irq_flag;
-       int cpu_id;
+       struct pt_regs fiq_pt_regs;
+       char *cpu_context;
+
+       /* calling fiq handler */
+       if (ft_fiq_mem_base) {
+               cpu_context = (char *)ft_fiq_mem_base + offset;
+               fiq_pt_regs = sip_fiq_debugger_get_pt_regs(cpu_context, sp_el1);
+               sip_fiq_debugger_uart_irq_tf(fiq_pt_regs, cpu);
+       }
+
+       /* fiq handler done, return to EL3(then EL3 return to EL1 entry) */
+       __invoke_sip_fn_smc(SIP_UARTDBG_FN, 0, 0, UARTDBG_CFG_OSHDL_TO_OS);
+}
 
-       if (fig_init_flag != 1)
-               return;
-       irq_flag = *((char *)(ft_fiq_mem_base) + 8 * 1024 - 0x04);
+int sip_fiq_debugger_uart_irq_tf_init(u32 irq_id, void *callback_fn)
+{
+       struct arm_smccc_res res;
 
-       cpu_id = read_cpuid_mpidr() & MPIDR_HWID_BITMASK;
-       if ((irq_flag == 0xAA) && (cpu_id == 0))
-               __invoke_sip_fn_smc(RK_SIP_ENABLE_FIQ, 0, 0, 0);
+       fiq_target_cpu = 0;
+
+       /* init fiq debugger callback */
+       sip_fiq_debugger_uart_irq_tf = callback_fn;
+       res = __invoke_sip_fn_smc(SIP_UARTDBG_FN, irq_id,
+                                 (unsigned long)sip_fiq_debugger_uart_irq_tf_cb,
+                                 UARTDBG_CFG_INIT);
+       if (IS_SIP_ERROR(res.a0)) {
+               pr_err("%s error: %d\n", __func__, (int)res.a0);
+               return res.a0;
+       }
+
+       /* share memory ioremap */
+       if (!ft_fiq_mem_base) {
+               ft_fiq_mem_phy = res.a1;
+               ft_fiq_mem_base = ioremap(ft_fiq_mem_phy,
+                                         FIQ_UARTDBG_SHARE_MEM_SIZE);
+               if (!ft_fiq_mem_base) {
+                       pr_err("%s: share memory ioremap failed\n", __func__);
+                       return -ENOMEM;
+               }
+       }
+
+       fiq_sip_enabled = 1;
+
+       return SIP_RET_SUCCESS;
 }
 
-u32 psci_fiq_debugger_switch_cpu(u32 cpu)
+int sip_fiq_debugger_switch_cpu(u32 cpu)
 {
-       struct arm_smccc_res sip_smmc;
+       struct arm_smccc_res res;
 
-               sip_smmc = __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64,
-                                              cpu_logical_map(cpu),
-                                              0, UARTDBG_CFG_OSHDL_CPUSW);
-       return sip_smmc.a0;
+       fiq_target_cpu = cpu;
+       res = __invoke_sip_fn_smc(SIP_UARTDBG_FN, cpu_logical_map(cpu),
+                                 0, UARTDBG_CFG_OSHDL_CPUSW);
+       return res.a0;
 }
 
-void psci_fiq_debugger_enable_debug(bool val)
+void sip_fiq_debugger_enable_debug(bool enable)
 {
-       if (val)
-               __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64, 0,
-                                   0, UARTDBG_CFG_OSHDL_DEBUG_ENABLE);
-       else
-               __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64, 0,
-                                   0, UARTDBG_CFG_OSHDL_DEBUG_DISABLE);
+       unsigned long val;
+
+       val = enable ? UARTDBG_CFG_OSHDL_DEBUG_ENABLE :
+                      UARTDBG_CFG_OSHDL_DEBUG_DISABLE;
+
+       __invoke_sip_fn_smc(SIP_UARTDBG_FN, 0, 0, val);
 }
 
-int psci_fiq_debugger_set_print_port(u32 port, u32 baudrate)
+int sip_fiq_debugger_set_print_port(u32 port_phyaddr, u32 baudrate)
 {
        struct arm_smccc_res res;
 
-       res = __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64, port, baudrate,
+       res = __invoke_sip_fn_smc(SIP_UARTDBG_FN, port_phyaddr, baudrate,
                                  UARTDBG_CFG_PRINT_PORT);
        return res.a0;
 }
 
-struct arm_smccc_res sip_smc_get_share_mem_page(u32 page_num,
-                                               share_page_type_t page_type)
+int sip_fiq_debugger_request_share_memory(void)
 {
        struct arm_smccc_res res;
-       unsigned long share_mem_phy;
 
-       res = __invoke_sip_fn_smc(SIP_SHARE_MEM32, page_num, page_type, 0);
-       if (res.a0)
-               goto error;
+       /* request page share memory */
+       res = sip_smc_request_share_mem(FIQ_UARTDBG_PAGE_NUMS,
+                                       SHARE_PAGE_TYPE_UARTDBG);
+       if (IS_SIP_ERROR(res.a0))
+               return res.a0;
 
-       share_mem_phy = res.a1;
-       res.a1 = (unsigned long)ioremap(share_mem_phy, SIZE_PAGE(page_num));
+       return SIP_RET_SUCCESS;
+}
 
-error:
-       return res;
+int sip_fiq_debugger_get_target_cpu(void)
+{
+       return fiq_target_cpu;
 }
 
-struct arm_smccc_res sip_smc_get_call_count(void)
+void sip_fiq_debugger_enable_fiq(bool enable, uint32_t tgt_cpu)
 {
-       return __invoke_sip_fn_smc(SIP_SVC_CALL_COUNT, 0, 0, 0);
+       u32 en;
+
+       fiq_target_cpu = tgt_cpu;
+       en = enable ? UARTDBG_CFG_FIQ_ENABEL : UARTDBG_CFG_FIQ_DISABEL;
+       __invoke_sip_fn_smc(SIP_UARTDBG_FN, tgt_cpu, 0, en);
 }
+
index ac6d9977697a1094d4efcf5335a1176c1179ebcd..43b2e0f33343bf018959b0e58be57097cf59c272 100644 (file)
@@ -106,7 +106,7 @@ static void rockchip_pm_virt_pwroff_prepare(void)
        }
 
        sip_smc_set_suspend_mode(VIRTUAL_POWEROFF, 0, 1);
-       rk_psci_virtual_poweroff();
+       sip_smc_virtual_poweroff();
 }
 
 static int __init pm_config_init(struct platform_device *pdev)
index 27b35463a604bb2f432fe343956cf2bc84e7d692..c9265cb91b287b20b99ef6f088dc77f9fc8089fa 100644 (file)
 #include <linux/arm-smccc.h>
 #include <linux/io.h>
 
-/* SMC function IDs for SiP Service queries */
-#define SIP_SVC_CALL_COUNT             0x8200ff00
-#define SIP_SVC_UID                    0x8200ff01
-#define SIP_SVC_VERSION                        0x8200ff03
-
-#define SIP_ATF_VERSION32              0x82000001
+/* SMC function IDs for SiP Service queries, compatible with kernel-3.10 */
+#define SIP_ATF_VERSION                        0x82000001
 #define SIP_ACCESS_REG                 0x82000002
-#define SIP_SUSPEND_MODE32             0x82000003
-#define SIP_DDR_CFG32                  0x82000008
-#define SIP_SHARE_MEM32                        0x82000009
-#define SIP_SIP_VERSION32              0x8200000a
+#define SIP_SUSPEND_MODE               0x82000003
+#define SIP_PENDING_CPUS               0x82000004
+#define SIP_UARTDBG_CFG                        0x82000005
+#define SIP_UARTDBG_CFG64              0xc2000005
+#define SIP_MCU_EL3FIQ_CFG             0x82000006
+#define SIP_ACCESS_CHIP_STATE64                0xc2000006
+#define SIP_SECURE_MEM_CONFIG          0x82000007
+#define SIP_ACCESS_CHIP_EXTRA_STATE64  0xc2000007
+#define SIP_DDR_CFG                    0x82000008
+#define SIP_SHARE_MEM                  0x82000009
+#define SIP_SIP_VERSION                        0x8200000a
+#define SIP_REMOTECTL_CFG              0x8200000b
+
+/* Trust firmware version */
+#define ATF_VER_MAJOR(ver)             (((ver) >> 16) & 0xffff)
+#define ATF_VER_MINOR(ver)             (((ver) >> 0) & 0xffff)
 
-/* SIP_ACCESS_REG read/write */
+/* SIP_ACCESS_REG: read or write */
 #define SECURE_REG_RD                  0x0
 #define SECURE_REG_WR                  0x1
 
-/* Share mem page types */
-typedef enum {
-       SHARE_PAGE_TYPE_INVALID = 0,
-       SHARE_PAGE_TYPE_UARTDBG,
-       SHARE_PAGE_TYPE_MAX,
-} share_page_type_t;
+/* Fiq debugger share memory: 8KB enough */
+#define FIQ_UARTDBG_PAGE_NUMS          2
+#define FIQ_UARTDBG_SHARE_MEM_SIZE     ((FIQ_UARTDBG_PAGE_NUMS) * 4096)
 
 /* Error return code */
-#define SIP_RET_SUCCESS                        0
-#define SIP_RET_NOT_SUPPORTED          -1
-#define SIP_RET_INVALID_PARAMS         -2
-#define SIP_RET_INVALID_ADDRESS                -3
-#define SIP_RET_DENIED                 -4
-#define SIP_RET_SMC_UNKNOWN            0xffffffff
+#define IS_SIP_ERROR(x)                        (!!(x))
 
-/* Sip version */
-#define SIP_IMPLEMENT_V1               (1)
-#define SIP_IMPLEMENT_V2               (2)
-
-#define RK_SIP_DISABLE_FIQ             0xc2000006
-#define RK_SIP_ENABLE_FIQ              0xc2000007
-#define PSCI_SIP_RKTF_VER              0x82000001
-#define PSCI_SIP_ACCESS_REG            0x82000002
-#define PSCI_SIP_ACCESS_REG64          0xc2000002
-#define PSCI_SIP_SUSPEND_WR_CTRBITS    0x82000003
-#define PSCI_SIP_PENDING_CPUS          0x82000004
-#define PSCI_SIP_UARTDBG_CFG           0x82000005
-#define PSCI_SIP_UARTDBG_CFG64         0xc2000005
-#define PSCI_SIP_EL3FIQ_CFG            0x82000006
-#define PSCI_SIP_SMEM_CONFIG           0x82000007
+#define SIP_RET_SUCCESS                        0
+#define SIP_RET_SMC_UNKNOWN            -1
+#define SIP_RET_NOT_SUPPORTED          -2
+#define SIP_RET_INVALID_PARAMS         -3
+#define SIP_RET_INVALID_ADDRESS                -4
+#define SIP_RET_DENIED                 -5
 
+/* SIP_UARTDBG_CFG64 call types */
 #define UARTDBG_CFG_INIT               0xf0
 #define UARTDBG_CFG_OSHDL_TO_OS                0xf1
 #define UARTDBG_CFG_OSHDL_CPUSW                0xf3
 #define UARTDBG_CFG_OSHDL_DEBUG_ENABLE 0xf4
 #define UARTDBG_CFG_OSHDL_DEBUG_DISABLE        0xf5
 #define UARTDBG_CFG_PRINT_PORT         0xf7
+#define UARTDBG_CFG_FIQ_ENABEL         0xf8
+#define UARTDBG_CFG_FIQ_DISABEL                0xf9
 
+/* SIP_SUSPEND_MODE32 call types */
 #define SUSPEND_MODE_CONFIG            0x01
 #define WKUP_SOURCE_CONFIG             0x02
 #define PWM_REGULATOR_CONFIG           0x03
@@ -77,34 +72,85 @@ typedef enum {
 #define APIOS_SUSPEND_CONFIG           0x06
 #define VIRTUAL_POWEROFF               0x07
 
-/* struct arm_smccc_res: a0: error code; a1~a3: data */
-/* SMC32 Calls */
-int sip_smc_set_suspend_mode(u32 ctrl,
-                            u32 config1,
-                            u32 config2);
-int rk_psci_virtual_poweroff(void);
+/* SIP_REMOTECTL_CFG call types */
+#define        REMOTECTL_SET_IRQ               0xf0
+#define REMOTECTL_SET_PWM_CH           0xf1
+#define REMOTECTL_SET_PWRKEY           0xf2
+#define REMOTECTL_GET_WAKEUP_STATE     0xf3
+#define REMOTECTL_ENABLE               0xf4
+/* wakeup state */
+#define REMOTECTL_PWRKEY_WAKEUP                0xdeadbeaf
 
-struct arm_smccc_res sip_smc_get_call_count(void);
+/* Share mem page types */
+typedef enum {
+       SHARE_PAGE_TYPE_INVALID = 0,
+       SHARE_PAGE_TYPE_UARTDBG,
+       SHARE_PAGE_TYPE_MAX,
+} share_page_type_t;
+
+/*
+ * Rules: struct arm_smccc_res contains result and data, details:
+ *
+ * a0: error code(0: success, !0: error);
+ * a1~a3: data
+ */
 struct arm_smccc_res sip_smc_get_atf_version(void);
 struct arm_smccc_res sip_smc_get_sip_version(void);
-struct arm_smccc_res sip_smc_ddr_cfg(u32 arg0, u32 arg1,
-                                    u32 arg2);
-struct arm_smccc_res sip_smc_get_share_mem_page(u32 page_num,
-                                               share_page_type_t page_type);
+struct arm_smccc_res sip_smc_ddr_cfg(u32 arg0, u32 arg1, u32 arg2);
+struct arm_smccc_res sip_smc_request_share_mem(u32 page_num,
+                                              share_page_type_t page_type);
+struct arm_smccc_res sip_smc_mcu_el3fiq(u32 arg0, u32 arg1, u32 arg2);
+
+int sip_smc_set_suspend_mode(u32 ctrl, u32 config1, u32 config2);
+int sip_smc_virtual_poweroff(void);
 #ifdef CONFIG_ROCKCHIP_SIP
-u32 sip_smc_secure_reg_read(u32 addr_phy);
 int sip_smc_secure_reg_write(u32 addr_phy, u32 val);
+u32 sip_smc_secure_reg_read(u32 addr_phy);
 #else
 u32 sip_smc_secure_reg_read(u32 addr_phy) { return 0; }
 int sip_smc_secure_reg_write(u32 addr_phy, u32 val) { return 0; }
 #endif
+/***************************fiq debugger **************************************/
+void sip_fiq_debugger_enable_fiq(bool enable, uint32_t tgt_cpu);
+void sip_fiq_debugger_enable_debug(bool enable);
+int sip_fiq_debugger_uart_irq_tf_init(u32 irq_id, void *callback_fn);
+int sip_fiq_debugger_set_print_port(u32 port_phyaddr, u32 baudrate);
+int sip_fiq_debugger_request_share_memory(void);
+int sip_fiq_debugger_get_target_cpu(void);
+int sip_fiq_debugger_switch_cpu(u32 cpu);
+int sip_fiq_debugger_is_enabled(void);
 
-void psci_enable_fiq(void);
-u32 rockchip_psci_smc_get_tf_ver(void);
-void psci_fiq_debugger_uart_irq_tf_cb(u64 sp_el1, u64 offset);
-void psci_fiq_debugger_uart_irq_tf_init(u32 irq_id, void *callback);
-u32 psci_fiq_debugger_switch_cpu(u32 cpu);
-void psci_fiq_debugger_enable_debug(bool val);
-int psci_fiq_debugger_set_print_port(u32 port, u32 baudrate);
+/* optee cpu_context */
+struct sm_nsec_ctx {
+       u32 usr_sp;
+       u32 usr_lr;
+       u32 irq_spsr;
+       u32 irq_sp;
+       u32 irq_lr;
+       u32 svc_spsr;
+       u32 svc_sp;
+       u32 svc_lr;
+       u32 abt_spsr;
+       u32 abt_sp;
+       u32 abt_lr;
+       u32 und_spsr;
+       u32 und_sp;
+       u32 und_lr;
+       u32 mon_lr;
+       u32 mon_spsr;
+       u32 r4;
+       u32 r5;
+       u32 r6;
+       u32 r7;
+       u32 r8;
+       u32 r9;
+       u32 r10;
+       u32 r11;
+       u32 r12;
+       u32 r0;
+       u32 r1;
+       u32 r2;
+       u32 r3;
+};
 
 #endif