Coverage collection speed up 4x!

Also, adjust disk cache size and
move set_eflags_tf() to trace_lbr.c.
This commit is contained in:
Ivan Baravy 2020-02-21 05:21:09 +03:00
parent 2a4cfff503
commit 67f7873e27
10 changed files with 74 additions and 44 deletions

1
.gitignore vendored
View File

@ -17,6 +17,7 @@ umka.fas
umka.sym umka.sym
umka.lst umka.lst
umka.prp umka.prp
umka.cov
tags tags
*.out *.out
coverage.* coverage.*

View File

@ -3,7 +3,7 @@
#include <string.h> #include <string.h>
#include <inttypes.h> #include <inttypes.h>
#define MAX_COVERED_CODE_SIZE (128*1024) #define MAX_COVERED_CODE_SIZE (256*1024)
typedef struct { typedef struct {
uint64_t to_cnt, from_cnt; uint64_t to_cnt, from_cnt;
@ -18,16 +18,18 @@ void read_coverage_file(const char *fname) {
fseeko(f, 0, SEEK_END); fseeko(f, 0, SEEK_END);
off_t fsize = ftello(f); off_t fsize = ftello(f);
fseeko(f, 0, SEEK_SET); 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++) { for (size_t i = 0; i < branch_cnt; i++) {
uint32_t from, to; uint32_t from, to;
fread(&from, sizeof(uint32_t), 1, f); fread(&from, sizeof(uint32_t), 1, f);
fread(&to, 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; from = from - coverage_begin + coverage_offset;
branches[from].from_cnt++; 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; to = to - coverage_begin + coverage_offset;
branches[to].to_cnt++; branches[to].to_cnt++;
} }
@ -94,15 +96,13 @@ int is_cond_jump(const char *s) {
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
if (argc < 6) { if (argc < 4) {
fprintf(stderr, "usage: covpreproc <listing file> <coverage_begin offset> <coverage_begin address> <coverage_end address> <coverage files ...>\n"); fprintf(stderr, "usage: covpreproc <listing file> <coverage_begin offset> <coverage files ...>\n");
exit(1); exit(1);
} }
sscanf(argv[2], "%" SCNx32, &coverage_offset); 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]); read_coverage_file(argv[i]);
} }
@ -123,8 +123,10 @@ int main(int argc, char **argv) {
unsigned long pos = strtoul(tmp, NULL, 16); unsigned long pos = strtoul(tmp, NULL, 16);
size_t total_to = 0, total_from = 0; size_t total_to = 0, total_from = 0;
for (size_t i = 0; i < inst_len; i++) { for (size_t i = 0; i < inst_len; i++) {
total_to += branches[pos + i].to_cnt; if (pos + i < coverage_end - coverage_begin + coverage_offset) {
total_from += branches[pos + i].from_cnt; total_to += branches[pos + i].to_cnt;
total_from += branches[pos + i].from_cnt;
}
} }
cur += total_to; cur += total_to;
if (is_cond) { if (is_cond) {

View File

@ -110,8 +110,8 @@ typedef struct {
int (*querymedia)(void *userdata, diskmediainfo_t *info) __attribute__((__stdcall__)); int (*querymedia)(void *userdata, diskmediainfo_t *info) __attribute__((__stdcall__));
int (*read)(void *userdata, void *buffer, off_t startsector, size_t *numsectors) __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 (*write)(void *userdata, void *buffer, off_t startsector, size_t *numsectors) __attribute__((__stdcall__));
int (*flush)(void* userdata) __attribute__((__stdcall__)); int (*flush)(void *userdata) __attribute__((__stdcall__));
unsigned int (*adjust_cache_size)(uint32_t suggested_size) __attribute__((__stdcall__)); unsigned int (*adjust_cache_size)(void *userdata, uint32_t suggested_size) __attribute__((__stdcall__));
} diskfunc_t; } diskfunc_t;
struct disk_t { struct disk_t {
@ -231,7 +231,6 @@ typedef struct {
void kos_init(void); void kos_init(void);
void i40(void); void i40(void);
uint32_t kos_time_to_epoch(uint32_t *time); 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_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__)); void *disk_media_changed(diskfunc_t *disk, int inserted) __attribute__((__stdcall__));

View File

@ -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=$(WARNINGS) -g -O0 -D_FILE_OFFSET_BITS=64 -Wno-address-of-packed-member -DNDEBUG -masm=intel
CFLAGS_32=$(CFLAGS) -m32 CFLAGS_32=$(CFLAGS) -m32
LDFLAGS= 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 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 $@ $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@
umka_shell: umka_shell.o umka.o trace.o trace_lbr.o vdisk.o lodepng.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 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 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 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 $< fasmtags.py $<
trace.o: trace.c trace.h trace_lbr.h 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 trace_lbr.o: trace_lbr.c trace_lbr.h kolibri.h
$(CC) $(CFLAGS) $(CFLAGS_32) -c $< $(CC) $(CFLAGS_32) -c $<
vdisk.o: vdisk.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 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 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 tools/mkdirrange: tools/mkdirrange.c
$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@

View File

@ -37,3 +37,11 @@ draw: $(draw_tests)
$(UMKA_SHELL) < $*.t > $@ $(UMKA_SHELL) < $*.t > $@
@ cmp $@ $< @ cmp $@ $<
@ if [ -f "$*.ref.png" ]; then cmp $*.out.png $*.ref.png; fi @ 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

View File

@ -10,6 +10,12 @@
#include <sched.h> #include <sched.h>
#include "kolibri.h" #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; int covfd, msrfd;
uint64_t rdmsr(uint32_t reg) uint64_t rdmsr(uint32_t reg)
@ -43,8 +49,8 @@ void wrmsr(uint32_t reg, uint64_t data)
} }
void handle_sigtrap() { void handle_sigtrap() {
uint64_t from = rdmsr(0x1db); uint64_t from = rdmsr(MSR_IA32_LASTBRANCHFROMIP);
uint64_t to = rdmsr(0x1dc); uint64_t to = rdmsr(MSR_IA32_LASTBRANCHTOIP);
if ((from >= (uintptr_t)coverage_begin && from < (uintptr_t)coverage_end) || if ((from >= (uintptr_t)coverage_begin && from < (uintptr_t)coverage_end) ||
(to >= (uintptr_t)coverage_begin && to < (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); 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() { void trace_lbr_begin() {
@ -66,7 +86,7 @@ void trace_lbr_begin() {
CPU_ZERO(&my_set); CPU_ZERO(&my_set);
CPU_SET(0, &my_set); CPU_SET(0, &my_set);
sched_setaffinity(0, sizeof(cpu_set_t), &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); msrfd = open("/dev/cpu/0/msr", O_RDONLY);
if (msrfd < 0) { if (msrfd < 0) {
perror("rdmsr: open"); perror("rdmsr: open");
@ -75,12 +95,16 @@ void trace_lbr_begin() {
char coverage_filename[32]; char coverage_filename[32];
sprintf(coverage_filename, "coverage.%i", getpid()); 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); 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); set_eflags_tf(1);
} }
void trace_lbr_end() { void trace_lbr_end() {
set_eflags_tf(0); set_eflags_tf(0);
wrmsr(0x1d9, 0); wrmsr(MSR_IA32_DEBUGCTLMSR, 0);
close(msrfd); close(msrfd);
close(covfd); close(covfd);
} }

View File

@ -19,7 +19,6 @@ public coverage_begin
public coverage_end public coverage_end
public sha3_256_oneshot as 'hash_oneshot' public sha3_256_oneshot as 'hash_oneshot'
public set_eflags_tf
public kos_time_to_epoch public kos_time_to_epoch
public kos_init public kos_init
@ -145,19 +144,6 @@ proc sha3_256_oneshot c uses ebx esi edi ebp, _ctx, _data, _len
ret ret
endp 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 proc kos_time_to_epoch c uses ebx esi edi ebp, _time
mov esi, [_time] mov esi, [_time]
call fsCalculateTime call fsCalculateTime

View File

@ -62,14 +62,14 @@ diskfunc_t vdisk_functions = {
.read = vdisk_read, .read = vdisk_read,
.write = vdisk_write, .write = vdisk_write,
.flush = NULL, .flush = NULL,
.adjust_cache_size = NULL, .adjust_cache_size = vdisk_adjust_cache_size,
}; };
char cur_dir[PATH_MAX] = "/"; char cur_dir[PATH_MAX] = "/";
const char *last_dir = cur_dir; const char *last_dir = cur_dir;
bool cur_dir_changed = true; bool cur_dir_changed = true;
char cmd_buf[FGETS_BUF_LEN]; char cmd_buf[FGETS_BUF_LEN];
int trace; int trace = 0;
const char *f70_status_name[] = { const char *f70_status_name[] = {
"success", "success",
@ -974,7 +974,7 @@ void *run_test(const char *infile_name) {
usage(); usage();
return NULL; return NULL;
} }
strcpy(last_dot, ".out"); strcpy(last_dot, ".out.log");
infile = fopen(infile_name, "r"); infile = fopen(infile_name, "r");
outfile = fopen(outfile_name, "w"); outfile = fopen(outfile_name, "w");
if (!infile || !outfile) { if (!infile || !outfile) {

View File

@ -60,3 +60,10 @@ int vdisk_querymedia(void *userdata, diskmediainfo_t *minfo) {
minfo->capacity = vdisk->sect_cnt; minfo->capacity = vdisk->sect_cnt;
return ERROR_SUCCESS; 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;
}

View File

@ -19,4 +19,7 @@ int vdisk_write(void *userdata, void *buffer, off_t startsector, size_t *numsect
__attribute__((__stdcall__)) __attribute__((__stdcall__))
int vdisk_querymedia(void *userdata, diskmediainfo_t *minfo); 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 #endif // VDISK_H_INCLUDED