From 9878543356f18af48e1568041ee1e751cfe636d2 Mon Sep 17 00:00:00 2001 From: Yin Fengwei Date: Mon, 16 Jul 2018 18:15:24 +0800 Subject: [PATCH] DM: add system reset (with RAM content kept) This function add high level reset_vdev function. Which is implemented to call deinit/init pairing to emulate the virtual device reset operation. This patch also add the system reset which keep the UOS RAM content functionality to DM. Signed-off-by: Yin Fengwei Acked-by: Anthony Xu --- devicemodel/core/main.c | 79 ++++++++++++++++++++++++++++++++-- devicemodel/hw/pci/core.c | 20 +++++++++ devicemodel/include/pci_core.h | 1 + 3 files changed, 96 insertions(+), 4 deletions(-) diff --git a/devicemodel/core/main.c b/devicemodel/core/main.c index c451e107d..dfc639a7b 100644 --- a/devicemodel/core/main.c +++ b/devicemodel/core/main.c @@ -509,6 +509,73 @@ vm_deinit_vdevs(struct vmctx *ctx) ioapic_deinit(); } +static void +vm_reset_vdevs(struct vmctx *ctx) +{ + /* + * The current virtual devices doesn't define virtual + * device reset function. So we call vdev deinit/init + * pairing to emulate the device reset operation. + * + * pci/ioapic deinit/init is needed because of dependency + * of pci irq allocation/free. + * + * acpi build is necessary because irq for each vdev + * could be assigned with different number after reset. + */ + atkbdc_deinit(ctx); + vrtc_deinit(ctx); + + deinit_pci(ctx); + pci_irq_deinit(ctx); + ioapic_deinit(); + + atkbdc_init(ctx); + vrtc_init(ctx); + + ioapic_init(ctx); + pci_irq_init(ctx); + init_pci(ctx); + + if (acpi) { + acpi_build(ctx, guest_ncpus); + } +} + +static void +vm_system_reset(struct vmctx *ctx) +{ + int vcpu_id = 0; + + /* + * If we get system reset request, we don't want to exit the + * vcpu_loop/vm_loop/mevent_loop. So we do: + * 1. pause VM + * 2. notify request done to reset ioreq state in vhm + * 3. reset virtual devices + * 4. load software for UOS + * 5. hypercall reset vm + * 6. reset suspend mode to VM_SUSPEND_NONE + */ + + vm_pause(ctx); + for (vcpu_id = 0; vcpu_id < 4; vcpu_id++) { + struct vhm_request *vhm_req; + + vhm_req = &vhm_req_buf[vcpu_id]; + if (vhm_req->valid && + (vhm_req->processed == REQ_STATE_PROCESSING) && + (vhm_req->client == ctx->ioreq_client)) + vm_notify_request_done(ctx, vcpu_id); + } + + vm_reset_vdevs(ctx); + + acrn_sw_load(ctx); + vm_reset(ctx); + vm_set_suspend_mode(VM_SUSPEND_NONE); +} + static void vm_loop(struct vmctx *ctx) { @@ -521,19 +588,23 @@ vm_loop(struct vmctx *ctx) assert(error == 0); while (1) { - int vcpu; + int vcpu_id; struct vhm_request *vhm_req; error = vm_attach_ioreq_client(ctx); if (error) break; - for (vcpu = 0; vcpu < 4; vcpu++) { - vhm_req = &vhm_req_buf[vcpu]; + for (vcpu_id = 0; vcpu_id < 4; vcpu_id++) { + vhm_req = &vhm_req_buf[vcpu_id]; if (vhm_req->valid && (vhm_req->processed == REQ_STATE_PROCESSING) && (vhm_req->client == ctx->ioreq_client)) - handle_vmexit(ctx, vhm_req, vcpu); + handle_vmexit(ctx, vhm_req, vcpu_id); + } + + if (VM_SUSPEND_SYSTEM_RESET == vm_get_suspend_mode()) { + vm_system_reset(ctx); } } quit_vm_loop = 0; diff --git a/devicemodel/hw/pci/core.c b/devicemodel/hw/pci/core.c index da0b1831a..5fda67db4 100644 --- a/devicemodel/hw/pci/core.c +++ b/devicemodel/hw/pci/core.c @@ -827,6 +827,7 @@ pci_emul_deinit(struct vmctx *ctx, struct pci_vdev_ops *ops, int bus, int slot, free(fi->fi_param); if (fi->fi_devi) { + pci_lintr_release(fi->fi_devi); pci_emul_free_bars(fi->fi_devi); free(fi->fi_devi); } @@ -1621,6 +1622,25 @@ pci_lintr_request(struct pci_vdev *dev) pci_set_cfgdata8(dev, PCIR_INTPIN, bestpin + 1); } +void +pci_lintr_release(struct pci_vdev *dev) +{ + struct businfo *bi; + struct slotinfo *si; + int pin; + + bi = pci_businfo[dev->bus]; + assert(bi != NULL); + + si = &bi->slotinfo[dev->slot]; + + for (pin = 1; pin < 4; pin++) { + si->si_intpins[pin].ii_count = 0; + si->si_intpins[pin].ii_pirq_pin = 0; + si->si_intpins[pin].ii_ioapic_irq = 0; + } +} + static void pci_lintr_route(struct pci_vdev *dev) { diff --git a/devicemodel/include/pci_core.h b/devicemodel/include/pci_core.h index c8aa4f31f..ba3aa3d89 100644 --- a/devicemodel/include/pci_core.h +++ b/devicemodel/include/pci_core.h @@ -257,6 +257,7 @@ void pci_generate_msix(struct pci_vdev *pi, int msgnum); void pci_lintr_assert(struct pci_vdev *pi); void pci_lintr_deassert(struct pci_vdev *pi); void pci_lintr_request(struct pci_vdev *pi); +void pci_lintr_release(struct pci_vdev *pi); int pci_msi_enabled(struct pci_vdev *pi); int pci_msix_enabled(struct pci_vdev *pi); int pci_msix_table_bar(struct pci_vdev *pi);