高通 msm8909 watchdog overview

高通的描述

看门狗定时器是一个固定长度的计数器,它使系统能够从意外的硬件或软件灾难中恢复。
除非系统定期重置看门狗定时器,否则看门狗定时器会在定时器超时后自动重置系统。
MSM ASIC 为芯片系统使用了一个看门狗定时器。
调制解调器软件负责重置看门狗(kicking or petting the dog)并通过定期检查系统中的其他处理器(通过中断线握手)来检查系统中的其他处理器是否正常工作。
除了复位触发信号(wdog expired),还可以在看门狗到期之前生成看门狗中断,以允许处理器在重置系统之前尝试恢复系统。在以应用程序为中心的引导系统中,系统中驻留的看门狗不止一个。
全局系统重置将由系统信任根(SRoT)控制,例如应用处理器。所有其他子系统,包括调制解调器,一旦它们的看门狗到期,它只能向应用程序处理器生成中断。
然后应用处理器处理其余的操作。为了提供来自应用处理器的实时反应,子系统应该有一个专用的看门狗定时器。
在提供 BITE 和 BARK 看门狗定时器支持的系统中,当定时器超时时,相应的中断将被触发。
BITE 超时将向应用处理器发送中断并立即触发子系统复位。 BARK 超时将对子系统本身产生 FIQ 中断。
子系统必须将这种情况作为灾难性重启情况进行处理。还需要一次性写入看门狗寄存器以阻止恶意攻击禁用看门狗并允许

软件流程

代码路径

kernel/drivers/soc/qcom/watchdog_v2.c.

还有一个由应用程序端驱动的硬件看门狗。 如果硬件看门狗在 10 秒内没有受到pet,则会断言中断,这将使 Linux 内核panic并打印回溯(触发panic超时并在配置时重置)。
这被称为bark。 如果看门狗持续 11 秒没有被pet,将会重启。 这是dog bite。 看门狗驱动程序当前安排自己每 10 秒pet看门狗。

设备树中的配置

在msm8909平台上,看门狗的设备树配置信息默认保存在msm8909.dtsi中。

qcom,wdt@b017000 {
        compatible = "qcom,msm-watchdog"  ;//Compatible name for matching
        reg = <0xb017000 0x1000>;               //Watchdog register address
        reg-names = "wdt-base";                  //resouce name
        interrupts = <0 3 0>, <0 4 0>;
        qcom,bark-time = <11000>;              //Dog bark time configuration
        qcom,pet-time = <10000>;               //Feed dog time configuration
        qcom,ipi-ping;                         //Used to ping other cpu states
};

驱动 Watchdog_v2.c

主要结构体

        struct msm_watchdog_data {
            unsigned int __iomem phys_base;
            size_t size;
            void __iomem *base;
            void __iomem *wdog_absent_base;
            unsigned int pet_time;                               
            unsigned int bark_time;                              
            unsigned int bark_irq;                               
            unsigned int bite_irq;                               
            bool do_ipi_ping;                                    
            unsigned long long last_pet;                         
            struct work_struct init_dogwork_struct;              
            struct delayed_work dogwork_struct;                  
            bool irq_ppi;                                        
            struct msm_watchdog_data __percpu **wdog_cpu_dd;     
            struct notifier_block panic_blk;                     
            bool enabled;                                        
           };
           

主要流程图

probe->   

msm_wdog_dt_to_pdata(pdev, wdog_dd);   
//Obtain information about device tree configuration, apply for memory space, and map memory.
      INIT_WORK(&wdog_dd->init_dogwork_struct, init_watchdog_work);    
      INIT_DELAYED_WORK(&wdog_dd->dogwork_struct, pet_watchdog_work);  
      queue_work(wdog_wq, &wdog_dd->init_dogwork_struct);  
//Scheduling init work
           	devm_request_irq(wdog_dd->dev, wdog_dd->bark_irq,wdog_bark_handler, IRQF_TRIGGER_RISING,"apps_wdog_bark", wdog_dd); 
//Application interrupt
           	timeout = (wdog_dd->bark_time * WDT_HZ)/1000;                      
          	__raw_writel(timeout, wdog_dd->base + WDT0_BARK_TIME);                 
// set register for bark-time   Default 11s
           	__raw_writel(timeout + 3*WDT_HZ, wdog_dd->base + WDT0_BITE_TIME);      
// set register for bite-time   Default 14s
             wdog_dd->panic_blk.notifier_call = panic_wdog_handler;                
 // set handle for panic
             queue_delayed_work(wdog_wq, &wdog_dd->dogwork_struct,delay_time);      
// Calling a delayed work queue
             __raw_writel(1, wdog_dd->base + WDT0_EN);                             
 // enable WDT0
             __raw_writel(1, wdog_dd->base + WDT0_RST);                             
// RST WDT0
             wdog_dd->last_pet = sched_clock();                                     
// Record the time of the last dog feeding

queue_delayed_work-> 

ping_other_cpus(wdog_dd);
//ping the status of other cpu
pet_watchdog(wdog_dd);                                                
//pet_watchdog
queue_delayed_work(wdog_wq,&wdog_dd->dogwork_struct, delay_time);      
// delay_time = msecs_to_jiffies(wdog_dd->pet_time);

pet_watchdog->

 static void pet_watchdog(struct msm_watchdog_data *wdog_dd)
            {
                int slack, i, count, prev_count = 0;
                unsigned long long time_ns;
                unsigned long long slack_ns;
                unsigned long long bark_time_ns = wdog_dd->bark_time * 1000000ULL;

                for (i = 0; i < 2; i++) {
                    count = (__raw_readl(wdog_dd->base + WDT0_STS) >> 1) & 0xFFFFF;
                    if (count != prev_count) {
                        prev_count = count;
                        i = 0;
                    }
                }
                slack = ((wdog_dd->bark_time * WDT_HZ) / 1000) - count;
                if (slack < wdog_dd->min_slack_ticks)
                    wdog_dd->min_slack_ticks = slack;
                __raw_writel(1, wdog_dd->base + WDT0_RST);
                time_ns = sched_clock();
                slack_ns = (wdog_dd->last_pet + bark_time_ns) - time_ns;
                if (slack_ns < wdog_dd->min_slack_ns)
                    wdog_dd->min_slack_ns = slack_ns;
                wdog_dd->last_pet = time_ns;
            }  

如果未喂狗,则会触发看门狗中断

        static irqreturn_t wdog_bark_handler(int irq, void *dev_id)
            {
                struct msm_watchdog_data *wdog_dd = (struct msm_watchdog_data *)dev_id;
                unsigned long nanosec_rem;
                unsigned long long t = sched_clock();

                nanosec_rem = do_div(t, 1000000000);
                printk(KERN_INFO "Watchdog bark! Now = %lu.%06lu\n", (unsigned long) t,
                    nanosec_rem / 1000);

                nanosec_rem = do_div(wdog_dd->last_pet, 1000000000);
                printk(KERN_INFO "Watchdog last pet at %lu.%06lu\n", (unsigned long)
                    wdog_dd->last_pet, nanosec_rem / 1000);
                if (wdog_dd->do_ipi_ping)
                    dump_cpu_alive_mask(wdog_dd);
                msm_trigger_wdog_bite();  
  //wdog bite The machine needs to be reset
                panic("Failed to cause a watchdog bite! - Falling back to kernel panic!");
                return IRQ_HANDLED;
            }

msm_trigger_wdog_bite

    void msm_trigger_wdog_bite(void)
        {
            if (!wdog_data)
                return;
            pr_info("Causing a watchdog bite!");
            __raw_writel(1, wdog_data->base + WDT0_BITE_TIME); 
            mb();
            __raw_writel(1, wdog_data->base + WDT0_RST);  
 //Write a value to the hardware watchdog register. Trigger a hardware reset.
            mb();
            /* Delay to make sure bite occurs */
            mdelay(1);
            pr_err("Wdog - STS: 0x%x, CTL: 0x%x, BARK TIME: 0x%x, BITE TIME: 0x%x",
                __raw_readl(wdog_data->base + WDT0_STS),
                __raw_readl(wdog_data->base + WDT0_EN),
                __raw_readl(wdog_data->base + WDT0_BARK_TIME),
                __raw_readl(wdog_data->base + WDT0_BITE_TIME));
        }   

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值