1 /* 2 * Generic watchdog device model for SBSA 3 * 4 * The watchdog device has been implemented as revision 1 variant of 5 * the ARM SBSA specification v6.0 6 * (https://developer.arm.com/documentation/den0029/d?lang=en) 7 * 8 * Copyright Linaro.org 2020 9 * 10 * Authors: 11 * Shashi Mallela <shashi.mallela@linaro.org> 12 * 13 * This work is licensed under the terms of the GNU GPL, version 2 or (at your 14 * option) any later version. See the COPYING file in the top-level directory. 15 * 16 */ 17 18 #include "qemu/osdep.h" 19 #include "sysemu/reset.h" 20 #include "sysemu/watchdog.h" 21 #include "hw/qdev-properties.h" 22 #include "hw/watchdog/sbsa_gwdt.h" 23 #include "qemu/timer.h" 24 #include "migration/vmstate.h" 25 #include "qemu/log.h" 26 #include "qemu/module.h" 27 28 static const VMStateDescription vmstate_sbsa_gwdt = { 29 .name = "sbsa-gwdt", 30 .version_id = 1, 31 .minimum_version_id = 1, 32 .fields = (const VMStateField[]) { 33 VMSTATE_TIMER_PTR(timer, SBSA_GWDTState), 34 VMSTATE_UINT32(wcs, SBSA_GWDTState), 35 VMSTATE_UINT32(worl, SBSA_GWDTState), 36 VMSTATE_UINT32(woru, SBSA_GWDTState), 37 VMSTATE_UINT32(wcvl, SBSA_GWDTState), 38 VMSTATE_UINT32(wcvu, SBSA_GWDTState), 39 VMSTATE_END_OF_LIST() 40 } 41 }; 42 43 typedef enum WdtRefreshType { 44 EXPLICIT_REFRESH = 0, 45 TIMEOUT_REFRESH = 1, 46 } WdtRefreshType; 47 48 static uint64_t sbsa_gwdt_rread(void *opaque, hwaddr addr, unsigned int size) 49 { 50 SBSA_GWDTState *s = SBSA_GWDT(opaque); 51 uint32_t ret = 0; 52 53 switch (addr) { 54 case SBSA_GWDT_WRR: 55 /* watch refresh read has no effect and returns 0 */ 56 ret = 0; 57 break; 58 case SBSA_GWDT_W_IIDR: 59 ret = s->id; 60 break; 61 default: 62 qemu_log_mask(LOG_GUEST_ERROR, "bad address in refresh frame read :" 63 " 0x%x\n", (int)addr); 64 } 65 return ret; 66 } 67 68 static uint64_t sbsa_gwdt_read(void *opaque, hwaddr addr, unsigned int size) 69 { 70 SBSA_GWDTState *s = SBSA_GWDT(opaque); 71 uint32_t ret = 0; 72 73 switch (addr) { 74 case SBSA_GWDT_WCS: 75 ret = s->wcs; 76 break; 77 case SBSA_GWDT_WOR: 78 ret = s->worl; 79 break; 80 case SBSA_GWDT_WORU: 81 ret = s->woru; 82 break; 83 case SBSA_GWDT_WCV: 84 ret = s->wcvl; 85 break; 86 case SBSA_GWDT_WCVU: 87 ret = s->wcvu; 88 break; 89 case SBSA_GWDT_W_IIDR: 90 ret = s->id; 91 break; 92 default: 93 qemu_log_mask(LOG_GUEST_ERROR, "bad address in control frame read :" 94 " 0x%x\n", (int)addr); 95 } 96 return ret; 97 } 98 99 static void sbsa_gwdt_update_timer(SBSA_GWDTState *s, WdtRefreshType rtype) 100 { 101 uint64_t timeout = 0; 102 103 timer_del(s->timer); 104 105 if (s->wcs & SBSA_GWDT_WCS_EN) { 106 /* 107 * Extract the upper 16 bits from woru & 32 bits from worl 108 * registers to construct the 48 bit offset value 109 */ 110 timeout = s->woru; 111 timeout <<= 32; 112 timeout |= s->worl; 113 timeout = muldiv64(timeout, NANOSECONDS_PER_SECOND, s->freq); 114 timeout += qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 115 116 if ((rtype == EXPLICIT_REFRESH) || ((rtype == TIMEOUT_REFRESH) && 117 (!(s->wcs & SBSA_GWDT_WCS_WS0)))) { 118 /* store the current timeout value into compare registers */ 119 s->wcvu = timeout >> 32; 120 s->wcvl = timeout; 121 } 122 timer_mod(s->timer, timeout); 123 } 124 } 125 126 static void sbsa_gwdt_rwrite(void *opaque, hwaddr offset, uint64_t data, 127 unsigned size) { 128 SBSA_GWDTState *s = SBSA_GWDT(opaque); 129 130 if (offset == SBSA_GWDT_WRR) { 131 s->wcs &= ~(SBSA_GWDT_WCS_WS0 | SBSA_GWDT_WCS_WS1); 132 133 sbsa_gwdt_update_timer(s, EXPLICIT_REFRESH); 134 } else { 135 qemu_log_mask(LOG_GUEST_ERROR, "bad address in refresh frame write :" 136 " 0x%x\n", (int)offset); 137 } 138 } 139 140 static void sbsa_gwdt_write(void *opaque, hwaddr offset, uint64_t data, 141 unsigned size) { 142 SBSA_GWDTState *s = SBSA_GWDT(opaque); 143 144 switch (offset) { 145 case SBSA_GWDT_WCS: 146 s->wcs = data & SBSA_GWDT_WCS_EN; 147 qemu_set_irq(s->irq, 0); 148 sbsa_gwdt_update_timer(s, EXPLICIT_REFRESH); 149 break; 150 151 case SBSA_GWDT_WOR: 152 s->worl = data; 153 s->wcs &= ~(SBSA_GWDT_WCS_WS0 | SBSA_GWDT_WCS_WS1); 154 qemu_set_irq(s->irq, 0); 155 sbsa_gwdt_update_timer(s, EXPLICIT_REFRESH); 156 break; 157 158 case SBSA_GWDT_WORU: 159 s->woru = data & SBSA_GWDT_WOR_MASK; 160 s->wcs &= ~(SBSA_GWDT_WCS_WS0 | SBSA_GWDT_WCS_WS1); 161 qemu_set_irq(s->irq, 0); 162 sbsa_gwdt_update_timer(s, EXPLICIT_REFRESH); 163 break; 164 165 case SBSA_GWDT_WCV: 166 s->wcvl = data; 167 break; 168 169 case SBSA_GWDT_WCVU: 170 s->wcvu = data; 171 break; 172 173 default: 174 qemu_log_mask(LOG_GUEST_ERROR, "bad address in control frame write :" 175 " 0x%x\n", (int)offset); 176 } 177 return; 178 } 179 180 static void wdt_sbsa_gwdt_reset(DeviceState *dev) 181 { 182 SBSA_GWDTState *s = SBSA_GWDT(dev); 183 184 timer_del(s->timer); 185 186 s->wcs = 0; 187 s->wcvl = 0; 188 s->wcvu = 0; 189 s->worl = 0; 190 s->woru = 0; 191 s->id = SBSA_GWDT_ID; 192 } 193 194 static void sbsa_gwdt_timer_sysinterrupt(void *opaque) 195 { 196 SBSA_GWDTState *s = SBSA_GWDT(opaque); 197 198 if (!(s->wcs & SBSA_GWDT_WCS_WS0)) { 199 s->wcs |= SBSA_GWDT_WCS_WS0; 200 sbsa_gwdt_update_timer(s, TIMEOUT_REFRESH); 201 qemu_set_irq(s->irq, 1); 202 } else { 203 s->wcs |= SBSA_GWDT_WCS_WS1; 204 qemu_log_mask(CPU_LOG_RESET, "Watchdog timer expired.\n"); 205 /* 206 * Reset the watchdog only if the guest gets notified about 207 * expiry. watchdog_perform_action() may temporarily relinquish 208 * the BQL; reset before triggering the action to avoid races with 209 * sbsa_gwdt instructions. 210 */ 211 switch (get_watchdog_action()) { 212 case WATCHDOG_ACTION_DEBUG: 213 case WATCHDOG_ACTION_NONE: 214 case WATCHDOG_ACTION_PAUSE: 215 break; 216 default: 217 wdt_sbsa_gwdt_reset(DEVICE(s)); 218 } 219 watchdog_perform_action(); 220 } 221 } 222 223 static const MemoryRegionOps sbsa_gwdt_rops = { 224 .read = sbsa_gwdt_rread, 225 .write = sbsa_gwdt_rwrite, 226 .endianness = DEVICE_LITTLE_ENDIAN, 227 .valid.min_access_size = 4, 228 .valid.max_access_size = 4, 229 .valid.unaligned = false, 230 }; 231 232 static const MemoryRegionOps sbsa_gwdt_ops = { 233 .read = sbsa_gwdt_read, 234 .write = sbsa_gwdt_write, 235 .endianness = DEVICE_LITTLE_ENDIAN, 236 .valid.min_access_size = 4, 237 .valid.max_access_size = 4, 238 .valid.unaligned = false, 239 }; 240 241 static void wdt_sbsa_gwdt_realize(DeviceState *dev, Error **errp) 242 { 243 SBSA_GWDTState *s = SBSA_GWDT(dev); 244 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 245 246 memory_region_init_io(&s->rmmio, OBJECT(dev), 247 &sbsa_gwdt_rops, s, 248 "sbsa_gwdt.refresh", 249 SBSA_GWDT_RMMIO_SIZE); 250 251 memory_region_init_io(&s->cmmio, OBJECT(dev), 252 &sbsa_gwdt_ops, s, 253 "sbsa_gwdt.control", 254 SBSA_GWDT_CMMIO_SIZE); 255 256 sysbus_init_mmio(sbd, &s->rmmio); 257 sysbus_init_mmio(sbd, &s->cmmio); 258 259 sysbus_init_irq(sbd, &s->irq); 260 261 s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sbsa_gwdt_timer_sysinterrupt, 262 dev); 263 } 264 265 static Property wdt_sbsa_gwdt_props[] = { 266 /* 267 * Timer frequency in Hz. This must match the frequency used by 268 * the CPU's generic timer. Default 62.5Hz matches QEMU's legacy 269 * CPU timer frequency default. 270 */ 271 DEFINE_PROP_UINT64("clock-frequency", struct SBSA_GWDTState, freq, 272 62500000), 273 DEFINE_PROP_END_OF_LIST(), 274 }; 275 276 static void wdt_sbsa_gwdt_class_init(ObjectClass *klass, void *data) 277 { 278 DeviceClass *dc = DEVICE_CLASS(klass); 279 280 dc->realize = wdt_sbsa_gwdt_realize; 281 device_class_set_legacy_reset(dc, wdt_sbsa_gwdt_reset); 282 dc->hotpluggable = false; 283 set_bit(DEVICE_CATEGORY_WATCHDOG, dc->categories); 284 dc->vmsd = &vmstate_sbsa_gwdt; 285 dc->desc = "SBSA-compliant generic watchdog device"; 286 device_class_set_props(dc, wdt_sbsa_gwdt_props); 287 } 288 289 static const TypeInfo wdt_sbsa_gwdt_info = { 290 .class_init = wdt_sbsa_gwdt_class_init, 291 .parent = TYPE_SYS_BUS_DEVICE, 292 .name = TYPE_WDT_SBSA, 293 .instance_size = sizeof(SBSA_GWDTState), 294 }; 295 296 static void wdt_sbsa_gwdt_register_types(void) 297 { 298 type_register_static(&wdt_sbsa_gwdt_info); 299 } 300 301 type_init(wdt_sbsa_gwdt_register_types) 302