mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-30 05:21:55 -06: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 += rtl8139.o
|
||||||
obj-y += e1000.o
|
obj-y += e1000.o
|
||||||
|
|
||||||
# Generic watchdog support and some watchdog devices
|
# PCI watchdog devices
|
||||||
obj-y += wdt_ib700.o wdt_i6300esb.o
|
obj-y += wdt_i6300esb.o
|
||||||
|
|
||||||
# Hardware support
|
# Hardware support
|
||||||
obj-i386-y = ide.o pckbd.o vga.o $(sound-obj-y) dma.o isa-bus.o
|
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 += 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 += 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 += 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
|
# shared objects
|
||||||
obj-ppc-y = ppc.o ide.o vga.o $(sound-obj-y) dma.o isa-bus.o openpic.o
|
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++) {
|
for(i = 0; i < nb_nics; i++) {
|
||||||
NICInfo *nd = &nd_table[i];
|
NICInfo *nd = &nd_table[i];
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
|
#include "qemu-option.h"
|
||||||
|
#include "qemu-config.h"
|
||||||
#include "sys-queue.h"
|
#include "sys-queue.h"
|
||||||
#include "sysemu.h"
|
#include "sysemu.h"
|
||||||
#include "hw/watchdog.h"
|
#include "hw/watchdog.h"
|
||||||
|
@ -32,7 +34,6 @@
|
||||||
#define WDT_DEBUG 5 /* Prints a message and continues running. */
|
#define WDT_DEBUG 5 /* Prints a message and continues running. */
|
||||||
#define WDT_NONE 6 /* Do nothing. */
|
#define WDT_NONE 6 /* Do nothing. */
|
||||||
|
|
||||||
static WatchdogTimerModel *watchdog;
|
|
||||||
static int watchdog_action = WDT_RESET;
|
static int watchdog_action = WDT_RESET;
|
||||||
static LIST_HEAD(watchdog_list, WatchdogTimerModel) watchdog_list;
|
static LIST_HEAD(watchdog_list, WatchdogTimerModel) watchdog_list;
|
||||||
|
|
||||||
|
@ -49,12 +50,7 @@ void watchdog_add_model(WatchdogTimerModel *model)
|
||||||
int select_watchdog(const char *p)
|
int select_watchdog(const char *p)
|
||||||
{
|
{
|
||||||
WatchdogTimerModel *model;
|
WatchdogTimerModel *model;
|
||||||
|
QemuOpts *opts;
|
||||||
if (watchdog) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"qemu: only one watchdog option may be given\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -watchdog ? lists available devices and exits cleanly. */
|
/* -watchdog ? lists available devices and exits cleanly. */
|
||||||
if (strcmp(p, "?") == 0) {
|
if (strcmp(p, "?") == 0) {
|
||||||
|
@ -67,7 +63,9 @@ int select_watchdog(const char *p)
|
||||||
|
|
||||||
LIST_FOREACH(model, &watchdog_list, entry) {
|
LIST_FOREACH(model, &watchdog_list, entry) {
|
||||||
if (strcasecmp(model->wdt_name, p) == 0) {
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,15 +128,3 @@ void watchdog_perform_action(void)
|
||||||
break;
|
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
|
#ifndef QEMU_WATCHDOG_H
|
||||||
#define QEMU_WATCHDOG_H
|
#define QEMU_WATCHDOG_H
|
||||||
|
|
||||||
extern void wdt_i6300esb_init(void);
|
|
||||||
extern void wdt_ib700_init(void);
|
|
||||||
|
|
||||||
|
|
||||||
struct WatchdogTimerModel {
|
struct WatchdogTimerModel {
|
||||||
LIST_ENTRY(WatchdogTimerModel) entry;
|
LIST_ENTRY(WatchdogTimerModel) entry;
|
||||||
|
|
||||||
|
@ -33,11 +29,6 @@ struct WatchdogTimerModel {
|
||||||
const char *wdt_name;
|
const char *wdt_name;
|
||||||
/* Longer description (eg. manufacturer and full model number). */
|
/* Longer description (eg. manufacturer and full model number). */
|
||||||
const char *wdt_description;
|
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;
|
typedef struct WatchdogTimerModel WatchdogTimerModel;
|
||||||
|
|
||||||
|
@ -46,7 +37,5 @@ extern int select_watchdog(const char *p);
|
||||||
extern int select_watchdog_action(const char *action);
|
extern int select_watchdog_action(const char *action);
|
||||||
extern void watchdog_add_model(WatchdogTimerModel *model);
|
extern void watchdog_add_model(WatchdogTimerModel *model);
|
||||||
extern void watchdog_perform_action(void);
|
extern void watchdog_perform_action(void);
|
||||||
extern void watchdog_pc_init(PCIBus *pci_bus);
|
|
||||||
extern void register_watchdogs(void);
|
|
||||||
|
|
||||||
#endif /* QEMU_WATCHDOG_H */
|
#endif /* QEMU_WATCHDOG_H */
|
||||||
|
|
|
@ -413,22 +413,11 @@ static int i6300esb_load(QEMUFile *f, void *vp, int version)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create and initialize a virtual Intel 6300ESB during PC creation. */
|
static void i6300esb_init(PCIDevice *dev)
|
||||||
static void i6300esb_pc_init(PCIBus *pci_bus)
|
|
||||||
{
|
{
|
||||||
I6300State *d;
|
I6300State *d = container_of(dev, I6300State, dev);
|
||||||
uint8_t *pci_conf;
|
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->reboot_enabled = 1;
|
||||||
d->clock_scale = CLOCK_SCALE_1KHZ;
|
d->clock_scale = CLOCK_SCALE_1KHZ;
|
||||||
d->int_type = INT_TYPE_IRQ;
|
d->int_type = INT_TYPE_IRQ;
|
||||||
|
@ -458,10 +447,20 @@ static void i6300esb_pc_init(PCIBus *pci_bus)
|
||||||
static WatchdogTimerModel model = {
|
static WatchdogTimerModel model = {
|
||||||
.wdt_name = "i6300esb",
|
.wdt_name = "i6300esb",
|
||||||
.wdt_description = "Intel 6300ESB",
|
.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);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create and initialize a virtual IB700 during PC creation. */
|
static void wdt_ib700_init(ISADevice *dev)
|
||||||
static void ib700_pc_init(PCIBus *unused)
|
|
||||||
{
|
{
|
||||||
|
timer = qemu_new_timer(vm_clock, ib700_timer_expired, NULL);
|
||||||
register_savevm("ib700_wdt", -1, 0, ib700_save, ib700_load, 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(0x441, 2, 1, ib700_write_disable_reg, NULL);
|
||||||
register_ioport_write(0x443, 2, 1, ib700_write_enable_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 = {
|
static WatchdogTimerModel model = {
|
||||||
.wdt_name = "ib700",
|
.wdt_name = "ib700",
|
||||||
.wdt_description = "iBASE 700",
|
.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);
|
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
|
#ifndef _WIN32
|
||||||
int daemonize = 0;
|
int daemonize = 0;
|
||||||
#endif
|
#endif
|
||||||
|
const char *watchdog;
|
||||||
const char *option_rom[MAX_OPTION_ROMS];
|
const char *option_rom[MAX_OPTION_ROMS];
|
||||||
int nb_option_roms;
|
int nb_option_roms;
|
||||||
int semihosting_enabled = 0;
|
int semihosting_enabled = 0;
|
||||||
|
@ -4948,8 +4949,6 @@ int main(int argc, char **argv, char **envp)
|
||||||
tb_size = 0;
|
tb_size = 0;
|
||||||
autostart= 1;
|
autostart= 1;
|
||||||
|
|
||||||
register_watchdogs();
|
|
||||||
|
|
||||||
optind = 1;
|
optind = 1;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if (optind >= argc)
|
if (optind >= argc)
|
||||||
|
@ -5361,9 +5360,12 @@ int main(int argc, char **argv, char **envp)
|
||||||
serial_device_index++;
|
serial_device_index++;
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_watchdog:
|
case QEMU_OPTION_watchdog:
|
||||||
i = select_watchdog(optarg);
|
if (watchdog) {
|
||||||
if (i > 0)
|
fprintf(stderr,
|
||||||
exit (i == 1 ? 1 : 0);
|
"qemu: only one watchdog option may be given\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
watchdog = optarg;
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_watchdog_action:
|
case QEMU_OPTION_watchdog_action:
|
||||||
if (select_watchdog_action(optarg) == -1) {
|
if (select_watchdog_action(optarg) == -1) {
|
||||||
|
@ -5927,6 +5929,12 @@ int main(int argc, char **argv, char **envp)
|
||||||
|
|
||||||
module_call_init(MODULE_INIT_DEVICE);
|
module_call_init(MODULE_INIT_DEVICE);
|
||||||
|
|
||||||
|
if (watchdog) {
|
||||||
|
i = select_watchdog(watchdog);
|
||||||
|
if (i > 0)
|
||||||
|
exit (i == 1 ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (machine->compat_props) {
|
if (machine->compat_props) {
|
||||||
qdev_prop_register_compat(machine->compat_props);
|
qdev_prop_register_compat(machine->compat_props);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue