diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
index 374e16efcdf13..6b70da28a18ad 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -11,6 +11,10 @@ jobs:
       uses: actions/setup-python@v4
       with:
         python-version: '3.x'
+    - name: Install Python dependencies
+      run: |
+        pip install --upgrade pip
+        pip install distlib setuptools wheel
     - name: Install deps
       run: |
         sudo apt-get -y update
@@ -32,5 +36,5 @@ jobs:
         cd qemu
         mkdir build
         cd build
-        ../configure --enable-plugins --target-list=sparc-linux-user,sparc64-linux-user
+        ../configure --enable-plugins --target-list=sparc-linux-user,sparc64-linux-user,tricore-softmmu
         ninja
diff --git a/.gitmodules b/.gitmodules
index 439b531cfbdda..5998c94376a00 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -45,4 +45,4 @@
 	url = https://gitlab.com/libvirt/libvirt-ci.git
 [submodule "contrib/plugins/bap-tracing/bap-frames"]
 	path = contrib/plugins/bap-tracing/bap-frames
-	url = git@github.com:BinaryAnalysisPlatform/bap-frames.git
+	url = https://github.com/BinaryAnalysisPlatform/bap-frames.git
diff --git a/README.md b/README.md
index c48b0cff261dd..d87a9854f2089 100644
--- a/README.md
+++ b/README.md
@@ -11,6 +11,7 @@ Known to work:
 - Sparc
 - Hexagon
 - PPC
+- TriCore
 
 Needs fixes:
 
diff --git a/configs/targets/tricore-softmmu.mak b/configs/targets/tricore-softmmu.mak
index 781ce49a62fe0..dee80251e43f4 100644
--- a/configs/targets/tricore-softmmu.mak
+++ b/configs/targets/tricore-softmmu.mak
@@ -1,2 +1,3 @@
 TARGET_ARCH=tricore
 TARGET_LONG_BITS=32
+TARGET_XML_FILES=gdb-xml/tricore-core.xml
diff --git a/contrib/plugins/bap-tracing/bap-frames b/contrib/plugins/bap-tracing/bap-frames
index 75878683e9fef..de612ffce48cb 160000
--- a/contrib/plugins/bap-tracing/bap-frames
+++ b/contrib/plugins/bap-tracing/bap-frames
@@ -1 +1 @@
-Subproject commit 75878683e9fef27bb3053e2237ea098de81ff267
+Subproject commit de612ffce48cb93f7a462f8b0ab28f2884adec0b
diff --git a/contrib/plugins/bap-tracing/meson.build b/contrib/plugins/bap-tracing/meson.build
index 08ddca168141b..743282e703b3f 100644
--- a/contrib/plugins/bap-tracing/meson.build
+++ b/contrib/plugins/bap-tracing/meson.build
@@ -31,7 +31,11 @@ frame_proto_src = custom_target(
 )
 
 libprotobuf = dependency('libprotobuf-c')
-frame_protobuf = static_library('protobuf', [frame_proto_src], pic: true)
+frame_protobuf = static_library(
+    'protobuf',
+    [frame_proto_src],
+    dependencies: [libprotobuf],
+    pic: true)
 dep_libprotobuf = declare_dependency(
     sources : [frame_proto_src, frame_arch_h],
     link_with : [frame_protobuf],
diff --git a/contrib/plugins/bap-tracing/tracing.c b/contrib/plugins/bap-tracing/tracing.c
index fbb7161f0e5ce..dc7eaf7d53d52 100644
--- a/contrib/plugins/bap-tracing/tracing.c
+++ b/contrib/plugins/bap-tracing/tracing.c
@@ -184,6 +184,7 @@ static void flush_and_write_toc_entry(FrameBuffer *fbuf) {
   g_rw_lock_writer_unlock(&state.file_lock);
 }
 
+static void flush_all_frame_bufs(void) __attribute__((unused));
 static void flush_all_frame_bufs(void) {
   g_rw_lock_writer_lock(&state.file_lock);
   g_rw_lock_writer_lock(&state.toc_entries_offsets_lock);
@@ -339,7 +340,37 @@ static void cb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) {
 }
 
 static void plugin_exit(qemu_plugin_id_t id, void *udata) {
-  flush_all_frame_bufs();
+  qemu_plugin_outs("Exiting bap-tracing plugin\n");
+  /**
+   * FIXME: flush_all_frame_bufs() is currently commented out due to an
+   * assertion failure in qemu_plugin_get_registers when used in the plugin
+   * exit callback.
+   *
+   * Root cause: When the plugin exits, current_cpu has already been set to
+   * NULL by QEMU's shutdown sequence. However, flush_all_frame_bufs() calls
+   * qemu_plugin_get_registers() (via add_post_reg_state()) to capture the
+   * final register state, which internally asserts that current_cpu is
+   * non-NULL. This causes the assertion to fail.
+   *
+   * This issue is specific to the TriCore architecture tracing but may affect
+   * other architectures as well.
+   *
+   * Potential drawbacks of commenting out this call:
+   * 1. The last few instruction frames in each vCPU's buffer may not be
+   *    written to the trace file, resulting in incomplete traces.
+   * 2. Post-execution register states for the final instructions will not
+   *    be captured, potentially losing important state information.
+   * 3. If the frame buffers have accumulated data that hasn't reached the
+   *    flush threshold, that data will be lost entirely.
+   *
+   * Possible solutions:
+   * - Modify QEMU to allow qemu_plugin_get_registers() to gracefully handle
+   *   NULL current_cpu during shutdown
+   * - Add a pre-exit flush mechanism that runs before current_cpu is cleared
+   * - Skip register state capture in flush_all_frame_bufs() when called from
+   *   plugin_exit, flushing only the instruction frames without post-state
+   */
+  // flush_all_frame_bufs();
 
   g_rw_lock_writer_lock(&state.file_lock);
   g_rw_lock_reader_lock(&state.toc_entries_offsets_lock);
diff --git a/contrib/plugins/bap-tracing/tracing.h b/contrib/plugins/bap-tracing/tracing.h
index 131ac73a27b2b..f39509e2fc3f8 100644
--- a/contrib/plugins/bap-tracing/tracing.h
+++ b/contrib/plugins/bap-tracing/tracing.h
@@ -104,6 +104,7 @@ static struct arch_enum_entry arch_map[] = {
     {.name = "8051", .arch = frame_arch_8051, .machine = 0},
     {.name = "sm83", .arch = frame_arch_sm83, .machine = 0},
     {.name = "hexagon", .arch = frame_arch_hexagon, .machine = 0},
+    {.name = "tricore", .arch = frame_arch_tricore, .machine = frame_mach_tricore_162},
     {.name = NULL, .arch = frame_arch_last, .machine = 0},
 };
 
diff --git a/gdb-xml/tricore-core.xml b/gdb-xml/tricore-core.xml
new file mode 100644
index 0000000000000..1ce0276d5d33a
--- /dev/null
+++ b/gdb-xml/tricore-core.xml
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+
+  
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  
+
+  
+  
+  
+  
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+  
+  
+  
+  
+
diff --git a/gdb-xml/tricore-fpu.xml b/gdb-xml/tricore-fpu.xml
new file mode 100644
index 0000000000000..d2dbe4da117ff
--- /dev/null
+++ b/gdb-xml/tricore-fpu.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+  
+  
+  
+  
+  
+  
+  
+
diff --git a/gdb-xml/tricore.xml b/gdb-xml/tricore.xml
new file mode 100644
index 0000000000000..1b0a3a561feac
--- /dev/null
+++ b/gdb-xml/tricore.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+  tricore
+  
+  
+
diff --git a/target/tricore/cpu.c b/target/tricore/cpu.c
index 16acc4ecb92ec..68b2cd84cf4c8 100644
--- a/target/tricore/cpu.c
+++ b/target/tricore/cpu.c
@@ -199,6 +199,7 @@ static void tricore_cpu_class_init(ObjectClass *c, void *data)
     cc->gdb_read_register = tricore_cpu_gdb_read_register;
     cc->gdb_write_register = tricore_cpu_gdb_write_register;
     cc->gdb_num_core_regs = 44;
+    cc->gdb_core_xml_file = "tricore-core.xml";
     cc->gdb_arch_name = tricore_gdb_arch_name;
 
     cc->dump_state = tricore_cpu_dump_state;