Update to a hopefully more future proof FSF address
[qemu] / hw / wdt_i6300esb.c
1 /*
2  * Virtual hardware watchdog.
3  *
4  * Copyright (C) 2009 Red Hat Inc.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  *
19  * By Richard W.M. Jones (rjones@redhat.com).
20  */
21
22 #include <inttypes.h>
23
24 #include "qemu-common.h"
25 #include "qemu-timer.h"
26 #include "watchdog.h"
27 #include "hw.h"
28 #include "isa.h"
29 #include "pc.h"
30 #include "pci.h"
31
32 /*#define I6300ESB_DEBUG 1*/
33
34 #ifdef I6300ESB_DEBUG
35 #define i6300esb_debug(fs,...) \
36     fprintf(stderr,"i6300esb: %s: "fs,__func__,##__VA_ARGS__)
37 #else
38 #define i6300esb_debug(fs,...)
39 #endif
40
41 #ifndef PCI_DEVICE_ID_INTEL_ESB_9
42 #define PCI_DEVICE_ID_INTEL_ESB_9 0x25ab
43 #endif
44
45 /* PCI configuration registers */
46 #define ESB_CONFIG_REG  0x60            /* Config register                   */
47 #define ESB_LOCK_REG    0x68            /* WDT lock register                 */
48
49 /* Memory mapped registers (offset from base address) */
50 #define ESB_TIMER1_REG  0x00            /* Timer1 value after each reset     */
51 #define ESB_TIMER2_REG  0x04            /* Timer2 value after each reset     */
52 #define ESB_GINTSR_REG  0x08            /* General Interrupt Status Register */
53 #define ESB_RELOAD_REG  0x0c            /* Reload register                   */
54
55 /* Lock register bits */
56 #define ESB_WDT_FUNC    (0x01 << 2)   /* Watchdog functionality            */
57 #define ESB_WDT_ENABLE  (0x01 << 1)   /* Enable WDT                        */
58 #define ESB_WDT_LOCK    (0x01 << 0)   /* Lock (nowayout)                   */
59
60 /* Config register bits */
61 #define ESB_WDT_REBOOT  (0x01 << 5)   /* Enable reboot on timeout          */
62 #define ESB_WDT_FREQ    (0x01 << 2)   /* Decrement frequency               */
63 #define ESB_WDT_INTTYPE (0x11 << 0)   /* Interrupt type on timer1 timeout  */
64
65 /* Reload register bits */
66 #define ESB_WDT_RELOAD  (0x01 << 8)    /* prevent timeout                   */
67
68 /* Magic constants */
69 #define ESB_UNLOCK1     0x80            /* Step 1 to unlock reset registers  */
70 #define ESB_UNLOCK2     0x86            /* Step 2 to unlock reset registers  */
71
72 /* Device state. */
73 struct I6300State {
74     PCIDevice dev;              /* PCI device state, must be first field. */
75
76     int reboot_enabled;         /* "Reboot" on timer expiry.  The real action
77                                  * performed depends on the -watchdog-action
78                                  * param passed on QEMU command line.
79                                  */
80     int clock_scale;            /* Clock scale. */
81 #define CLOCK_SCALE_1KHZ 0
82 #define CLOCK_SCALE_1MHZ 1
83
84     int int_type;               /* Interrupt type generated. */
85 #define INT_TYPE_IRQ 0          /* APIC 1, INT 10 */
86 #define INT_TYPE_SMI 2
87 #define INT_TYPE_DISABLED 3
88
89     int free_run;               /* If true, reload timer on expiry. */
90     int locked;                 /* If true, enabled field cannot be changed. */
91     int enabled;                /* If true, watchdog is enabled. */
92
93     QEMUTimer *timer;           /* The actual watchdog timer. */
94
95     uint32_t timer1_preload;    /* Values preloaded into timer1, timer2. */
96     uint32_t timer2_preload;
97     int stage;                  /* Stage (1 or 2). */
98
99     int unlock_state;           /* Guest writes 0x80, 0x86 to unlock the
100                                  * registers, and we transition through
101                                  * states 0 -> 1 -> 2 when this happens.
102                                  */
103
104     int previous_reboot_flag;   /* If the watchdog caused the previous
105                                  * reboot, this flag will be set.
106                                  */
107 };
108
109 typedef struct I6300State I6300State;
110
111 /* This function is called when the watchdog has either been enabled
112  * (hence it starts counting down) or has been keep-alived.
113  */
114 static void i6300esb_restart_timer(I6300State *d, int stage)
115 {
116     int64_t timeout;
117
118     if (!d->enabled)
119         return;
120
121     d->stage = stage;
122
123     if (d->stage <= 1)
124         timeout = d->timer1_preload;
125     else
126         timeout = d->timer2_preload;
127
128     if (d->clock_scale == CLOCK_SCALE_1KHZ)
129         timeout <<= 15;
130     else
131         timeout <<= 5;
132
133     /* Get the timeout in units of ticks_per_sec. */
134     timeout = ticks_per_sec * timeout / 33000000;
135
136     i6300esb_debug("stage %d, timeout %" PRIi64 "\n", d->stage, timeout);
137
138     qemu_mod_timer(d->timer, qemu_get_clock(vm_clock) + timeout);
139 }
140
141 /* This is called when the guest disables the watchdog. */
142 static void i6300esb_disable_timer(I6300State *d)
143 {
144     i6300esb_debug("timer disabled\n");
145
146     qemu_del_timer(d->timer);
147 }
148
149 static void i6300esb_reset(I6300State *d)
150 {
151     /* XXX We should probably reset other parts of the state here,
152      * but we should also reset our state on general machine reset
153      * too.  For now just disable the timer so it doesn't fire
154      * again after the reboot.
155      */
156     i6300esb_disable_timer(d);
157 }
158
159 /* This function is called when the watchdog expires.  Note that
160  * the hardware has two timers, and so expiry happens in two stages.
161  * If d->stage == 1 then we perform the first stage action (usually,
162  * sending an interrupt) and then restart the timer again for the
163  * second stage.  If the second stage expires then the watchdog
164  * really has run out.
165  */
166 static void i6300esb_timer_expired(void *vp)
167 {
168     I6300State *d = (I6300State *) vp;
169
170     i6300esb_debug("stage %d\n", d->stage);
171
172     if (d->stage == 1) {
173         /* What to do at the end of stage 1? */
174         switch (d->int_type) {
175         case INT_TYPE_IRQ:
176             fprintf(stderr, "i6300esb_timer_expired: I would send APIC 1 INT 10 here if I knew how (XXX)\n");
177             break;
178         case INT_TYPE_SMI:
179             fprintf(stderr, "i6300esb_timer_expired: I would send SMI here if I knew how (XXX)\n");
180             break;
181         }
182
183         /* Start the second stage. */
184         i6300esb_restart_timer(d, 2);
185     } else {
186         /* Second stage expired, reboot for real. */
187         if (d->reboot_enabled) {
188             d->previous_reboot_flag = 1;
189             watchdog_perform_action(); /* This reboots, exits, etc */
190             i6300esb_reset(d);
191         }
192
193         /* In "free running mode" we start stage 1 again. */
194         if (d->free_run)
195             i6300esb_restart_timer(d, 1);
196     }
197 }
198
199 static void i6300esb_config_write(PCIDevice *dev, uint32_t addr,
200                                   uint32_t data, int len)
201 {
202     I6300State *d = (I6300State *) dev;
203     int old;
204
205     i6300esb_debug("addr = %x, data = %x, len = %d\n", addr, data, len);
206
207     if (addr == ESB_CONFIG_REG && len == 2) {
208         d->reboot_enabled = (data & ESB_WDT_REBOOT) == 0;
209         d->clock_scale =
210             (data & ESB_WDT_FREQ) != 0 ? CLOCK_SCALE_1MHZ : CLOCK_SCALE_1KHZ;
211         d->int_type = (data & ESB_WDT_INTTYPE);
212     } else if (addr == ESB_LOCK_REG && len == 1) {
213         if (!d->locked) {
214             d->locked = (data & ESB_WDT_LOCK) != 0;
215             d->free_run = (data & ESB_WDT_FUNC) != 0;
216             old = d->enabled;
217             d->enabled = (data & ESB_WDT_ENABLE) != 0;
218             if (!old && d->enabled) /* Enabled transitioned from 0 -> 1 */
219                 i6300esb_restart_timer(d, 1);
220             else if (!d->enabled)
221                 i6300esb_disable_timer(d);
222         }
223     } else {
224         pci_default_write_config(dev, addr, data, len);
225     }
226 }
227
228 static uint32_t i6300esb_config_read(PCIDevice *dev, uint32_t addr, int len)
229 {
230     I6300State *d = (I6300State *) dev;
231     uint32_t data;
232
233     i6300esb_debug ("addr = %x, len = %d\n", addr, len);
234
235     if (addr == ESB_CONFIG_REG && len == 2) {
236         data =
237             (d->reboot_enabled ? 0 : ESB_WDT_REBOOT) |
238             (d->clock_scale == CLOCK_SCALE_1MHZ ? ESB_WDT_FREQ : 0) |
239             d->int_type;
240         return data;
241     } else if (addr == ESB_LOCK_REG && len == 1) {
242         data =
243             (d->free_run ? ESB_WDT_FUNC : 0) |
244             (d->locked ? ESB_WDT_LOCK : 0) |
245             (d->enabled ? ESB_WDT_ENABLE : 0);
246         return data;
247     } else {
248         return pci_default_read_config(dev, addr, len);
249     }
250 }
251
252 static uint32_t i6300esb_mem_readb(void *vp, target_phys_addr_t addr)
253 {
254     i6300esb_debug ("addr = %x\n", (int) addr);
255
256     return 0;
257 }
258
259 static uint32_t i6300esb_mem_readw(void *vp, target_phys_addr_t addr)
260 {
261     uint32_t data = 0;
262     I6300State *d = (I6300State *) vp;
263
264     i6300esb_debug("addr = %x\n", (int) addr);
265
266     if (addr == 0xc) {
267         /* The previous reboot flag is really bit 9, but there is
268          * a bug in the Linux driver where it thinks it's bit 12.
269          * Set both.
270          */
271         data = d->previous_reboot_flag ? 0x1200 : 0;
272     }
273
274     return data;
275 }
276
277 static uint32_t i6300esb_mem_readl(void *vp, target_phys_addr_t addr)
278 {
279     i6300esb_debug("addr = %x\n", (int) addr);
280
281     return 0;
282 }
283
284 static void i6300esb_mem_writeb(void *vp, target_phys_addr_t addr, uint32_t val)
285 {
286     I6300State *d = (I6300State *) vp;
287
288     i6300esb_debug("addr = %x, val = %x\n", (int) addr, val);
289
290     if (addr == 0xc && val == 0x80)
291         d->unlock_state = 1;
292     else if (addr == 0xc && val == 0x86 && d->unlock_state == 1)
293         d->unlock_state = 2;
294 }
295
296 static void i6300esb_mem_writew(void *vp, target_phys_addr_t addr, uint32_t val)
297 {
298     I6300State *d = (I6300State *) vp;
299
300     i6300esb_debug("addr = %x, val = %x\n", (int) addr, val);
301
302     if (addr == 0xc && val == 0x80)
303         d->unlock_state = 1;
304     else if (addr == 0xc && val == 0x86 && d->unlock_state == 1)
305         d->unlock_state = 2;
306     else {
307         if (d->unlock_state == 2) {
308             if (addr == 0xc) {
309                 if ((val & 0x100) != 0)
310                     /* This is the "ping" from the userspace watchdog in
311                      * the guest ...
312                      */
313                     i6300esb_restart_timer(d, 1);
314
315                 /* Setting bit 9 resets the previous reboot flag.
316                  * There's a bug in the Linux driver where it sets
317                  * bit 12 instead.
318                  */
319                 if ((val & 0x200) != 0 || (val & 0x1000) != 0) {
320                     d->previous_reboot_flag = 0;
321                 }
322             }
323
324             d->unlock_state = 0;
325         }
326     }
327 }
328
329 static void i6300esb_mem_writel(void *vp, target_phys_addr_t addr, uint32_t val)
330 {
331     I6300State *d = (I6300State *) vp;
332
333     i6300esb_debug ("addr = %x, val = %x\n", (int) addr, val);
334
335     if (addr == 0xc && val == 0x80)
336         d->unlock_state = 1;
337     else if (addr == 0xc && val == 0x86 && d->unlock_state == 1)
338         d->unlock_state = 2;
339     else {
340         if (d->unlock_state == 2) {
341             if (addr == 0)
342                 d->timer1_preload = val & 0xfffff;
343             else if (addr == 4)
344                 d->timer2_preload = val & 0xfffff;
345
346             d->unlock_state = 0;
347         }
348     }
349 }
350
351 static void i6300esb_map(PCIDevice *dev, int region_num,
352                          uint32_t addr, uint32_t size, int type)
353 {
354     static CPUReadMemoryFunc *mem_read[3] = {
355         i6300esb_mem_readb,
356         i6300esb_mem_readw,
357         i6300esb_mem_readl,
358     };
359     static CPUWriteMemoryFunc *mem_write[3] = {
360         i6300esb_mem_writeb,
361         i6300esb_mem_writew,
362         i6300esb_mem_writel,
363     };
364     I6300State *d = (I6300State *) dev;
365     int io_mem;
366
367     i6300esb_debug("addr = %x, size = %x, type = %d\n", addr, size, type);
368
369     io_mem = cpu_register_io_memory(mem_read, mem_write, d);
370     cpu_register_physical_memory (addr, 0x10, io_mem);
371     /* qemu_register_coalesced_mmio (addr, 0x10); ? */
372 }
373
374 static void i6300esb_save(QEMUFile *f, void *vp)
375 {
376     I6300State *d = (I6300State *) vp;
377
378     pci_device_save(&d->dev, f);
379     qemu_put_be32(f, d->reboot_enabled);
380     qemu_put_be32(f, d->clock_scale);
381     qemu_put_be32(f, d->int_type);
382     qemu_put_be32(f, d->free_run);
383     qemu_put_be32(f, d->locked);
384     qemu_put_be32(f, d->enabled);
385     qemu_put_timer(f, d->timer);
386     qemu_put_be32(f, d->timer1_preload);
387     qemu_put_be32(f, d->timer2_preload);
388     qemu_put_be32(f, d->stage);
389     qemu_put_be32(f, d->unlock_state);
390     qemu_put_be32(f, d->previous_reboot_flag);
391 }
392
393 static int i6300esb_load(QEMUFile *f, void *vp, int version)
394 {
395     I6300State *d = (I6300State *) vp;
396
397     if (version != sizeof (I6300State))
398         return -EINVAL;
399
400     pci_device_load(&d->dev, f);
401     d->reboot_enabled = qemu_get_be32(f);
402     d->clock_scale = qemu_get_be32(f);
403     d->int_type = qemu_get_be32(f);
404     d->free_run = qemu_get_be32(f);
405     d->locked = qemu_get_be32(f);
406     d->enabled = qemu_get_be32(f);
407     qemu_get_timer(f, d->timer);
408     d->timer1_preload = qemu_get_be32(f);
409     d->timer2_preload = qemu_get_be32(f);
410     d->stage = qemu_get_be32(f);
411     d->unlock_state = qemu_get_be32(f);
412     d->previous_reboot_flag = qemu_get_be32(f);
413
414     return 0;
415 }
416
417 /* Create and initialize a virtual Intel 6300ESB during PC creation. */
418 static void i6300esb_pc_init(PCIBus *pci_bus)
419 {
420     I6300State *d;
421     uint8_t *pci_conf;
422
423     if (!pci_bus) {
424         fprintf(stderr, "wdt_i6300esb: no PCI bus in this machine\n");
425         return;
426     }
427
428     d = (I6300State *)
429         pci_register_device (pci_bus, "i6300esb_wdt", sizeof (I6300State),
430                              -1,
431                              i6300esb_config_read, i6300esb_config_write);
432
433     d->reboot_enabled = 1;
434     d->clock_scale = CLOCK_SCALE_1KHZ;
435     d->int_type = INT_TYPE_IRQ;
436     d->free_run = 0;
437     d->locked = 0;
438     d->enabled = 0;
439     d->timer = qemu_new_timer(vm_clock, i6300esb_timer_expired, d);
440     d->timer1_preload = 0xfffff;
441     d->timer2_preload = 0xfffff;
442     d->stage = 1;
443     d->unlock_state = 0;
444     d->previous_reboot_flag = 0;
445
446     pci_conf = d->dev.config;
447     pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
448     pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_ESB_9);
449     pci_config_set_class(pci_conf, PCI_CLASS_SYSTEM_OTHER);
450     pci_conf[0x0e] = 0x00;
451
452     pci_register_bar(&d->dev, 0, 0x10,
453                             PCI_ADDRESS_SPACE_MEM, i6300esb_map);
454
455     register_savevm("i6300esb_wdt", -1, sizeof(I6300State),
456                      i6300esb_save, i6300esb_load, d);
457 }
458
459 static WatchdogTimerModel model = {
460     .wdt_name = "i6300esb",
461     .wdt_description = "Intel 6300ESB",
462     .wdt_pc_init = i6300esb_pc_init,
463 };
464
465 void wdt_i6300esb_init(void)
466 {
467     watchdog_add_model(&model);
468 }