Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit f61d12c

Browse filesBrowse files
kvm: added support for device snapshots during symbex
Signed-off-by: Vitaly Chipounov <vitaly@cyberhaven.io>
1 parent e688954 commit f61d12c
Copy full SHA for f61d12c

File tree

Expand file treeCollapse file tree

2 files changed

+131
-0
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+131
-0
lines changed

‎accel/kvm/kvm-all.c

Copy file name to clipboardExpand all lines: accel/kvm/kvm-all.c
+112Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
#include "trace.h"
4040
#include "hw/irq.h"
4141
#include "sysemu/sev.h"
42+
#include "migration/qemu-memfile.h"
43+
#include "migration/savevm.h"
4244

4345
#include "hw/boards.h"
4446

@@ -145,6 +147,10 @@ static bool kvm_has_mem_rw_flag;
145147
static bool kvm_has_disk_rw_flag;
146148
#endif
147149

150+
#ifdef KVM_CAP_DEV_SNAPSHOT
151+
static bool kvm_dev_snapshot;
152+
#endif
153+
148154
static const KVMCapabilityInfo kvm_required_capabilites[] = {
149155
KVM_CAP_INFO(USER_MEMORY),
150156
KVM_CAP_INFO(DESTROY_MEMORY_REGION_WORKS),
@@ -1522,6 +1528,7 @@ int kvm_has_mem_rw(void)
15221528
{
15231529
return kvm_has_mem_rw_flag;
15241530
}
1531+
15251532
int kvm_mem_rw(void *dest, const void *source, uint64_t size, int is_write)
15261533
{
15271534
struct kvm_mem_rw rw;
@@ -1536,6 +1543,7 @@ int kvm_has_mem_rw(void)
15361543
{
15371544
return 0;
15381545
}
1546+
15391547
int kvm_mem_rw(void *dest, const void *source, uint64_t size, int is_write)
15401548
{
15411549
return -1;
@@ -1547,6 +1555,7 @@ int kvm_has_disk_rw(void)
15471555
{
15481556
return kvm_has_disk_rw_flag;
15491557
}
1558+
15501559
int kvm_disk_rw(void *buffer, uint64_t sector, int count, int is_write)
15511560
{
15521561
int ret;
@@ -1566,12 +1575,94 @@ int kvm_has_disk_rw(void)
15661575
{
15671576
return 0;
15681577
}
1578+
15691579
int kvm_disk_rw(void *buffer, uint64_t sector, int count, int is_write)
15701580
{
15711581
return -1;
15721582
}
15731583
#endif
15741584

1585+
#ifdef KVM_CAP_DEV_SNAPSHOT
1586+
1587+
static int kvm_dev_save_snapshot(void)
1588+
{
1589+
static bool unregistered = false;
1590+
int ret = -1;
1591+
struct kvm_dev_snapshot s;
1592+
size_t ssize;
1593+
Error *err = NULL;
1594+
QEMUFile *f = qemu_memfile_open();
1595+
1596+
if (kvm_dev_snapshot && !unregistered) {
1597+
vmstate_unregister_blacklisted_devices();
1598+
unregistered = true;
1599+
}
1600+
1601+
if (qemu_savevm_state(f, &err) < 0) {
1602+
if (err) {
1603+
error_report_err(err);
1604+
abort();
1605+
}
1606+
}
1607+
1608+
s.buffer = (uint64_t) qemu_file_get_internal_storage(f, &ssize);
1609+
if (!s.buffer) {
1610+
fprintf(stderr, "could not get internal storage\n");
1611+
abort();
1612+
}
1613+
s.size = (uint32_t) ssize;
1614+
1615+
s.is_write = 1;
1616+
1617+
ret = kvm_vm_ioctl(kvm_state, KVM_DEV_SNAPSHOT, &s);
1618+
1619+
if (ret < 0) {
1620+
fprintf(stderr, "Could not save device snapshot\n");
1621+
abort();
1622+
}
1623+
1624+
qemu_fclose(f);
1625+
return ret;
1626+
}
1627+
1628+
static int kvm_dev_restore_snapshot_cb(void *buffer, size_t pos, size_t size)
1629+
{
1630+
struct kvm_dev_snapshot s;
1631+
s.buffer = (uintptr_t) buffer;
1632+
s.size = size;
1633+
s.is_write = 0;
1634+
s.pos = pos;
1635+
1636+
return kvm_vm_ioctl(kvm_state, KVM_DEV_SNAPSHOT, &s);
1637+
}
1638+
1639+
static int kvm_dev_restore_snapshot(void)
1640+
{
1641+
QEMUFile *f = qemu_memfile_open_ro(kvm_dev_restore_snapshot_cb);
1642+
if (!f) {
1643+
return -1;
1644+
}
1645+
1646+
if (qemu_loadvm_state(f) < 0) {
1647+
error_report("Could not restore device state");
1648+
abort();
1649+
}
1650+
1651+
qemu_fclose(f);
1652+
return 0;
1653+
}
1654+
#else
1655+
static int kvm_dev_save_snapshot(void)
1656+
{
1657+
return -1;
1658+
}
1659+
1660+
static int kvm_dev_restore_snapshot(void)
1661+
{
1662+
return -1;
1663+
}
1664+
#endif
1665+
15751666

15761667
static int kvm_init(MachineState *ms)
15771668
{
@@ -1768,6 +1859,10 @@ static int kvm_init(MachineState *ms)
17681859
kvm_has_disk_rw_flag = kvm_check_extension(s, KVM_CAP_DISK_RW);
17691860
#endif
17701861

1862+
#ifdef KVM_CAP_DEV_SNAPSHOT
1863+
kvm_dev_snapshot = kvm_check_extension(s, KVM_CAP_DEV_SNAPSHOT);
1864+
#endif
1865+
17711866
kvm_state = s;
17721867

17731868
/*
@@ -2144,6 +2239,23 @@ int kvm_cpu_exec(CPUState *cpu)
21442239
break;
21452240
}
21462241
break;
2242+
case KVM_EXIT_FLUSH_DISK:
2243+
bdrv_drain_all_begin();
2244+
bdrv_flush_all();
2245+
ret = 0;
2246+
break;
2247+
case KVM_EXIT_SAVE_DEV_STATE:
2248+
qemu_mutex_lock_iothread();
2249+
kvm_dev_save_snapshot();
2250+
qemu_mutex_unlock_iothread();
2251+
ret = 0;
2252+
break;
2253+
case KVM_EXIT_RESTORE_DEV_STATE:
2254+
qemu_mutex_lock_iothread();
2255+
kvm_dev_restore_snapshot();
2256+
qemu_mutex_unlock_iothread();
2257+
ret = 0;
2258+
break;
21472259
default:
21482260
DPRINTF("kvm_arch_handle_exit\n");
21492261
ret = kvm_arch_handle_exit(cpu, run);

‎linux-headers/linux/kvm.h

Copy file name to clipboardExpand all lines: linux-headers/linux/kvm.h
+19Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,11 @@ struct kvm_hyperv_exit {
236236
#define KVM_EXIT_IOAPIC_EOI 26
237237
#define KVM_EXIT_HYPERV 27
238238

239+
/* Symbolic execution exit codes */
240+
#define KVM_EXIT_FLUSH_DISK 100
241+
#define KVM_EXIT_SAVE_DEV_STATE 101
242+
#define KVM_EXIT_RESTORE_DEV_STATE 102
243+
239244
/* For KVM_EXIT_INTERNAL_ERROR */
240245
/* Emulate instruction failed. */
241246
#define KVM_INTERNAL_ERROR_EMULATION 1
@@ -964,6 +969,9 @@ struct kvm_ppc_resize_hpt {
964969
/* Indicates presence of in-kvm disk support */
965970
#define KVM_CAP_DISK_RW 257
966971

972+
/* Indicates presence of device snapshots */
973+
#define KVM_CAP_DEV_SNAPSHOT 258
974+
967975
#define KVM_CAP_MEM_RW 1021
968976

969977
/****************************************/
@@ -1445,6 +1453,17 @@ struct kvm_disk_rw {
14451453
};
14461454
#define KVM_DISK_RW _IOWR(KVMIO, 0xf6, struct kvm_disk_rw)
14471455

1456+
/* Available with KVM_CAP_DEV_SNAPSHOT */
1457+
struct kvm_dev_snapshot {
1458+
__u64 buffer;
1459+
/* If is_write == 0, indicates expected size in case of error */
1460+
__u32 size;
1461+
/* Only when is_write == 0, indicates the position from which reading the state */
1462+
__u32 pos;
1463+
__u8 is_write;
1464+
};
1465+
#define KVM_DEV_SNAPSHOT _IOWR(KVMIO, 0xf7, struct kvm_dev_snapshot)
1466+
14481467
/* Secure Encrypted Virtualization command */
14491468
enum sev_cmd_id {
14501469
/* Guest initialization commands */

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.