Fix recovery mechanism for late-attach use-case in QNX
authorvwan@ti.com <vwan@ti.com>
Thu, 28 Aug 2014 21:55:50 +0000 (14:55 -0700)
committerRobert Tivy <rtivy@ti.com>
Wed, 3 Sep 2014 21:15:34 +0000 (14:15 -0700)
This patch adds support for recovery from MMU faults, exceptions,
and watchdog timeouts when 'late-attached' to a slave core (SDOCM00112666).

Signed-off-by: VW <vwan@ti.com>
packages/ti/deh/Watchdog.c
packages/ti/ipc/ipcmgr/IpcMgr.c
packages/ti/ipc/ipcmgr/package.bld
packages/ti/ipc/ipcmgr/package.xs
qnx/src/ipc3x_dev/ti/syslink/build/Qnx/resmgr/syslink_main.c
qnx/src/ipc3x_dev/ti/syslink/family/common/vayu/vayuipu/vayucore0/VAYUIpuCore0Proc.c
qnx/src/ipc3x_dev/ti/syslink/family/vayu/vayuipu/VAYUIpuEnabler.c
qnx/src/ipc3x_dev/ti/syslink/inc/knl/VAYUIpuEnabler.h

index 8031a4a6e552ef83ab8b8e6d6b3abea09106b0b5..53b5c502df3d2522e19eada86715bd3f98c248b3 100644 (file)
@@ -162,12 +162,15 @@ Void Watchdog_init( Void (*timerFxn)(Void) )
     Types_FreqHz        tFreq;
     Watchdog_TimerRegs  *timer;
     Int                 i;
+    static Bool         first = TRUE;
 
     tHandle = Timer_Object_get(NULL, 0);
     Timer_getFreq(tHandle, &tFreq);  /* get timer frequency */
 
 #if defined(IPU) && defined(OMAP5)
-    adjustGptClkCtrlAddr();
+    if (first) {
+        adjustGptClkCtrlAddr();
+    }
 #endif
     for (i = 0; i < Watchdog_module->wdtCores; i++) {  /* loop for SMP cores */
         timer = (Watchdog_TimerRegs *) Watchdog_module->device[i].baseAddr;
@@ -181,46 +184,54 @@ Void Watchdog_init( Void (*timerFxn)(Void) )
             continue;  /* for next core */
         }
 
-        /* Configure the timer */
-        initTimer(timer, TRUE);
-
-        /* Enable interrupt in BIOS */
-        Hwi_Params_init(&hwiParams);
-        hwiParams.priority = 1;
-        hwiParams.eventId = Watchdog_module->device[i].eventId;
-        hwiParams.maskSetting = Hwi_MaskingOption_LOWER;
-        hwiParams.arg = 1;     /* Exception_handler(abortFlag) */
-        key = Hwi_disable();
-        Hwi_create(Watchdog_module->device[i].intNum, (Hwi_FuncPtr) timerFxn,
+        if (Watchdog_module->status[i] != Watchdog_Mode_ENABLED) {
+            /* Configure the timer */
+            initTimer(timer, TRUE);
+
+            /* Enable interrupt in BIOS */
+            Hwi_Params_init(&hwiParams);
+            hwiParams.priority = 1;
+            hwiParams.eventId = Watchdog_module->device[i].eventId;
+            hwiParams.maskSetting = Hwi_MaskingOption_LOWER;
+            hwiParams.arg = 1;     /* Exception_handler(abortFlag) */
+            key = Hwi_disable();
+            Hwi_create(Watchdog_module->device[i].intNum, (Hwi_FuncPtr) timerFxn,
                                                             &hwiParams, NULL);
-        Hwi_enableInterrupt(Watchdog_module->device[i].intNum);
+            Hwi_enableInterrupt(Watchdog_module->device[i].intNum);
 #if defined(DSP) && defined(OMAP5)
-        Wugen_enableEvent(Watchdog_module->device[i].eventId);
+            Wugen_enableEvent(Watchdog_module->device[i].eventId);
 #endif
-        Hwi_restore(key);
+            Hwi_restore(key);
 
-        /* Enable timer */
-        while (timer->twps & WATCHDOG_TIMER_TWPS_W_PEND_TCLR);
-        timer->tclr |= 1;
-        Watchdog_module->status[i] = Watchdog_Mode_ENABLED;
+            /* Enable timer */
+            while (timer->twps & WATCHDOG_TIMER_TWPS_W_PEND_TCLR);
+            timer->tclr |= 1;
+            Watchdog_module->status[i] = Watchdog_Mode_ENABLED;
 
 #ifdef SMP
-        System_printf("Watchdog enabled: TimerBase = 0x%x SMP-Core = %d "
+            System_printf("Watchdog enabled: TimerBase = 0x%x SMP-Core = %d "
                                             "Freq = %d\n", timer, i, tFreq.lo);
 #else
-        System_printf("Watchdog enabled: TimerBase = 0x%x Freq = %d\n",
+            System_printf("Watchdog enabled: TimerBase = 0x%x Freq = %d\n",
                                                             timer, tFreq.lo);
 #endif
+        }
     }
 
 #if defined(OMAP5) || defined(IPU)
-    /* Register callback function */
-    if (!IpcPower_registerCallback(IpcPower_Event_RESUME, Watchdog_restore,
+    if (first) {
+        /* Register callback function */
+        if (!IpcPower_registerCallback(IpcPower_Event_RESUME, Watchdog_restore,
                                     NULL)) {
-        System_printf("Watchdog_restore registered as a resume callback\n");
+            System_printf("Watchdog_restore registered as a resume callback\n");
+        }
     }
 #endif
 
+    if (first) {
+        first = FALSE;
+    }
+
     return;
 }
 
index 4f9c6d4949c5fcdd785e40649045d58b13e65ed5..12976d5cacd88213f454591ac5c2f6be81063954 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2013, Texas Instruments Incorporated
+ * Copyright (c) 2012-2014, Texas Instruments Incorporated
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 #include <ti/ipc/transports/TransportRpmsgSetup.h>
 #include <ti/ipc/rpmsg/_RPMessage.h>
 
+#ifdef IpcMgr_USEDEH
+#include <ti/deh/Watchdog.h>
+#ifdef DSP
+#include <ti/sysbios/family/c64p/Exception.h>
+#elif IPU
+#include <ti/sysbios/family/arm/m3/Hwi.h>
+#endif
+#endif
+
 /*
  *  ======== IpcMgr_rpmsgStartup ========
  *  Initialize the RPMSG module.  This calls VirtQueue_startup().
@@ -53,6 +62,18 @@ Void IpcMgr_rpmsgStartup()
 {
     Assert_isTrue(MultiProc_self() != MultiProc_getId("HOST"), NULL);
     RPMessage_init(MultiProc_getId("HOST"));
+
+#ifdef IpcMgr_USEDEH
+    /*
+     * When using DEH, initialize the Watchdog timers if not already done
+     * (i.e. late-attach)
+     */
+#ifdef DSP
+    Watchdog_init((Void (*)(Void))ti_sysbios_family_c64p_Exception_handler);
+#elif IPU
+    Watchdog_init(ti_sysbios_family_arm_m3_Hwi_excHandlerAsm__I);
+#endif
+#endif
 }
 
 /*
@@ -74,6 +95,18 @@ Void IpcMgr_ipcStartup()
     /* Sets up to communicate with host's NameServer: */
     status = NameServerRemoteRpmsg_attach(procId, 0);
     Assert_isTrue(status >= 0, NULL);
+
+#ifdef IpcMgr_USEDEH
+    /*
+     * When using DEH, initialize the Watchdog timers if not already done
+     * (i.e. late-attach)
+     */
+#ifdef DSP
+    Watchdog_init((Void (*)(Void))ti_sysbios_family_c64p_Exception_handler);
+#elif IPU
+    Watchdog_init(ti_sysbios_family_arm_m3_Hwi_excHandlerAsm__I);
+#endif
+#endif
 }
 
 /*
index dcea6c7d186b6c90cc096a02770d471cfe439afe..d33c8eb888b224d6b60afaae077f676b3bd66940 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2013, Texas Instruments Incorporated
+ * Copyright (c) 2012-2014, Texas Instruments Incorporated
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -57,6 +57,19 @@ for (var i = 0; i < Build.targets.length; i++) {
 
     /* Build for all profiles */
     for (var profile in targ.profiles) {
+        /* Build a platform-specific library */
+        if ((targ.isa == "66") || (targ.isa == "64T")) {
+            Pkg.addLibrary("lib/" + profile + "/" + Pkg.name + "_deh", targ, {
+                profile: profile,
+                defs: "-DIpcMgr_USEDEH -DDSP"
+            }).addObjects(SRCS);
+        }
+        else if (targ.isa.match(/^v7M(|4)$/)) {
+            Pkg.addLibrary("lib/" + profile + "/" + Pkg.name + "_deh", targ, {
+                profile: profile,
+                defs: "-DIpcMgr_USEDEH -DIPU"
+            }).addObjects(SRCS);
+        }
 
         Pkg.addLibrary("lib/" + profile + "/" + Pkg.name, targ, {
             profile: profile
index 5c4356c9ee8e6d2717287f5c547d4efb77f9e84e..9830ae459a825c107a8627c9e118dc210874b9d0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Texas Instruments Incorporated
+ * Copyright (c) 2012-2014, Texas Instruments Incorporated
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -39,6 +39,7 @@
  */
 function getLibs(prog)
 {
+    var lib;
     var suffix = prog.build.target.findSuffix(this);
     if (suffix == null) {
         /* no matching lib found in this package, return "" */
@@ -47,9 +48,17 @@ function getLibs(prog)
         return ("");
     }
 
-    /* the location of the libraries are in lib/<profile>/* */
-    var lib = "lib/" + this.profile + "/ti.ipc.ipcmgr.a" + suffix;
+    var deh = xdc.module("ti.deh.Deh");
 
+    /* the location of the libraries are in lib/<profile>/* */
+    if (deh.$used) {
+        /* Deh is used */
+        lib = "lib/" + this.profile + "/ti.ipc.ipcmgr_deh.a" + suffix;
+    }
+    else {
+        /* Deh is not used */
+        lib = "lib/" + this.profile + "/ti.ipc.ipcmgr.a" + suffix;
+    }
 
     /*
      * If the requested profile doesn't exist, we return the 'release' library.
index f29f385008616372fda2b3cd0dbbb361df25e2ab..7024d4d1096dcf210d2292d0e1ebf6728afbc8e8 100644 (file)
@@ -481,6 +481,10 @@ static void ipc_recover(Ptr args)
         deinit_syslink_trace_device(dev);
         init_syslink_trace_device(dev);
     }
+    else {
+        GT_0trace(curTrace, GT_4CLASS,
+                  "ipc_recover: Recovery disabled.\n");
+    }
 }
 
 Int syslink_error_cb (UInt16 procId, ProcMgr_Handle handle,
@@ -970,6 +974,7 @@ int main(int argc, char *argv[])
             break;
         case 'a':
             numAttach = atoi(optarg);
+            printf("Late-attaching to %d core(s)\n", numAttach);
             break;
         case 'v':
             verbosity++;
index e569112dd2caed16ef5254989d915f053dfe3cd4..0c13a7e9dd52d533c6ce47e89ea4d1149699b1f8 100644 (file)
@@ -996,6 +996,12 @@ VAYUIPUCORE0PROC_attach(
             memcpy((Ptr)params->memEntries, (Ptr)object->params.memEntries,
                 sizeof(ProcMgr_AddrInfo) * params->numMemEntries);
 
+
+            /* Setup the xbar for MMU fault interrupts */
+            mmuEnableArgs.numMemEntries = 0;
+            status = VAYUIPU_halMmuCtrl(object->halObject,
+                Processor_MmuCtrlCmd_Enable, &mmuEnableArgs);
+
             if ((procHandle->bootMode == ProcMgr_BootMode_Boot)
                 || (procHandle->bootMode == ProcMgr_BootMode_NoLoad_Pwr)) {
 
@@ -1003,44 +1009,53 @@ VAYUIPUCORE0PROC_attach(
                 if (status < 0) {
                     GT_setFailureReason(curTrace, GT_4CLASS,
                         "VAYUIPUCORE0PROC_attach", status,
-                        "Failed to reset the slave processor");
+                        "Failed to enable the slave MMU");
                 }
                 else {
 #endif
-                    GT_0trace(curTrace, GT_1CLASS,
-                        "VAYUIPUCORE0PROC_attach: slave is now in reset");
+                    GT_0trace(curTrace, GT_2CLASS,
+                        "VAYUIPUCORE0PROC_attach: Slave MMU "
+                        "is configured!");
 
-                    mmuEnableArgs.numMemEntries = 0;
-                    status = VAYUIPU_halMmuCtrl(object->halObject,
-                        Processor_MmuCtrlCmd_Enable, &mmuEnableArgs);
-#if !defined(SYSLINK_BUILD_OPTIMIZE)
+                    /*
+                     * Pull IPU MMU out of reset to make internal
+                     * memory "loadable"
+                     */
+                    status = VAYUIPUCORE0_halResetCtrl(
+                        object->halObject,
+                        Processor_ResetCtrlCmd_MMU_Release);
                     if (status < 0) {
-                        GT_setFailureReason(curTrace, GT_4CLASS,
-                            "VAYUIPUCORE0PROC_attach", status,
-                            "Failed to enable the slave MMU");
+                        /*! @retval status */
+                        GT_setFailureReason(curTrace,
+                            GT_4CLASS,
+                            "VAYUIPUCORE0_halResetCtrl",
+                            status,
+                            "Reset MMU_Release failed");
                     }
-                    else {
+#if !defined(SYSLINK_BUILD_OPTIMIZE)
+                }
 #endif
-                        GT_0trace(curTrace, GT_2CLASS,
-                            "VAYUIPUCORE0PROC_attach: Slave MMU "
-                            "is configured!");
-                        /*
-                         * Pull IPU MMU out of reset to make internal
-                         * memory "loadable"
-                         */
-                        status = VAYUIPUCORE0_halResetCtrl(
-                            object->halObject,
-                            Processor_ResetCtrlCmd_MMU_Release);
-                        if (status < 0) {
-                            /*! @retval status */
-                            GT_setFailureReason(curTrace,
-                                GT_4CLASS,
-                                "VAYUIPUCORE0_halResetCtrl",
-                                status,
-                                "Reset MMU_Release failed");
-                        }
+            }
+            else {
+                /* NoBoot, late-attach */
+                /*
+                 * Setup MMU fault interrupt now since we won't have a chance
+                 * to do it in ProcMgr_start
+                 */
+                rproc_enable_fault_interrupt(object->halObject);
+
+#if !defined(SYSLINK_BUILD_OPTIMIZE)
+                if (status < 0) {
+                    GT_setFailureReason(curTrace, GT_4CLASS,
+                        "VAYUIPUCORE0PROC_attach", status,
+                        "Failed to enable the slave MMU");
+                }
+                else {
+#endif
+                    GT_0trace(curTrace, GT_1CLASS,
+                        "VAYUIPUCORE0PROC_attach: Slave MMU interrupt is "
+                        "configured");
 #if !defined(SYSLINK_BUILD_OPTIMIZE)
-                    }
                 }
 #endif
             }
@@ -1105,14 +1120,29 @@ VAYUIPUCORE0PROC_detach (Processor_Handle handle)
                 /*! @retval status */
                 GT_setFailureReason (curTrace,
                                      GT_4CLASS,
-                                     "VAYUIPUCORE0_halResetCtrl",
+                                     "VAYUIPUCORE0PROC_detach",
                                      status,
                                      "Reset MMU failed");
             }
 #endif /* #if !defined(SYSLINK_BUILD_OPTIMIZE) */
+        }
+        else {
+            status = rproc_disable_fault_interrupt(object->halObject);
+#if !defined(SYSLINK_BUILD_OPTIMIZE)
+            if (status < 0) {
+                /*! @retval status */
+                GT_setFailureReason (curTrace,
+                                     GT_4CLASS,
+                                     "VAYUIPUCORE0PROC_detach",
+                                     status,
+                                     "rproc_disable_fault_interrupt failed");
+            }
+#endif /* #if !defined(SYSLINK_BUILD_OPTIMIZE) */
+        }
 
-            status = VAYUIPU_halMmuCtrl(object->halObject,
-                                        Processor_MmuCtrlCmd_Disable, NULL);
+        if (status >= 0) {
+             status = VAYUIPU_halMmuCtrl(object->halObject,
+                                    Processor_MmuCtrlCmd_Disable, NULL);
 #if !defined(SYSLINK_BUILD_OPTIMIZE)
             if (status < 0) {
                 GT_setFailureReason(curTrace, GT_4CLASS,
@@ -1120,43 +1150,43 @@ VAYUIPUCORE0PROC_detach (Processor_Handle handle)
                     "Failed to disable the slave MMU");
             }
 #endif
+        }
 
-            /* delete all dynamically added entries */
-            for (i = 0; i <
-                AddrTable_count[PROCID_TO_IPU(procHandle->procId)]; i++) {
-                ai = &AddrTable[PROCID_TO_IPU(procHandle->procId)][i];
-                ai->addr[ProcMgr_AddrType_MasterKnlVirt] = -1u;
-                ai->addr[ProcMgr_AddrType_MasterUsrVirt] = -1u;
-                ai->addr[ProcMgr_AddrType_MasterPhys] = -1u;
-                ai->addr[ProcMgr_AddrType_SlaveVirt] = -1u;
-                ai->addr[ProcMgr_AddrType_SlavePhys] = -1u;
-                ai->size = 0u;
-                ai->isCached = FALSE;
-                ai->mapMask = 0u;
-                ai->isMapped = FALSE;
-                ai->refCount = 0u;
-            }
-            object->params.numMemEntries = 0;
-            AddrTable_count[PROCID_TO_IPU(procHandle->procId)] = 0;
+        /* delete all dynamically added entries */
+        for (i = 0; i <
+            AddrTable_count[PROCID_TO_IPU(procHandle->procId)]; i++) {
+            ai = &AddrTable[PROCID_TO_IPU(procHandle->procId)][i];
+            ai->addr[ProcMgr_AddrType_MasterKnlVirt] = -1u;
+            ai->addr[ProcMgr_AddrType_MasterUsrVirt] = -1u;
+            ai->addr[ProcMgr_AddrType_MasterPhys] = -1u;
+            ai->addr[ProcMgr_AddrType_SlaveVirt] = -1u;
+            ai->addr[ProcMgr_AddrType_SlavePhys] = -1u;
+            ai->size = 0u;
+            ai->isCached = FALSE;
+            ai->mapMask = 0u;
+            ai->isMapped = FALSE;
+            ai->refCount = 0u;
+        }
+        object->params.numMemEntries = 0;
+        AddrTable_count[PROCID_TO_IPU(procHandle->procId)] = 0;
 
-            //No need to reset.. that will be done in STOP
-            /*tmpStatus = VAYUIPUCORE0_halResetCtrl(object->halObject,
-                Processor_ResetCtrlCmd_Reset, NULL);
+        //No need to reset.. that will be done in STOP
+        /*tmpStatus = VAYUIPUCORE0_halResetCtrl(object->halObject,
+            Processor_ResetCtrlCmd_Reset, NULL);
 
-            GT_0trace(curTrace, GT_2CLASS,
-                "VAYUIPUCORE0PROC_detach: Slave processor is now in reset");*/
+        GT_0trace(curTrace, GT_2CLASS,
+            "VAYUIPUCORE0PROC_detach: Slave processor is now in reset");*/
 
 #if !defined(SYSLINK_BUILD_OPTIMIZE)
-            if ((tmpStatus < 0) && (status >= 0)) {
-                status = tmpStatus;
-                GT_setFailureReason (curTrace,
-                                     GT_4CLASS,
-                                     "VAYUIPUCORE0PROC_detach",
-                                     status,
-                                     "Failed to reset the slave processor");
-            }
-#endif
+        if ((tmpStatus < 0) && (status >= 0)) {
+            status = tmpStatus;
+            GT_setFailureReason (curTrace,
+                                 GT_4CLASS,
+                                 "VAYUIPUCORE0PROC_detach",
+                                 status,
+                                 "Failed to reset the slave processor");
         }
+#endif
 
         GT_0trace (curTrace,
                    GT_2CLASS,
index cde244b81614c23d8409ea58efe34a070b668e48..bcadd3236fdec3a70f71d934f3b4da61ed56e609 100644 (file)
@@ -817,6 +817,79 @@ error_exit:
     return ret_val;
 }
 
+/****************************************************
+* Function to enable interrupt for MMU faults
+*****************************************************/
+Int rproc_enable_fault_interrupt(VAYUIPU_HalObject * halObject)
+{
+    Int status = 0;
+    UInt32 reg;
+    VAYUIpu_MMURegs * mmuRegs = NULL;
+
+    if (halObject == NULL) {
+        status = -ENOMEM;
+        GT_setFailureReason (curTrace,
+                             GT_4CLASS,
+                             "rproc_enable_fault_interrupt",
+                             status,
+                             "halObject is NULL");
+    }
+    else if (halObject->mmuBase == 0) {
+        status = -ENOMEM;
+        GT_setFailureReason (curTrace,
+                             GT_4CLASS,
+                             "rproc_enable_fault_interrupt",
+                             status,
+                             "halObject->mmuBase is NULL");
+    }
+    else {
+        mmuRegs = (VAYUIpu_MMURegs *)halObject->mmuBase;
+        /*
+         * Enable generation of interrupt on fault.
+         * This also ensures the slave core stays halted in its
+         * fault state upon generating an MMU fault.
+         */
+        reg = INREG32(&mmuRegs->GP_REG);
+        reg &= ~MMU_FAULT_INTR_DIS_MASK;
+        OUTREG32(&mmuRegs->GP_REG, reg);
+
+        OUTREG32(&mmuRegs->IRQENABLE, MMU_IRQ_TLB_MISS_MASK);
+   }
+
+   return status;
+}
+
+/****************************************************
+* Function to disable interrupt for MMU faults
+*****************************************************/
+Int rproc_disable_fault_interrupt(VAYUIPU_HalObject * halObject)
+{
+    Int status = 0;
+    VAYUIpu_MMURegs * mmuRegs = NULL;
+
+    if (halObject == NULL) {
+        status = -ENOMEM;
+        GT_setFailureReason (curTrace,
+                             GT_4CLASS,
+                             "rproc_enable_fault_interrupt",
+                             status,
+                             "halObject is NULL");
+    }
+    else if (halObject->mmuBase == 0) {
+        status = -ENOMEM;
+        GT_setFailureReason (curTrace,
+                             GT_4CLASS,
+                             "rproc_enable_fault_interrupt",
+                             status,
+                             "halObject->mmuBase is NULL");
+    }
+    else {
+        mmuRegs = (VAYUIpu_MMURegs *)halObject->mmuBase;
+        OUTREG32(&mmuRegs->IRQENABLE, 0);
+   }
+
+   return status;
+}
 
 /****************************************************
 *
index 3d73cac4c1f7e3515d3c656f5070794c759066e2..226b98a297baa48f21fcb71ecc6a5763c0a4157a 100644 (file)
@@ -199,8 +199,8 @@ typedef unsigned short u16;
 #define MMU_CNTL_TWL_EN        (1 << 2)
 #define MMU_CNTL_MMU_EN        (1 << 1)
 
-
-
+/* MMU GPR */
+#define MMU_FAULT_INTR_DIS_MASK  (1 << 0)
 
 #define PAGE_MASK(pg_size) (~((pg_size)-1))
 #define PG_ALIGN_LOW(addr, pg_size) ((addr) & PAGE_MASK(pg_size))
@@ -262,4 +262,11 @@ Int save_ipu_mmu_ctxt (VAYUIPU_HalObject * halObject, UInt32 procId);
 Int restore_ipu_mmu_ctxt (VAYUIPU_HalObject * halObject,
                           UInt32 procId);
 
+/* Enable interrupt for MMU faults */
+Int rproc_enable_fault_interrupt(VAYUIPU_HalObject * halObject);
+
+/* Disable interrupt for MMU faults */
+Int rproc_disable_fault_interrupt(VAYUIPU_HalObject * halObject);
+
+
 #endif /* _DIpuMMU_ENABLER_H_*/