qdev: convert watchdogs

-watchdog NAME is now equivalent to -device NAME, except it treats
option argument '?' specially, and supports only one watchdog.

A side effect is that a device created with -watchdog may now receive
a different PCI address.

i6300esb is now available on any machine with a PCI bus, not just PCs.
ib700 is still PC only, but that could be changed easily.

The only remaining use of struct WatchdogTimerModel and
watchdog_add_model() is supporting '-watchdog ?'.  Should be replaced
by searching device_info_list for watchdog devices when we can
identify them there.

Also fixes ib700 not to use vm_clock before it is initialized: in
wdt_ib700_init(), called from register_watchdogs(), which runs before
init_timers().  The bug made ib700_write_enable_reg() crash in
qemu_del_timer().

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
Markus Armbruster 2009-08-21 10:31:34 +02:00 committed by Anthony Liguori
parent 9d472d51ea
commit 09aaa1602f
7 changed files with 48 additions and 62 deletions

View file

@ -179,15 +179,15 @@ obj-y += pcnet.o
obj-y += rtl8139.o
obj-y += e1000.o
# Generic watchdog support and some watchdog devices
obj-y += wdt_ib700.o wdt_i6300esb.o
# PCI watchdog devices
obj-y += wdt_i6300esb.o
# Hardware support
obj-i386-y = ide.o pckbd.o vga.o $(sound-obj-y) dma.o isa-bus.o
obj-i386-y += fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
obj-i386-y += cirrus_vga.o apic.o ioapic.o parallel.o acpi.o piix_pci.o
obj-i386-y += usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o
obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o
obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
# shared objects
obj-ppc-y = ppc.o ide.o vga.o $(sound-obj-y) dma.o isa-bus.o openpic.o

View file

@ -1343,8 +1343,6 @@ static void pc_init1(ram_addr_t ram_size,
}
}
watchdog_pc_init(pci_bus);
for(i = 0; i < nb_nics; i++) {
NICInfo *nd = &nd_table[i];

View file

@ -20,6 +20,8 @@
*/
#include "qemu-common.h"
#include "qemu-option.h"
#include "qemu-config.h"
#include "sys-queue.h"
#include "sysemu.h"
#include "hw/watchdog.h"
@ -32,7 +34,6 @@
#define WDT_DEBUG 5 /* Prints a message and continues running. */
#define WDT_NONE 6 /* Do nothing. */
static WatchdogTimerModel *watchdog;
static int watchdog_action = WDT_RESET;
static LIST_HEAD(watchdog_list, WatchdogTimerModel) watchdog_list;
@ -49,12 +50,7 @@ void watchdog_add_model(WatchdogTimerModel *model)
int select_watchdog(const char *p)
{
WatchdogTimerModel *model;
if (watchdog) {
fprintf(stderr,
"qemu: only one watchdog option may be given\n");
return 1;
}
QemuOpts *opts;
/* -watchdog ? lists available devices and exits cleanly. */
if (strcmp(p, "?") == 0) {
@ -67,7 +63,9 @@ int select_watchdog(const char *p)
LIST_FOREACH(model, &watchdog_list, entry) {
if (strcasecmp(model->wdt_name, p) == 0) {
watchdog = model;
/* add the device */
opts = qemu_opts_create(&qemu_device_opts, NULL, 0);
qemu_opt_set(opts, "driver", p);
return 0;
}
}
@ -130,15 +128,3 @@ void watchdog_perform_action(void)
break;
}
}
void watchdog_pc_init(PCIBus *pci_bus)
{
if (watchdog)
watchdog->wdt_pc_init(pci_bus);
}
void register_watchdogs(void)
{
wdt_ib700_init();
wdt_i6300esb_init();
}

View file

@ -22,10 +22,6 @@
#ifndef QEMU_WATCHDOG_H
#define QEMU_WATCHDOG_H
extern void wdt_i6300esb_init(void);
extern void wdt_ib700_init(void);
struct WatchdogTimerModel {
LIST_ENTRY(WatchdogTimerModel) entry;
@ -33,11 +29,6 @@ struct WatchdogTimerModel {
const char *wdt_name;
/* Longer description (eg. manufacturer and full model number). */
const char *wdt_description;
/* This callback should create/register the device. It is called
* indirectly from hw/pc.c when the virtual PC is being set up.
*/
void (*wdt_pc_init)(PCIBus *pci_bus);
};
typedef struct WatchdogTimerModel WatchdogTimerModel;
@ -46,7 +37,5 @@ extern int select_watchdog(const char *p);
extern int select_watchdog_action(const char *action);
extern void watchdog_add_model(WatchdogTimerModel *model);
extern void watchdog_perform_action(void);
extern void watchdog_pc_init(PCIBus *pci_bus);
extern void register_watchdogs(void);
#endif /* QEMU_WATCHDOG_H */

View file

@ -413,22 +413,11 @@ static int i6300esb_load(QEMUFile *f, void *vp, int version)
return 0;
}
/* Create and initialize a virtual Intel 6300ESB during PC creation. */
static void i6300esb_pc_init(PCIBus *pci_bus)
static void i6300esb_init(PCIDevice *dev)
{
I6300State *d;
I6300State *d = container_of(dev, I6300State, dev);
uint8_t *pci_conf;
if (!pci_bus) {
fprintf(stderr, "wdt_i6300esb: no PCI bus in this machine\n");
return;
}
d = (I6300State *)
pci_register_device (pci_bus, "i6300esb_wdt", sizeof (I6300State),
-1,
i6300esb_config_read, i6300esb_config_write);
d->reboot_enabled = 1;
d->clock_scale = CLOCK_SCALE_1KHZ;
d->int_type = INT_TYPE_IRQ;
@ -458,10 +447,20 @@ static void i6300esb_pc_init(PCIBus *pci_bus)
static WatchdogTimerModel model = {
.wdt_name = "i6300esb",
.wdt_description = "Intel 6300ESB",
.wdt_pc_init = i6300esb_pc_init,
};
void wdt_i6300esb_init(void)
static PCIDeviceInfo i6300esb_info = {
.qdev.name = "i6300esb",
.qdev.size = sizeof(I6300State),
.config_read = i6300esb_config_read,
.config_write = i6300esb_config_write,
.init = i6300esb_init,
};
static void i6300esb_register_devices(void)
{
watchdog_add_model(&model);
pci_qdev_register(&i6300esb_info);
}
device_init(i6300esb_register_devices);

View file

@ -88,11 +88,10 @@ static int ib700_load(QEMUFile *f, void *vp, int version)
return 0;
}
/* Create and initialize a virtual IB700 during PC creation. */
static void ib700_pc_init(PCIBus *unused)
static void wdt_ib700_init(ISADevice *dev)
{
timer = qemu_new_timer(vm_clock, ib700_timer_expired, NULL);
register_savevm("ib700_wdt", -1, 0, ib700_save, ib700_load, NULL);
register_ioport_write(0x441, 2, 1, ib700_write_disable_reg, NULL);
register_ioport_write(0x443, 2, 1, ib700_write_enable_reg, NULL);
}
@ -100,11 +99,18 @@ static void ib700_pc_init(PCIBus *unused)
static WatchdogTimerModel model = {
.wdt_name = "ib700",
.wdt_description = "iBASE 700",
.wdt_pc_init = ib700_pc_init,
};
void wdt_ib700_init(void)
static ISADeviceInfo wdt_ib700_info = {
.qdev.name = "ib700",
.qdev.size = sizeof(ISADevice),
.init = wdt_ib700_init,
};
static void wdt_ib700_register_devices(void)
{
watchdog_add_model(&model);
timer = qemu_new_timer(vm_clock, ib700_timer_expired, NULL);
isa_qdev_register(&wdt_ib700_info);
}
device_init(wdt_ib700_register_devices);

18
vl.c
View file

@ -233,6 +233,7 @@ uint8_t irq0override = 1;
#ifndef _WIN32
int daemonize = 0;
#endif
const char *watchdog;
const char *option_rom[MAX_OPTION_ROMS];
int nb_option_roms;
int semihosting_enabled = 0;
@ -4948,8 +4949,6 @@ int main(int argc, char **argv, char **envp)
tb_size = 0;
autostart= 1;
register_watchdogs();
optind = 1;
for(;;) {
if (optind >= argc)
@ -5361,9 +5360,12 @@ int main(int argc, char **argv, char **envp)
serial_device_index++;
break;
case QEMU_OPTION_watchdog:
i = select_watchdog(optarg);
if (i > 0)
exit (i == 1 ? 1 : 0);
if (watchdog) {
fprintf(stderr,
"qemu: only one watchdog option may be given\n");
return 1;
}
watchdog = optarg;
break;
case QEMU_OPTION_watchdog_action:
if (select_watchdog_action(optarg) == -1) {
@ -5927,6 +5929,12 @@ int main(int argc, char **argv, char **envp)
module_call_init(MODULE_INIT_DEVICE);
if (watchdog) {
i = select_watchdog(watchdog);
if (i > 0)
exit (i == 1 ? 1 : 0);
}
if (machine->compat_props) {
qdev_prop_register_compat(machine->compat_props);
}