diff --git a/builtin-run.c b/builtin-run.c index 73ca754..4f4843d 100644 --- a/builtin-run.c +++ b/builtin-run.c @@ -1115,7 +1115,11 @@ static int kvm_cmd_run_init(int argc, const char **argv) rtc__init(); - serial8250__init(kvm); + r = serial8250__init(kvm); + if (r < 0) { + pr_err("serial__init() failed with error %d\n", r); + goto fail; + } if (active_console == CONSOLE_VIRTIO) virtio_console__init(kvm); @@ -1224,6 +1228,7 @@ static int kvm_cmd_run_work(void) r = 0; kvm_cpu__delete(kvm_cpus[0]); + kvm_cpus[0] = NULL; for (i = 1; i < nrcpus; i++) { if (kvm_cpus[i]->is_running) { @@ -1261,6 +1266,10 @@ static void kvm_cmd_run_exit(int guest_ret) disk_image__close_all(kvm->disks, image_count); free(kvm_cpus); + r = serial8250__exit(kvm); + if (r < 0) + pr_warning("serial8250__exit() failed with error %d\n", r); + r = ioport__exit(kvm); if (r < 0) pr_warning("ioport__exit() failed with error %d\n", r); diff --git a/hw/serial.c b/hw/serial.c index d1d67b0..852aea4 100644 --- a/hw/serial.c +++ b/hw/serial.c @@ -396,19 +396,52 @@ static struct ioport_operations serial8250_ops = { .io_out = serial8250_out, }; -static void serial8250__device_init(struct kvm *kvm, struct serial8250_device *dev) +static int serial8250__device_init(struct kvm *kvm, struct serial8250_device *dev) { - ioport__register(dev->iobase, &serial8250_ops, 8, NULL); + int r; + + r = ioport__register(dev->iobase, &serial8250_ops, 8, NULL); kvm__irq_line(kvm, dev->irq, 0); + + return r; } -void serial8250__init(struct kvm *kvm) +int serial8250__init(struct kvm *kvm) { - unsigned int i; + unsigned int i, j; + int r = 0; for (i = 0; i < ARRAY_SIZE(devices); i++) { struct serial8250_device *dev = &devices[i]; - serial8250__device_init(kvm, dev); + r = serial8250__device_init(kvm, dev); + if (r < 0) + goto cleanup; } + + return r; +cleanup: + for (j = 0; j <= i; j++) { + struct serial8250_device *dev = &devices[j]; + + ioport__unregister(dev->iobase); + } + + return r; +} + +int serial8250__exit(struct kvm *kvm) +{ + unsigned int i; + int r; + + for (i = 0; i < ARRAY_SIZE(devices); i++) { + struct serial8250_device *dev = &devices[i]; + + r = ioport__unregister(dev->iobase); + if (r < 0) + return r; + } + + return 0; } diff --git a/include/kvm/8250-serial.h b/include/kvm/8250-serial.h index 8bd8798..df8ef53 100644 --- a/include/kvm/8250-serial.h +++ b/include/kvm/8250-serial.h @@ -3,7 +3,8 @@ struct kvm; -void serial8250__init(struct kvm *kvm); +int serial8250__init(struct kvm *kvm); +int serial8250__exit(struct kvm *kvm); void serial8250__update_consoles(struct kvm *kvm); void serial8250__inject_sysrq(struct kvm *kvm);