-
Notifications
You must be signed in to change notification settings - Fork 38
Syx snapshot fixes and tuning #112
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 11 commits
7462199
12ddfc3
fdb2844
5ea6158
ee8ec01
5b0a3cc
596b0a1
80791c9
8d8f145
6c4e904
d2936b1
99f3ff6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,6 +47,10 @@ | |
#endif | ||
#include "tcg/tcg-ldst.h" | ||
#include "tcg/oversized-guest.h" | ||
//// --- Begin LibAFL code --- | ||
//#define CONFIG_DEBUG_SYX | ||
#include "libafl/syx-snapshot/syx-snapshot.h" | ||
//// --- End LibAFL code --- | ||
|
||
/* DEBUG defines, enable DEBUG_TLB_LOG to log to the CPU_LOG_MMU target */ | ||
/* #define DEBUG_TLB */ | ||
|
@@ -89,13 +93,6 @@ QEMU_BUILD_BUG_ON(sizeof(vaddr) > sizeof(run_on_cpu_data)); | |
QEMU_BUILD_BUG_ON(NB_MMU_MODES > 16); | ||
#define ALL_MMUIDX_BITS ((1 << NB_MMU_MODES) - 1) | ||
|
||
//// --- Begin LibAFL code --- | ||
|
||
// void syx_snapshot_dirty_list_add(hwaddr paddr); | ||
void syx_snapshot_dirty_list_add_hostaddr(void* host_addr); | ||
|
||
//// --- End LibAFL code --- | ||
|
||
static inline size_t tlb_n_entries(CPUTLBDescFast *fast) | ||
{ | ||
return (fast->mask >> CPU_TLB_ENTRY_BITS) + 1; | ||
|
@@ -450,6 +447,15 @@ void tlb_flush_all_cpus_synced(CPUState *src_cpu) | |
tlb_flush_by_mmuidx_all_cpus_synced(src_cpu, ALL_MMUIDX_BITS); | ||
} | ||
|
||
void tlb_flush_all_cpus(void) | ||
{ | ||
const run_on_cpu_func fn = tlb_flush_by_mmuidx_async_work; | ||
|
||
tlb_debug("mmu_idx: 0x%"PRIx16"\n", ALL_MMUIDX_BITS); | ||
|
||
flush_all_helper(NULL, fn, RUN_ON_CPU_HOST_INT(ALL_MMUIDX_BITS)); | ||
} | ||
|
||
static bool tlb_hit_page_mask_anyprot(CPUTLBEntry *tlb_entry, | ||
vaddr page, vaddr mask) | ||
{ | ||
|
@@ -1406,16 +1412,19 @@ static int probe_access_internal(CPUState *cpu, vaddr addr, | |
|
||
/* Everything else is RAM. */ | ||
*phost = (void *)((uintptr_t)addr + entry->addend); | ||
//// --- Begin LibAFL code --- | ||
|
||
if (access_type == MMU_DATA_STORE) { | ||
syx_snapshot_dirty_list_add_hostaddr(*phost); | ||
} | ||
|
||
//// --- End LibAFL code --- | ||
return flags; | ||
} | ||
|
||
//// --- Begin LibAFL code --- | ||
// Use this snippet multiple times below | ||
#define SYX_SNAPSHOT_DIRTY_LIST_ADD_HOSTADDR_PROBE(dbg, access_type, addr, entry_full, phost) { \ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this should be moved to top of this file |
||
if (access_type == MMU_DATA_STORE && !(flags & (TLB_MMIO | TLB_DISCARD_WRITE))) { \ | ||
SYX_DEBUG("%s %llx %llx\n", dbg, addr, addr+ (entry_full)->xlat_section); \ | ||
syx_snapshot_dirty_list_add_hostaddr((phost)); \ | ||
}}\ | ||
//// --- End LibAFL code --- | ||
|
||
int probe_access_full(CPUArchState *env, vaddr addr, int size, | ||
MMUAccessType access_type, int mmu_idx, | ||
bool nonfault, void **phost, CPUTLBEntryFull **pfull, | ||
|
@@ -1430,6 +1439,10 @@ int probe_access_full(CPUArchState *env, vaddr addr, int size, | |
int dirtysize = size == 0 ? 1 : size; | ||
notdirty_write(env_cpu(env), addr, dirtysize, *pfull, retaddr); | ||
flags &= ~TLB_NOTDIRTY; | ||
|
||
//// --- Begin LibAFL code --- | ||
SYX_SNAPSHOT_DIRTY_LIST_ADD_HOSTADDR_PROBE("probe_access_full", access_type, addr, *pfull, *phost); | ||
//// --- End LibAFL code --- | ||
} | ||
|
||
return flags; | ||
|
@@ -1454,6 +1467,10 @@ int probe_access_full_mmu(CPUArchState *env, vaddr addr, int size, | |
int dirtysize = size == 0 ? 1 : size; | ||
notdirty_write(env_cpu(env), addr, dirtysize, *pfull, 0); | ||
flags &= ~TLB_NOTDIRTY; | ||
|
||
//// --- Begin LibAFL code --- | ||
SYX_SNAPSHOT_DIRTY_LIST_ADD_HOSTADDR_PROBE("probe_access_full_mmu", access_type, addr, *pfull, *phost); | ||
//// --- End LibAFL code --- | ||
} | ||
|
||
return flags; | ||
|
@@ -1477,6 +1494,10 @@ int probe_access_flags(CPUArchState *env, vaddr addr, int size, | |
int dirtysize = size == 0 ? 1 : size; | ||
notdirty_write(env_cpu(env), addr, dirtysize, full, retaddr); | ||
flags &= ~TLB_NOTDIRTY; | ||
|
||
//// --- Begin LibAFL code --- | ||
SYX_SNAPSHOT_DIRTY_LIST_ADD_HOSTADDR_PROBE("probe_access_flags", access_type, addr, full, *phost); | ||
//// --- End LibAFL code --- | ||
} | ||
|
||
return flags; | ||
|
@@ -1512,6 +1533,10 @@ void *probe_access(CPUArchState *env, vaddr addr, int size, | |
/* Handle clean RAM pages. */ | ||
if (flags & TLB_NOTDIRTY) { | ||
notdirty_write(env_cpu(env), addr, size, full, retaddr); | ||
|
||
//// --- Begin LibAFL code --- | ||
SYX_SNAPSHOT_DIRTY_LIST_ADD_HOSTADDR_PROBE("probe_access", access_type, addr, full, host); | ||
//// --- End LibAFL code --- | ||
} | ||
} | ||
|
||
|
@@ -1728,6 +1753,13 @@ static void mmu_watch_or_dirty(CPUState *cpu, MMULookupPageData *data, | |
if (flags & TLB_NOTDIRTY) { | ||
notdirty_write(cpu, addr, size, full, ra); | ||
flags &= ~TLB_NOTDIRTY; | ||
|
||
//// --- Begin LibAFL code --- | ||
if (!(flags & (TLB_MMIO | TLB_DISCARD_WRITE))) { | ||
SYX_DEBUG("mmu_watch_or_dirty %llx %llx\n", addr, addr+full->xlat_section); | ||
syx_snapshot_dirty_list_add_hostaddr(data->haddr); | ||
} | ||
//// --- End LibAFL code --- | ||
} | ||
data->flags = flags; | ||
} | ||
|
@@ -1772,14 +1804,6 @@ static bool mmu_lookup(CPUState *cpu, vaddr addr, MemOpIdx oi, | |
l->memop ^= MO_BSWAP; | ||
} | ||
|
||
//// --- Begin LibAFL code --- | ||
|
||
// TODO: Does not work? | ||
// if (type == MMU_DATA_STORE) { | ||
syx_snapshot_dirty_list_add_hostaddr(l->page[0].haddr); | ||
// } | ||
|
||
//// --- End LibAFL code --- | ||
|
||
} else { | ||
/* Finish compute of page crossing. */ | ||
|
@@ -1803,15 +1827,6 @@ static bool mmu_lookup(CPUState *cpu, vaddr addr, MemOpIdx oi, | |
mmu_watch_or_dirty(cpu, &l->page[1], type, ra); | ||
} | ||
|
||
//// --- Begin LibAFL code --- | ||
|
||
// if (type == MMU_DATA_STORE) { | ||
syx_snapshot_dirty_list_add_hostaddr(l->page[0].haddr); | ||
syx_snapshot_dirty_list_add_hostaddr(l->page[1].haddr); | ||
// } | ||
|
||
//// --- End LibAFL code --- | ||
|
||
/* | ||
* Since target/sparc is the only user of TLB_BSWAP, and all | ||
* Sparc accesses are aligned, any treatment across two pages | ||
|
@@ -1907,14 +1922,12 @@ static void *atomic_mmu_lookup(CPUState *cpu, vaddr addr, MemOpIdx oi, | |
hostaddr = (void *)((uintptr_t)addr + tlbe->addend); | ||
full = &cpu->neg.tlb.d[mmu_idx].fulltlb[index]; | ||
|
||
//// --- Begin LibAFL code --- | ||
|
||
syx_snapshot_dirty_list_add_hostaddr(hostaddr); | ||
|
||
//// --- End LibAFL code --- | ||
|
||
if (unlikely(tlb_addr & TLB_NOTDIRTY)) { | ||
notdirty_write(cpu, addr, size, full, retaddr); | ||
//// --- Begin LibAFL code --- | ||
SYX_DEBUG("atomic_mmu_lookup %llx %llx\n", addr, addr+full->xlat_section); | ||
syx_snapshot_dirty_list_add_hostaddr(hostaddr); | ||
//// --- End LibAFL code --- | ||
} | ||
|
||
if (unlikely(tlb_addr & TLB_FORCE_SLOW)) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,9 +29,8 @@ | |
#include "migration/misc.h" | ||
|
||
//// --- Begin LibAFL code --- | ||
#ifdef CONFIG_SOFTMMU | ||
//#define CONFIG_DEBUG_SYX | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. clean this |
||
#include "libafl/syx-snapshot/syx-snapshot.h" | ||
#endif | ||
//// --- End LibAFL code --- | ||
|
||
/* Number of coroutines to reserve per attached device model */ | ||
|
@@ -1650,18 +1649,14 @@ static void coroutine_fn blk_aio_read_entry(void *opaque) | |
assert(qiov->size == acb->bytes); | ||
|
||
//// --- Begin LibAFL code --- | ||
#ifdef CONFIG_SOFTMMU | ||
if (!syx_snapshot_cow_cache_read_entry(rwco->blk, rwco->offset, acb->bytes, qiov, 0, rwco->flags)) { | ||
#endif | ||
//// --- End LibAFL code --- | ||
rwco->ret = blk_co_do_preadv_part(rwco->blk, rwco->offset, acb->bytes, qiov, | ||
rwco->ret = blk_co_do_preadv_part(rwco->blk, rwco->offset, acb->bytes, qiov, | ||
0, rwco->flags); | ||
//// --- Begin LibAFL code --- | ||
#ifdef CONFIG_SOFTMMU | ||
} else { | ||
rwco->ret = 0; | ||
rwco->ret = 0; | ||
} | ||
#endif | ||
//// --- End LibAFL code --- | ||
|
||
blk_aio_complete(acb); | ||
|
@@ -1676,17 +1671,14 @@ static void coroutine_fn blk_aio_write_entry(void *opaque) | |
assert(!qiov || qiov->size == acb->bytes); | ||
|
||
//// --- Begin LibAFL code --- | ||
#ifdef CONFIG_SOFTMMU | ||
if (!syx_snapshot_cow_cache_write_entry(rwco->blk, rwco->offset, acb->bytes, qiov, 0, rwco->flags)) { | ||
#endif | ||
if (!syx_snapshot_cow_cache_write_entry(rwco->blk, rwco->offset, acb->bytes, qiov, 0, rwco->flags)) { | ||
//// --- End LibAFL code --- | ||
rwco->ret = blk_co_do_pwritev_part(rwco->blk, rwco->offset, acb->bytes, qiov, 0, rwco->flags); | ||
//// --- Begin LibAFL code --- | ||
#ifdef CONFIG_SOFTMMU | ||
} else { | ||
rwco->ret = 0; | ||
} | ||
#endif | ||
} else { | ||
SYX_DEBUG("Write to COW cache: 0x%llx 0x%llx\n", rwco->offset, acb->bytes); | ||
rwco->ret = 0; | ||
} | ||
//// --- End LibAFL code --- | ||
|
||
blk_aio_complete(acb); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,7 @@ | |
#include "device-save.h" | ||
#include "syx-cow-cache.h" | ||
|
||
//#define CONFIG_DEBUG_SYX | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. clean up this |
||
#include "libafl/syx-misc.h" | ||
|
||
#define SYX_SNAPSHOT_COW_CACHE_DEFAULT_CHUNK_SIZE 64 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
|
||
#include "qemu/osdep.h" | ||
|
||
#include "qapi/error.h" | ||
#include "qapi/qmp/qdict.h" | ||
#include "qemu/option.h" | ||
#include "qemu/main-loop.h" | ||
#include "block/qdict.h" | ||
#include "libafl/system.h" | ||
|
||
|
||
|
||
#define NOT_DONE 0x7fffffff | ||
|
||
static void blk_rw_done(void *opaque, int ret) | ||
{ | ||
*(int *)opaque = ret; | ||
} | ||
|
||
int libafl_blk_write(BlockBackend *blk, void *buf, int64_t offset, int64_t sz) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why do we need this? i don't see it used anywhere else in your pr. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah yes you are right, it is not related directly to SYX. I placed this in This is only low-level api yet, I can remove it of course. |
||
{ | ||
void *pattern_buf = NULL; | ||
QEMUIOVector qiov; | ||
int async_ret = NOT_DONE; | ||
|
||
qemu_iovec_init(&qiov, 1); | ||
qemu_iovec_add(&qiov, buf, sz); | ||
|
||
blk_aio_pwritev(blk, offset, &qiov, 0, blk_rw_done, &async_ret); | ||
while (async_ret == NOT_DONE) { | ||
main_loop_wait(false); | ||
} | ||
|
||
//printf("async_ret: %d\n", async_ret); | ||
//g_assert(async_ret == 0); | ||
|
||
g_free(pattern_buf); | ||
qemu_iovec_destroy(&qiov); | ||
return async_ret; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why move this to higher-level functions?
i start to think we should not keep this call in probe, there are many places where memory gets probed for write but it in fact never written to.
it's only a matter of optimization though, nothing too problematic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The probes are used by guest helpers. Even though not every probe may lead to an actual write, we have no way to get this feedback as of now. This is how the QEMU TCG is set up.
A rule of thumb for me was the following:
Whenever QEMU uses
notdirty_write
, we want to make a backup of the page (syx_snapshot_dirty_list_add_hostaddr
). Because these are mostly the same features.But we cannot use
notdirty_write
, it misseshostaddr
, so I came up with this.