[PATCH] contrib/plugins: add a drcov plugin

2021-10-11 Thread Arkadiy
From: NDNF 

This patch adds the ability to generate files in drcov format.
Primary goal this script is to have coverage
logfiles thatwork in Lighthouse.
Problems:
- The path to the executable file is not specified.
- base, end, entry take incorrect values.
  (Lighthouse + IDA Pro anyway work).

Signed-off-by: Ivanov Arkady 
---
 contrib/plugins/Makefile |   1 +
 contrib/plugins/drcov.c  | 112 +++
 2 files changed, 113 insertions(+)
 create mode 100644 contrib/plugins/drcov.c

diff --git a/contrib/plugins/Makefile b/contrib/plugins/Makefile
index 7801b08b0d..0a681efeec 100644
--- a/contrib/plugins/Makefile
+++ b/contrib/plugins/Makefile
@@ -17,6 +17,7 @@ NAMES += hotblocks
 NAMES += hotpages
 NAMES += howvec
 NAMES += lockstep
+NAMES += drcov
 
 SONAMES := $(addsuffix .so,$(addprefix lib,$(NAMES)))
 
diff --git a/contrib/plugins/drcov.c b/contrib/plugins/drcov.c
new file mode 100644
index 00..d6a7d131c0
--- /dev/null
+++ b/contrib/plugins/drcov.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2021, Ivanov Arkady 
+ *
+ * Drcov - a DynamoRIO-based tool that collects coverage information
+ * from a binary. Primary goal this script is to have coverage log
+ * files that work in Lighthouse.
+ *
+ * License: GNU GPL, version 2 or later.
+ *   See the COPYING file in the top-level directory.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
+
+static char header[] = "DRCOV VERSION: 2\n"
+"DRCOV FLAVOR: drcov-64\n"
+"Module Table: version 2, count 1\n"
+"Columns: id, base, end, entry, path\n";
+
+static FILE *fp;
+
+typedef struct {
+uint32_t start;
+uint16_t size;
+uint16_t mod_id;
+} bb_entry_t;
+
+static GSList *bbs;
+
+static void printfHeader()
+{
+g_autoptr(GString) head = g_string_new("");
+g_string_append(head, header);
+g_string_append_printf(head, "0, 0x%x, 0x%x, 0x%x, %s\n",
+   0, 0x, 0, "path");
+g_string_append_printf(head, "BB Table: %d bbs\n", g_slist_length(bbs));
+fwrite(head->str, sizeof(char), head->len, fp);
+}
+
+static void printfCharArray32(uint32_t data)
+{
+const uint8_t *bytes = (const uint8_t *)(&data);
+fwrite(bytes, sizeof(char), sizeof(data), fp);
+}
+
+static void printfCharArray16(uint16_t data)
+{
+const uint8_t *bytes = (const uint8_t *)(&data);
+fwrite(bytes, sizeof(char), sizeof(data), fp);
+}
+
+
+static void printf_el(gpointer data, gpointer user_data)
+{
+bb_entry_t *bb = (bb_entry_t *)data;
+printfCharArray32(bb->start);
+printfCharArray16(bb->size);
+printfCharArray16(bb->mod_id);
+}
+
+static void plugin_exit(qemu_plugin_id_t id, void *p)
+{
+/* Print function */
+printfHeader();
+g_slist_foreach(bbs, printf_el, NULL);
+
+/* Clear */
+g_slist_free_full(bbs, &g_free);
+fclose(fp);
+}
+
+static void plugin_init(void)
+{
+fp = fopen("file.drcov.trace", "wb");
+}
+
+static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)
+{
+bb_entry_t *bb = g_new0(bb_entry_t, 1);
+uint64_t pc = qemu_plugin_tb_vaddr(tb);
+
+size_t n = qemu_plugin_tb_n_insns(tb);
+for (int i = 0; i < n; i++) {
+bb->size += qemu_plugin_insn_size(qemu_plugin_tb_get_insn(tb, i));
+}
+
+bb->start = pc;
+bb->mod_id = 0;
+bbs = g_slist_append(bbs, bb);
+
+}
+
+QEMU_PLUGIN_EXPORT
+int qemu_plugin_install(qemu_plugin_id_t id, const qemu_info_t *info,
+int argc, char **argv)
+{
+plugin_init();
+
+qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans);
+qemu_plugin_register_atexit_cb(id, plugin_exit, NULL);
+return 0;
+}
-- 
2.25.1




[PATCH] gdb-xml/avr-cpu.xml: fix pc and sp dimension

2021-03-18 Thread Arkadiy
From: NDNF 

fix pc and sp dimension in xml for avr-gdb

Signed-off-by: Arkasha 
---
 gdb-xml/avr-cpu.xml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/gdb-xml/avr-cpu.xml b/gdb-xml/avr-cpu.xml
index c4747f5b40..89458b717f 100644
--- a/gdb-xml/avr-cpu.xml
+++ b/gdb-xml/avr-cpu.xml
@@ -10,7 +10,7 @@
  register descriptions.  -->
 
 
-
+
   
   
   
@@ -44,6 +44,6 @@
   
   
   
-  
-  
+  
+  
 
-- 
2.17.1




[PATCH] target/avr: Fix interrupt execution

2021-03-12 Thread Arkadiy
From: NDNF 

Only one interrupt is in progress at the moment.It is necessary to set to
reset interrupt_request only after all interrupts have been executed

Signed-off-by: Arkasha 
---
 target/avr/helper.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/target/avr/helper.c b/target/avr/helper.c
index 65880b9928..9f20cc198e 100644
--- a/target/avr/helper.c
+++ b/target/avr/helper.c
@@ -49,7 +49,9 @@ bool avr_cpu_exec_interrupt(CPUState *cs, int 
interrupt_request)
 cc->tcg_ops->do_interrupt(cs);
 
 env->intsrc &= env->intsrc - 1; /* clear the interrupt */
-cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
+if (!env->intsrc) {
+cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
+}
 
 ret = true;
 }
-- 
2.17.1




[PATCH v2] block: increased maximum size of vvfat devices

2021-03-17 Thread Arkadiy
From: NDNF 

This fixes the problem of the impossibility to create
FAT16 disks larger than 504 mb:
The change CHS made it possible to obtain a larger disk.
Also, auto-detection of disk parameters was added depending
on the volume of the connected files:
The size of all folders and files on the created disk is calculated
and the size of the FAT table is added.
This size allows to choose the future size of the FAT drive
from the standard limitations.

Signed-off-by: Arkasha 
---
 block/vvfat.c | 94 ++-
 1 file changed, 85 insertions(+), 9 deletions(-)

diff --git a/block/vvfat.c b/block/vvfat.c
index 54807f82ca..b9e3d7e003 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -932,8 +932,6 @@ static int init_directories(BDRVVVFATState* s,
 /* Now build FAT, and write back information into directory */
 init_fat(s);
 
-/* TODO: if there are more entries, bootsector has to be adjusted! */
-s->root_entries = 0x02 * 0x10 * s->sectors_per_cluster;
 s->cluster_count=sector2cluster(s, s->sector_count);
 
 mapping = array_get_next(&(s->mapping));
@@ -1133,11 +1131,52 @@ static void vvfat_parse_filename(const char *filename, 
QDict *options,
 qdict_put_bool(options, "rw", rw);
 }
 
+static bool check_size(uint32_t offset_to_bootsector, int cyls, int heads,
+  int secs, uint8_t sectors_per_cluster, int fat_type,
+  uint64_t sum, uint64_t size_disk)
+{
+uint32_t sector_count = cyls * heads * secs - offset_to_bootsector;
+int i = 1 + sectors_per_cluster * 0x200 * 8 / fat_type;
+uint16_t sectors_per_fat = (sector_count + i) / i;
+/*size + FAT1 and FAT2 table size*/
+if ((sum + sectors_per_fat * 512 * 2) < size_disk) {
+return true;
+}
+return false;
+}
+
+static uint64_t find_size(const char *dirname, unsigned int cluster)
+{
+uint64_t sum = 0;
+DIR *dir = opendir(dirname);
+struct dirent *entry;
+while ((entry = readdir(dir))) {
+uint16_t length = strlen(dirname) + 2 + strlen(entry->d_name);
+char *buffer;
+struct stat st;
+buffer = g_malloc(length);
+snprintf(buffer, length, "%s/%s", dirname, entry->d_name);
+if (stat(buffer, &st) < 0) {
+g_free(buffer);
+continue;
+}
+if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")
+&& S_ISDIR(st.st_mode)) {
+sum += find_size(buffer, cluster);
+}
+g_free(buffer);
+sum += (st.st_size + cluster - 1) / (cluster) * (cluster);
+}
+closedir(dir);
+return sum;
+}
+
 static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
   Error **errp)
 {
 BDRVVVFATState *s = bs->opaque;
 int cyls, heads, secs;
+uint64_t size_disk;
 bool floppy;
 const char *dirname, *label;
 QemuOpts *opts;
@@ -1163,6 +1202,28 @@ static int vvfat_open(BlockDriverState *bs, QDict 
*options, int flags,
 s->fat_type = qemu_opt_get_number(opts, "fat-type", 0);
 floppy = qemu_opt_get_bool(opts, "floppy", false);
 
+uint64_t sum = 0;
+if (floppy) {
+if (!s->fat_type) {
+s->sectors_per_cluster = 2;
+} else {
+s->sectors_per_cluster = 1;
+}
+} else if (s->fat_type == 12) {
+s->offset_to_bootsector = 0x3f;
+s->sectors_per_cluster = 0x10;
+} else {
+s->offset_to_bootsector = 0x3f;
+/* LATER TODO: if FAT32, adjust */
+s->sectors_per_cluster = 0x80;
+}
+
+sum += find_size(dirname, s->sectors_per_cluster * 0x200);
+/* TODO: if there are more entries, bootsector has to be adjusted! */
+s->root_entries = 0x02 * 0x10 * s->sectors_per_cluster;
+/*File size + boot sector size + root directory size*/
+sum += 512 + s->root_entries * 32;
+
 memset(s->volume_label, ' ', sizeof(s->volume_label));
 label = qemu_opt_get(opts, "label");
 if (label) {
@@ -1182,22 +1243,40 @@ static int vvfat_open(BlockDriverState *bs, QDict 
*options, int flags,
 if (!s->fat_type) {
 s->fat_type = 12;
 secs = 36;
-s->sectors_per_cluster = 2;
 } else {
 secs = s->fat_type == 12 ? 18 : 36;
-s->sectors_per_cluster = 1;
 }
 cyls = 80;
 heads = 2;
 } else {
-/* 32MB or 504MB disk*/
 if (!s->fat_type) {
 s->fat_type = 16;
 }
-s->offset_to_bootsector = 0x3f;
+size_disk = 528482304;
 cyls = s->fat_type == 12 ? 64 : 1024;
 heads = 16;
 secs = 63;
+if (!check_size(s->offset_to_bootsector, cyls, heads, secs,
+  s->sectors_per_cluster, s->fat_type, sum, 
+  size_disk)) {
+if (s->fat_type > 12) {
+size_disk = 4294950912;
+cyls = 8322;
+heads

[PATCH V2] block: increased maximum size of vvfat devices

2021-03-17 Thread Arkadiy
From: NDNF 

This fixes the problem of the impossibility to create
FAT16 disks larger than 504 mb:
The change CHS made it possible to obtain a larger disk.
Also, auto-detection of disk parameters was added depending
on the volume of the connected files:
The size of all folders and files on the created disk is calculated
and the size of the FAT table is added.
This size allows to choose the future size of the FAT drive
from the standard limitations.

Signed-off-by: Arkasha 
---
 block/vvfat.c | 94 ++-
 1 file changed, 85 insertions(+), 9 deletions(-)

diff --git a/block/vvfat.c b/block/vvfat.c
index 54807f82ca..b9e3d7e003 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -932,8 +932,6 @@ static int init_directories(BDRVVVFATState* s,
 /* Now build FAT, and write back information into directory */
 init_fat(s);
 
-/* TODO: if there are more entries, bootsector has to be adjusted! */
-s->root_entries = 0x02 * 0x10 * s->sectors_per_cluster;
 s->cluster_count=sector2cluster(s, s->sector_count);
 
 mapping = array_get_next(&(s->mapping));
@@ -1133,11 +1131,52 @@ static void vvfat_parse_filename(const char *filename, 
QDict *options,
 qdict_put_bool(options, "rw", rw);
 }
 
+static bool check_size(uint32_t offset_to_bootsector, int cyls, int heads,
+  int secs, uint8_t sectors_per_cluster, int fat_type,
+  uint64_t sum, uint64_t size_disk)
+{
+uint32_t sector_count = cyls * heads * secs - offset_to_bootsector;
+int i = 1 + sectors_per_cluster * 0x200 * 8 / fat_type;
+uint16_t sectors_per_fat = (sector_count + i) / i;
+/*size + FAT1 and FAT2 table size*/
+if ((sum + sectors_per_fat * 512 * 2) < size_disk) {
+return true;
+}
+return false;
+}
+
+static uint64_t find_size(const char *dirname, unsigned int cluster)
+{
+uint64_t sum = 0;
+DIR *dir = opendir(dirname);
+struct dirent *entry;
+while ((entry = readdir(dir))) {
+uint16_t length = strlen(dirname) + 2 + strlen(entry->d_name);
+char *buffer;
+struct stat st;
+buffer = g_malloc(length);
+snprintf(buffer, length, "%s/%s", dirname, entry->d_name);
+if (stat(buffer, &st) < 0) {
+g_free(buffer);
+continue;
+}
+if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")
+&& S_ISDIR(st.st_mode)) {
+sum += find_size(buffer, cluster);
+}
+g_free(buffer);
+sum += (st.st_size + cluster - 1) / (cluster) * (cluster);
+}
+closedir(dir);
+return sum;
+}
+
 static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
   Error **errp)
 {
 BDRVVVFATState *s = bs->opaque;
 int cyls, heads, secs;
+uint64_t size_disk;
 bool floppy;
 const char *dirname, *label;
 QemuOpts *opts;
@@ -1163,6 +1202,28 @@ static int vvfat_open(BlockDriverState *bs, QDict 
*options, int flags,
 s->fat_type = qemu_opt_get_number(opts, "fat-type", 0);
 floppy = qemu_opt_get_bool(opts, "floppy", false);
 
+uint64_t sum = 0;
+if (floppy) {
+if (!s->fat_type) {
+s->sectors_per_cluster = 2;
+} else {
+s->sectors_per_cluster = 1;
+}
+} else if (s->fat_type == 12) {
+s->offset_to_bootsector = 0x3f;
+s->sectors_per_cluster = 0x10;
+} else {
+s->offset_to_bootsector = 0x3f;
+/* LATER TODO: if FAT32, adjust */
+s->sectors_per_cluster = 0x80;
+}
+
+sum += find_size(dirname, s->sectors_per_cluster * 0x200);
+/* TODO: if there are more entries, bootsector has to be adjusted! */
+s->root_entries = 0x02 * 0x10 * s->sectors_per_cluster;
+/*File size + boot sector size + root directory size*/
+sum += 512 + s->root_entries * 32;
+
 memset(s->volume_label, ' ', sizeof(s->volume_label));
 label = qemu_opt_get(opts, "label");
 if (label) {
@@ -1182,22 +1243,40 @@ static int vvfat_open(BlockDriverState *bs, QDict 
*options, int flags,
 if (!s->fat_type) {
 s->fat_type = 12;
 secs = 36;
-s->sectors_per_cluster = 2;
 } else {
 secs = s->fat_type == 12 ? 18 : 36;
-s->sectors_per_cluster = 1;
 }
 cyls = 80;
 heads = 2;
 } else {
-/* 32MB or 504MB disk*/
 if (!s->fat_type) {
 s->fat_type = 16;
 }
-s->offset_to_bootsector = 0x3f;
+size_disk = 528482304;
 cyls = s->fat_type == 12 ? 64 : 1024;
 heads = 16;
 secs = 63;
+if (!check_size(s->offset_to_bootsector, cyls, heads, secs,
+  s->sectors_per_cluster, s->fat_type, sum,
+  size_disk)) {
+if (s->fat_type > 12) {
+size_disk = 4294950912;
+cyls = 8322;
+heads 

[PATCH] mips/tlb_helper: Add support for 'info tlb' cmd

2021-07-20 Thread Arkadiy
From: NDNF 

This adds hmp 'info tlb' command support for the mips platform.
1k pages are not supported.

Signed-off-by: NDNF 
---
 hmp-commands-info.hx |  3 ++-
 target/mips/cpu.h|  3 +++
 target/mips/meson.build  |  1 +
 target/mips/monitor.c| 26 ++
 target/mips/tlb_helper.c | 48 
 5 files changed, 80 insertions(+), 1 deletion(-)
 create mode 100644 target/mips/monitor.c

diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
index 117ba25f91..d6aab9839c 100644
--- a/hmp-commands-info.hx
+++ b/hmp-commands-info.hx
@@ -222,7 +222,8 @@ SRST
 ERST
 
 #if defined(TARGET_I386) || defined(TARGET_SH4) || defined(TARGET_SPARC) || \
-defined(TARGET_PPC) || defined(TARGET_XTENSA) || defined(TARGET_M68K)
+defined(TARGET_PPC) || defined(TARGET_XTENSA) || defined(TARGET_M68K) || \
+defined(TARGET_MIPS) || defined(TARGET_MIPS64)
 {
 .name   = "tlb",
 .args_type  = "",
diff --git a/target/mips/cpu.h b/target/mips/cpu.h
index b9e227a30e..5aa6f2b760 100644
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -1337,6 +1337,9 @@ void itc_reconfigure(struct MIPSITUState *tag);
 /* helper.c */
 target_ulong exception_resume_pc(CPUMIPSState *env);
 
+/*tlb_helper.c*/
+void dump_mmu(CPUMIPSState *env);
+
 static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc,
 target_ulong *cs_base, uint32_t *flags)
 {
diff --git a/target/mips/meson.build b/target/mips/meson.build
index 9741545440..c0b19048ee 100644
--- a/target/mips/meson.build
+++ b/target/mips/meson.build
@@ -31,6 +31,7 @@ mips_softmmu_ss.add(files(
   'cp0_timer.c',
   'machine.c',
   'mips-semi.c',
+  'monitor.c',
 ))
 mips_softmmu_ss.add(when: 'CONFIG_TCG', if_true: files(
   'cp0_helper.c',
diff --git a/target/mips/monitor.c b/target/mips/monitor.c
new file mode 100644
index 00..9c9dfd2caa
--- /dev/null
+++ b/target/mips/monitor.c
@@ -0,0 +1,26 @@
+/*
+ * monitor.c
+ *
+ * Copyright (c) 2010-2021 Institute for System Programming
+ * of the Russian Academy of Sciences.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "monitor/monitor.h"
+#include "monitor/hmp-target.h"
+#include "monitor/hmp.h"
+
+void hmp_info_tlb(Monitor *mon, const QDict *qdict)
+{
+CPUArchState *env = mon_get_cpu_env(mon);
+if (!env) {
+monitor_printf(mon, "No CPU available\n");
+return;
+}
+dump_mmu(env);
+}
diff --git a/target/mips/tlb_helper.c b/target/mips/tlb_helper.c
index 082c17928d..1c0c2831d6 100644
--- a/target/mips/tlb_helper.c
+++ b/target/mips/tlb_helper.c
@@ -24,6 +24,7 @@
 #include "exec/cpu_ldst.h"
 #include "exec/log.h"
 #include "hw/mips/cpudevs.h"
+#include "qemu/qemu-print.h"
 
 enum {
 TLBRET_XI = -6,
@@ -37,6 +38,53 @@ enum {
 
 #if !defined(CONFIG_USER_ONLY)
 
+static void r4k_mmu_dump(CPUMIPSState *env)
+{
+int i;
+for (i = 0; i < env->tlb->tlb_in_use; i++) {
+r4k_tlb_t *tlb = &env->tlb->mmu.r4k.tlb[i];
+
+bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1);
+
+qemu_printf("TLB[%i]:\nG = %i EHINV = %i\nPageMask = %08x", i, tlb->G,
+tlb->EHINV, tlb->PageMask);
+if (!tlb->EHINV) {
+if (mi) {
+qemu_printf(" MMID = %i", tlb->MMID);
+} else if (!tlb->G) {
+qemu_printf(" ASID = %i", tlb->ASID);
+}
+qemu_printf("\nVPN = "TARGET_FMT_lx" PFN[0] = %08lx RI0 = %i"
+" XI0 = %i C0 = %i D0 = %i V0 = %i\n"
+"VPN = "TARGET_FMT_lx" PFN[1] = %08lx RI1 = %i XI1 = 
%i"
+" C1 = %i D1 = %i V1 = %i\n", tlb->VPN, tlb->PFN[0],
+tlb->RI0, tlb->XI0, tlb->C0, tlb->D0, tlb->V0, 
tlb->VPN,
+tlb->PFN[1], tlb->RI1, tlb->XI1,
+tlb->C1, tlb->D1, tlb->V1);
+}
+}
+}
+
+void dump_mmu(CPUMIPSState *env)
+{
+switch (env->cpu_model->mmu_type) {
+case MMU_TYPE_NONE:
+qemu_printf("no MMU emulation\n");
+break;
+case MMU_TYPE_R4000:
+r4k_mmu_dump(env);
+break;
+case MMU_TYPE_FMT:
+qemu_printf("fixed mapping MMU emulation\n");
+break;
+case MMU_TYPE_R3000:
+case MMU_TYPE_R6000:
+case MMU_TYPE_R8000:
+default:
+qemu_printf("MMU type not supported\n");
+}
+}
+
 /* no MMU emulation */
 int no_mmu_map_address(CPUMIPSState *env, hwaddr *physical, int *prot,
target_ulong address, int rw, int access_type)
-- 
2.25.1




[PATCH v2] mips/tlb_helper: Add support for 'info tlb' cmd

2021-07-23 Thread Arkadiy
From: NDNF 

This adds hmp 'info tlb' command support for the mips platform.
1k pages are not supported.

Signed-off-by: Ivanov Arkady 
---
 hmp-commands-info.hx |  3 ++-
 target/mips/cpu.h|  3 +++
 target/mips/meson.build  |  1 +
 target/mips/monitor.c| 26 ++
 target/mips/tlb_helper.c | 48 
 5 files changed, 80 insertions(+), 1 deletion(-)
 create mode 100644 target/mips/monitor.c

diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
index 117ba25f91..d6aab9839c 100644
--- a/hmp-commands-info.hx
+++ b/hmp-commands-info.hx
@@ -222,7 +222,8 @@ SRST
 ERST
 
 #if defined(TARGET_I386) || defined(TARGET_SH4) || defined(TARGET_SPARC) || \
-defined(TARGET_PPC) || defined(TARGET_XTENSA) || defined(TARGET_M68K)
+defined(TARGET_PPC) || defined(TARGET_XTENSA) || defined(TARGET_M68K) || \
+defined(TARGET_MIPS) || defined(TARGET_MIPS64)
 {
 .name   = "tlb",
 .args_type  = "",
diff --git a/target/mips/cpu.h b/target/mips/cpu.h
index b9e227a30e..5aa6f2b760 100644
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -1337,6 +1337,9 @@ void itc_reconfigure(struct MIPSITUState *tag);
 /* helper.c */
 target_ulong exception_resume_pc(CPUMIPSState *env);
 
+/*tlb_helper.c*/
+void dump_mmu(CPUMIPSState *env);
+
 static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc,
 target_ulong *cs_base, uint32_t *flags)
 {
diff --git a/target/mips/meson.build b/target/mips/meson.build
index 9741545440..c0b19048ee 100644
--- a/target/mips/meson.build
+++ b/target/mips/meson.build
@@ -31,6 +31,7 @@ mips_softmmu_ss.add(files(
   'cp0_timer.c',
   'machine.c',
   'mips-semi.c',
+  'monitor.c',
 ))
 mips_softmmu_ss.add(when: 'CONFIG_TCG', if_true: files(
   'cp0_helper.c',
diff --git a/target/mips/monitor.c b/target/mips/monitor.c
new file mode 100644
index 00..9c9dfd2caa
--- /dev/null
+++ b/target/mips/monitor.c
@@ -0,0 +1,26 @@
+/*
+ * monitor.c
+ *
+ * Copyright (c) 2010-2021 Institute for System Programming
+ * of the Russian Academy of Sciences.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "monitor/monitor.h"
+#include "monitor/hmp-target.h"
+#include "monitor/hmp.h"
+
+void hmp_info_tlb(Monitor *mon, const QDict *qdict)
+{
+CPUArchState *env = mon_get_cpu_env(mon);
+if (!env) {
+monitor_printf(mon, "No CPU available\n");
+return;
+}
+dump_mmu(env);
+}
diff --git a/target/mips/tlb_helper.c b/target/mips/tlb_helper.c
index 082c17928d..1c0c2831d6 100644
--- a/target/mips/tlb_helper.c
+++ b/target/mips/tlb_helper.c
@@ -24,6 +24,7 @@
 #include "exec/cpu_ldst.h"
 #include "exec/log.h"
 #include "hw/mips/cpudevs.h"
+#include "qemu/qemu-print.h"
 
 enum {
 TLBRET_XI = -6,
@@ -37,6 +38,53 @@ enum {
 
 #if !defined(CONFIG_USER_ONLY)
 
+static void r4k_mmu_dump(CPUMIPSState *env)
+{
+int i;
+for (i = 0; i < env->tlb->tlb_in_use; i++) {
+r4k_tlb_t *tlb = &env->tlb->mmu.r4k.tlb[i];
+
+bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1);
+
+qemu_printf("TLB[%i]:\nG = %i EHINV = %i\nPageMask = %08x", i, tlb->G,
+tlb->EHINV, tlb->PageMask);
+if (!tlb->EHINV) {
+if (mi) {
+qemu_printf(" MMID = %i", tlb->MMID);
+} else if (!tlb->G) {
+qemu_printf(" ASID = %i", tlb->ASID);
+}
+qemu_printf("\nVPN = "TARGET_FMT_lx" PFN[0] = %08lx RI0 = %i"
+" XI0 = %i C0 = %i D0 = %i V0 = %i\n"
+"VPN = "TARGET_FMT_lx" PFN[1] = %08lx RI1 = %i XI1 = 
%i"
+" C1 = %i D1 = %i V1 = %i\n", tlb->VPN, tlb->PFN[0],
+tlb->RI0, tlb->XI0, tlb->C0, tlb->D0, tlb->V0, 
tlb->VPN,
+tlb->PFN[1], tlb->RI1, tlb->XI1,
+tlb->C1, tlb->D1, tlb->V1);
+}
+}
+}
+
+void dump_mmu(CPUMIPSState *env)
+{
+switch (env->cpu_model->mmu_type) {
+case MMU_TYPE_NONE:
+qemu_printf("no MMU emulation\n");
+break;
+case MMU_TYPE_R4000:
+r4k_mmu_dump(env);
+break;
+case MMU_TYPE_FMT:
+qemu_printf("fixed mapping MMU emulation\n");
+break;
+case MMU_TYPE_R3000:
+case MMU_TYPE_R6000:
+case MMU_TYPE_R8000:
+default:
+qemu_printf("MMU type not supported\n");
+}
+}
+
 /* no MMU emulation */
 int no_mmu_map_address(CPUMIPSState *env, hwaddr *physical, int *prot,
target_ulong address, int rw, int access_type)
-- 
2.25.1




[PATCH v3] mips/tlb_helper: Add support for 'info tlb' cmd

2021-07-26 Thread Arkadiy
From: NDNF 

This adds hmp 'info tlb' command support for the mips platform.
1k pages are not supported.

Signed-off-by: Ivanov Arkady 
---
v3: dump all cores, fixed output
---
 hmp-commands-info.hx |  3 ++-
 target/mips/cpu.h|  3 +++
 target/mips/meson.build  |  1 +
 target/mips/monitor.c| 27 ++
 target/mips/tlb_helper.c | 50 
 5 files changed, 83 insertions(+), 1 deletion(-)
 create mode 100644 target/mips/monitor.c

diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
index 117ba25f91..d6aab9839c 100644
--- a/hmp-commands-info.hx
+++ b/hmp-commands-info.hx
@@ -222,7 +222,8 @@ SRST
 ERST
 
 #if defined(TARGET_I386) || defined(TARGET_SH4) || defined(TARGET_SPARC) || \
-defined(TARGET_PPC) || defined(TARGET_XTENSA) || defined(TARGET_M68K)
+defined(TARGET_PPC) || defined(TARGET_XTENSA) || defined(TARGET_M68K) || \
+defined(TARGET_MIPS) || defined(TARGET_MIPS64)
 {
 .name   = "tlb",
 .args_type  = "",
diff --git a/target/mips/cpu.h b/target/mips/cpu.h
index b9e227a30e..5aa6f2b760 100644
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -1337,6 +1337,9 @@ void itc_reconfigure(struct MIPSITUState *tag);
 /* helper.c */
 target_ulong exception_resume_pc(CPUMIPSState *env);
 
+/*tlb_helper.c*/
+void dump_mmu(CPUMIPSState *env);
+
 static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc,
 target_ulong *cs_base, uint32_t *flags)
 {
diff --git a/target/mips/meson.build b/target/mips/meson.build
index 9741545440..c0b19048ee 100644
--- a/target/mips/meson.build
+++ b/target/mips/meson.build
@@ -31,6 +31,7 @@ mips_softmmu_ss.add(files(
   'cp0_timer.c',
   'machine.c',
   'mips-semi.c',
+  'monitor.c',
 ))
 mips_softmmu_ss.add(when: 'CONFIG_TCG', if_true: files(
   'cp0_helper.c',
diff --git a/target/mips/monitor.c b/target/mips/monitor.c
new file mode 100644
index 00..b7ca9b77e6
--- /dev/null
+++ b/target/mips/monitor.c
@@ -0,0 +1,27 @@
+/*
+ * monitor.c
+ *
+ * Copyright (c) 2010-2021 Institute for System Programming
+ * of the Russian Academy of Sciences.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "monitor/monitor.h"
+#include "monitor/hmp-target.h"
+#include "monitor/hmp.h"
+#include "qapi/qmp/qdict.h"
+
+void hmp_info_tlb(Monitor *mon, const QDict *qdict)
+{
+CPUState *cs;
+CPU_FOREACH(cs) {
+monitor_printf(mon, "\nCPU#%d\n", cs->cpu_index);
+dump_mmu(cs->env_ptr);
+}
+
+}
diff --git a/target/mips/tlb_helper.c b/target/mips/tlb_helper.c
index 082c17928d..d2a56a7196 100644
--- a/target/mips/tlb_helper.c
+++ b/target/mips/tlb_helper.c
@@ -24,6 +24,7 @@
 #include "exec/cpu_ldst.h"
 #include "exec/log.h"
 #include "hw/mips/cpudevs.h"
+#include "qemu/qemu-print.h"
 
 enum {
 TLBRET_XI = -6,
@@ -37,6 +38,55 @@ enum {
 
 #if !defined(CONFIG_USER_ONLY)
 
+static void r4k_mmu_dump(CPUMIPSState *env)
+{
+int i;
+qemu_printf("TLB count = %i\n", env->tlb->tlb_in_use);
+for (i = 0; i < env->tlb->tlb_in_use; i++) {
+r4k_tlb_t *tlb = &env->tlb->mmu.r4k.tlb[i];
+
+bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1);
+
+qemu_printf("TLB[%i]:\nG = %i EHINV = %i\nPageMask = 0x%08x", i, 
tlb->G,
+tlb->EHINV, tlb->PageMask);
+if (!tlb->EHINV) {
+if (mi) {
+qemu_printf(" MMID = %i", tlb->MMID);
+} else if (!tlb->G) {
+qemu_printf(" ASID = %i", tlb->ASID);
+}
+qemu_printf("\nVPN = 0x"TARGET_FMT_lx" PFN[0] = 0x%08lx RI0 = %i"
+" XI0 = %i C0 = %i D0 = %i V0 = %i\n"
+"VPN = 0x"TARGET_FMT_lx" PFN[1] = 0x%08lx RI1 = %i"
+" XI1 = %i C1 = %i D1 = %i V1 = %i\n", tlb->VPN,
+tlb->PFN[0], tlb->RI0, tlb->XI0, tlb->C0, tlb->D0,
+tlb->V0, tlb->VPN, tlb->PFN[1], tlb->RI1, tlb->XI1,
+tlb->C1, tlb->D1, tlb->V1);
+}
+}
+}
+
+void dump_mmu(CPUMIPSState *env)
+{
+switch (env->cpu_model->mmu_type) {
+case MMU_TYPE_NONE:
+qemu_printf("No TLB (no MMU)\n");
+break;
+case MMU_TYPE_R4000:
+r4k_mmu_dump(env);
+break;
+case MMU_TYPE_FMT:
+qemu_printf("No TLB (fixed mapping MMU)\n");
+break;
+case MMU_TYPE_R3000:
+case MMU_TYPE_R6000:
+case MMU_TYPE_R8000:
+default:
+qemu_printf("MMU type not supported\n");
+g_assert_not_reached();
+}
+}
+
 /* no MMU emulation */
 int no_mmu_map_address(CPUMIPSState *env, hwaddr *physical, int *prot,
target_ulong address, int rw, int access_type)
-- 
2.25.1




[PATCH] trace: add hardware interrupt calls tracing

2021-06-29 Thread Arkadiy
From: NDNF 

Adds hardware interrupt call tracing. This is necessary to debugging Qemu and
virtual devices. It was decided to use function names. This allow us tracing
IRQ without global code changes.
There was an attempt to use device names, but appeared the problem:
it wasn't always possible to find out the name of the calling device or
the receiver. For example GSI is not a device in Qemu.
Hence, there will be a gap in the interrupt chain.

Signed-off-by: NDNF 
---
 hw/core/irq.c  | 28 --
 hw/core/qdev.c | 20 ++--
 hw/core/trace-events   |  3 +++
 include/hw/irq.h   | 54 --
 include/hw/qdev-core.h | 32 ++---
 5 files changed, 97 insertions(+), 40 deletions(-)

diff --git a/hw/core/irq.c b/hw/core/irq.c
index 8a9cbdd556..ee32b58cec 100644
--- a/hw/core/irq.c
+++ b/hw/core/irq.c
@@ -26,6 +26,9 @@
 #include "hw/irq.h"
 #include "qom/object.h"
 
+
+#include "trace.h"
+
 DECLARE_INSTANCE_CHECKER(struct IRQState, IRQ,
  TYPE_IRQ)
 
@@ -35,18 +38,24 @@ struct IRQState {
 qemu_irq_handler handler;
 void *opaque;
 int n;
+const char *targetFunc;
 };
 
-void qemu_set_irq(qemu_irq irq, int level)
+void qemu_set_irq_with_trace(qemu_irq irq, int level, const char *callFunc)
 {
 if (!irq)
 return;
 
+const char *targetFunc = irq->targetFunc;
+trace_irq_tracker(callFunc, targetFunc, irq->n, level);
 irq->handler(irq->opaque, irq->n, level);
 }
 
-qemu_irq *qemu_extend_irqs(qemu_irq *old, int n_old, qemu_irq_handler handler,
-   void *opaque, int n)
+/*Tracking irq function*/
+
+qemu_irq *qemu_extend_irqs_with_trace(qemu_irq *old, int n_old,
+  qemu_irq_handler handler, void *opaque,
+  int n, const char *targetFunc)
 {
 qemu_irq *s;
 int i;
@@ -56,17 +65,19 @@ qemu_irq *qemu_extend_irqs(qemu_irq *old, int n_old, 
qemu_irq_handler handler,
 }
 s = old ? g_renew(qemu_irq, old, n + n_old) : g_new(qemu_irq, n);
 for (i = n_old; i < n + n_old; i++) {
-s[i] = qemu_allocate_irq(handler, opaque, i);
+s[i] = qemu_allocate_irq_with_trace(handler, opaque, i, targetFunc);
 }
 return s;
 }
 
-qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n)
+qemu_irq *qemu_allocate_irqs_with_trace(qemu_irq_handler handler, void *opaque,
+int n, const char *targetFunc)
 {
-return qemu_extend_irqs(NULL, 0, handler, opaque, n);
+return qemu_extend_irqs_with_trace(NULL, 0, handler, opaque, n, 
targetFunc);
 }
 
-qemu_irq qemu_allocate_irq(qemu_irq_handler handler, void *opaque, int n)
+qemu_irq qemu_allocate_irq_with_trace(qemu_irq_handler handler, void *opaque,
+  int n, const char *targetFunc)
 {
 struct IRQState *irq;
 
@@ -74,10 +85,13 @@ qemu_irq qemu_allocate_irq(qemu_irq_handler handler, void 
*opaque, int n)
 irq->handler = handler;
 irq->opaque = opaque;
 irq->n = n;
+irq->targetFunc = targetFunc;
 
 return irq;
 }
 
+/*Tracking irq function*/
+
 void qemu_free_irqs(qemu_irq *s, int n)
 {
 int i;
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index cefc5eaa0a..e621de506d 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -450,17 +450,20 @@ static NamedGPIOList 
*qdev_get_named_gpio_list(DeviceState *dev,
 return ngl;
 }
 
-void qdev_init_gpio_in_named_with_opaque(DeviceState *dev,
+/*Tracking irq function*/
+
+void qdev_init_gpio_in_named_with_opaque_with_trace(DeviceState *dev,
  qemu_irq_handler handler,
- void *opaque,
- const char *name, int n)
+ void *opaque, const char *name,
+ int n, const char *target)
 {
 int i;
 NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name);
 
 assert(gpio_list->num_out == 0 || !name);
-gpio_list->in = qemu_extend_irqs(gpio_list->in, gpio_list->num_in, handler,
- opaque, n);
+gpio_list->in = qemu_extend_irqs_with_trace(gpio_list->in,
+gpio_list->num_in, handler,
+opaque, n, target);
 
 if (!name) {
 name = "unnamed-gpio-in";
@@ -476,11 +479,14 @@ void qdev_init_gpio_in_named_with_opaque(DeviceState *dev,
 gpio_list->num_in += n;
 }
 
-void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
+void qdev_init_gpio_in_with_trace(DeviceState *dev, qemu_irq_handler handler,
+  int n, const char *target)
 {
-qdev_init_gpio_in_named(dev, handler, NULL, n);
+qdev_init_gpio_in_named_with_trace(dev, handler, NULL, n, target);
 }
 
+/*Tracking i

Re: [PATCH] contrib/plugins: add a drcov plugin

2021-10-13 Thread arkadiy . ivanov

Alex Bennée писал 2021-10-12 13:36:

Arkadiy  writes:


From: NDNF 

This patch adds the ability to generate files in drcov format.
Primary goal this script is to have coverage
logfiles thatwork in Lighthouse.
Problems:
- The path to the executable file is not specified.


I don't see a problem in introducing a plugin helper function to expose
the path to the binary/kernel to the plugin.


- base, end, entry take incorrect values.
  (Lighthouse + IDA Pro anyway work).


What are they meant to be? Again we could add a helper.



Signed-off-by: Ivanov Arkady 
---
 contrib/plugins/Makefile |   1 +
 contrib/plugins/drcov.c  | 112 
+++

 2 files changed, 113 insertions(+)
 create mode 100644 contrib/plugins/drcov.c

diff --git a/contrib/plugins/Makefile b/contrib/plugins/Makefile
index 7801b08b0d..0a681efeec 100644
--- a/contrib/plugins/Makefile
+++ b/contrib/plugins/Makefile
@@ -17,6 +17,7 @@ NAMES += hotblocks
 NAMES += hotpages
 NAMES += howvec
 NAMES += lockstep
+NAMES += drcov

 SONAMES := $(addsuffix .so,$(addprefix lib,$(NAMES)))

diff --git a/contrib/plugins/drcov.c b/contrib/plugins/drcov.c
new file mode 100644
index 00..d6a7d131c0
--- /dev/null
+++ b/contrib/plugins/drcov.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2021, Ivanov Arkady 
+ *
+ * Drcov - a DynamoRIO-based tool that collects coverage information
+ * from a binary. Primary goal this script is to have coverage log
+ * files that work in Lighthouse.
+ *
+ * License: GNU GPL, version 2 or later.
+ *   See the COPYING file in the top-level directory.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
+
+static char header[] = "DRCOV VERSION: 2\n"
+"DRCOV FLAVOR: drcov-64\n"
+"Module Table: version 2, count 1\n"
+"Columns: id, base, end, entry, path\n";
+
+static FILE *fp;
+
+typedef struct {
+uint32_t start;
+uint16_t size;
+uint16_t mod_id;
+} bb_entry_t;
+
+static GSList *bbs;
+
+static void printfHeader()


missing void in args.


+{
+g_autoptr(GString) head = g_string_new("");
+g_string_append(head, header);


You could just initialise with your header:

  g_autoptr(GString) head = g_string_new(header);


+g_string_append_printf(head, "0, 0x%x, 0x%x, 0x%x, %s\n",
+   0, 0x, 0, "path");


Why pass consts intro the printf instead of just appending the data as 
a string?


+g_string_append_printf(head, "BB Table: %d bbs\n", 
g_slist_length(bbs));

+fwrite(head->str, sizeof(char), head->len, fp);
+}
+
+static void printfCharArray32(uint32_t data)
+{
+const uint8_t *bytes = (const uint8_t *)(&data);
+fwrite(bytes, sizeof(char), sizeof(data), fp);
+}
+
+static void printfCharArray16(uint16_t data)
+{
+const uint8_t *bytes = (const uint8_t *)(&data);
+fwrite(bytes, sizeof(char), sizeof(data), fp);
+}


Can the above function names follow the QEMU house style please?


+
+
+static void printf_el(gpointer data, gpointer user_data)
+{
+bb_entry_t *bb = (bb_entry_t *)data;
+printfCharArray32(bb->start);
+printfCharArray16(bb->size);
+printfCharArray16(bb->mod_id);
+}
+
+static void plugin_exit(qemu_plugin_id_t id, void *p)
+{
+/* Print function */
+printfHeader();
+g_slist_foreach(bbs, printf_el, NULL);
+
+/* Clear */
+g_slist_free_full(bbs, &g_free);
+fclose(fp);
+}
+
+static void plugin_init(void)
+{
+fp = fopen("file.drcov.trace", "wb");


Could we make this configurable and just have "file.drcov.trace" as the
default if not set?


+}
+
+static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb 
*tb)

+{
+bb_entry_t *bb = g_new0(bb_entry_t, 1);
+uint64_t pc = qemu_plugin_tb_vaddr(tb);
+
+size_t n = qemu_plugin_tb_n_insns(tb);
+for (int i = 0; i < n; i++) {
+bb->size += qemu_plugin_insn_size(qemu_plugin_tb_get_insn(tb, 
i));

+}
+
+bb->start = pc;
+bb->mod_id = 0;
+bbs = g_slist_append(bbs, bb);
+
+}


I'm guessing this works in the simple case but beware that not all
translations get executed. It might be better to as a install an actual
tracer when the TB gets executed.

Although most TBs run to completion there are cases where execution
stops in them middle of TB. Generally this will be when a synchronous
fault has occurred and we exit the block early, potentially 
regenerating

a block at the PC the fault was at.

The g_list_append should be protected by a mutex as translation can be
multi-threaded (at least for system emulation).


+
+QEMU_PLUGIN_EXPORT
+int qemu_plugin_install(qemu_plugin_id_t id, const qemu_info_t *info,
+int argc, char **argv)
+{
+plugi

Re: [PATCH] contrib/plugins: add a drcov plugin

2021-10-15 Thread arkadiy . ivanov

Alex Bennée писал 2021-10-12 13:36:

Arkadiy  writes:


From: NDNF 

This patch adds the ability to generate files in drcov format.
Primary goal this script is to have coverage
logfiles thatwork in Lighthouse.
Problems:
- The path to the executable file is not specified.


I don't see a problem in introducing a plugin helper function to expose
the path to the binary/kernel to the plugin.


- base, end, entry take incorrect values.
  (Lighthouse + IDA Pro anyway work).


What are they meant to be? Again we could add a helper.



Signed-off-by: Ivanov Arkady 
---
 contrib/plugins/Makefile |   1 +
 contrib/plugins/drcov.c  | 112 
+++

 2 files changed, 113 insertions(+)
 create mode 100644 contrib/plugins/drcov.c

diff --git a/contrib/plugins/Makefile b/contrib/plugins/Makefile
index 7801b08b0d..0a681efeec 100644
--- a/contrib/plugins/Makefile
+++ b/contrib/plugins/Makefile
@@ -17,6 +17,7 @@ NAMES += hotblocks
 NAMES += hotpages
 NAMES += howvec
 NAMES += lockstep
+NAMES += drcov

 SONAMES := $(addsuffix .so,$(addprefix lib,$(NAMES)))

diff --git a/contrib/plugins/drcov.c b/contrib/plugins/drcov.c
new file mode 100644
index 00..d6a7d131c0
--- /dev/null
+++ b/contrib/plugins/drcov.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2021, Ivanov Arkady 
+ *
+ * Drcov - a DynamoRIO-based tool that collects coverage information
+ * from a binary. Primary goal this script is to have coverage log
+ * files that work in Lighthouse.
+ *
+ * License: GNU GPL, version 2 or later.
+ *   See the COPYING file in the top-level directory.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
+
+static char header[] = "DRCOV VERSION: 2\n"
+"DRCOV FLAVOR: drcov-64\n"
+"Module Table: version 2, count 1\n"
+"Columns: id, base, end, entry, path\n";
+
+static FILE *fp;
+
+typedef struct {
+uint32_t start;
+uint16_t size;
+uint16_t mod_id;
+} bb_entry_t;
+
+static GSList *bbs;
+
+static void printfHeader()


missing void in args.


+{
+g_autoptr(GString) head = g_string_new("");
+g_string_append(head, header);


You could just initialise with your header:

  g_autoptr(GString) head = g_string_new(header);


+g_string_append_printf(head, "0, 0x%x, 0x%x, 0x%x, %s\n",
+   0, 0x, 0, "path");


Why pass consts intro the printf instead of just appending the data as 
a string?


+g_string_append_printf(head, "BB Table: %d bbs\n", 
g_slist_length(bbs));

+fwrite(head->str, sizeof(char), head->len, fp);
+}
+
+static void printfCharArray32(uint32_t data)
+{
+const uint8_t *bytes = (const uint8_t *)(&data);
+fwrite(bytes, sizeof(char), sizeof(data), fp);
+}
+
+static void printfCharArray16(uint16_t data)
+{
+const uint8_t *bytes = (const uint8_t *)(&data);
+fwrite(bytes, sizeof(char), sizeof(data), fp);
+}


Can the above function names follow the QEMU house style please?


+
+
+static void printf_el(gpointer data, gpointer user_data)
+{
+bb_entry_t *bb = (bb_entry_t *)data;
+printfCharArray32(bb->start);
+printfCharArray16(bb->size);
+printfCharArray16(bb->mod_id);
+}
+
+static void plugin_exit(qemu_plugin_id_t id, void *p)
+{
+/* Print function */
+printfHeader();
+g_slist_foreach(bbs, printf_el, NULL);
+
+/* Clear */
+g_slist_free_full(bbs, &g_free);
+fclose(fp);
+}
+
+static void plugin_init(void)
+{
+fp = fopen("file.drcov.trace", "wb");


Could we make this configurable and just have "file.drcov.trace" as the
default if not set?


+}
+
+static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb 
*tb)

+{
+bb_entry_t *bb = g_new0(bb_entry_t, 1);
+uint64_t pc = qemu_plugin_tb_vaddr(tb);
+
+size_t n = qemu_plugin_tb_n_insns(tb);
+for (int i = 0; i < n; i++) {
+bb->size += qemu_plugin_insn_size(qemu_plugin_tb_get_insn(tb, 
i));

+}
+
+bb->start = pc;
+bb->mod_id = 0;
+bbs = g_slist_append(bbs, bb);
+
+}


I'm guessing this works in the simple case but beware that not all
translations get executed. It might be better to as a install an actual
tracer when the TB gets executed.

Although most TBs run to completion there are cases where execution
stops in them middle of TB. Generally this will be when a synchronous
fault has occurred and we exit the block early, potentially 
regenerating

a block at the PC the fault was at.

The g_list_append should be protected by a mutex as translation can be
multi-threaded (at least for system emulation).


+
+QEMU_PLUGIN_EXPORT
+int qemu_plugin_install(qemu_plugin_id_t id, const qemu_info_t *info,
+int argc, char **argv)
+{
+plugi

Re: [PATCH] trace: add hardware interrupt calls tracing

2021-07-07 Thread Arkadiy Isp
Ping?

https://patchwork.kernel.org/project/qemu-devel/patch/20210625073844.1229-3-mark.cave-ayl...@ilande.co.uk/


вт, 29 июн. 2021 г. в 16:38, Arkadiy :

> From: NDNF 
>
> Adds hardware interrupt call tracing. This is necessary to debugging Qemu
> and
> virtual devices. It was decided to use function names. This allow us
> tracing
> IRQ without global code changes.
> There was an attempt to use device names, but appeared the problem:
> it wasn't always possible to find out the name of the calling device or
> the receiver. For example GSI is not a device in Qemu.
> Hence, there will be a gap in the interrupt chain.
>
> Signed-off-by: NDNF 
> ---
>  hw/core/irq.c  | 28 --
>  hw/core/qdev.c | 20 ++--
>  hw/core/trace-events   |  3 +++
>  include/hw/irq.h   | 54 --
>  include/hw/qdev-core.h | 32 ++---
>  5 files changed, 97 insertions(+), 40 deletions(-)
>
> diff --git a/hw/core/irq.c b/hw/core/irq.c
> index 8a9cbdd556..ee32b58cec 100644
> --- a/hw/core/irq.c
> +++ b/hw/core/irq.c
> @@ -26,6 +26,9 @@
>  #include "hw/irq.h"
>  #include "qom/object.h"
>
> +
> +#include "trace.h"
> +
>  DECLARE_INSTANCE_CHECKER(struct IRQState, IRQ,
>   TYPE_IRQ)
>
> @@ -35,18 +38,24 @@ struct IRQState {
>  qemu_irq_handler handler;
>  void *opaque;
>  int n;
> +const char *targetFunc;
>  };
>
> -void qemu_set_irq(qemu_irq irq, int level)
> +void qemu_set_irq_with_trace(qemu_irq irq, int level, const char
> *callFunc)
>  {
>  if (!irq)
>  return;
>
> +const char *targetFunc = irq->targetFunc;
> +trace_irq_tracker(callFunc, targetFunc, irq->n, level);
>  irq->handler(irq->opaque, irq->n, level);
>  }
>
> -qemu_irq *qemu_extend_irqs(qemu_irq *old, int n_old, qemu_irq_handler
> handler,
> -   void *opaque, int n)
> +/*Tracking irq function*/
> +
> +qemu_irq *qemu_extend_irqs_with_trace(qemu_irq *old, int n_old,
> +  qemu_irq_handler handler, void
> *opaque,
> +  int n, const char *targetFunc)
>  {
>  qemu_irq *s;
>  int i;
> @@ -56,17 +65,19 @@ qemu_irq *qemu_extend_irqs(qemu_irq *old, int n_old,
> qemu_irq_handler handler,
>  }
>  s = old ? g_renew(qemu_irq, old, n + n_old) : g_new(qemu_irq, n);
>  for (i = n_old; i < n + n_old; i++) {
> -s[i] = qemu_allocate_irq(handler, opaque, i);
> +s[i] = qemu_allocate_irq_with_trace(handler, opaque, i,
> targetFunc);
>  }
>  return s;
>  }
>
> -qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int
> n)
> +qemu_irq *qemu_allocate_irqs_with_trace(qemu_irq_handler handler, void
> *opaque,
> +int n, const char *targetFunc)
>  {
> -return qemu_extend_irqs(NULL, 0, handler, opaque, n);
> +return qemu_extend_irqs_with_trace(NULL, 0, handler, opaque, n,
> targetFunc);
>  }
>
> -qemu_irq qemu_allocate_irq(qemu_irq_handler handler, void *opaque, int n)
> +qemu_irq qemu_allocate_irq_with_trace(qemu_irq_handler handler, void
> *opaque,
> +  int n, const char *targetFunc)
>  {
>  struct IRQState *irq;
>
> @@ -74,10 +85,13 @@ qemu_irq qemu_allocate_irq(qemu_irq_handler handler,
> void *opaque, int n)
>  irq->handler = handler;
>  irq->opaque = opaque;
>  irq->n = n;
> +irq->targetFunc = targetFunc;
>
>  return irq;
>  }
>
> +/*Tracking irq function*/
> +
>  void qemu_free_irqs(qemu_irq *s, int n)
>  {
>  int i;
> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
> index cefc5eaa0a..e621de506d 100644
> --- a/hw/core/qdev.c
> +++ b/hw/core/qdev.c
> @@ -450,17 +450,20 @@ static NamedGPIOList
> *qdev_get_named_gpio_list(DeviceState *dev,
>  return ngl;
>  }
>
> -void qdev_init_gpio_in_named_with_opaque(DeviceState *dev,
> +/*Tracking irq function*/
> +
> +void qdev_init_gpio_in_named_with_opaque_with_trace(DeviceState *dev,
>   qemu_irq_handler handler,
> - void *opaque,
> - const char *name, int n)
> + void *opaque, const char *name,
> + int n, const char *target)
>  {
>  int i;
>  NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name);
>
>  assert(gpio_list->num_out == 0 || !name);
> -