From 67f7873e27033dc35260e2944f1a7041bcb66358 Mon Sep 17 00:00:00 2001 From: Ivan Baravy Date: Fri, 21 Feb 2020 05:21:09 +0300 Subject: [PATCH] Coverage collection speed up 4x! Also, adjust disk cache size and move set_eflags_tf() to trace_lbr.c. --- .gitignore | 1 + covpreproc.c | 24 +++++++++++++----------- kolibri.h | 5 ++--- makefile | 16 ++++++++-------- test/makefile | 8 ++++++++ trace_lbr.c | 34 +++++++++++++++++++++++++++++----- umka.asm | 14 -------------- umka_shell.c | 6 +++--- vdisk.c | 7 +++++++ vdisk.h | 3 +++ 10 files changed, 74 insertions(+), 44 deletions(-) diff --git a/.gitignore b/.gitignore index f41ec62..17addf0 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ umka.fas umka.sym umka.lst umka.prp +umka.cov tags *.out coverage.* diff --git a/covpreproc.c b/covpreproc.c index ca2f7d1..af9c637 100644 --- a/covpreproc.c +++ b/covpreproc.c @@ -3,7 +3,7 @@ #include #include -#define MAX_COVERED_CODE_SIZE (128*1024) +#define MAX_COVERED_CODE_SIZE (256*1024) typedef struct { uint64_t to_cnt, from_cnt; @@ -18,16 +18,18 @@ void read_coverage_file(const char *fname) { fseeko(f, 0, SEEK_END); off_t fsize = ftello(f); fseeko(f, 0, SEEK_SET); - size_t branch_cnt = fsize/(2*sizeof(uint32_t)); + fread(&coverage_begin, sizeof(uint32_t), 1, f); + fread(&coverage_end, sizeof(uint32_t), 1, f); + size_t branch_cnt = (fsize-4*2)/(2*4); for (size_t i = 0; i < branch_cnt; i++) { uint32_t from, to; fread(&from, sizeof(uint32_t), 1, f); fread(&to, sizeof(uint32_t), 1, f); - if (from >= coverage_begin && from < coverage_end /*&& to < 0x80000000u*/) { + if (from >= coverage_begin && from < coverage_end) { from = from - coverage_begin + coverage_offset; branches[from].from_cnt++; } - if (to >= coverage_begin && to < coverage_end /*&& from < 0x80000000u*/) { + if (to >= coverage_begin && to < coverage_end) { to = to - coverage_begin + coverage_offset; branches[to].to_cnt++; } @@ -94,15 +96,13 @@ int is_cond_jump(const char *s) { } int main(int argc, char **argv) { - if (argc < 6) { - fprintf(stderr, "usage: covpreproc \n"); + if (argc < 4) { + fprintf(stderr, "usage: covpreproc \n"); exit(1); } sscanf(argv[2], "%" SCNx32, &coverage_offset); - sscanf(argv[3], "%" SCNx32, &coverage_begin); - sscanf(argv[4], "%" SCNx32, &coverage_end); - for (int i = 5; i < argc; i++) { + for (int i = 3; i < argc; i++) { read_coverage_file(argv[i]); } @@ -123,8 +123,10 @@ int main(int argc, char **argv) { unsigned long pos = strtoul(tmp, NULL, 16); size_t total_to = 0, total_from = 0; for (size_t i = 0; i < inst_len; i++) { - total_to += branches[pos + i].to_cnt; - total_from += branches[pos + i].from_cnt; + if (pos + i < coverage_end - coverage_begin + coverage_offset) { + total_to += branches[pos + i].to_cnt; + total_from += branches[pos + i].from_cnt; + } } cur += total_to; if (is_cond) { diff --git a/kolibri.h b/kolibri.h index 0fbbdf4..0538c8f 100644 --- a/kolibri.h +++ b/kolibri.h @@ -110,8 +110,8 @@ typedef struct { int (*querymedia)(void *userdata, diskmediainfo_t *info) __attribute__((__stdcall__)); int (*read)(void *userdata, void *buffer, off_t startsector, size_t *numsectors) __attribute__((__stdcall__)); int (*write)(void *userdata, void *buffer, off_t startsector, size_t *numsectors) __attribute__((__stdcall__)); - int (*flush)(void* userdata) __attribute__((__stdcall__)); - unsigned int (*adjust_cache_size)(uint32_t suggested_size) __attribute__((__stdcall__)); + int (*flush)(void *userdata) __attribute__((__stdcall__)); + unsigned int (*adjust_cache_size)(void *userdata, uint32_t suggested_size) __attribute__((__stdcall__)); } diskfunc_t; struct disk_t { @@ -231,7 +231,6 @@ typedef struct { void kos_init(void); void i40(void); uint32_t kos_time_to_epoch(uint32_t *time); -void set_eflags_tf(int x); void *disk_add(diskfunc_t *disk, const char *name, void *userdata, uint32_t flags) __attribute__((__stdcall__)); void *disk_media_changed(diskfunc_t *disk, int inserted) __attribute__((__stdcall__)); diff --git a/makefile b/makefile index 4e2e9df..59eee80 100644 --- a/makefile +++ b/makefile @@ -4,7 +4,7 @@ WARNINGS=-Wall -Wextra -Wduplicated-cond -Wduplicated-branches -Wlogical-op -Wre CFLAGS=$(WARNINGS) -g -O0 -D_FILE_OFFSET_BITS=64 -Wno-address-of-packed-member -DNDEBUG -masm=intel CFLAGS_32=$(CFLAGS) -m32 LDFLAGS= -LDFLAGS_32=-m32 +LDFLAGS_32=$(LDFLAGS) -m32 all: umka_shell umka_fuse umka.sym umka.prp umka.lst tags tools/mkdirrange tools/mkfilepattern covpreproc @@ -12,10 +12,10 @@ covpreproc: covpreproc.c $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ umka_shell: umka_shell.o umka.o trace.o trace_lbr.o vdisk.o lodepng.o - $(CC) $(LDFLAGS) $(LDFLAGS_32) $^ -o $@ -static + $(CC) $(LDFLAGS_32) $^ -o $@ -static umka_fuse: umka_fuse.o umka.o vdisk.o - $(CC) $(LDFLAGS) $(LDFLAGS_32) $^ -o $@ `pkg-config fuse3 --libs` + $(CC) $(LDFLAGS_32) $^ -o $@ `pkg-config fuse3 --libs` umka.o umka.fas: umka.asm skin.skn INCLUDE="$(KOLIBRI)/kernel/trunk;$(KOLIBRI)/programs/develop/libraries/libcrash/trunk" $(FASM) $< umka.o -s umka.fas -m 1234567 @@ -39,19 +39,19 @@ tags: umka.sym fasmtags.py $< trace.o: trace.c trace.h trace_lbr.h - $(CC) $(CFLAGS) $(CFLAGS_32) -c $< + $(CC) $(CFLAGS_32) -c $< trace_lbr.o: trace_lbr.c trace_lbr.h kolibri.h - $(CC) $(CFLAGS) $(CFLAGS_32) -c $< + $(CC) $(CFLAGS_32) -c $< vdisk.o: vdisk.c - $(CC) $(CFLAGS) $(CFLAGS_32) -c $< + $(CC) $(CFLAGS_32) -c $< umka_shell.o: umka_shell.c kolibri.h trace.h syscalls.h - $(CC) $(CFLAGS) $(CFLAGS_32) -c $< -std=c99 -D_POSIX_C_SOURCE=2 + $(CC) $(CFLAGS_32) -c $< -std=c99 -D_POSIX_C_SOURCE=2 umka_fuse.o: umka_fuse.c kolibri.h - $(CC) $(CFLAGS) $(CFLAGS_32) `pkg-config fuse3 --cflags` -c $< -std=gnu99 + $(CC) $(CFLAGS_32) `pkg-config fuse3 --cflags` -c $< -std=gnu99 tools/mkdirrange: tools/mkdirrange.c $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ diff --git a/test/makefile b/test/makefile index d3d3ddb..dea5906 100644 --- a/test/makefile +++ b/test/makefile @@ -37,3 +37,11 @@ draw: $(draw_tests) $(UMKA_SHELL) < $*.t > $@ @ cmp $@ $< @ if [ -f "$*.ref.png" ]; then cmp $*.out.png $*.ref.png; fi + +coverage: + ../covpreproc ../umka.lst 0x34 coverage.* > ../umka.cov + +clean: + rm -f ???_*.out.{log,png} coverage coverage.* + +.PHONY: clean coverage diff --git a/trace_lbr.c b/trace_lbr.c index e7bb8b1..1431b0f 100644 --- a/trace_lbr.c +++ b/trace_lbr.c @@ -10,6 +10,12 @@ #include #include "kolibri.h" +#define MSR_IA32_DEBUGCTLMSR 0x1d9 +#define MSR_IA32_LASTBRANCHFROMIP 0x1db +#define MSR_IA32_LASTBRANCHTOIP 0x1dc +#define MSR_IA32_LASTINTFROMIP 0x1dd +#define MSR_IA32_LASTINTTOIP 0x1de + int covfd, msrfd; uint64_t rdmsr(uint32_t reg) @@ -43,8 +49,8 @@ void wrmsr(uint32_t reg, uint64_t data) } void handle_sigtrap() { - uint64_t from = rdmsr(0x1db); - uint64_t to = rdmsr(0x1dc); + uint64_t from = rdmsr(MSR_IA32_LASTBRANCHFROMIP); + uint64_t to = rdmsr(MSR_IA32_LASTBRANCHTOIP); if ((from >= (uintptr_t)coverage_begin && from < (uintptr_t)coverage_end) || (to >= (uintptr_t)coverage_begin && to < (uintptr_t)coverage_end)) { @@ -52,7 +58,21 @@ void handle_sigtrap() { write(covfd, &to, 4); } - wrmsr(0x1d9, 3); + wrmsr(MSR_IA32_DEBUGCTLMSR, 3); +} + +void set_eflags_tf(uint32_t tf) { + __asm__ __inline__ __volatile__ ( + "pushfd;" + "pop eax;" + "shl ecx, 8;" // TF + "and eax, ~(1 << 8);" + "or eax, ecx;" + "push eax;" + "popfd" + : + : "c"(tf) + : "eax", "memory"); } void trace_lbr_begin() { @@ -66,7 +86,7 @@ void trace_lbr_begin() { CPU_ZERO(&my_set); CPU_SET(0, &my_set); sched_setaffinity(0, sizeof(cpu_set_t), &my_set); - wrmsr(0x1d9, 3); + wrmsr(MSR_IA32_DEBUGCTLMSR, 3); msrfd = open("/dev/cpu/0/msr", O_RDONLY); if (msrfd < 0) { perror("rdmsr: open"); @@ -75,12 +95,16 @@ void trace_lbr_begin() { char coverage_filename[32]; sprintf(coverage_filename, "coverage.%i", getpid()); covfd = open(coverage_filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + void *coverage_begin_addr = &coverage_begin; + void *coverage_end_addr = &coverage_end; + write(covfd, &coverage_begin_addr, 4); + write(covfd, &coverage_end_addr, 4); set_eflags_tf(1); } void trace_lbr_end() { set_eflags_tf(0); - wrmsr(0x1d9, 0); + wrmsr(MSR_IA32_DEBUGCTLMSR, 0); close(msrfd); close(covfd); } diff --git a/umka.asm b/umka.asm index f9562de..cabaa2f 100644 --- a/umka.asm +++ b/umka.asm @@ -19,7 +19,6 @@ public coverage_begin public coverage_end public sha3_256_oneshot as 'hash_oneshot' -public set_eflags_tf public kos_time_to_epoch public kos_init @@ -145,19 +144,6 @@ proc sha3_256_oneshot c uses ebx esi edi ebp, _ctx, _data, _len ret endp -; TODO: move to trace_lbr -set_eflags_tf: - pushfd - pop eax - mov ecx, [esp + 4] - and ecx, 1 - shl ecx, 8 ; TF - and eax, NOT (1 SHL 8) - or eax, ecx - push eax - popfd - ret - proc kos_time_to_epoch c uses ebx esi edi ebp, _time mov esi, [_time] call fsCalculateTime diff --git a/umka_shell.c b/umka_shell.c index b279c5b..da3789b 100644 --- a/umka_shell.c +++ b/umka_shell.c @@ -62,14 +62,14 @@ diskfunc_t vdisk_functions = { .read = vdisk_read, .write = vdisk_write, .flush = NULL, - .adjust_cache_size = NULL, + .adjust_cache_size = vdisk_adjust_cache_size, }; char cur_dir[PATH_MAX] = "/"; const char *last_dir = cur_dir; bool cur_dir_changed = true; char cmd_buf[FGETS_BUF_LEN]; -int trace; +int trace = 0; const char *f70_status_name[] = { "success", @@ -974,7 +974,7 @@ void *run_test(const char *infile_name) { usage(); return NULL; } - strcpy(last_dot, ".out"); + strcpy(last_dot, ".out.log"); infile = fopen(infile_name, "r"); outfile = fopen(outfile_name, "w"); if (!infile || !outfile) { diff --git a/vdisk.c b/vdisk.c index 7ce0782..088dec8 100644 --- a/vdisk.c +++ b/vdisk.c @@ -60,3 +60,10 @@ int vdisk_querymedia(void *userdata, diskmediainfo_t *minfo) { minfo->capacity = vdisk->sect_cnt; return ERROR_SUCCESS; } + +__attribute__((__stdcall__)) +unsigned int vdisk_adjust_cache_size(void *userdata, unsigned int suggested_size) { + (void)userdata; + (void)suggested_size; + return 64*1024; +} diff --git a/vdisk.h b/vdisk.h index 54a54fb..e1c71ba 100644 --- a/vdisk.h +++ b/vdisk.h @@ -19,4 +19,7 @@ int vdisk_write(void *userdata, void *buffer, off_t startsector, size_t *numsect __attribute__((__stdcall__)) int vdisk_querymedia(void *userdata, diskmediainfo_t *minfo); +__attribute__((__stdcall__)) +unsigned int vdisk_adjust_cache_size(void *userdata, unsigned int suggested_size); + #endif // VDISK_H_INCLUDED