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 <fengwei.yin@intel.com>
Acked-by: Anthony Xu <anthony.xu@intel.com>
This commit is contained in:
Yin Fengwei 2018-07-16 18:15:24 +08:00 committed by lijinxia
parent b33012aee8
commit 9878543356
3 changed files with 96 additions and 4 deletions

View File

@ -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;

View File

@ -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)
{

View File

@ -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);