From 7ed292eeef3eff039eaae44e669c4424f33b8c16 Mon Sep 17 00:00:00 2001 From: Yin Fengwei Date: Wed, 4 Jul 2018 17:17:48 +0800 Subject: [PATCH] DM: extend i6300esb device to support watchdog timeout query 6300esb has bit in its register to show whether the watchdog timeout is hit. This patch adds this bit support. So the guest could query whether last reset is triggered by watchdog reset. Signed-off-by: Yin Fengwei Reviewed-by: Cao Minggui Acked-by: Eddie Dong Tested-by: Binbin Wu --- devicemodel/core/sw_load_vsbl.c | 2 +- devicemodel/hw/pci/wdt_i6300esb.c | 44 ++++++++++++++++++++++++++----- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/devicemodel/core/sw_load_vsbl.c b/devicemodel/core/sw_load_vsbl.c index 32d17f19d..a14f9969e 100644 --- a/devicemodel/core/sw_load_vsbl.c +++ b/devicemodel/core/sw_load_vsbl.c @@ -99,7 +99,7 @@ struct vsbl_para { uint64_t bootargs_address; uint32_t trusty_enabled; uint32_t key_info_lock; - uint32_t watchdog_reset; + uint32_t reserved; uint32_t boot_device_address; }; diff --git a/devicemodel/hw/pci/wdt_i6300esb.c b/devicemodel/hw/pci/wdt_i6300esb.c index f8d1afa5b..a41833fb2 100644 --- a/devicemodel/hw/pci/wdt_i6300esb.c +++ b/devicemodel/hw/pci/wdt_i6300esb.c @@ -40,6 +40,7 @@ #define ESB_WDT_REBOOT (0x01 << 5) /* Enable reboot on timeout */ #define ESB_WDT_RELOAD (0x01 << 8) /* Ping/kick dog */ +#define ESB_WDT_TIMEOUT (0x01 << 9) /* WDT timeout happened? */ #define TIMER_TO_SECONDS(val) (val >> 9) /* Magic constants */ @@ -75,6 +76,11 @@ struct info_wdt { int unlock_state; /* unlock states 0 -> 1 -> 2 */ }; +/* Whether watchdog is timeout. This info should cross reset. So + * we didn't add to struct info_wdt. + */ +static int wdt_timeout = 0; + static struct info_wdt wdt_state; static void start_wdt_timer(void); @@ -95,6 +101,9 @@ wdt_expired_thread(union sigval v) start_wdt_timer(); } else { if (wdt_state.reboot_enabled) { + wdt_state.stage = 1; + wdt_timeout = 1; + /* watchdog timer out, set the uos to reboot */ vm_set_suspend_mode(VM_SUSPEND_RESET); mevent_notify(); @@ -264,10 +273,18 @@ pci_wdt_bar_write(struct vmctx *ctx, int vcpu, struct pci_vdev *dev, else if ((value == ESB_UNLOCK2) && (wdt_state.unlock_state == 1)) wdt_state.unlock_state = 2; - else if ((wdt_state.unlock_state == 2) - && (value & ESB_WDT_RELOAD)) { - wdt_state.stage = 1; - start_wdt_timer(); + else if (wdt_state.unlock_state == 2) { + if (value & ESB_WDT_RELOAD) { + wdt_state.stage = 1; + start_wdt_timer(); + } + + /* write ES_WDT_TIMEOUT bit clear wdt timeout */ + if (value & ESB_WDT_TIMEOUT) { + DPRINTF("%s: timeout cleaned\n\r", __func__); + wdt_timeout = 0; + } + wdt_state.unlock_state = 0; } } else if (wdt_state.unlock_state == 2) { @@ -284,10 +301,23 @@ uint64_t pci_wdt_bar_read(struct vmctx *ctx, int vcpu, struct pci_vdev *dev, int baridx, uint64_t offset, int size) { - assert(baridx == 0); - DPRINTF("%s: addr = 0x%x, size=%d\n", __func__, (int) offset, size); + uint64_t ret = 0; - return 0; + assert(baridx == 0); + DPRINTF("%s: addr = 0x%x, size=%d\n\r", __func__, (int) offset, size); + + if (offset == ESB_RELOAD_REG) { + assert(size == 2); + + DPRINTF("%s: timeout: %d\n\r", __func__, wdt_timeout); + if (wdt_timeout != 0) + ret |= ESB_WDT_TIMEOUT; + + if (wdt_state.stage == 1) + ret |= ESB_WDT_RELOAD; + } + + return ret; } static int