mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-07-01 17:52:26 +00:00
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:
parent
b33012aee8
commit
9878543356
@ -509,6 +509,73 @@ vm_deinit_vdevs(struct vmctx *ctx)
|
|||||||
ioapic_deinit();
|
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
|
static void
|
||||||
vm_loop(struct vmctx *ctx)
|
vm_loop(struct vmctx *ctx)
|
||||||
{
|
{
|
||||||
@ -521,19 +588,23 @@ vm_loop(struct vmctx *ctx)
|
|||||||
assert(error == 0);
|
assert(error == 0);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
int vcpu;
|
int vcpu_id;
|
||||||
struct vhm_request *vhm_req;
|
struct vhm_request *vhm_req;
|
||||||
|
|
||||||
error = vm_attach_ioreq_client(ctx);
|
error = vm_attach_ioreq_client(ctx);
|
||||||
if (error)
|
if (error)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
for (vcpu = 0; vcpu < 4; vcpu++) {
|
for (vcpu_id = 0; vcpu_id < 4; vcpu_id++) {
|
||||||
vhm_req = &vhm_req_buf[vcpu];
|
vhm_req = &vhm_req_buf[vcpu_id];
|
||||||
if (vhm_req->valid
|
if (vhm_req->valid
|
||||||
&& (vhm_req->processed == REQ_STATE_PROCESSING)
|
&& (vhm_req->processed == REQ_STATE_PROCESSING)
|
||||||
&& (vhm_req->client == ctx->ioreq_client))
|
&& (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;
|
quit_vm_loop = 0;
|
||||||
|
@ -827,6 +827,7 @@ pci_emul_deinit(struct vmctx *ctx, struct pci_vdev_ops *ops, int bus, int slot,
|
|||||||
free(fi->fi_param);
|
free(fi->fi_param);
|
||||||
|
|
||||||
if (fi->fi_devi) {
|
if (fi->fi_devi) {
|
||||||
|
pci_lintr_release(fi->fi_devi);
|
||||||
pci_emul_free_bars(fi->fi_devi);
|
pci_emul_free_bars(fi->fi_devi);
|
||||||
free(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);
|
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
|
static void
|
||||||
pci_lintr_route(struct pci_vdev *dev)
|
pci_lintr_route(struct pci_vdev *dev)
|
||||||
{
|
{
|
||||||
|
@ -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_assert(struct pci_vdev *pi);
|
||||||
void pci_lintr_deassert(struct pci_vdev *pi);
|
void pci_lintr_deassert(struct pci_vdev *pi);
|
||||||
void pci_lintr_request(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_msi_enabled(struct pci_vdev *pi);
|
||||||
int pci_msix_enabled(struct pci_vdev *pi);
|
int pci_msix_enabled(struct pci_vdev *pi);
|
||||||
int pci_msix_table_bar(struct pci_vdev *pi);
|
int pci_msix_table_bar(struct pci_vdev *pi);
|
||||||
|
Loading…
Reference in New Issue
Block a user