mirror of https://github.com/xemu-project/xemu.git
Hi,
"Host Memory Backends" and "Memory devices" queue ("mem"): - Kconfig fix for virtio-based memory devices - virtio-mem support for suspend+wake-up with plugged memory - hostmem fix when specifying "merge=off" -----BEGIN PGP SIGNATURE----- iQJFBAABCAAvFiEEG9nKrXNcTDpGDfzKTd4Q9wD/g1oFAmbyikMRHGRhdmlkQHJl ZGhhdC5jb20ACgkQTd4Q9wD/g1q6MBAAitNST73Shc+j327WvRLHQDkzkAlIYm+M E8NqtDiV11h7A0eNVu+5BkY/ejtY0Fduae3nxIkrHjK20eHHpiNPUp3hBNIhkKs3 vlSaU8FLGdt58CteMGcLYsP2E32WNNTckaFGwGjDmyUEfk+Gug4r/rJAZXDfuuLV 083I0/MuUF+ozPA0c2MrOwhoBPerg3a5aflVpbgPwGNrT9BHMjo62Q5QzG3U7mxr HnlLAScSXsYg2z+d5XLXkKLAiZ4C7UN4vfUAOZwqkfs7IFUTtFO/ev6e7VZI747n XhAqOAKzLqPu7tBPZJIC6jwZAUIv5yM0/v5qhVvVVdu7H0ZMtSCXyvCVtnT25Rsn yiA+XvCOb7yQ3hRbBIi60IzjNYfWbvw+oTVIDfXkG35TeNf4ZdjWtAiUmw9s5U9Q z0tINsD7VlSkbh5h3PkFw1+xagIuJAVkp673HHTtQsg+xgYK2ur5jhhWJdJlnpzA 77CAu07UaqU39ssnC2zeGG1eNRA4uzjwQtREzqH2jMfkw/7UuUeXMF+v/fEuLn6w JneSMq/a0gmD42HNae0Y40cn2Akfj6+wFu1rW3djF8F6TeLUSssQhbQSHCMwGoOg qX7O/3SeSRzlnp3Zyx9Tr7s+BkMz0EGGDe17GQwTQUX2t5wR5iXoGqpKZgOBA8En 6uUIcjBUckc= =PExj -----END PGP SIGNATURE----- Merge tag 'mem-2024-09-24' of https://github.com/davidhildenbrand/qemu into staging Hi, "Host Memory Backends" and "Memory devices" queue ("mem"): - Kconfig fix for virtio-based memory devices - virtio-mem support for suspend+wake-up with plugged memory - hostmem fix when specifying "merge=off" # -----BEGIN PGP SIGNATURE----- # # iQJFBAABCAAvFiEEG9nKrXNcTDpGDfzKTd4Q9wD/g1oFAmbyikMRHGRhdmlkQHJl # ZGhhdC5jb20ACgkQTd4Q9wD/g1q6MBAAitNST73Shc+j327WvRLHQDkzkAlIYm+M # E8NqtDiV11h7A0eNVu+5BkY/ejtY0Fduae3nxIkrHjK20eHHpiNPUp3hBNIhkKs3 # vlSaU8FLGdt58CteMGcLYsP2E32WNNTckaFGwGjDmyUEfk+Gug4r/rJAZXDfuuLV # 083I0/MuUF+ozPA0c2MrOwhoBPerg3a5aflVpbgPwGNrT9BHMjo62Q5QzG3U7mxr # HnlLAScSXsYg2z+d5XLXkKLAiZ4C7UN4vfUAOZwqkfs7IFUTtFO/ev6e7VZI747n # XhAqOAKzLqPu7tBPZJIC6jwZAUIv5yM0/v5qhVvVVdu7H0ZMtSCXyvCVtnT25Rsn # yiA+XvCOb7yQ3hRbBIi60IzjNYfWbvw+oTVIDfXkG35TeNf4ZdjWtAiUmw9s5U9Q # z0tINsD7VlSkbh5h3PkFw1+xagIuJAVkp673HHTtQsg+xgYK2ur5jhhWJdJlnpzA # 77CAu07UaqU39ssnC2zeGG1eNRA4uzjwQtREzqH2jMfkw/7UuUeXMF+v/fEuLn6w # JneSMq/a0gmD42HNae0Y40cn2Akfj6+wFu1rW3djF8F6TeLUSssQhbQSHCMwGoOg # qX7O/3SeSRzlnp3Zyx9Tr7s+BkMz0EGGDe17GQwTQUX2t5wR5iXoGqpKZgOBA8En # 6uUIcjBUckc= # =PExj # -----END PGP SIGNATURE----- # gpg: Signature made Tue 24 Sep 2024 10:45:39 BST # gpg: using RSA key 1BD9CAAD735C4C3A460DFCCA4DDE10F700FF835A # gpg: issuer "david@redhat.com" # gpg: Good signature from "David Hildenbrand <david@redhat.com>" [marginal] # gpg: aka "David Hildenbrand <davidhildenbrand@gmail.com>" [full] # gpg: aka "David Hildenbrand <hildenbr@in.tum.de>" [unknown] # Primary key fingerprint: 1BD9 CAAD 735C 4C3A 460D FCCA 4DDE 10F7 00FF 835A * tag 'mem-2024-09-24' of https://github.com/davidhildenbrand/qemu: hostmem: Apply merge property after the memory region is initialized virtio-mem: Add support for suspend+wake-up with plugged memory virtio-mem: Use new Resettable framework instead of LegacyReset reset: Add RESET_TYPE_WAKEUP reset: Use ResetType for qemu_devices_reset() and MachineClass::reset() virtio: kconfig: memory devices are PCI only Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
e10cd93872
|
@ -178,7 +178,7 @@ static void host_memory_backend_set_merge(Object *obj, bool value, Error **errp)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!host_memory_backend_mr_inited(backend) &&
|
if (host_memory_backend_mr_inited(backend) &&
|
||||||
value != backend->merge) {
|
value != backend->merge) {
|
||||||
void *ptr = memory_region_get_ram_ptr(&backend->mr);
|
void *ptr = memory_region_get_ram_ptr(&backend->mr);
|
||||||
uint64_t sz = memory_region_size(&backend->mr);
|
uint64_t sz = memory_region_size(&backend->mr);
|
||||||
|
|
|
@ -44,6 +44,17 @@ The Resettable interface handles reset types with an enum ``ResetType``:
|
||||||
value on each cold reset, such as RNG seed information, and which they
|
value on each cold reset, such as RNG seed information, and which they
|
||||||
must not reinitialize on a snapshot-load reset.
|
must not reinitialize on a snapshot-load reset.
|
||||||
|
|
||||||
|
``RESET_TYPE_WAKEUP``
|
||||||
|
If the machine supports waking up from a suspended state and needs to reset
|
||||||
|
its devices during wake-up (from the ``MachineClass::wakeup()`` method), this
|
||||||
|
reset type should be used for such a request. Devices can utilize this reset
|
||||||
|
type to differentiate the reset requested during machine wake-up from other
|
||||||
|
reset requests. For example, RAM content must not be lost during wake-up, and
|
||||||
|
memory devices like virtio-mem that provide additional RAM must not reset
|
||||||
|
such state during wake-ups, but might do so during cold resets. However, this
|
||||||
|
reset type should not be used for wake-up detection, as not every machine
|
||||||
|
type issues a device reset request during wake-up.
|
||||||
|
|
||||||
``RESET_TYPE_S390_CPU_NORMAL``
|
``RESET_TYPE_S390_CPU_NORMAL``
|
||||||
This is only used for S390 CPU objects; it clears interrupts, stops
|
This is only used for S390 CPU objects; it clears interrupts, stops
|
||||||
processing, and clears the TLB, but does not touch register contents.
|
processing, and clears the TLB, but does not touch register contents.
|
||||||
|
@ -53,7 +64,6 @@ The Resettable interface handles reset types with an enum ``ResetType``:
|
||||||
``RESET_TYPE_S390_CPU_NORMAL`` does and also clears the PSW, prefix,
|
``RESET_TYPE_S390_CPU_NORMAL`` does and also clears the PSW, prefix,
|
||||||
FPC, timer and control registers. It does not touch gprs, fprs or acrs.
|
FPC, timer and control registers. It does not touch gprs, fprs or acrs.
|
||||||
|
|
||||||
|
|
||||||
Devices which implement reset methods must treat any unknown ``ResetType``
|
Devices which implement reset methods must treat any unknown ``ResetType``
|
||||||
as equivalent to ``RESET_TYPE_COLD``; this will reduce the amount of
|
as equivalent to ``RESET_TYPE_COLD``; this will reduce the amount of
|
||||||
existing code we need to change if we add more types in future.
|
existing code we need to change if we add more types in future.
|
||||||
|
|
|
@ -1529,12 +1529,12 @@ static void aspeed_machine_bletchley_class_init(ObjectClass *oc, void *data)
|
||||||
aspeed_machine_class_init_cpus_defaults(mc);
|
aspeed_machine_class_init_cpus_defaults(mc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fby35_reset(MachineState *state, ShutdownCause reason)
|
static void fby35_reset(MachineState *state, ResetType type)
|
||||||
{
|
{
|
||||||
AspeedMachineState *bmc = ASPEED_MACHINE(state);
|
AspeedMachineState *bmc = ASPEED_MACHINE(state);
|
||||||
AspeedGPIOState *gpio = &bmc->soc->gpio;
|
AspeedGPIOState *gpio = &bmc->soc->gpio;
|
||||||
|
|
||||||
qemu_devices_reset(reason);
|
qemu_devices_reset(type);
|
||||||
|
|
||||||
/* Board ID: 7 (Class-1, 4 slots) */
|
/* Board ID: 7 (Class-1, 4 slots) */
|
||||||
object_property_set_bool(OBJECT(gpio), "gpioV4", true, &error_fatal);
|
object_property_set_bool(OBJECT(gpio), "gpioV4", true, &error_fatal);
|
||||||
|
|
|
@ -1254,7 +1254,7 @@ static void mps2_set_remap(Object *obj, const char *value, Error **errp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mps2_machine_reset(MachineState *machine, ShutdownCause reason)
|
static void mps2_machine_reset(MachineState *machine, ResetType type)
|
||||||
{
|
{
|
||||||
MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
|
MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
|
||||||
|
|
||||||
|
@ -1264,7 +1264,7 @@ static void mps2_machine_reset(MachineState *machine, ShutdownCause reason)
|
||||||
* reset see the correct mapping.
|
* reset see the correct mapping.
|
||||||
*/
|
*/
|
||||||
remap_memory(mms, mms->remap);
|
remap_memory(mms, mms->remap);
|
||||||
qemu_devices_reset(reason);
|
qemu_devices_reset(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mps2tz_class_init(ObjectClass *oc, void *data)
|
static void mps2tz_class_init(ObjectClass *oc, void *data)
|
||||||
|
|
|
@ -170,11 +170,8 @@ void qemu_unregister_resettable(Object *obj)
|
||||||
resettable_container_remove(get_root_reset_container(), obj);
|
resettable_container_remove(get_root_reset_container(), obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_devices_reset(ShutdownCause reason)
|
void qemu_devices_reset(ResetType type)
|
||||||
{
|
{
|
||||||
ResetType type = (reason == SHUTDOWN_CAUSE_SNAPSHOT_LOAD) ?
|
|
||||||
RESET_TYPE_SNAPSHOT_LOAD : RESET_TYPE_COLD;
|
|
||||||
|
|
||||||
/* Reset the simulation */
|
/* Reset the simulation */
|
||||||
resettable_reset(OBJECT(get_root_reset_container()), type);
|
resettable_reset(OBJECT(get_root_reset_container()), type);
|
||||||
}
|
}
|
||||||
|
|
|
@ -642,12 +642,12 @@ static void machine_HP_C3700_init(MachineState *machine)
|
||||||
machine_HP_common_init_tail(machine, pci_bus, translate);
|
machine_HP_common_init_tail(machine, pci_bus, translate);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hppa_machine_reset(MachineState *ms, ShutdownCause reason)
|
static void hppa_machine_reset(MachineState *ms, ResetType type)
|
||||||
{
|
{
|
||||||
unsigned int smp_cpus = ms->smp.cpus;
|
unsigned int smp_cpus = ms->smp.cpus;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
qemu_devices_reset(reason);
|
qemu_devices_reset(type);
|
||||||
|
|
||||||
/* Start all CPUs at the firmware entry point.
|
/* Start all CPUs at the firmware entry point.
|
||||||
* Monarch CPU will initialize firmware, secondary CPUs
|
* Monarch CPU will initialize firmware, secondary CPUs
|
||||||
|
|
|
@ -462,7 +462,7 @@ static void microvm_machine_state_init(MachineState *machine)
|
||||||
microvm_devices_init(mms);
|
microvm_devices_init(mms);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void microvm_machine_reset(MachineState *machine, ShutdownCause reason)
|
static void microvm_machine_reset(MachineState *machine, ResetType type)
|
||||||
{
|
{
|
||||||
MicrovmMachineState *mms = MICROVM_MACHINE(machine);
|
MicrovmMachineState *mms = MICROVM_MACHINE(machine);
|
||||||
CPUState *cs;
|
CPUState *cs;
|
||||||
|
@ -475,7 +475,7 @@ static void microvm_machine_reset(MachineState *machine, ShutdownCause reason)
|
||||||
mms->kernel_cmdline_fixed = true;
|
mms->kernel_cmdline_fixed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_devices_reset(reason);
|
qemu_devices_reset(type);
|
||||||
|
|
||||||
CPU_FOREACH(cs) {
|
CPU_FOREACH(cs) {
|
||||||
cpu = X86_CPU(cs);
|
cpu = X86_CPU(cs);
|
||||||
|
|
|
@ -1712,12 +1712,12 @@ static void pc_machine_initfn(Object *obj)
|
||||||
qemu_add_machine_init_done_notifier(&pcms->machine_done);
|
qemu_add_machine_init_done_notifier(&pcms->machine_done);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pc_machine_reset(MachineState *machine, ShutdownCause reason)
|
static void pc_machine_reset(MachineState *machine, ResetType type)
|
||||||
{
|
{
|
||||||
CPUState *cs;
|
CPUState *cs;
|
||||||
X86CPU *cpu;
|
X86CPU *cpu;
|
||||||
|
|
||||||
qemu_devices_reset(reason);
|
qemu_devices_reset(type);
|
||||||
|
|
||||||
/* Reset APIC after devices have been reset to cancel
|
/* Reset APIC after devices have been reset to cancel
|
||||||
* any changes that qemu_devices_reset() might have done.
|
* any changes that qemu_devices_reset() might have done.
|
||||||
|
@ -1732,7 +1732,7 @@ static void pc_machine_reset(MachineState *machine, ShutdownCause reason)
|
||||||
static void pc_machine_wakeup(MachineState *machine)
|
static void pc_machine_wakeup(MachineState *machine)
|
||||||
{
|
{
|
||||||
cpu_synchronize_all_states();
|
cpu_synchronize_all_states();
|
||||||
pc_machine_reset(machine, SHUTDOWN_CAUSE_NONE);
|
pc_machine_reset(machine, RESET_TYPE_WAKEUP);
|
||||||
cpu_synchronize_all_post_reset();
|
cpu_synchronize_all_post_reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -291,14 +291,14 @@ static void pegasos2_superio_write(uint8_t addr, uint8_t val)
|
||||||
cpu_physical_memory_write(PCI1_IO_BASE + 0x3f1, &val, 1);
|
cpu_physical_memory_write(PCI1_IO_BASE + 0x3f1, &val, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pegasos2_machine_reset(MachineState *machine, ShutdownCause reason)
|
static void pegasos2_machine_reset(MachineState *machine, ResetType type)
|
||||||
{
|
{
|
||||||
Pegasos2MachineState *pm = PEGASOS2_MACHINE(machine);
|
Pegasos2MachineState *pm = PEGASOS2_MACHINE(machine);
|
||||||
void *fdt;
|
void *fdt;
|
||||||
uint64_t d[2];
|
uint64_t d[2];
|
||||||
int sz;
|
int sz;
|
||||||
|
|
||||||
qemu_devices_reset(reason);
|
qemu_devices_reset(type);
|
||||||
if (!pm->vof) {
|
if (!pm->vof) {
|
||||||
return; /* Firmware should set up machine so nothing to do */
|
return; /* Firmware should set up machine so nothing to do */
|
||||||
}
|
}
|
||||||
|
|
|
@ -709,13 +709,13 @@ static void pnv_powerdown_notify(Notifier *n, void *opaque)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pnv_reset(MachineState *machine, ShutdownCause reason)
|
static void pnv_reset(MachineState *machine, ResetType type)
|
||||||
{
|
{
|
||||||
PnvMachineState *pnv = PNV_MACHINE(machine);
|
PnvMachineState *pnv = PNV_MACHINE(machine);
|
||||||
IPMIBmc *bmc;
|
IPMIBmc *bmc;
|
||||||
void *fdt;
|
void *fdt;
|
||||||
|
|
||||||
qemu_devices_reset(reason);
|
qemu_devices_reset(type);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The machine should provide by default an internal BMC simulator.
|
* The machine should provide by default an internal BMC simulator.
|
||||||
|
|
|
@ -1725,7 +1725,7 @@ void spapr_check_mmu_mode(bool guest_radix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void spapr_machine_reset(MachineState *machine, ShutdownCause reason)
|
static void spapr_machine_reset(MachineState *machine, ResetType type)
|
||||||
{
|
{
|
||||||
SpaprMachineState *spapr = SPAPR_MACHINE(machine);
|
SpaprMachineState *spapr = SPAPR_MACHINE(machine);
|
||||||
PowerPCCPU *first_ppc_cpu;
|
PowerPCCPU *first_ppc_cpu;
|
||||||
|
@ -1733,7 +1733,7 @@ static void spapr_machine_reset(MachineState *machine, ShutdownCause reason)
|
||||||
void *fdt;
|
void *fdt;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (reason != SHUTDOWN_CAUSE_SNAPSHOT_LOAD) {
|
if (type != RESET_TYPE_SNAPSHOT_LOAD) {
|
||||||
/*
|
/*
|
||||||
* Record-replay snapshot load must not consume random, this was
|
* Record-replay snapshot load must not consume random, this was
|
||||||
* already replayed from initial machine reset.
|
* already replayed from initial machine reset.
|
||||||
|
@ -1762,7 +1762,7 @@ static void spapr_machine_reset(MachineState *machine, ShutdownCause reason)
|
||||||
spapr_setup_hpt(spapr);
|
spapr_setup_hpt(spapr);
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_devices_reset(reason);
|
qemu_devices_reset(type);
|
||||||
|
|
||||||
spapr_ovec_cleanup(spapr->ov5_cas);
|
spapr_ovec_cleanup(spapr->ov5_cas);
|
||||||
spapr->ov5_cas = spapr_ovec_new();
|
spapr->ov5_cas = spapr_ovec_new();
|
||||||
|
|
|
@ -440,7 +440,7 @@ static void s390_pv_prepare_reset(S390CcwMachineState *ms)
|
||||||
s390_pv_prep_reset();
|
s390_pv_prep_reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void s390_machine_reset(MachineState *machine, ShutdownCause reason)
|
static void s390_machine_reset(MachineState *machine, ResetType type)
|
||||||
{
|
{
|
||||||
S390CcwMachineState *ms = S390_CCW_MACHINE(machine);
|
S390CcwMachineState *ms = S390_CCW_MACHINE(machine);
|
||||||
enum s390_reset reset_type;
|
enum s390_reset reset_type;
|
||||||
|
@ -472,7 +472,7 @@ static void s390_machine_reset(MachineState *machine, ShutdownCause reason)
|
||||||
* Device reset includes CPU clear resets so this has to be
|
* Device reset includes CPU clear resets so this has to be
|
||||||
* done AFTER the unprotect call above.
|
* done AFTER the unprotect call above.
|
||||||
*/
|
*/
|
||||||
qemu_devices_reset(reason);
|
qemu_devices_reset(type);
|
||||||
s390_crypto_reset();
|
s390_crypto_reset();
|
||||||
|
|
||||||
/* configure and start the ipl CPU only */
|
/* configure and start the ipl CPU only */
|
||||||
|
|
|
@ -16,6 +16,7 @@ config VIRTIO_PCI
|
||||||
default y if PCI_DEVICES
|
default y if PCI_DEVICES
|
||||||
depends on PCI
|
depends on PCI
|
||||||
select VIRTIO
|
select VIRTIO
|
||||||
|
select VIRTIO_MD_SUPPORTED
|
||||||
|
|
||||||
config VIRTIO_MMIO
|
config VIRTIO_MMIO
|
||||||
bool
|
bool
|
||||||
|
@ -35,10 +36,17 @@ config VIRTIO_CRYPTO
|
||||||
default y
|
default y
|
||||||
depends on VIRTIO
|
depends on VIRTIO
|
||||||
|
|
||||||
|
# not all virtio transports support memory devices; if none does,
|
||||||
|
# no need to include the code
|
||||||
|
config VIRTIO_MD_SUPPORTED
|
||||||
|
bool
|
||||||
|
|
||||||
config VIRTIO_MD
|
config VIRTIO_MD
|
||||||
bool
|
bool
|
||||||
|
depends on VIRTIO_MD_SUPPORTED
|
||||||
select MEM_DEVICE
|
select MEM_DEVICE
|
||||||
|
|
||||||
|
# selected by the board if it has the required support code
|
||||||
config VIRTIO_PMEM_SUPPORTED
|
config VIRTIO_PMEM_SUPPORTED
|
||||||
bool
|
bool
|
||||||
|
|
||||||
|
@ -46,9 +54,11 @@ config VIRTIO_PMEM
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
depends on VIRTIO
|
depends on VIRTIO
|
||||||
|
depends on VIRTIO_MD_SUPPORTED
|
||||||
depends on VIRTIO_PMEM_SUPPORTED
|
depends on VIRTIO_PMEM_SUPPORTED
|
||||||
select VIRTIO_MD
|
select VIRTIO_MD
|
||||||
|
|
||||||
|
# selected by the board if it has the required support code
|
||||||
config VIRTIO_MEM_SUPPORTED
|
config VIRTIO_MEM_SUPPORTED
|
||||||
bool
|
bool
|
||||||
|
|
||||||
|
@ -57,6 +67,7 @@ config VIRTIO_MEM
|
||||||
default y
|
default y
|
||||||
depends on VIRTIO
|
depends on VIRTIO
|
||||||
depends on LINUX
|
depends on LINUX
|
||||||
|
depends on VIRTIO_MD_SUPPORTED
|
||||||
depends on VIRTIO_MEM_SUPPORTED
|
depends on VIRTIO_MEM_SUPPORTED
|
||||||
select VIRTIO_MD
|
select VIRTIO_MD
|
||||||
|
|
||||||
|
|
|
@ -890,6 +890,9 @@ static uint64_t virtio_mem_get_features(VirtIODevice *vdev, uint64_t features,
|
||||||
if (vmem->unplugged_inaccessible == ON_OFF_AUTO_ON) {
|
if (vmem->unplugged_inaccessible == ON_OFF_AUTO_ON) {
|
||||||
virtio_add_feature(&features, VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE);
|
virtio_add_feature(&features, VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE);
|
||||||
}
|
}
|
||||||
|
if (qemu_wakeup_suspend_enabled()) {
|
||||||
|
virtio_add_feature(&features, VIRTIO_MEM_F_PERSISTENT_SUSPEND);
|
||||||
|
}
|
||||||
return features;
|
return features;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -902,18 +905,6 @@ static int virtio_mem_validate_features(VirtIODevice *vdev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void virtio_mem_system_reset(void *opaque)
|
|
||||||
{
|
|
||||||
VirtIOMEM *vmem = VIRTIO_MEM(opaque);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* During usual resets, we will unplug all memory and shrink the usable
|
|
||||||
* region size. This is, however, not possible in all scenarios. Then,
|
|
||||||
* the guest has to deal with this manually (VIRTIO_MEM_REQ_UNPLUG_ALL).
|
|
||||||
*/
|
|
||||||
virtio_mem_unplug_all(vmem);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void virtio_mem_prepare_mr(VirtIOMEM *vmem)
|
static void virtio_mem_prepare_mr(VirtIOMEM *vmem)
|
||||||
{
|
{
|
||||||
const uint64_t region_size = memory_region_size(&vmem->memdev->mr);
|
const uint64_t region_size = memory_region_size(&vmem->memdev->mr);
|
||||||
|
@ -1130,7 +1121,7 @@ static void virtio_mem_device_realize(DeviceState *dev, Error **errp)
|
||||||
vmstate_register_any(VMSTATE_IF(vmem),
|
vmstate_register_any(VMSTATE_IF(vmem),
|
||||||
&vmstate_virtio_mem_device_early, vmem);
|
&vmstate_virtio_mem_device_early, vmem);
|
||||||
}
|
}
|
||||||
qemu_register_reset(virtio_mem_system_reset, vmem);
|
qemu_register_resettable(OBJECT(vmem));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set ourselves as RamDiscardManager before the plug handler maps the
|
* Set ourselves as RamDiscardManager before the plug handler maps the
|
||||||
|
@ -1150,7 +1141,7 @@ static void virtio_mem_device_unrealize(DeviceState *dev)
|
||||||
* found via an address space anymore. Unset ourselves.
|
* found via an address space anymore. Unset ourselves.
|
||||||
*/
|
*/
|
||||||
memory_region_set_ram_discard_manager(&vmem->memdev->mr, NULL);
|
memory_region_set_ram_discard_manager(&vmem->memdev->mr, NULL);
|
||||||
qemu_unregister_reset(virtio_mem_system_reset, vmem);
|
qemu_unregister_resettable(OBJECT(vmem));
|
||||||
if (vmem->early_migration) {
|
if (vmem->early_migration) {
|
||||||
vmstate_unregister(VMSTATE_IF(vmem), &vmstate_virtio_mem_device_early,
|
vmstate_unregister(VMSTATE_IF(vmem), &vmstate_virtio_mem_device_early,
|
||||||
vmem);
|
vmem);
|
||||||
|
@ -1850,12 +1841,38 @@ static void virtio_mem_unplug_request_check(VirtIOMEM *vmem, Error **errp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ResettableState *virtio_mem_get_reset_state(Object *obj)
|
||||||
|
{
|
||||||
|
VirtIOMEM *vmem = VIRTIO_MEM(obj);
|
||||||
|
return &vmem->reset_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virtio_mem_system_reset_hold(Object *obj, ResetType type)
|
||||||
|
{
|
||||||
|
VirtIOMEM *vmem = VIRTIO_MEM(obj);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When waking up from standby/suspend-to-ram, do not unplug any memory.
|
||||||
|
*/
|
||||||
|
if (type == RESET_TYPE_WAKEUP) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* During usual resets, we will unplug all memory and shrink the usable
|
||||||
|
* region size. This is, however, not possible in all scenarios. Then,
|
||||||
|
* the guest has to deal with this manually (VIRTIO_MEM_REQ_UNPLUG_ALL).
|
||||||
|
*/
|
||||||
|
virtio_mem_unplug_all(vmem);
|
||||||
|
}
|
||||||
|
|
||||||
static void virtio_mem_class_init(ObjectClass *klass, void *data)
|
static void virtio_mem_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
|
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
|
||||||
VirtIOMEMClass *vmc = VIRTIO_MEM_CLASS(klass);
|
VirtIOMEMClass *vmc = VIRTIO_MEM_CLASS(klass);
|
||||||
RamDiscardManagerClass *rdmc = RAM_DISCARD_MANAGER_CLASS(klass);
|
RamDiscardManagerClass *rdmc = RAM_DISCARD_MANAGER_CLASS(klass);
|
||||||
|
ResettableClass *rc = RESETTABLE_CLASS(klass);
|
||||||
|
|
||||||
device_class_set_props(dc, virtio_mem_properties);
|
device_class_set_props(dc, virtio_mem_properties);
|
||||||
dc->vmsd = &vmstate_virtio_mem;
|
dc->vmsd = &vmstate_virtio_mem;
|
||||||
|
@ -1882,6 +1899,9 @@ static void virtio_mem_class_init(ObjectClass *klass, void *data)
|
||||||
rdmc->replay_discarded = virtio_mem_rdm_replay_discarded;
|
rdmc->replay_discarded = virtio_mem_rdm_replay_discarded;
|
||||||
rdmc->register_listener = virtio_mem_rdm_register_listener;
|
rdmc->register_listener = virtio_mem_rdm_register_listener;
|
||||||
rdmc->unregister_listener = virtio_mem_rdm_unregister_listener;
|
rdmc->unregister_listener = virtio_mem_rdm_unregister_listener;
|
||||||
|
|
||||||
|
rc->get_state = virtio_mem_get_reset_state;
|
||||||
|
rc->phases.hold = virtio_mem_system_reset_hold;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo virtio_mem_info = {
|
static const TypeInfo virtio_mem_info = {
|
||||||
|
|
|
@ -450,6 +450,9 @@ static const qmp_virtio_feature_map_t virtio_mem_feature_map[] = {
|
||||||
FEATURE_ENTRY(VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE, \
|
FEATURE_ENTRY(VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE, \
|
||||||
"VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE: Unplugged memory cannot be "
|
"VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE: Unplugged memory cannot be "
|
||||||
"accessed"),
|
"accessed"),
|
||||||
|
FEATURE_ENTRY(VIRTIO_MEM_F_PERSISTENT_SUSPEND, \
|
||||||
|
"VIRTIO_MEM_F_PERSISTENT_SUSPND: Plugged memory will remain "
|
||||||
|
"plugged when suspending+resuming"),
|
||||||
{ -1, "" }
|
{ -1, "" }
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "qemu/module.h"
|
#include "qemu/module.h"
|
||||||
#include "qom/object.h"
|
#include "qom/object.h"
|
||||||
#include "hw/core/cpu.h"
|
#include "hw/core/cpu.h"
|
||||||
|
#include "hw/resettable.h"
|
||||||
|
|
||||||
#define TYPE_MACHINE_SUFFIX "-machine"
|
#define TYPE_MACHINE_SUFFIX "-machine"
|
||||||
|
|
||||||
|
@ -257,7 +258,7 @@ struct MachineClass {
|
||||||
const char *deprecation_reason;
|
const char *deprecation_reason;
|
||||||
|
|
||||||
void (*init)(MachineState *state);
|
void (*init)(MachineState *state);
|
||||||
void (*reset)(MachineState *state, ShutdownCause reason);
|
void (*reset)(MachineState *state, ResetType type);
|
||||||
void (*wakeup)(MachineState *state);
|
void (*wakeup)(MachineState *state);
|
||||||
int (*kvm_type)(MachineState *machine, const char *arg);
|
int (*kvm_type)(MachineState *machine, const char *arg);
|
||||||
int (*hvf_get_physical_address_range)(MachineState *machine);
|
int (*hvf_get_physical_address_range)(MachineState *machine);
|
||||||
|
|
|
@ -29,6 +29,7 @@ typedef struct ResettableState ResettableState;
|
||||||
* Types of reset.
|
* Types of reset.
|
||||||
*
|
*
|
||||||
* + Cold: reset resulting from a power cycle of the object.
|
* + Cold: reset resulting from a power cycle of the object.
|
||||||
|
* + Wakeup: reset resulting from a wake-up from a suspended state.
|
||||||
*
|
*
|
||||||
* TODO: Support has to be added to handle more types. In particular,
|
* TODO: Support has to be added to handle more types. In particular,
|
||||||
* ResettableState structure needs to be expanded.
|
* ResettableState structure needs to be expanded.
|
||||||
|
@ -36,6 +37,7 @@ typedef struct ResettableState ResettableState;
|
||||||
typedef enum ResetType {
|
typedef enum ResetType {
|
||||||
RESET_TYPE_COLD,
|
RESET_TYPE_COLD,
|
||||||
RESET_TYPE_SNAPSHOT_LOAD,
|
RESET_TYPE_SNAPSHOT_LOAD,
|
||||||
|
RESET_TYPE_WAKEUP,
|
||||||
RESET_TYPE_S390_CPU_INITIAL,
|
RESET_TYPE_S390_CPU_INITIAL,
|
||||||
RESET_TYPE_S390_CPU_NORMAL,
|
RESET_TYPE_S390_CPU_NORMAL,
|
||||||
} ResetType;
|
} ResetType;
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#define HW_VIRTIO_MEM_H
|
#define HW_VIRTIO_MEM_H
|
||||||
|
|
||||||
#include "standard-headers/linux/virtio_mem.h"
|
#include "standard-headers/linux/virtio_mem.h"
|
||||||
|
#include "hw/resettable.h"
|
||||||
#include "hw/virtio/virtio.h"
|
#include "hw/virtio/virtio.h"
|
||||||
#include "qapi/qapi-types-misc.h"
|
#include "qapi/qapi-types-misc.h"
|
||||||
#include "sysemu/hostmem.h"
|
#include "sysemu/hostmem.h"
|
||||||
|
@ -115,6 +116,9 @@ struct VirtIOMEM {
|
||||||
|
|
||||||
/* listeners to notify on plug/unplug activity. */
|
/* listeners to notify on plug/unplug activity. */
|
||||||
QLIST_HEAD(, RamDiscardListener) rdl_list;
|
QLIST_HEAD(, RamDiscardListener) rdl_list;
|
||||||
|
|
||||||
|
/* State of the resettable container */
|
||||||
|
ResettableState reset_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VirtIOMEMClass {
|
struct VirtIOMEMClass {
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#ifndef QEMU_SYSEMU_RESET_H
|
#ifndef QEMU_SYSEMU_RESET_H
|
||||||
#define QEMU_SYSEMU_RESET_H
|
#define QEMU_SYSEMU_RESET_H
|
||||||
|
|
||||||
|
#include "hw/resettable.h"
|
||||||
#include "qapi/qapi-events-run-state.h"
|
#include "qapi/qapi-events-run-state.h"
|
||||||
|
|
||||||
typedef void QEMUResetHandler(void *opaque);
|
typedef void QEMUResetHandler(void *opaque);
|
||||||
|
@ -110,7 +111,7 @@ void qemu_unregister_reset(QEMUResetHandler *func, void *opaque);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qemu_devices_reset: Perform a complete system reset
|
* qemu_devices_reset: Perform a complete system reset
|
||||||
* @reason: reason for the reset
|
* @reason: type of the reset
|
||||||
*
|
*
|
||||||
* This function performs the low-level work needed to do a complete reset
|
* This function performs the low-level work needed to do a complete reset
|
||||||
* of the system (calling all the callbacks registered with
|
* of the system (calling all the callbacks registered with
|
||||||
|
@ -121,6 +122,6 @@ void qemu_unregister_reset(QEMUResetHandler *func, void *opaque);
|
||||||
* If you want to trigger a system reset from, for instance, a device
|
* If you want to trigger a system reset from, for instance, a device
|
||||||
* model, don't use this function. Use qemu_system_reset_request().
|
* model, don't use this function. Use qemu_system_reset_request().
|
||||||
*/
|
*/
|
||||||
void qemu_devices_reset(ShutdownCause reason);
|
void qemu_devices_reset(ResetType type);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "exec/cpu-common.h"
|
#include "exec/cpu-common.h"
|
||||||
#include "gdbstub/syscalls.h"
|
#include "gdbstub/syscalls.h"
|
||||||
#include "hw/boards.h"
|
#include "hw/boards.h"
|
||||||
|
#include "hw/resettable.h"
|
||||||
#include "migration/misc.h"
|
#include "migration/misc.h"
|
||||||
#include "migration/postcopy-ram.h"
|
#include "migration/postcopy-ram.h"
|
||||||
#include "monitor/monitor.h"
|
#include "monitor/monitor.h"
|
||||||
|
@ -507,15 +508,23 @@ static int qemu_debug_requested(void)
|
||||||
void qemu_system_reset(ShutdownCause reason)
|
void qemu_system_reset(ShutdownCause reason)
|
||||||
{
|
{
|
||||||
MachineClass *mc;
|
MachineClass *mc;
|
||||||
|
ResetType type;
|
||||||
|
|
||||||
mc = current_machine ? MACHINE_GET_CLASS(current_machine) : NULL;
|
mc = current_machine ? MACHINE_GET_CLASS(current_machine) : NULL;
|
||||||
|
|
||||||
cpu_synchronize_all_states();
|
cpu_synchronize_all_states();
|
||||||
|
|
||||||
|
switch (reason) {
|
||||||
|
case SHUTDOWN_CAUSE_SNAPSHOT_LOAD:
|
||||||
|
type = RESET_TYPE_SNAPSHOT_LOAD;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
type = RESET_TYPE_COLD;
|
||||||
|
}
|
||||||
if (mc && mc->reset) {
|
if (mc && mc->reset) {
|
||||||
mc->reset(current_machine, reason);
|
mc->reset(current_machine, type);
|
||||||
} else {
|
} else {
|
||||||
qemu_devices_reset(reason);
|
qemu_devices_reset(type);
|
||||||
}
|
}
|
||||||
switch (reason) {
|
switch (reason) {
|
||||||
case SHUTDOWN_CAUSE_NONE:
|
case SHUTDOWN_CAUSE_NONE:
|
||||||
|
|
Loading…
Reference in New Issue