mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-11-05 20:35:44 +00:00
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:
parent
9d472d51ea
commit
09aaa1602f
7 changed files with 48 additions and 62 deletions
|
@ -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
|
||||
|
|
2
hw/pc.c
2
hw/pc.c
|
@ -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];
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
18
vl.c
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue