Re: [PATCH 16/16] rust: allow older version of bindgen

2024-10-16 Thread Paolo Bonzini
Il mer 16 ott 2024, 08:29 Junjie Mao  ha scritto:

>
> The bindgen 0.59.1 installed from Ubuntu 22.04 apt source does not
> support the following args:
>
> '--formatter', 'rustfmt',
> '--merge-extern-blocks',
> '--allowlist-file', meson.project_source_root() + '/include/.*',
> '--allowlist-file', meson.project_source_root() + '/.*',
> '--allowlist-file', meson.project_build_root() + '/.*'
>
>
Ouch. --allowlist-file was added in 0.60, so Debian has it. I think we
should ask Canonical if they can update bindgen in addition to rustc.

Paolo

The first two args are cosmetic and should not hurt if removed (but I
> need to double check).
>
> Removing the allowlist-file, however, causes IPPORT_RESERVED to be
> generated twice using different types and thus break the
> build. Allowlists for bindgen 0.59.1 can only be specified as regex on
> function, type or var. I don't find (yet) an equivalent way of
> --allowlist-file. A dirty trick is `--blocklist-item IPPORT_RESERVED`,
> which works but is so ad-hoc.
>
> --
> Best Regards
> Junjie Mao
>
>


Re: [PATCH 12/16] rust: allow version 1.63.0 of rustc

2024-10-16 Thread Paolo Bonzini
Il mer 16 ott 2024, 08:10 Junjie Mao  ha scritto:

> In my Ubuntu 22.04 environment (rustc 1.76.0 and bindgen 0.59.1 from
> apt) the feature `proc_macro_byte_character` is not yet stablized but
> used in proc-macro2. Downgrading proc-macro2 to 1.0.79 [1] and syn to
> 2.0.58 fixes that issue for me.
>

This is handled by patch 5. Try "meson subprojects update --reset".

Paolo

[1]
> https://github.com/drmingdrmer/openraft/commit/d496b6db4c6128d33f0f211165c08a7925cf20f7
>
> Here're my changes:
>
> diff --git a/subprojects/proc-macro2-1-rs.wrap
> b/subprojects/proc-macro2-1-rs.wrap
> index 7053e2c013..d5713b45d7 100644
> --- a/subprojects/proc-macro2-1-rs.wrap
> +++ b/subprojects/proc-macro2-1-rs.wrap
> @@ -1,7 +1,7 @@
>  [wrap-file]
> -directory = proc-macro2-1.0.84
> -source_url = https://crates.io/api/v1/crates/proc-macro2/1.0.84/download
> -source_filename
> 
> = proc-macro2-1.0.84.0.tar.gz
> -source_hash =
> ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6
> +directory = proc-macro2-1.0.79
> +source_url = https://crates.io/api/v1/crates/proc-macro2/1.0.79/download
> +source_filename = proc-macro2-1.0.79.0.tar.gz
> +source_hash =
> e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e
>  #method = cargo
>  patch_directory = proc-macro2-1-rs
> diff --git a/subprojects/syn-2-rs.wrap b/subprojects/syn-2-rs.wrap
> index 13ffdac3c3..9d413a0c57 100644
> --- a/subprojects/syn-2-rs.wrap
> +++ b/subprojects/syn-2-rs.wrap
> @@ -1,7 +1,7 @@
>  [wrap-file]
> -directory = syn-2.0.66
> -source_url = https://crates.io/api/v1/crates/syn/2.0.66/download
> -source_filename
>  =
> syn-2.0.66.0.tar.gz
> -source_hash =
> c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5
> +directory = syn-2.0.58
> +source_url = https://crates.io/api/v1/crates/syn/2.0.58/download
> +source_filename = syn-2.0.58.0.tar.gz
> +source_hash =
> 44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687
>  #method = cargo
>  patch_directory = syn-2-rs
>
> --
> Best Regards
> Junjie Mao
>
> >  if get_option('rust').enabled()
> > -  error('rustc version ' + rustc.version() + ' is unsupported:
> Please upgrade to at least 1.80.0')
> > +  error('rustc version ' + rustc.version() + ' is unsupported:
> Please upgrade to at least 1.63.0')
> >  else
> > -  warning('rustc version ' + rustc.version() + ' is unsupported:
> Disabling Rust compilation. Please upgrade to at least 1.80.0 to use Rust.')
> > +  warning('rustc version ' + rustc.version() + ' is unsupported:
> Disabling Rust compilation. Please upgrade to at least 1.63.0 to use Rust.')
> >have_rust = false
> >  endif
> >endif
>
>


[PATCH v3 3/4] migration: Support periodic ramblock dirty sync

2024-10-16 Thread yong . huang
From: Hyman Huang 

When VM is configured with huge memory, the current throttle logic
doesn't look like to scale, because migration_trigger_throttle()
is only called for each iteration, so it won't be invoked for a long
time if one iteration can take a long time.

The periodic dirty sync aims to fix the above issue by synchronizing
the ramblock from remote dirty bitmap and, when necessary, triggering
the CPU throttle multiple times during a long iteration.

This is a trade-off between synchronization overhead and CPU throttle
impact.

Signed-off-by: Hyman Huang 
---
 migration/cpu-throttle.c | 70 +++-
 migration/cpu-throttle.h | 14 
 migration/migration.h|  1 +
 migration/ram.c  |  9 --
 migration/trace-events   |  1 +
 5 files changed, 92 insertions(+), 3 deletions(-)

diff --git a/migration/cpu-throttle.c b/migration/cpu-throttle.c
index fa47ee2e21..784b51ab35 100644
--- a/migration/cpu-throttle.c
+++ b/migration/cpu-throttle.c
@@ -28,16 +28,23 @@
 #include "qemu/main-loop.h"
 #include "sysemu/cpus.h"
 #include "cpu-throttle.h"
+#include "migration.h"
+#include "migration-stats.h"
+#include "options.h"
 #include "trace.h"
 
 /* vcpu throttling controls */
-static QEMUTimer *throttle_timer;
+static QEMUTimer *throttle_timer, *throttle_dirty_sync_timer;
 static unsigned int throttle_percentage;
+static bool throttle_dirty_sync_timer_active;
 
 #define CPU_THROTTLE_PCT_MIN 1
 #define CPU_THROTTLE_PCT_MAX 99
 #define CPU_THROTTLE_TIMESLICE_NS 1000
 
+/* RAMBlock dirty sync trigger every five seconds */
+#define CPU_THROTTLE_DIRTY_SYNC_TIMESLICE_MS 5000
+
 static void cpu_throttle_thread(CPUState *cpu, run_on_cpu_data opaque)
 {
 double pct;
@@ -112,6 +119,7 @@ void cpu_throttle_set(int new_throttle_pct)
 void cpu_throttle_stop(void)
 {
 qatomic_set(&throttle_percentage, 0);
+cpu_throttle_dirty_sync_timer(false);
 }
 
 bool cpu_throttle_active(void)
@@ -124,8 +132,68 @@ int cpu_throttle_get_percentage(void)
 return qatomic_read(&throttle_percentage);
 }
 
+void cpu_throttle_dirty_sync_timer_tick(void *opaque)
+{
+static uint64_t prev_sync_cnt = 2;
+uint64_t sync_cnt = stat64_get(&mig_stats.dirty_sync_count);
+
+if (!migrate_auto_converge()) {
+/* Stop the timer when auto converge is disabled */
+return;
+}
+
+/*
+ * The first iteration copies all memory anyhow and has no
+ * effect on guest performance, therefore omit it to avoid
+ * paying extra for the sync penalty.
+ */
+if (sync_cnt <= 1) {
+goto end;
+}
+
+if (sync_cnt == prev_sync_cnt) {
+trace_cpu_throttle_dirty_sync();
+WITH_RCU_READ_LOCK_GUARD() {
+migration_bitmap_sync_precopy(false);
+}
+}
+
+end:
+prev_sync_cnt = stat64_get(&mig_stats.dirty_sync_count);
+
+timer_mod(throttle_dirty_sync_timer,
+qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL_RT) +
+CPU_THROTTLE_DIRTY_SYNC_TIMESLICE_MS);
+}
+
+static bool cpu_throttle_dirty_sync_active(void)
+{
+return qatomic_read(&throttle_dirty_sync_timer_active);
+}
+
+void cpu_throttle_dirty_sync_timer(bool enable)
+{
+if (enable) {
+assert(throttle_dirty_sync_timer);
+if (!cpu_throttle_dirty_sync_active()) {
+timer_mod(throttle_dirty_sync_timer,
+qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL_RT) +
+CPU_THROTTLE_DIRTY_SYNC_TIMESLICE_MS);
+qatomic_set(&throttle_dirty_sync_timer_active, 1);
+}
+} else {
+if (throttle_dirty_sync_timer != NULL) {
+timer_del(throttle_dirty_sync_timer);
+qatomic_set(&throttle_dirty_sync_timer_active, 0);
+}
+}
+}
+
 void cpu_throttle_init(void)
 {
 throttle_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL_RT,
   cpu_throttle_timer_tick, NULL);
+throttle_dirty_sync_timer =
+timer_new_ms(QEMU_CLOCK_VIRTUAL_RT,
+ cpu_throttle_dirty_sync_timer_tick, NULL);
 }
diff --git a/migration/cpu-throttle.h b/migration/cpu-throttle.h
index d65bdef6d0..420702b8d3 100644
--- a/migration/cpu-throttle.h
+++ b/migration/cpu-throttle.h
@@ -65,4 +65,18 @@ bool cpu_throttle_active(void);
  */
 int cpu_throttle_get_percentage(void);
 
+/**
+ * cpu_throttle_dirty_sync_timer_tick:
+ *
+ * Dirty sync timer hook.
+ */
+void cpu_throttle_dirty_sync_timer_tick(void *opaque);
+
+/**
+ * cpu_throttle_dirty_sync_timer:
+ *
+ * Start or stop the dirty sync timer.
+ */
+void cpu_throttle_dirty_sync_timer(bool enable);
+
 #endif /* SYSEMU_CPU_THROTTLE_H */
diff --git a/migration/migration.h b/migration/migration.h
index 38aa1402d5..fbd0d19092 100644
--- a/migration/migration.h
+++ b/migration/migration.h
@@ -537,4 +537,5 @@ int migration_rp_wait(MigrationState *s);
  */
 void migration_rp_kick(MigrationState *s);
 
+void migration_bitmap_sync_precopy(bool last_stage);
 #endif
diff --git a/migration/ram.c b/migration/ram.c
inde

[PATCH v3 0/4] migration: auto-converge refinements for huge VM

2024-10-16 Thread yong . huang
From: Hyman Huang 

v3:
1. drop the responsive throttle patchset
2. rename background sync to periodic ramblock dirty sync
3. move the cpu-throttle.* from system to migration
4. remove "rs" parameter in migration_bitmap_sync_precopy
5. implement periodic ramblock dirty sync in cpu-throttle.c
6. move the test change into a separate patch

To simplify the cover letter, i have dropped the test data,
please refer to 
https://lore.kernel.org/qemu-devel/cover.172763.git.yong.hu...@smartx.com/
for more test details.

Thanks Peter and Fabiano for the suggestions and comments.

Please review.

Yong

Hyman Huang (4):
  migration: Move cpu-throttole.c from system to migration
  migration: Remove "rs" parameter in migration_bitmap_sync_precopy
  migration: Support periodic ramblock dirty sync
  tests/migration: Add case for periodic ramblock dirty sync

 accel/tcg/icount-common.c|  1 -
 {system => migration}/cpu-throttle.c | 72 +++-
 {include/sysemu => migration}/cpu-throttle.h | 14 
 migration/meson.build|  1 +
 migration/migration.c| 11 ++-
 migration/migration.h|  1 +
 migration/ram.c  | 20 --
 migration/trace-events   |  4 ++
 system/cpu-timers.c  |  3 -
 system/meson.build   |  1 -
 system/trace-events  |  3 -
 tests/qtest/migration-test.c | 32 +
 12 files changed, 144 insertions(+), 19 deletions(-)
 rename {system => migration}/cpu-throttle.c (65%)
 rename {include/sysemu => migration}/cpu-throttle.h (87%)

-- 
2.27.0




[PATCH v3 4/4] tests/migration: Add case for periodic ramblock dirty sync

2024-10-16 Thread yong . huang
From: Hyman Huang 

Signed-off-by: Hyman Huang 
---
 tests/qtest/migration-test.c | 32 
 1 file changed, 32 insertions(+)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 95e45b5029..e6a2803e71 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -2791,6 +2791,8 @@ static void test_migrate_auto_converge(void)
  * so we need to decrease a bandwidth.
  */
 const int64_t init_pct = 5, inc_pct = 25, max_pct = 95;
+uint64_t prev_dirty_sync_cnt, dirty_sync_cnt;
+int max_try_count, hit = 0;
 
 if (test_migrate_start(&from, &to, uri, &args)) {
 return;
@@ -2827,6 +2829,36 @@ static void test_migrate_auto_converge(void)
 } while (true);
 /* The first percentage of throttling should be at least init_pct */
 g_assert_cmpint(percentage, >=, init_pct);
+
+/*
+ * End the loop when the dirty sync count greater than 1.
+ */
+while ((dirty_sync_cnt = get_migration_pass(from)) < 2) {
+usleep(1000 * 1000);
+}
+
+prev_dirty_sync_cnt = dirty_sync_cnt;
+
+/*
+ * The RAMBlock dirty sync count must changes in 5 seconds, here we set
+ * the timeout to 10 seconds to ensure it changes.
+ *
+ * Note that migrate_ensure_non_converge set the max-bandwidth to 3MB/s,
+ * while the qtest mem is >= 100MB, one iteration takes at least 33s 
(100/3)
+ * to complete; this ensures that the RAMBlock dirty sync occurs.
+ */
+max_try_count = 10;
+while (--max_try_count) {
+dirty_sync_cnt = get_migration_pass(from);
+if (dirty_sync_cnt != prev_dirty_sync_cnt) {
+hit = 1;
+break;
+}
+prev_dirty_sync_cnt = dirty_sync_cnt;
+sleep(1);
+}
+g_assert_cmpint(hit, ==, 1);
+
 /* Now, when we tested that throttling works, let it converge */
 migrate_ensure_converge(from);
 
-- 
2.27.0




[PATCH v3 2/4] migration: Remove "rs" parameter in migration_bitmap_sync_precopy

2024-10-16 Thread yong . huang
From: Hyman Huang 

The global static variable ram_state in fact is referred to by the
"rs" parameter in migration_bitmap_sync_precopy. For ease of calling
by the callees, use the global variable directly in
migration_bitmap_sync_precopy and remove "rs" parameter.

The migration_bitmap_sync_precopy will be exported in the next commit.

Signed-off-by: Hyman Huang 
---
 migration/ram.c | 11 ++-
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/migration/ram.c b/migration/ram.c
index 54d352b152..9b5b350405 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -1088,9 +1088,10 @@ static void migration_bitmap_sync(RAMState *rs, bool 
last_stage)
 }
 }
 
-static void migration_bitmap_sync_precopy(RAMState *rs, bool last_stage)
+static void migration_bitmap_sync_precopy(bool last_stage)
 {
 Error *local_err = NULL;
+assert(ram_state);
 
 /*
  * The current notifier usage is just an optimization to migration, so we
@@ -1101,7 +1102,7 @@ static void migration_bitmap_sync_precopy(RAMState *rs, 
bool last_stage)
 local_err = NULL;
 }
 
-migration_bitmap_sync(rs, last_stage);
+migration_bitmap_sync(ram_state, last_stage);
 
 if (precopy_notify(PRECOPY_NOTIFY_AFTER_BITMAP_SYNC, &local_err)) {
 error_report_err(local_err);
@@ -2782,7 +2783,7 @@ static bool ram_init_bitmaps(RAMState *rs, Error **errp)
 if (!ret) {
 goto out_unlock;
 }
-migration_bitmap_sync_precopy(rs, false);
+migration_bitmap_sync_precopy(false);
 }
 }
 out_unlock:
@@ -3248,7 +3249,7 @@ static int ram_save_complete(QEMUFile *f, void *opaque)
 
 WITH_RCU_READ_LOCK_GUARD() {
 if (!migration_in_postcopy()) {
-migration_bitmap_sync_precopy(rs, true);
+migration_bitmap_sync_precopy(true);
 }
 
 ret = rdma_registration_start(f, RAM_CONTROL_FINISH);
@@ -3330,7 +3331,7 @@ static void ram_state_pending_exact(void *opaque, 
uint64_t *must_precopy,
 if (!migration_in_postcopy()) {
 bql_lock();
 WITH_RCU_READ_LOCK_GUARD() {
-migration_bitmap_sync_precopy(rs, false);
+migration_bitmap_sync_precopy(false);
 }
 bql_unlock();
 }
-- 
2.27.0




[PATCH v3 1/4] migration: Move cpu-throttole.c from system to migration

2024-10-16 Thread yong . huang
From: Hyman Huang 

Move cpu-throttle.c from system to migration since it's
only used for migration; this makes us avoid exporting the
util functions and variables in misc.h but export them in
migration.h when implementing the background ramblock dirty
sync feature in the upcoming commits.

Additionally, make the two modifications below:

1. Delay the timer registering of CPU throttle until
   migration starts since it is only used in migration.

2. Stop CPU throttle if auto converge capability is
   enabled since it only happens with auto converge.

3. Remove the unused header file reference in
   accel/tcg/icount-common.c.

Signed-off-by: Hyman Huang 
---
 accel/tcg/icount-common.c|  1 -
 {system => migration}/cpu-throttle.c |  2 +-
 {include/sysemu => migration}/cpu-throttle.h |  0
 migration/meson.build|  1 +
 migration/migration.c| 11 +--
 migration/ram.c  |  2 +-
 migration/trace-events   |  3 +++
 system/cpu-timers.c  |  3 ---
 system/meson.build   |  1 -
 system/trace-events  |  3 ---
 10 files changed, 15 insertions(+), 12 deletions(-)
 rename {system => migration}/cpu-throttle.c (99%)
 rename {include/sysemu => migration}/cpu-throttle.h (100%)

diff --git a/accel/tcg/icount-common.c b/accel/tcg/icount-common.c
index 8d3d3a7e9d..30bf8500dc 100644
--- a/accel/tcg/icount-common.c
+++ b/accel/tcg/icount-common.c
@@ -36,7 +36,6 @@
 #include "sysemu/runstate.h"
 #include "hw/core/cpu.h"
 #include "sysemu/cpu-timers.h"
-#include "sysemu/cpu-throttle.h"
 #include "sysemu/cpu-timers-internal.h"
 
 /*
diff --git a/system/cpu-throttle.c b/migration/cpu-throttle.c
similarity index 99%
rename from system/cpu-throttle.c
rename to migration/cpu-throttle.c
index 7632dc6143..fa47ee2e21 100644
--- a/system/cpu-throttle.c
+++ b/migration/cpu-throttle.c
@@ -27,7 +27,7 @@
 #include "hw/core/cpu.h"
 #include "qemu/main-loop.h"
 #include "sysemu/cpus.h"
-#include "sysemu/cpu-throttle.h"
+#include "cpu-throttle.h"
 #include "trace.h"
 
 /* vcpu throttling controls */
diff --git a/include/sysemu/cpu-throttle.h b/migration/cpu-throttle.h
similarity index 100%
rename from include/sysemu/cpu-throttle.h
rename to migration/cpu-throttle.h
diff --git a/migration/meson.build b/migration/meson.build
index 66d3de86f0..d53cf3417a 100644
--- a/migration/meson.build
+++ b/migration/meson.build
@@ -13,6 +13,7 @@ system_ss.add(files(
   'block-dirty-bitmap.c',
   'channel.c',
   'channel-block.c',
+  'cpu-throttle.c',
   'dirtyrate.c',
   'exec.c',
   'fd.c',
diff --git a/migration/migration.c b/migration/migration.c
index 021faee2f3..7e71184257 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -24,7 +24,7 @@
 #include "socket.h"
 #include "sysemu/runstate.h"
 #include "sysemu/sysemu.h"
-#include "sysemu/cpu-throttle.h"
+#include "cpu-throttle.h"
 #include "rdma.h"
 #include "ram.h"
 #include "migration/global_state.h"
@@ -3289,7 +3289,9 @@ static MigIterateState 
migration_iteration_run(MigrationState *s)
 static void migration_iteration_finish(MigrationState *s)
 {
 /* If we enabled cpu throttling for auto-converge, turn it off. */
-cpu_throttle_stop();
+if (migrate_auto_converge()) {
+cpu_throttle_stop();
+}
 
 bql_lock();
 switch (s->state) {
@@ -3508,6 +3510,11 @@ static void *migration_thread(void *opaque)
 qemu_savevm_send_colo_enable(s->to_dst_file);
 }
 
+if (migrate_auto_converge()) {
+/* Start cpu throttle timers */
+cpu_throttle_init();
+}
+
 bql_lock();
 ret = qemu_savevm_state_setup(s->to_dst_file, &local_err);
 bql_unlock();
diff --git a/migration/ram.c b/migration/ram.c
index 326ce7eb79..54d352b152 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -52,7 +52,7 @@
 #include "exec/target_page.h"
 #include "qemu/rcu_queue.h"
 #include "migration/colo.h"
-#include "sysemu/cpu-throttle.h"
+#include "cpu-throttle.h"
 #include "savevm.h"
 #include "qemu/iov.h"
 #include "multifd.h"
diff --git a/migration/trace-events b/migration/trace-events
index c65902f042..9a19599804 100644
--- a/migration/trace-events
+++ b/migration/trace-events
@@ -378,3 +378,6 @@ migration_block_progression(unsigned percent) "Completed 
%u%%"
 # page_cache.c
 migration_pagecache_init(int64_t max_num_items) "Setting cache buckets to %" 
PRId64
 migration_pagecache_insert(void) "Error allocating page"
+
+# cpu-throttle.c
+cpu_throttle_set(int new_throttle_pct)  "set guest CPU throttled by %d%%"
diff --git a/system/cpu-timers.c b/system/cpu-timers.c
index 0b31c9a1b6..856e502e34 100644
--- a/system/cpu-timers.c
+++ b/system/cpu-timers.c
@@ -35,7 +35,6 @@
 #include "sysemu/runstate.h"
 #include "hw/core/cpu.h"
 #include "sysemu/cpu-timers.h"
-#include "sysemu/cpu-throttle.h"
 #include "sysemu/cpu-timers-internal.h"
 
 /* clock and ticks */
@@ -272,6 +271,4 @@ 

Re: [PATCH v4 6/8] chardev/char-mux: implement backend chardev multiplexing

2024-10-16 Thread Marc-André Lureau
Hi

On Wed, Oct 16, 2024 at 2:29 PM Roman Penyaev  wrote:

> This patch implements multiplexing capability of several backend
> devices, which opens up an opportunity to use a single frontend
> device on the guest, which can be manipulated from several
> backend devices.
>
> The idea of the change is trivial: keep list of backend devices
> (up to 4), init them on demand and forward data buffer back and
> forth.
>
> Patch implements another multiplexer type `mux-be`. The following
> is QEMU command line example:
>
>-chardev mux-be,id=mux0 \
>-chardev
> socket,path=/tmp/sock,server=on,wait=off,id=sock0,mux-be-id=mux0 \
>-chardev vc,id=vc0,mux-be-id=mux0 \
>

I am not sure about adding "mux-be-id" to all chardev. It avoids the issue
of expressing a list of ids in mux-be though (while it may have potential
loop!)

Markus, do you have a suggestion to take an array of chardev ids as a CLI
option? It looks like we could require QAPIfy -chardev from Kevin here..

thanks

   -device virtconsole,chardev=mux0 \
>
   -vnc 0.0.0.0:0
>
> Which creates 2 backend devices: text virtual console (`vc0`) and a
> socket (`sock0`) connected to the single virtio hvc console with the
> backend multiplexer (`mux0`) help. `vc0` renders text to an image,
> which can be shared over the VNC protocol.  `sock0` is a socket
> backend which provides biderectional communication to the virtio hvc
> console.
>
> Signed-off-by: Roman Penyaev 
> Cc: "Marc-André Lureau" 
> Cc: qemu-devel@nongnu.org
> ---
>  chardev/char-fe.c  |   9 ++
>  chardev/char-mux-be.c  | 290 +
>  chardev/char.c |  56 +--
>  chardev/chardev-internal.h |  34 -
>  chardev/meson.build|   1 +
>  include/chardev/char.h |   1 +
>  qapi/char.json |  25 
>  7 files changed, 403 insertions(+), 13 deletions(-)
>  create mode 100644 chardev/char-mux-be.c
>
> diff --git a/chardev/char-fe.c b/chardev/char-fe.c
> index a2b5bff39fd9..2f794674563b 100644
> --- a/chardev/char-fe.c
> +++ b/chardev/char-fe.c
> @@ -200,6 +200,12 @@ bool qemu_chr_fe_init(CharBackend *b, Chardev *s,
> Error **errp)
>  if (!mux_fe_chr_attach_frontend(d, b, &tag, errp)) {
>  return false;
>  }
> +} else if (CHARDEV_IS_MUX_BE(s)) {
> +MuxBeChardev *d = MUX_BE_CHARDEV(s);
> +
> +if (!mux_be_chr_attach_frontend(d, b, errp)) {
> +return false;
> +}
>  } else if (s->be) {
>  error_setg(errp, "chardev '%s' is already in use", s->label);
>  return false;
> @@ -226,6 +232,9 @@ void qemu_chr_fe_deinit(CharBackend *b, bool del)
>  if (CHARDEV_IS_MUX_FE(b->chr)) {
>  MuxFeChardev *d = MUX_FE_CHARDEV(b->chr);
>  mux_fe_chr_detach_frontend(d, b->tag);
> +} else if (CHARDEV_IS_MUX_BE(b->chr)) {
> +MuxBeChardev *d = MUX_BE_CHARDEV(b->chr);
> +mux_be_chr_detach_frontend(d);
>  }
>  if (del) {
>  Object *obj = OBJECT(b->chr);
> diff --git a/chardev/char-mux-be.c b/chardev/char-mux-be.c
> new file mode 100644
> index ..64a4f2c00034
> --- /dev/null
> +++ b/chardev/char-mux-be.c
> @@ -0,0 +1,290 @@
> +/*
> + * QEMU Character Backend Multiplexer
> + *
> + * Author: Roman Penyaev 
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining
> a copy
> + * of this software and associated documentation files (the "Software"),
> to deal
> + * in the Software without restriction, including without limitation the
> rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or
> sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be
> included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
> OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> IN
> + * THE SOFTWARE.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "qemu/module.h"
> +#include "qemu/option.h"
> +#include "qemu/cutils.h"
> +#include "chardev/char.h"
> +#include "sysemu/block-backend.h"
> +#include "qapi/qapi-commands-control.h"
> +#include "qapi/clone-visitor.h"
> +#include "qapi/qapi-builtin-visit.h"
> +#include "chardev-internal.h"
> +
> +/*
> + * MUX-BE driver for multiplexing 1 frontend device with N backend devices
> + */
> +
> +/*
> + * Write to all backend

Re: [PULL v3 00/18] Rust initial PoC + meson changes for 2024-10-07

2024-10-16 Thread Marc-André Lureau
Hi

On Fri, Oct 11, 2024 at 9:19 PM Paolo Bonzini  wrote:

> The following changes since commit
> b5ab62b3c0050612c7f9b0b4baeb44ebab42775a:
>
>   Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into
> staging (2024-10-04 19:28:37 +0100)
>
> are available in the Git repository at:
>
>   https://gitlab.com/bonzini/qemu.git tags/for-upstream
>
> for you to fetch changes up to 381d2c36e1242f849a55f4622e50b9a69cb92842:
>
>   docs: use consistent markup for footnotes (2024-10-11 13:08:32 +0200)
>
> v2->v3: new patches
> - scripts/archive-source: find directory name for subprojects
> - docs: fix invalid footnote syntax
> - docs: avoid footnotes consisting of just URLs
> - docs: use consistent markup for footnotes
>
> 
> * first commit for Rust support
> * add CI job using Fedora + Rust nightly
> * fix detection of ATOMIC128 on x86_64
> * fix compilation with Sphinx 8.1.0
>


fwiw, after a rustc update, I got this error:
error[E0514]: found crate `bilge` compiled by an incompatible version of
rustc
... tons of other errors

It is fixed after a ninja clean.

Apparently there is an "old" meson issue:
https://github.com/mesonbuild/meson/issues/10706



> 
> Manos Pitsidianakis (6):
>   build-sys: Add rust feature option
>   rust: add bindgen step as a meson dependency
>   .gitattributes: add Rust diff and merge attributes
>   meson.build: add HAVE_GLIB_WITH_ALIGNED_ALLOC flag
>   rust: add crate to expose bindings and interfaces
>   rust: add utility procedural macro crate
>
> Paolo Bonzini (11):
>   Require meson version 1.5.0
>   configure, meson: detect Rust toolchain
>   scripts/archive-source: find directory name for subprojects
>   rust: add PL011 device model
>   meson: define qemu_isa_flags
>   meson: ensure -mcx16 is passed when detecting ATOMIC128
>   dockerfiles: add a Dockerfile using a nightly Rust toolchain
>   gitlab-ci: add Rust-enabled CI job
>   docs: fix invalid footnote syntax
>   docs: avoid footnotes consisting of just URLs
>   docs: use consistent markup for footnotes
>
> Pierrick Bouvier (1):
>   meson: fix machine option for x86_version
>
>  MAINTAINERS|  21 +
>  docs/devel/atomics.rst |   6 +-
>  docs/devel/build-system.rst|   6 +-
>  docs/devel/loads-stores.rst|   2 +-
>  docs/devel/maintainers.rst |   4 +-
>  docs/devel/migration/mapped-ram.rst|   4 +-
>  docs/devel/testing/acpi-bits.rst   |  26 +-
>  docs/specs/fw_cfg.rst  |   4 +-
>  docs/specs/rapl-msr.rst|  25 +-
>  configure  | 170 +-
>  meson.build| 158 +-
>  rust/wrapper.h |  47 ++
>  .gitattributes |   3 +
>  .gitlab-ci.d/buildtest.yml |  13 +
>  .gitlab-ci.d/containers.yml|   6 +
>  Kconfig|   1 +
>  Kconfig.host   |   3 +
>  hw/arm/Kconfig |  30 +-
>  meson_options.txt  |   3 +
>  python/scripts/vendor.py   |   4 +-
>  python/wheels/meson-1.2.3-py3-none-any.whl | Bin 964928 -> 0 bytes
>  python/wheels/meson-1.5.0-py3-none-any.whl | Bin 0 -> 959846 bytes
>  pythondeps.toml|   2 +-
>  rust/.gitignore|   3 +
>  rust/Kconfig   |   1 +
>  rust/hw/Kconfig|   2 +
>  rust/hw/char/Kconfig   |   3 +
>  rust/hw/char/meson.build   |   1 +
>  rust/hw/char/pl011/.gitignore  |   2 +
>  rust/hw/char/pl011/Cargo.lock  | 134 +
>  rust/hw/char/pl011/Cargo.toml  |  26 +
>  rust/hw/char/pl011/README.md   |  31 ++
>  rust/hw/char/pl011/meson.build |  26 +
>  rust/hw/char/pl011/src/device.rs   | 599
> +
>  rust/hw/char/pl011/src/device_class.rs |  70 +++
>  rust/hw/char/pl011/src/lib.rs  | 586
> 
>  rust/hw/char/pl011/src/memory_ops.rs   |  59 ++
>  rust/hw/meson.build|   1 +
>  rust/meson.build   |   4 +
>  rust/qemu-api-macros/Cargo.lock|  47 ++
>  rust/qemu-api-macros/Cargo.toml|  25 +
>  rust/qemu-api-macros/README.md 

Re: [PATCH] linux-headers: loongarch: add kvm_para.h and unistd_64.h

2024-10-16 Thread gaosong

在 2024/10/16 下午4:13, maobibo 写道:

ping.

@Song

Could you give some comments since it is LoongArch specific?

Regards
Bibo Mao

On 2024/9/29 下午3:22, Bibo Mao wrote:

KVM LBT supports on LoongArch requires the linux-header kvm_para.h,
also unistd_64.h is required by unistd.h on LoongArch since 6.11

Signed-off-by: Bibo Mao 
---
  scripts/update-linux-headers.sh | 4 
  1 file changed, 4 insertions(+)


Acked-by: Song Gao 

Could you update the linux-headers togather?

the series[1]  need update kvm.h.

[1]: https://patchew.org/QEMU/20240929070405.235200-1-maob...@loongson.cn/

Thanks.
Song Gao
diff --git a/scripts/update-linux-headers.sh 
b/scripts/update-linux-headers.sh

index c34ac6454e..3c411f0318 100755
--- a/scripts/update-linux-headers.sh
+++ b/scripts/update-linux-headers.sh
@@ -186,6 +186,10 @@ EOF
  if [ $arch = riscv ]; then
  cp "$hdrdir/include/asm/ptrace.h" 
"$output/linux-headers/asm-riscv/"

  fi
+    if [ $arch = loongarch ]; then
+    cp "$hdrdir/include/asm/kvm_para.h" 
"$output/linux-headers/asm-loongarch/"
+    cp "$hdrdir/include/asm/unistd_64.h" 
"$output/linux-headers/asm-loongarch/"

+    fi
  done
  arch=

base-commit: 3b14a767eaca3df5534a162851f04787b363670e






Re: [PATCH v9 08/12] hw/riscv/riscv-iommu: add Address Translation Cache (IOATC)

2024-10-16 Thread Jason Chien

Hi Daniel,

On 2024/10/4 下午 11:57, Daniel Henrique Barboza wrote:

From: Tomasz Jeznach 

The RISC-V IOMMU spec predicts that the IOMMU can use translation caches
to hold entries from the DDT. This includes implementation for all cache
commands that are marked as 'not implemented'.

There are some artifacts included in the cache that predicts s-stage and
g-stage elements, although we don't support it yet. We'll introduce them
next.

Signed-off-by: Tomasz Jeznach 
Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Frank Chang 
Acked-by: Alistair Francis 
---
  hw/riscv/riscv-iommu.c | 204 -
  hw/riscv/riscv-iommu.h |   3 +
  2 files changed, 203 insertions(+), 4 deletions(-)

diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c
index f2679f3740..cef54b56ba 100644
--- a/hw/riscv/riscv-iommu.c
+++ b/hw/riscv/riscv-iommu.c
@@ -64,6 +64,15 @@ struct RISCVIOMMUContext {
  uint64_t msiptp;/* MSI redirection page table pointer */
  };
  
+/* Address translation cache entry */

+struct RISCVIOMMUEntry {
+uint64_t iova:44;   /* IOVA Page Number */
+uint64_t pscid:20;  /* Process Soft-Context identifier */
+uint64_t phys:44;   /* Physical Page Number */
+uint64_t gscid:16;  /* Guest Soft-Context identifier */
+uint64_t perm:2;/* IOMMU_RW flags */
+};
+
  /* IOMMU index for transactions without process_id specified. */
  #define RISCV_IOMMU_NOPROCID 0
  
@@ -1154,13 +1163,132 @@ static AddressSpace *riscv_iommu_space(RISCVIOMMUState *s, uint32_t devid)

  return &as->iova_as;
  }
  
+/* Translation Object cache support */

+static gboolean riscv_iommu_iot_equal(gconstpointer v1, gconstpointer v2)
+{
+RISCVIOMMUEntry *t1 = (RISCVIOMMUEntry *) v1;
+RISCVIOMMUEntry *t2 = (RISCVIOMMUEntry *) v2;
+return t1->gscid == t2->gscid && t1->pscid == t2->pscid &&
+   t1->iova == t2->iova;
+}
+
+static guint riscv_iommu_iot_hash(gconstpointer v)
+{
+RISCVIOMMUEntry *t = (RISCVIOMMUEntry *) v;
+return (guint)t->iova;
+}
+
+/* GV: 1 PSCV: 1 AV: 1 */
+static void riscv_iommu_iot_inval_pscid_iova(gpointer key, gpointer value,
+ gpointer data)
+{
+RISCVIOMMUEntry *iot = (RISCVIOMMUEntry *) value;
+RISCVIOMMUEntry *arg = (RISCVIOMMUEntry *) data;
+if (iot->gscid == arg->gscid &&
+iot->pscid == arg->pscid &&
+iot->iova == arg->iova) {
+iot->perm = IOMMU_NONE;
+}
+}
+
+/* GV: 1 PSCV: 1 AV: 0 */
+static void riscv_iommu_iot_inval_pscid(gpointer key, gpointer value,
+gpointer data)
+{
+RISCVIOMMUEntry *iot = (RISCVIOMMUEntry *) value;
+RISCVIOMMUEntry *arg = (RISCVIOMMUEntry *) data;
+if (iot->gscid == arg->gscid &&
+iot->pscid == arg->pscid) {
+iot->perm = IOMMU_NONE;
+}
+}
+
+/* GV: 1 GVMA: 1 */
+static void riscv_iommu_iot_inval_gscid_gpa(gpointer key, gpointer value,
+gpointer data)
+{
+RISCVIOMMUEntry *iot = (RISCVIOMMUEntry *) value;
+RISCVIOMMUEntry *arg = (RISCVIOMMUEntry *) data;
+if (iot->gscid == arg->gscid) {
+/* simplified cache, no GPA matching */
+iot->perm = IOMMU_NONE;
+}
+}
+
+/* GV: 1 GVMA: 0 */
+static void riscv_iommu_iot_inval_gscid(gpointer key, gpointer value,
+gpointer data)
+{
+RISCVIOMMUEntry *iot = (RISCVIOMMUEntry *) value;
+RISCVIOMMUEntry *arg = (RISCVIOMMUEntry *) data;
+if (iot->gscid == arg->gscid) {
+iot->perm = IOMMU_NONE;
+}
+}
+
+/* GV: 0 */
+static void riscv_iommu_iot_inval_all(gpointer key, gpointer value,
+  gpointer data)
+{
+RISCVIOMMUEntry *iot = (RISCVIOMMUEntry *) value;
+iot->perm = IOMMU_NONE;
+}
+
+/* caller should keep ref-count for iot_cache object */
+static RISCVIOMMUEntry *riscv_iommu_iot_lookup(RISCVIOMMUContext *ctx,
+GHashTable *iot_cache, hwaddr iova)
+{
+RISCVIOMMUEntry key = {
+.gscid = get_field(ctx->gatp, RISCV_IOMMU_DC_IOHGATP_GSCID),
+.pscid = get_field(ctx->ta, RISCV_IOMMU_DC_TA_PSCID),
+.iova  = PPN_DOWN(iova),
+};
+return g_hash_table_lookup(iot_cache, &key);
+}
+
+/* caller should keep ref-count for iot_cache object */
+static void riscv_iommu_iot_update(RISCVIOMMUState *s,
+GHashTable *iot_cache, RISCVIOMMUEntry *iot)
+{
+if (!s->iot_limit) {
+return;
+}
+
+if (g_hash_table_size(s->iot_cache) >= s->iot_limit) {
+iot_cache = g_hash_table_new_full(riscv_iommu_iot_hash,
+  riscv_iommu_iot_equal,
+  g_free, NULL);
+g_hash_table_unref(qatomic_xchg(&s->iot_cache, iot_cache));
+}
+g_hash_table_add(iot_cache, iot);
+}
+
+static void riscv_iommu_iot_inval(RISCVIOMMUState *s, GHFunc func,
+uint32_t gscid, uint32_t pscid,

[PULL 0/5] loongarch-to-apply queue

2024-10-16 Thread Song Gao
The following changes since commit f774a677507966222624a9b2859f06ede7608100:

  Merge tag 'pull-target-arm-20241015-1' of 
https://git.linaro.org/people/pmaydell/qemu-arm into staging (2024-10-15 
15:18:22 +0100)

are available in the Git repository at:

  https://gitlab.com/gaosong/qemu.git tags/pull-loongarch-20241016

for you to fetch changes up to e376c2d87cbbad3483adcd5e827bdd144edb7d2c:

  hw/loongarch/fw_cfg: Build in common_ss[] (2024-10-16 16:06:07 +0800)


pull-loongarch-20241016


Bibo Mao (3):
  acpi: ged: Add macro for acpi sleep control register
  hw/loongarch/virt: Add FDT table support with acpi ged pm register
  target/loongarch: Avoid bits shift exceeding width of bool type

Philippe Mathieu-Daudé (2):
  hw/loongarch/virt: Remove unnecessary 'cpu.h' inclusion
  hw/loongarch/fw_cfg: Build in common_ss[]

 hw/acpi/generic_event_device.c |  6 +++---
 hw/loongarch/meson.build   |  2 +-
 hw/loongarch/virt.c| 39 ++
 include/hw/acpi/generic_event_device.h |  7 --
 include/hw/loongarch/virt.h|  1 -
 target/loongarch/arch_dump.c   |  6 +-
 6 files changed, 49 insertions(+), 12 deletions(-)




[PULL 4/5] hw/loongarch/virt: Remove unnecessary 'cpu.h' inclusion

2024-10-16 Thread Song Gao
From: Philippe Mathieu-Daudé 

Signed-off-by: Philippe Mathieu-Daudé 
Reviewed-by: Song Gao 
Reviewed-by: Thomas Huth 
Message-Id: <20240927213254.17552-2-phi...@linaro.org>
Signed-off-by: Song Gao 
---
 include/hw/loongarch/virt.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
index c373e48f27..9ba47793ef 100644
--- a/include/hw/loongarch/virt.h
+++ b/include/hw/loongarch/virt.h
@@ -8,7 +8,6 @@
 #ifndef HW_LOONGARCH_H
 #define HW_LOONGARCH_H
 
-#include "target/loongarch/cpu.h"
 #include "hw/boards.h"
 #include "qemu/queue.h"
 #include "hw/block/flash.h"
-- 
2.34.1




[PULL 5/5] hw/loongarch/fw_cfg: Build in common_ss[]

2024-10-16 Thread Song Gao
From: Philippe Mathieu-Daudé 

Nothing in LoongArch fw_cfg.c requires target specific definitions.

Signed-off-by: Philippe Mathieu-Daudé 
Reviewed-by: Song Gao 
Reviewed-by: Thomas Huth 
Message-Id: <20240927213254.17552-3-phi...@linaro.org>
Signed-off-by: Song Gao 
---
 hw/loongarch/meson.build | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/loongarch/meson.build b/hw/loongarch/meson.build
index bce7ebac97..005f017e21 100644
--- a/hw/loongarch/meson.build
+++ b/hw/loongarch/meson.build
@@ -1,8 +1,8 @@
 loongarch_ss = ss.source_set()
 loongarch_ss.add(files(
-'fw_cfg.c',
 'boot.c',
 ))
+common_ss.add(when: 'CONFIG_LOONGARCH_VIRT', if_true: files('fw_cfg.c'))
 loongarch_ss.add(when: 'CONFIG_LOONGARCH_VIRT', if_true: files('virt.c'))
 loongarch_ss.add(when: 'CONFIG_ACPI', if_true: files('acpi-build.c'))
 
-- 
2.34.1




[PULL 2/5] hw/loongarch/virt: Add FDT table support with acpi ged pm register

2024-10-16 Thread Song Gao
From: Bibo Mao 

ACPI ged is used for power management on LoongArch virt platform, in
general it is parsed from acpi table. However if system boot directly from
elf kernel, no UEFI bios is provided and acpi table cannot be used also.

Here acpi ged pm register is exposed with FDT table, it is compatbile
with syscon method in FDT table, only that acpi ged pm register is accessed
with 8-bit mode, rather with 32-bit mode.

Signed-off-by: Bibo Mao 
Reviewed-by: Song Gao 
Tested-by: Song Gao 
Message-Id: <20240918014206.2165821-3-maob...@loongson.cn>
Signed-off-by: Song Gao 
---
 hw/loongarch/virt.c | 39 +++
 1 file changed, 39 insertions(+)

diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index ddd886f69b..9a635d1d3d 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -280,6 +280,44 @@ static void fdt_add_rtc_node(LoongArchVirtMachineState 
*lvms,
 g_free(nodename);
 }
 
+static void fdt_add_ged_reset(LoongArchVirtMachineState *lvms)
+{
+char *name;
+uint32_t ged_handle;
+MachineState *ms = MACHINE(lvms);
+hwaddr base = VIRT_GED_REG_ADDR;
+hwaddr size = ACPI_GED_REG_COUNT;
+
+ged_handle = qemu_fdt_alloc_phandle(ms->fdt);
+name = g_strdup_printf("/ged@%" PRIx64, base);
+qemu_fdt_add_subnode(ms->fdt, name);
+qemu_fdt_setprop_string(ms->fdt, name, "compatible", "syscon");
+qemu_fdt_setprop_cells(ms->fdt, name, "reg", 0x0, base, 0x0, size);
+/* 8 bit registers */
+qemu_fdt_setprop_cell(ms->fdt, name, "reg-shift", 0);
+qemu_fdt_setprop_cell(ms->fdt, name, "reg-io-width", 1);
+qemu_fdt_setprop_cell(ms->fdt, name, "phandle", ged_handle);
+ged_handle = qemu_fdt_get_phandle(ms->fdt, name);
+g_free(name);
+
+name = g_strdup_printf("/reboot");
+qemu_fdt_add_subnode(ms->fdt, name);
+qemu_fdt_setprop_string(ms->fdt, name, "compatible", "syscon-reboot");
+qemu_fdt_setprop_cell(ms->fdt, name, "regmap", ged_handle);
+qemu_fdt_setprop_cell(ms->fdt, name, "offset", ACPI_GED_REG_RESET);
+qemu_fdt_setprop_cell(ms->fdt, name, "value", ACPI_GED_RESET_VALUE);
+g_free(name);
+
+name = g_strdup_printf("/poweroff");
+qemu_fdt_add_subnode(ms->fdt, name);
+qemu_fdt_setprop_string(ms->fdt, name, "compatible", "syscon-poweroff");
+qemu_fdt_setprop_cell(ms->fdt, name, "regmap", ged_handle);
+qemu_fdt_setprop_cell(ms->fdt, name, "offset", ACPI_GED_REG_SLEEP_CTL);
+qemu_fdt_setprop_cell(ms->fdt, name, "value", ACPI_GED_SLP_EN |
+  (ACPI_GED_SLP_TYP_S5 << ACPI_GED_SLP_TYP_POS));
+g_free(name);
+}
+
 static void fdt_add_uart_node(LoongArchVirtMachineState *lvms,
   uint32_t *pch_pic_phandle, hwaddr base,
   int irq, bool chosen)
@@ -737,6 +775,7 @@ static void virt_devices_init(DeviceState *pch_pic,
  qdev_get_gpio_in(pch_pic,
  VIRT_RTC_IRQ - VIRT_GSI_BASE));
 fdt_add_rtc_node(lvms, pch_pic_phandle);
+fdt_add_ged_reset(lvms);
 
 /* acpi ged */
 lvms->acpi_ged = create_acpi_ged(pch_pic, lvms);
-- 
2.34.1




[PULL 1/5] acpi: ged: Add macro for acpi sleep control register

2024-10-16 Thread Song Gao
From: Bibo Mao 

Macro definition is added for acpi sleep control register, ged emulation
driver can use the macro , also it can be used in FDT table if ged is
exposed with FDT table.

Signed-off-by: Bibo Mao 
Reviewed-by: Igor Mammedov 
Message-Id: <20240918014206.2165821-2-maob...@loongson.cn>
Signed-off-by: Song Gao 
---
 hw/acpi/generic_event_device.c | 6 +++---
 include/hw/acpi/generic_event_device.h | 7 +--
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
index 15b4c3ebbf..d00f5a6c1c 100644
--- a/hw/acpi/generic_event_device.c
+++ b/hw/acpi/generic_event_device.c
@@ -201,9 +201,9 @@ static void ged_regs_write(void *opaque, hwaddr addr, 
uint64_t data,
 
 switch (addr) {
 case ACPI_GED_REG_SLEEP_CTL:
-slp_typ = (data >> 2) & 0x07;
-slp_en  = (data >> 5) & 0x01;
-if (slp_en && slp_typ == 5) {
+slp_typ = (data >> ACPI_GED_SLP_TYP_POS) & ACPI_GED_SLP_TYP_MASK;
+slp_en  = !!(data & ACPI_GED_SLP_EN);
+if (slp_en && slp_typ == ACPI_GED_SLP_TYP_S5) {
 qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
 }
 return;
diff --git a/include/hw/acpi/generic_event_device.h 
b/include/hw/acpi/generic_event_device.h
index 40af3550b5..d2dac87b4a 100644
--- a/include/hw/acpi/generic_event_device.h
+++ b/include/hw/acpi/generic_event_device.h
@@ -81,8 +81,11 @@ OBJECT_DECLARE_SIMPLE_TYPE(AcpiGedState, ACPI_GED)
 /* ACPI_GED_REG_RESET value for reset*/
 #define ACPI_GED_RESET_VALUE   0x42
 
-/* ACPI_GED_REG_SLEEP_CTL.SLP_TYP value for S5 (aka poweroff) */
-#define ACPI_GED_SLP_TYP_S50x05
+/* [ACPI 5.0 Chapter 4.8.3.7] Sleep Control and Status Register */
+#define ACPI_GED_SLP_TYP_POS   0x2   /* SLP_TYPx Bit Offset */
+#define ACPI_GED_SLP_TYP_MASK  0x07  /* SLP_TYPx 3-bit mask */
+#define ACPI_GED_SLP_TYP_S50x05  /* System _S5 State (Soft Off) */
+#define ACPI_GED_SLP_EN0x20  /* SLP_EN write-only bit */
 
 #define GED_DEVICE  "GED"
 #define AML_GED_EVT_REG "EREG"
-- 
2.34.1




[PULL 3/5] target/loongarch: Avoid bits shift exceeding width of bool type

2024-10-16 Thread Song Gao
From: Bibo Mao 

Variable env->cf[i] is defined as bool type, it is treated as int type
with shift operation. However the max possible width is 56 for the shift
operation, exceeding the width of int type. And there is existing api
read_fcc() which is converted to u64 type with bitwise shift, it can be
used to dump fp registers into coredump note segment.

Resolves: Coverity CID 1561133
Signed-off-by: Bibo Mao 
Reviewed-by: Richard Henderson 
Message-Id: <20240914064645.2099169-1-maob...@loongson.cn>
Signed-off-by: Song Gao 
---
 target/loongarch/arch_dump.c | 6 +-
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/target/loongarch/arch_dump.c b/target/loongarch/arch_dump.c
index 4986db970e..d9e1120333 100644
--- a/target/loongarch/arch_dump.c
+++ b/target/loongarch/arch_dump.c
@@ -97,11 +97,7 @@ static int 
loongarch_write_elf64_fprpreg(WriteCoreDumpFunction f,
 
 loongarch_note_init(¬e, s, "CORE", 5, NT_PRFPREG, sizeof(note.fpu));
 note.fpu.fcsr = cpu_to_dump64(s, env->fcsr0);
-
-for (i = 0; i < 8; i++) {
-note.fpu.fcc |= env->cf[i] << (8 * i);
-}
-note.fpu.fcc = cpu_to_dump64(s, note.fpu.fcc);
+note.fpu.fcc = cpu_to_dump64(s, read_fcc(env));
 
 for (i = 0; i < 32; ++i) {
 note.fpu.fpr[i] = cpu_to_dump64(s, env->fpr[i].vreg.UD[0]);
-- 
2.34.1




Re: [PATCH v4 6/8] chardev/char-mux: implement backend chardev multiplexing

2024-10-16 Thread Marc-André Lureau
Hi

On Wed, Oct 16, 2024 at 3:13 PM Marc-André Lureau <
marcandre.lur...@gmail.com> wrote:

> Hi
>
> On Wed, Oct 16, 2024 at 2:29 PM Roman Penyaev  wrote:
>
>> This patch implements multiplexing capability of several backend
>> devices, which opens up an opportunity to use a single frontend
>> device on the guest, which can be manipulated from several
>> backend devices.
>>
>> The idea of the change is trivial: keep list of backend devices
>> (up to 4), init them on demand and forward data buffer back and
>> forth.
>>
>> Patch implements another multiplexer type `mux-be`. The following
>> is QEMU command line example:
>>
>>-chardev mux-be,id=mux0 \
>>-chardev
>> socket,path=/tmp/sock,server=on,wait=off,id=sock0,mux-be-id=mux0 \
>>-chardev vc,id=vc0,mux-be-id=mux0 \
>>
>
> I am not sure about adding "mux-be-id" to all chardev. It avoids the issue
> of expressing a list of ids in mux-be though (while it may have potential
> loop!)
>
>
(well, the loop can be expressed with an array list as well, and deepen.. I
don't think we have enough sanity check around that, especially at run
time).


-- 
Marc-André Lureau


Re: [PATCH v4 8/8] qemu-options.hx: describe multiplexing of several backend devices

2024-10-16 Thread Marc-André Lureau
Hi

On Wed, Oct 16, 2024 at 2:28 PM Roman Penyaev  wrote:
>
> This adds a few lines describing `mux-be` multiplexer configuration
> for multiplexing several backend devices with a single frontend
> device.
>
> Signed-off-by: Roman Penyaev 
> Cc: "Marc-André Lureau" 
> Cc: qemu-devel@nongnu.org
> ---
>  qemu-options.hx | 78 -
>  1 file changed, 58 insertions(+), 20 deletions(-)
>
> diff --git a/qemu-options.hx b/qemu-options.hx
> index daae49414740..dd5dfe8596f0 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -3677,37 +3677,37 @@ DEFHEADING(Character device options:)
>
>  DEF("chardev", HAS_ARG, QEMU_OPTION_chardev,
>  "-chardev help\n"
> -"-chardev null,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
> +"-chardev 
> null,id=id[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n"
>  "-chardev 
> socket,id=id[,host=host],port=port[,to=to][,ipv4=on|off][,ipv6=on|off][,nodelay=on|off]\n"
> -" 
> [,server=on|off][,wait=on|off][,telnet=on|off][,websocket=on|off][,reconnect=seconds][,mux=on|off]\n"
> +" 
> [,server=on|off][,wait=on|off][,telnet=on|off][,websocket=on|off][,reconnect=seconds][,mux=on|off][,mux-be-id=id]\n"
>  " 
> [,logfile=PATH][,logappend=on|off][,tls-creds=ID][,tls-authz=ID] (tcp)\n"
>  "-chardev 
> socket,id=id,path=path[,server=on|off][,wait=on|off][,telnet=on|off][,websocket=on|off][,reconnect=seconds]\n"
> -" 
> [,mux=on|off][,logfile=PATH][,logappend=on|off][,abstract=on|off][,tight=on|off]
>  (unix)\n"
> +" 
> [,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off][,abstract=on|off][,tight=on|off]
>  (unix)\n"
>  "-chardev udp,id=id[,host=host],port=port[,localaddr=localaddr]\n"
> -" 
> [,localport=localport][,ipv4=on|off][,ipv6=on|off][,mux=on|off]\n"
> +" 
> [,localport=localport][,ipv4=on|off][,ipv6=on|off][,mux=on|off][,mux-be-id=id]\n"
>  " [,logfile=PATH][,logappend=on|off]\n"
> -"-chardev msmouse,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
> +"-chardev 
> msmouse,id=id[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n"
>  "-chardev 
> vc,id=id[[,width=width][,height=height]][[,cols=cols][,rows=rows]]\n"
> -" [,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
> +" 
> [,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n"
>  "-chardev ringbuf,id=id[,size=size][,logfile=PATH][,logappend=on|off]\n"
> -"-chardev 
> file,id=id,path=path[,input-path=input-file][,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
> -"-chardev 
> pipe,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
> +"-chardev 
> file,id=id,path=path[,input-path=input-file][,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n"
> +"-chardev 
> pipe,id=id,path=path[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n"
>  #ifdef _WIN32
> -"-chardev console,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
> -"-chardev 
> serial,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
> +"-chardev 
> console,id=id[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n"
> +"-chardev 
> serial,id=id,path=path[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n"
>  #else
> -"-chardev 
> pty,id=id[,path=path][,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
> -"-chardev 
> stdio,id=id[,mux=on|off][,signal=on|off][,logfile=PATH][,logappend=on|off]\n"
> +"-chardev 
> pty,id=id[,path=path][,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n"
> +"-chardev 
> stdio,id=id[,mux=on|off][,mux-be-id=id][,signal=on|off][,logfile=PATH][,logappend=on|off]\n"
>  #endif
>  #ifdef CONFIG_BRLAPI
> -"-chardev braille,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
> +"-chardev 
> braille,id=id[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n"
>  #endif
>  #if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \
>  || defined(__NetBSD__) || defined(__OpenBSD__) || 
> defined(__DragonFly__)
> -"-chardev 
> serial,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
> +"-chardev 
> serial,id=id,path=path[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n"
>  #endif
>  #if defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__)
> -"-chardev 
> parallel,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
> +"-chardev 
> parallel,id=id,path=path[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n"
>  #endif
>  #if defined(CONFIG_SPICE)
>  "-chardev 
> spicevmc,id=id,name=name[,debug=debug][,logfile=PATH][,logappend=on|off]\n"
> @@ -3719,8 +3719,8 @@ DEF("chardev", HAS_ARG, QEMU_OPTION_chardev,
>  SRST
>  The general form of a character device option is:
>
> -``-chardev backend,id=id[,mux=on|off][,options]``
> -

Re: [PATCH 14/14] qtest/xive: Add test of pool interrupts

2024-10-16 Thread Thomas Huth

On 15/10/2024 23.13, Michael Kowal wrote:

From: Glenn Miles 

Added new test for pool interrupts.

Signed-off-by: Glenn Miles 
Signed-off-by: Michael Kowal 
---
  tests/qtest/pnv-xive2-test.c | 77 
  1 file changed, 77 insertions(+)

diff --git a/tests/qtest/pnv-xive2-test.c b/tests/qtest/pnv-xive2-test.c
index a6008bc053..6e7e7f0d9b 100644
--- a/tests/qtest/pnv-xive2-test.c
+++ b/tests/qtest/pnv-xive2-test.c
@@ -4,6 +4,7 @@
   *  - Test 'Pull Thread Context to Odd Thread Reporting Line'
   *  - Test irq to hardware group
   *  - Test irq to hardware group going through backlog
+ *  - Test irq to pool thread
   *
   * Copyright (c) 2024, IBM Corporation.
   *
@@ -267,6 +268,79 @@ static void test_hw_irq(QTestState *qts)
  g_assert_cmphex(cppr, ==, 0xFF);
  }
  
+static void test_pool_irq(QTestState *qts)

+{
+uint32_t irq = 2;
+uint32_t irq_data = 0x600d0d06;
+uint32_t end_index = 5;
+uint32_t target_pir = 1;
+uint32_t target_nvp = 0x100 + target_pir;
+uint8_t priority = 5;
+uint32_t reg32;
+uint16_t reg16;
+uint8_t pq, nsr, cppr, ipb;
+
+printf("# \n");
+printf("# Testing irq %d to pool thread %d\n", irq, target_pir);


Please don't use direct printfs in the qtest framework. If you really have 
to log stuff, use g_test_message() instead.


 Thomas




Re: [PATCH 12/16] rust: allow version 1.63.0 of rustc

2024-10-16 Thread Junjie Mao


Paolo Bonzini  writes:

> Il mer 16 ott 2024, 08:10 Junjie Mao  ha scritto:
>
>  In my Ubuntu 22.04 environment (rustc 1.76.0 and bindgen 0.59.1 from
>  apt) the feature `proc_macro_byte_character` is not yet stablized but
>  used in proc-macro2. Downgrading proc-macro2 to 1.0.79 [1] and syn to
>  2.0.58 fixes that issue for me.
>
> This is handled by patch 5. Try "meson subprojects update --reset".
>

Yes, that works. Thanks for the info!

--
Best Regards
Junjie Mao



[PATCH v2 3/3] include/crypto: clarify @result/@result_len for hash/hmac APIs

2024-10-16 Thread Daniel P . Berrangé
The @result parameter passed to hash/hmac APIs may either contain
a pre-allocated buffer, or a buffer can be allocated on the fly.
Clarify these two different usage models in the API docs.

Signed-off-by: Daniel P. Berrangé 
---
 include/crypto/hash.h | 30 +++---
 include/crypto/hmac.h | 17 -
 2 files changed, 35 insertions(+), 12 deletions(-)

diff --git a/include/crypto/hash.h b/include/crypto/hash.h
index b791ca92a4..317bf9ecde 100644
--- a/include/crypto/hash.h
+++ b/include/crypto/hash.h
@@ -98,11 +98,18 @@ int qcrypto_hash_bytesv(QCryptoHashAlgo alg,
  * @errp: pointer to a NULL-initialized error object
  *
  * Computes the hash across all the memory region
- * @buf of length @len. The @result pointer will be
- * filled with raw bytes representing the computed
- * hash, which will have length @resultlen. The
- * memory pointer in @result must be released
- * with a call to g_free() when no longer required.
+ * @buf of length @len.
+ *
+ * If @result_len is set to a non-zero value by the caller, then
+ * @result must hold a pointer that is @result_len in size, and
+ * @result_len match the size of the hash output. The digest will
+ * be written into @result.
+ *
+ * If @result_len is set to zero, then this function will allocate
+ * a buffer to hold the hash output digest, storing a pointer to
+ * the buffer in @result, and setting @result_len to its size.
+ * The memory referenced in @result must be released with a call
+ * to g_free() when no longer required by the caller.
  *
  * Returns: 0 on success, -1 on error
  */
@@ -215,8 +222,17 @@ int qcrypto_hash_finalize_base64(QCryptoHash *hash,
  *
  * Computes the hash from the given hash object. Hash object
  * is expected to have it's data updated from the qcrypto_hash_update function.
- * The memory pointer in @result must be released with a call to g_free()
- * when no longer required.
+ *
+ * If @result_len is set to a non-zero value by the caller, then
+ * @result must hold a pointer that is @result_len in size, and
+ * @result_len match the size of the hash output. The digest will
+ * be written into @result.
+ *
+ * If @result_len is set to zero, then this function will allocate
+ * a buffer to hold the hash output digest, storing a pointer to
+ * the buffer in @result, and setting @result_len to its size.
+ * The memory referenced in @result must be released with a call
+ * to g_free() when no longer required by the caller.
  *
  * Returns: 0 on success, -1 on error
  */
diff --git a/include/crypto/hmac.h b/include/crypto/hmac.h
index c69a0dfab3..aaff95f7db 100644
--- a/include/crypto/hmac.h
+++ b/include/crypto/hmac.h
@@ -103,11 +103,18 @@ int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
  * @errp: pointer to a NULL-initialized error object
  *
  * Computes the hmac across all the memory region
- * @buf of length @len. The @result pointer will be
- * filled with raw bytes representing the computed
- * hmac, which will have length @resultlen. The
- * memory pointer in @result must be released
- * with a call to g_free() when no longer required.
+ * @buf of length @len.
+ *
+ * If @result_len is set to a non-zero value by the caller, then
+ * @result must hold a pointer that is @result_len in size, and
+ * @result_len match the size of the hash output. The digest will
+ * be written into @result.
+ *
+ * If @result_len is set to zero, then this function will allocate
+ * a buffer to hold the hash output digest, storing a pointer to
+ * the buffer in @result, and setting @result_len to its size.
+ * The memory referenced in @result must be released with a call
+ * to g_free() when no longer required by the caller.
  *
  * Returns:
  *  0 on success, -1 on error
-- 
2.46.0




[PATCH v2 0/3] crypto: fix regression in hash result buffer handling

2024-10-16 Thread Daniel P . Berrangé



Daniel P. Berrangé (3):
  crypto/hash: avoid overwriting user supplied result pointer
  tests: correctly validate result buffer in hash/hmac tests
  include/crypto: clarify @result/@result_len for hash/hmac APIs

 crypto/hash-gcrypt.c  | 15 ---
 crypto/hash-glib.c| 11 +--
 crypto/hash-gnutls.c  | 16 +---
 crypto/hash-nettle.c  | 14 +++---
 include/crypto/hash.h | 30 +++---
 include/crypto/hmac.h | 17 -
 tests/unit/test-crypto-hash.c |  7 ---
 tests/unit/test-crypto-hmac.c |  6 --
 8 files changed, 88 insertions(+), 28 deletions(-)

-- 
2.46.0




[PATCH v2 2/3] tests: correctly validate result buffer in hash/hmac tests

2024-10-16 Thread Daniel P . Berrangé
Validate that the pre-allocated buffer pointer was not overwritten
by the hash/hmac APIs.

Signed-off-by: Daniel P. Berrangé 
---
 tests/unit/test-crypto-hash.c | 7 ---
 tests/unit/test-crypto-hmac.c | 6 --
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/tests/unit/test-crypto-hash.c b/tests/unit/test-crypto-hash.c
index e5829ca766..76c4699c15 100644
--- a/tests/unit/test-crypto-hash.c
+++ b/tests/unit/test-crypto-hash.c
@@ -123,7 +123,7 @@ static void test_hash_prealloc(void)
 size_t i;
 
 for (i = 0; i < G_N_ELEMENTS(expected_outputs) ; i++) {
-uint8_t *result;
+uint8_t *result, *origresult;
 size_t resultlen;
 int ret;
 size_t j;
@@ -133,7 +133,7 @@ static void test_hash_prealloc(void)
 }
 
 resultlen = expected_lens[i];
-result = g_new0(uint8_t, resultlen);
+origresult = result = g_new0(uint8_t, resultlen);
 
 ret = qcrypto_hash_bytes(i,
  INPUT_TEXT,
@@ -142,7 +142,8 @@ static void test_hash_prealloc(void)
  &resultlen,
  &error_fatal);
 g_assert(ret == 0);
-
+/* Validate that our pre-allocated pointer was not replaced */
+g_assert(result == origresult);
 g_assert(resultlen == expected_lens[i]);
 for (j = 0; j < resultlen; j++) {
 g_assert(expected_outputs[i][j * 2] == hex[(result[j] >> 4) & 
0xf]);
diff --git a/tests/unit/test-crypto-hmac.c b/tests/unit/test-crypto-hmac.c
index 3fa50f24bb..cdb8774443 100644
--- a/tests/unit/test-crypto-hmac.c
+++ b/tests/unit/test-crypto-hmac.c
@@ -126,7 +126,7 @@ static void test_hmac_prealloc(void)
 for (i = 0; i < G_N_ELEMENTS(test_data); i++) {
 QCryptoHmacTestData *data = &test_data[i];
 QCryptoHmac *hmac = NULL;
-uint8_t *result = NULL;
+uint8_t *result = NULL, *origresult = NULL;
 size_t resultlen = 0;
 const char *exp_output = NULL;
 int ret;
@@ -139,7 +139,7 @@ static void test_hmac_prealloc(void)
 exp_output = data->hex_digest;
 
 resultlen = strlen(exp_output) / 2;
-result = g_new0(uint8_t, resultlen);
+origresult = result = g_new0(uint8_t, resultlen);
 
 hmac = qcrypto_hmac_new(data->alg, (const uint8_t *)KEY,
 strlen(KEY), &error_fatal);
@@ -149,6 +149,8 @@ static void test_hmac_prealloc(void)
  strlen(INPUT_TEXT), &result,
  &resultlen, &error_fatal);
 g_assert(ret == 0);
+/* Validate that our pre-allocated pointer was not replaced */
+g_assert(result == origresult);
 
 exp_output = data->hex_digest;
 for (j = 0; j < resultlen; j++) {
-- 
2.46.0




[PATCH v2 1/3] crypto/hash: avoid overwriting user supplied result pointer

2024-10-16 Thread Daniel P . Berrangé
If the user provides a pre-allocated buffer for the hash result,
we must use that rather than re-allocating a new buffer.

Reported-by: Dorjoy Chowdhury 
Signed-off-by: Daniel P. Berrangé 
---
 crypto/hash-gcrypt.c | 15 ---
 crypto/hash-glib.c   | 11 +--
 crypto/hash-gnutls.c | 16 +---
 crypto/hash-nettle.c | 14 +++---
 4 files changed, 45 insertions(+), 11 deletions(-)

diff --git a/crypto/hash-gcrypt.c b/crypto/hash-gcrypt.c
index ccc3cce3f8..73533a4949 100644
--- a/crypto/hash-gcrypt.c
+++ b/crypto/hash-gcrypt.c
@@ -103,16 +103,25 @@ int qcrypto_gcrypt_hash_finalize(QCryptoHash *hash,
  size_t *result_len,
  Error **errp)
 {
+int ret;
 unsigned char *digest;
 gcry_md_hd_t *ctx = hash->opaque;
 
-*result_len = gcry_md_get_algo_dlen(qcrypto_hash_alg_map[hash->alg]);
-if (*result_len == 0) {
+ret = gcry_md_get_algo_dlen(qcrypto_hash_alg_map[hash->alg]);
+if (ret == 0) {
 error_setg(errp, "Unable to get hash length");
 return -1;
 }
 
-*result = g_new(uint8_t, *result_len);
+if (*result_len == 0) {
+*result_len = ret;
+*result = g_new(uint8_t, *result_len);
+} else if (*result_len != ret) {
+error_setg(errp,
+   "Result buffer size %zu is smaller than hash %d",
+   *result_len, ret);
+return -1;
+}
 
 /* Digest is freed by gcry_md_close(), copy it */
 digest = gcry_md_read(*ctx, 0);
diff --git a/crypto/hash-glib.c b/crypto/hash-glib.c
index 02a6ec1edf..809cef98ae 100644
--- a/crypto/hash-glib.c
+++ b/crypto/hash-glib.c
@@ -99,8 +99,15 @@ int qcrypto_glib_hash_finalize(QCryptoHash *hash,
 return -1;
 }
 
-*result_len = ret;
-*result = g_new(uint8_t, *result_len);
+if (*result_len == 0) {
+*result_len = ret;
+*result = g_new(uint8_t, *result_len);
+} else if (*result_len != ret) {
+error_setg(errp,
+   "Result buffer size %zu is smaller than hash %d",
+   *result_len, ret);
+return -1;
+}
 
 g_checksum_get_digest(ctx, *result, result_len);
 return 0;
diff --git a/crypto/hash-gnutls.c b/crypto/hash-gnutls.c
index 34a63994c9..99fbe824ea 100644
--- a/crypto/hash-gnutls.c
+++ b/crypto/hash-gnutls.c
@@ -115,14 +115,24 @@ int qcrypto_gnutls_hash_finalize(QCryptoHash *hash,
  Error **errp)
 {
 gnutls_hash_hd_t *ctx = hash->opaque;
+int ret;
 
-*result_len = gnutls_hash_get_len(qcrypto_hash_alg_map[hash->alg]);
-if (*result_len == 0) {
+ret = gnutls_hash_get_len(qcrypto_hash_alg_map[hash->alg]);
+if (ret == 0) {
 error_setg(errp, "Unable to get hash length");
 return -1;
 }
 
-*result = g_new(uint8_t, *result_len);
+if (*result_len == 0) {
+*result_len = ret;
+*result = g_new(uint8_t, *result_len);
+} else if (*result_len != ret) {
+error_setg(errp,
+   "Result buffer size %zu is smaller than hash %d",
+   *result_len, ret);
+return -1;
+}
+
 gnutls_hash_output(*ctx, *result);
 return 0;
 }
diff --git a/crypto/hash-nettle.c b/crypto/hash-nettle.c
index 3b847aa60e..c78624b347 100644
--- a/crypto/hash-nettle.c
+++ b/crypto/hash-nettle.c
@@ -150,9 +150,17 @@ int qcrypto_nettle_hash_finalize(QCryptoHash *hash,
  Error **errp)
 {
 union qcrypto_hash_ctx *ctx = hash->opaque;
-
-*result_len = qcrypto_hash_alg_map[hash->alg].len;
-*result = g_new(uint8_t, *result_len);
+int ret = qcrypto_hash_alg_map[hash->alg].len;
+
+if (*result_len == 0) {
+*result_len = ret;
+*result = g_new(uint8_t, *result_len);
+} else if (*result_len != ret) {
+error_setg(errp,
+   "Result buffer size %zu is smaller than hash %d",
+   *result_len, ret);
+return -1;
+}
 
 qcrypto_hash_alg_map[hash->alg].result(ctx, *result_len, *result);
 
-- 
2.46.0




[PATCH v4 7/8] tests/unit/test-char: add unit test for the `mux-be` multiplexer

2024-10-16 Thread Roman Penyaev
The test is trivial: several backends, 1 `mux-be`, 1 frontend
do the buffer write and read. Pipe is used for EAGAIN verification.

Signed-off-by: Roman Penyaev 
Cc: "Marc-André Lureau" 
Cc: qemu-devel@nongnu.org
---
 tests/unit/test-char.c | 306 -
 1 file changed, 304 insertions(+), 2 deletions(-)

diff --git a/tests/unit/test-char.c b/tests/unit/test-char.c
index a1c6bb874c8e..3eb0692b199f 100644
--- a/tests/unit/test-char.c
+++ b/tests/unit/test-char.c
@@ -178,7 +178,7 @@ static void char_ringbuf_test(void)
 qemu_opts_del(opts);
 }
 
-static void char_mux_test(void)
+static void char_mux_fe_test(void)
 {
 QemuOpts *opts;
 Chardev *chr, *base;
@@ -359,6 +359,307 @@ static void char_mux_test(void)
 qmp_chardev_remove("mux-label", &error_abort);
 }
 
+static void char_mux_be_test(void)
+{
+QemuOpts *opts;
+Chardev *mux_be, *chr1, *chr2, *base;
+char *data;
+FeHandler h = { 0, false, 0, false, };
+Error *error = NULL;
+CharBackend chr_be;
+int ret, i;
+
+#define RB_SIZE 128
+
+/* Create mux-be */
+opts = qemu_opts_create(qemu_find_opts("chardev"), "mux0",
+1, &error_abort);
+qemu_opt_set(opts, "backend", "mux-be", &error_abort);
+mux_be = qemu_chr_new_from_opts(opts, NULL, &error_abort);
+g_assert_nonnull(mux_be);
+qemu_opts_del(opts);
+
+/* Check maximum allowed backends */
+for (i = 0; true; i++) {
+char name[8];
+
+snprintf(name, sizeof(name), "chr%d", i);
+opts = qemu_opts_create(qemu_find_opts("chardev"), name,
+1, &error_abort);
+qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
+qemu_opt_set(opts, "size", stringify(RB_SIZE), &error_abort);
+qemu_opt_set(opts, "mux-be-id", "mux0", &error_abort);
+base = qemu_chr_new_from_opts(opts, NULL, &error);
+if (error) {
+const char *err_fmt =
+"too many uses of multiplexed chardev 'mux0' (maximum is %u)";
+unsigned n;
+
+ret = sscanf(error_get_pretty(error), err_fmt, &n);
+error_free(error);
+error = NULL;
+g_assert_cmpint(ret, ==, 1);
+g_assert_cmpint(i, ==, n);
+break;
+}
+g_assert_nonnull(base);
+qemu_opts_del(opts);
+}
+/* Finalize mux0 */
+qmp_chardev_remove("mux0", &error_abort);
+
+/* Finalize all backends */
+while (i--) {
+char name[8];
+snprintf(name, sizeof(name), "chr%d", i);
+qmp_chardev_remove(name, &error_abort);
+}
+
+/* Create mux-be */
+opts = qemu_opts_create(qemu_find_opts("chardev"), "mux0",
+1, &error_abort);
+qemu_opt_set(opts, "backend", "mux-be", &error_abort);
+mux_be = qemu_chr_new_from_opts(opts, NULL, &error_abort);
+g_assert_nonnull(mux_be);
+qemu_opts_del(opts);
+
+/* Create chardev which fails */
+opts = qemu_opts_create(qemu_find_opts("chardev"), "chr1",
+1, &error_abort);
+qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
+qemu_opt_set(opts, "size", stringify(RB_SIZE), &error_abort);
+qemu_opt_set(opts, "mux-be-id", "mux0", &error_abort);
+qemu_opt_set(opts, "mux", "on", &error_abort);
+chr1 = qemu_chr_new_from_opts(opts, NULL, &error);
+g_assert_cmpstr(error_get_pretty(error), ==, "chardev: mux and mux-be "
+"can't be used for the same device");
+error_free(error);
+error = NULL;
+qemu_opts_del(opts);
+
+/* Create first chardev */
+opts = qemu_opts_create(qemu_find_opts("chardev"), "chr1",
+1, &error_abort);
+qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
+qemu_opt_set(opts, "size", stringify(RB_SIZE), &error_abort);
+qemu_opt_set(opts, "mux-be-id", "mux0", &error_abort);
+chr1 = qemu_chr_new_from_opts(opts, NULL, &error_abort);
+g_assert_nonnull(chr1);
+qemu_opts_del(opts);
+
+/* Create second chardev */
+opts = qemu_opts_create(qemu_find_opts("chardev"), "chr2",
+1, &error_abort);
+qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
+qemu_opt_set(opts, "size", stringify(RB_SIZE), &error_abort);
+qemu_opt_set(opts, "mux-be-id", "mux0", &error_abort);
+chr2 = qemu_chr_new_from_opts(opts, NULL, &error_abort);
+g_assert_nonnull(chr2);
+qemu_opts_del(opts);
+
+/* Attach mux-be to a frontend */
+qemu_chr_fe_init(&chr_be, mux_be, &error_abort);
+qemu_chr_fe_set_handlers(&chr_be,
+ fe_can_read,
+ fe_read,
+ fe_event,
+ NULL,
+ &h,
+ NULL, true);
+
+/* Fails second time */
+qemu_chr_fe_init(&chr_be, mux_be, &error);
+g_assert_cmpstr(error_get_pret

[PATCH v4 1/8] chardev/char: rename `MuxChardev` struct to `MuxFeChardev`

2024-10-16 Thread Roman Penyaev
In the following patches backend multiplexer will be
introduced. This patch renames the structure and a
few mux macros to reflect that this mux is responsible
only for multiplexing of frontend devices.

This patch does the following:

  s/MuxChardev/MuxFeChardev/g
  s/CHARDEV_IS_MUX/CHARDEV_IS_MUX_FE/g
  s/MUX_CHARDEV/MUX_FE_CHARDEV/g
  s/TYPE_CHARDEV_MUX/TYPE_CHARDEV_MUX_FE/g

No json or string types are changed for the sake of
compatibility.

Signed-off-by: Roman Penyaev 
Cc: "Marc-André Lureau" 
Cc: qemu-devel@nongnu.org
---
 chardev/char-fe.c  | 10 +-
 chardev/char-mux.c | 36 ++--
 chardev/char.c |  8 
 chardev/chardev-internal.h | 16 
 include/chardev/char.h |  2 +-
 5 files changed, 36 insertions(+), 36 deletions(-)

diff --git a/chardev/char-fe.c b/chardev/char-fe.c
index 8ac6bebb6f74..7b1ae16c62a4 100644
--- a/chardev/char-fe.c
+++ b/chardev/char-fe.c
@@ -194,8 +194,8 @@ bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error 
**errp)
 unsigned int tag = 0;
 
 if (s) {
-if (CHARDEV_IS_MUX(s)) {
-MuxChardev *d = MUX_CHARDEV(s);
+if (CHARDEV_IS_MUX_FE(s)) {
+MuxFeChardev *d = MUX_FE_CHARDEV(s);
 
 if (!mux_chr_attach_frontend(d, b, &tag, errp)) {
 return false;
@@ -223,8 +223,8 @@ void qemu_chr_fe_deinit(CharBackend *b, bool del)
 if (b->chr->be == b) {
 b->chr->be = NULL;
 }
-if (CHARDEV_IS_MUX(b->chr)) {
-MuxChardev *d = MUX_CHARDEV(b->chr);
+if (CHARDEV_IS_MUX_FE(b->chr)) {
+MuxFeChardev *d = MUX_FE_CHARDEV(b->chr);
 mux_chr_detach_frontend(d, b->tag);
 }
 if (del) {
@@ -305,7 +305,7 @@ void qemu_chr_fe_take_focus(CharBackend *b)
 return;
 }
 
-if (CHARDEV_IS_MUX(b->chr)) {
+if (CHARDEV_IS_MUX_FE(b->chr)) {
 mux_set_focus(b->chr, b->tag);
 }
 }
diff --git a/chardev/char-mux.c b/chardev/char-mux.c
index bda5c45e6058..dfaea5aefac3 100644
--- a/chardev/char-mux.c
+++ b/chardev/char-mux.c
@@ -44,7 +44,7 @@ static bool muxes_opened = true;
 /* Called with chr_write_lock held.  */
 static int mux_chr_write(Chardev *chr, const uint8_t *buf, int len)
 {
-MuxChardev *d = MUX_CHARDEV(chr);
+MuxFeChardev *d = MUX_FE_CHARDEV(chr);
 int ret;
 if (!d->timestamps) {
 ret = qemu_chr_fe_write(&d->chr, buf, len);
@@ -125,7 +125,7 @@ static void mux_print_help(Chardev *chr)
 }
 }
 
-static void mux_chr_send_event(MuxChardev *d, unsigned int mux_nr,
+static void mux_chr_send_event(MuxFeChardev *d, unsigned int mux_nr,
QEMUChrEvent event)
 {
 CharBackend *be = d->backends[mux_nr];
@@ -137,14 +137,14 @@ static void mux_chr_send_event(MuxChardev *d, unsigned 
int mux_nr,
 
 static void mux_chr_be_event(Chardev *chr, QEMUChrEvent event)
 {
-MuxChardev *d = MUX_CHARDEV(chr);
+MuxFeChardev *d = MUX_FE_CHARDEV(chr);
 
 if (d->focus != -1) {
 mux_chr_send_event(d, d->focus, event);
 }
 }
 
-static int mux_proc_byte(Chardev *chr, MuxChardev *d, int ch)
+static int mux_proc_byte(Chardev *chr, MuxFeChardev *d, int ch)
 {
 if (d->term_got_escape) {
 d->term_got_escape = false;
@@ -198,7 +198,7 @@ static int mux_proc_byte(Chardev *chr, MuxChardev *d, int 
ch)
 
 static void mux_chr_accept_input(Chardev *chr)
 {
-MuxChardev *d = MUX_CHARDEV(chr);
+MuxFeChardev *d = MUX_FE_CHARDEV(chr);
 int m = d->focus;
 CharBackend *be = d->backends[m];
 
@@ -211,7 +211,7 @@ static void mux_chr_accept_input(Chardev *chr)
 
 static int mux_chr_can_read(void *opaque)
 {
-MuxChardev *d = MUX_CHARDEV(opaque);
+MuxFeChardev *d = MUX_FE_CHARDEV(opaque);
 int m = d->focus;
 CharBackend *be = d->backends[m];
 
@@ -229,7 +229,7 @@ static int mux_chr_can_read(void *opaque)
 static void mux_chr_read(void *opaque, const uint8_t *buf, int size)
 {
 Chardev *chr = CHARDEV(opaque);
-MuxChardev *d = MUX_CHARDEV(opaque);
+MuxFeChardev *d = MUX_FE_CHARDEV(opaque);
 int m = d->focus;
 CharBackend *be = d->backends[m];
 int i;
@@ -250,7 +250,7 @@ static void mux_chr_read(void *opaque, const uint8_t *buf, 
int size)
 
 void mux_chr_send_all_event(Chardev *chr, QEMUChrEvent event)
 {
-MuxChardev *d = MUX_CHARDEV(chr);
+MuxFeChardev *d = MUX_FE_CHARDEV(chr);
 int bit;
 
 if (!muxes_opened) {
@@ -271,7 +271,7 @@ static void mux_chr_event(void *opaque, QEMUChrEvent event)
 
 static GSource *mux_chr_add_watch(Chardev *s, GIOCondition cond)
 {
-MuxChardev *d = MUX_CHARDEV(s);
+MuxFeChardev *d = MUX_FE_CHARDEV(s);
 Chardev *chr = qemu_chr_fe_get_driver(&d->chr);
 ChardevClass *cc = CHARDEV_GET_CLASS(chr);
 
@@ -284,7 +284,7 @@ static GSource *mux_chr_add_watch(Chardev *s, GIOCondition 
cond)
 
 static void char_mux_finalize(Object *obj)
 {
-MuxChardev *d = MUX_CHARDEV(obj);
+MuxFeCharde

[PATCH v4 0/8] chardev: implement backend chardev multiplexing

2024-10-16 Thread Roman Penyaev
Mux is a character backend (host side) device, which multiplexes
multiple frontends with one backend device. The following is a
few lines from the QEMU manpage [1]:

  A multiplexer is a "1:N" device, and here the "1" end is your
  specified chardev backend, and the "N" end is the various parts
  of QEMU that can talk to a chardev.

But sadly multiple backends are not supported.

This work implements multiplexing capability of several backend
devices, which opens up an opportunity to use a single frontend
device on the guest, which can be manipulated from several
backend devices.

The motivation is the EVE project [2], where it would be very
convenient to have a virtio console frontend device on the guest that
can be controlled from multiple backend devices, namely VNC and local
TTY emulator. The following is an example of the QEMU command line:

   -chardev mux-be,id=mux0 \
   -chardev socket,path=/tmp/sock,server=on,wait=off,id=sock0,mux-be-id=mux0 \
   -chardev vc,id=vc0,mux-be-id=mux0 \
   -device virtconsole,chardev=mux0 \
   -vnc 0.0.0.0:0

which creates 2 backend devices: text virtual console (`vc0`) and a
socket (`sock0`) connected to the single virtio hvc console with the
backend multiplexer (`mux0`) help. `vc0` renders text to an image,
which can be shared over the VNC protocol.  `sock0` is a socket
backend which provides biderectional communication to the virtio hvc
console.

Once QEMU starts VNC client and any TTY emulator can be used to
control a single hvc console, for example these two different
consoles should have similar input and output due the buffer
multiplexing:

   # VNC client
   vncviewer :0

   # TTY emulator
   socat unix-connect:/tmp/sock pty,link=/tmp/pty
   tio /tmp/pty

v3 .. v4:

* Rebase on latest chardev changes
* Add unit tests which test corner cases:
   * Inability to remove mux with active frontend
   * Inability to add more chardevs to a mux than `MUX_MAX`
   * Inability to mix mux-fe and mux-be for the same chardev

v2 .. v3:

* Split frontend and backend multiplexer implementations and
  move them to separate files: char-mux-fe.c and char-mux-be.c

v1 .. v2:

* Separate type for the backend multiplexer `mux-be`
* Handle EAGAIN on write to the backend device
* Support of watch of previously failed backend device
* Proper json support of the `mux-be-id` option
* Unit test for the `mux-be` multiplexer

[1] https://www.qemu.org/docs/master/system/qemu-manpage.html#hxtool-6
[2] https://github.com/lf-edge/eve

Roman Penyaev (8):
  chardev/char: rename `MuxChardev` struct to `MuxFeChardev`
  chardev/char: rename `char-mux.c` to `char-mux-fe.c`
  chardev/char: move away mux suspend/resume calls
  chardev/char: rename frontend mux calls
  chardev/char: introduce `mux-be-id=ID` option
  chardev/char-mux: implement backend chardev multiplexing
  tests/unit/test-char: add unit test for the `mux-be` multiplexer
  qemu-options.hx: describe multiplexing of several backend devices

 chardev/char-fe.c |  25 ++-
 chardev/char-mux-be.c | 290 
 chardev/{char-mux.c => char-mux-fe.c} | 157 +
 chardev/char.c| 133 +--
 chardev/chardev-internal.h|  55 -
 chardev/meson.build   |   3 +-
 include/chardev/char.h|   8 +-
 qapi/char.json|  31 ++-
 qemu-options.hx   |  78 +--
 system/vl.c   |   4 +-
 tests/unit/test-char.c| 306 +-
 11 files changed, 922 insertions(+), 168 deletions(-)
 create mode 100644 chardev/char-mux-be.c
 rename chardev/{char-mux.c => char-mux-fe.c} (71%)

Signed-off-by: Roman Penyaev 
Cc: "Marc-André Lureau" 
Cc: qemu-devel@nongnu.org

-- 
2.34.1




[PATCH v4 5/8] chardev/char: introduce `mux-be-id=ID` option

2024-10-16 Thread Roman Penyaev
Patch introduces `mux-be-id=ID` option for all chardev devices.
This is necessary to attach chardev to `mux-be` for backend
multiplexing. Actual implementation wimplementation will follow.

Signed-off-by: Roman Penyaev 
Cc: "Marc-André Lureau" 
Cc: qemu-devel@nongnu.org
---
 chardev/char.c | 3 +++
 qapi/char.json | 6 +-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/chardev/char.c b/chardev/char.c
index d8dbdb6f84f1..cffe60860589 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -933,6 +933,9 @@ QemuOptsList qemu_chardev_opts = {
 },{
 .name = "mux",
 .type = QEMU_OPT_BOOL,
+},{
+.name = "mux-be-id",
+.type = QEMU_OPT_STRING,
 },{
 .name = "signal",
 .type = QEMU_OPT_BOOL,
diff --git a/qapi/char.json b/qapi/char.json
index e04535435034..fb0dedb24383 100644
--- a/qapi/char.json
+++ b/qapi/char.json
@@ -199,11 +199,15 @@
 # @logappend: true to append instead of truncate (default to false to
 # truncate)
 #
+# @mux-be-id: id of the mux-be device for backend multiplexing
+# (since: 9.2)
+#
 # Since: 2.6
 ##
 { 'struct': 'ChardevCommon',
   'data': { '*logfile': 'str',
-'*logappend': 'bool' } }
+'*logappend': 'bool',
+'*mux-be-id': 'str' } }
 
 ##
 # @ChardevFile:
-- 
2.34.1




[PATCH v4 2/8] chardev/char: rename `char-mux.c` to `char-mux-fe.c`

2024-10-16 Thread Roman Penyaev
In the following patches backend multiplexer will be
introduced and the implementation will be named as
follows: `char-mux-be.c`. This patch renames the
frontend multiplexer from `char-mux.c` to
`char-mux-fe.c`.

Signed-off-by: Roman Penyaev 
Cc: "Marc-André Lureau" 
Cc: qemu-devel@nongnu.org
---
 chardev/{char-mux.c => char-mux-fe.c} | 0
 chardev/meson.build   | 2 +-
 2 files changed, 1 insertion(+), 1 deletion(-)
 rename chardev/{char-mux.c => char-mux-fe.c} (100%)

diff --git a/chardev/char-mux.c b/chardev/char-mux-fe.c
similarity index 100%
rename from chardev/char-mux.c
rename to chardev/char-mux-fe.c
diff --git a/chardev/meson.build b/chardev/meson.build
index 70070a8279a9..778444a00ca6 100644
--- a/chardev/meson.build
+++ b/chardev/meson.build
@@ -2,7 +2,7 @@ chardev_ss.add(files(
   'char-fe.c',
   'char-file.c',
   'char-io.c',
-  'char-mux.c',
+  'char-mux-fe.c',
   'char-null.c',
   'char-pipe.c',
   'char-ringbuf.c',
-- 
2.34.1




[PATCH v4 6/8] chardev/char-mux: implement backend chardev multiplexing

2024-10-16 Thread Roman Penyaev
This patch implements multiplexing capability of several backend
devices, which opens up an opportunity to use a single frontend
device on the guest, which can be manipulated from several
backend devices.

The idea of the change is trivial: keep list of backend devices
(up to 4), init them on demand and forward data buffer back and
forth.

Patch implements another multiplexer type `mux-be`. The following
is QEMU command line example:

   -chardev mux-be,id=mux0 \
   -chardev socket,path=/tmp/sock,server=on,wait=off,id=sock0,mux-be-id=mux0 \
   -chardev vc,id=vc0,mux-be-id=mux0 \
   -device virtconsole,chardev=mux0 \
   -vnc 0.0.0.0:0

Which creates 2 backend devices: text virtual console (`vc0`) and a
socket (`sock0`) connected to the single virtio hvc console with the
backend multiplexer (`mux0`) help. `vc0` renders text to an image,
which can be shared over the VNC protocol.  `sock0` is a socket
backend which provides biderectional communication to the virtio hvc
console.

Signed-off-by: Roman Penyaev 
Cc: "Marc-André Lureau" 
Cc: qemu-devel@nongnu.org
---
 chardev/char-fe.c  |   9 ++
 chardev/char-mux-be.c  | 290 +
 chardev/char.c |  56 +--
 chardev/chardev-internal.h |  34 -
 chardev/meson.build|   1 +
 include/chardev/char.h |   1 +
 qapi/char.json |  25 
 7 files changed, 403 insertions(+), 13 deletions(-)
 create mode 100644 chardev/char-mux-be.c

diff --git a/chardev/char-fe.c b/chardev/char-fe.c
index a2b5bff39fd9..2f794674563b 100644
--- a/chardev/char-fe.c
+++ b/chardev/char-fe.c
@@ -200,6 +200,12 @@ bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error 
**errp)
 if (!mux_fe_chr_attach_frontend(d, b, &tag, errp)) {
 return false;
 }
+} else if (CHARDEV_IS_MUX_BE(s)) {
+MuxBeChardev *d = MUX_BE_CHARDEV(s);
+
+if (!mux_be_chr_attach_frontend(d, b, errp)) {
+return false;
+}
 } else if (s->be) {
 error_setg(errp, "chardev '%s' is already in use", s->label);
 return false;
@@ -226,6 +232,9 @@ void qemu_chr_fe_deinit(CharBackend *b, bool del)
 if (CHARDEV_IS_MUX_FE(b->chr)) {
 MuxFeChardev *d = MUX_FE_CHARDEV(b->chr);
 mux_fe_chr_detach_frontend(d, b->tag);
+} else if (CHARDEV_IS_MUX_BE(b->chr)) {
+MuxBeChardev *d = MUX_BE_CHARDEV(b->chr);
+mux_be_chr_detach_frontend(d);
 }
 if (del) {
 Object *obj = OBJECT(b->chr);
diff --git a/chardev/char-mux-be.c b/chardev/char-mux-be.c
new file mode 100644
index ..64a4f2c00034
--- /dev/null
+++ b/chardev/char-mux-be.c
@@ -0,0 +1,290 @@
+/*
+ * QEMU Character Backend Multiplexer
+ *
+ * Author: Roman Penyaev 
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/module.h"
+#include "qemu/option.h"
+#include "qemu/cutils.h"
+#include "chardev/char.h"
+#include "sysemu/block-backend.h"
+#include "qapi/qapi-commands-control.h"
+#include "qapi/clone-visitor.h"
+#include "qapi/qapi-builtin-visit.h"
+#include "chardev-internal.h"
+
+/*
+ * MUX-BE driver for multiplexing 1 frontend device with N backend devices
+ */
+
+/*
+ * Write to all backends. Different backend devices accept data with
+ * various rate, so it is quite possible that one device returns less,
+ * then others. In this case we return minimum to the caller,
+ * expecting caller will repeat operation soon. When repeat happens
+ * send to the devices which consume data faster must be avoided
+ * for obvious reasons not to send data, which was already sent.
+ */
+static int mux_be_chr_write_to_all(MuxBeChardev *d, const uint8_t *buf, int 
len)
+{
+int r, i, ret = len;
+unsigned int written;
+
+for (i = 0; i < d->be_cnt; i++) {
+written = d->be_written[i] - d->be_min_w

[PATCH v4 8/8] qemu-options.hx: describe multiplexing of several backend devices

2024-10-16 Thread Roman Penyaev
This adds a few lines describing `mux-be` multiplexer configuration
for multiplexing several backend devices with a single frontend
device.

Signed-off-by: Roman Penyaev 
Cc: "Marc-André Lureau" 
Cc: qemu-devel@nongnu.org
---
 qemu-options.hx | 78 -
 1 file changed, 58 insertions(+), 20 deletions(-)

diff --git a/qemu-options.hx b/qemu-options.hx
index daae49414740..dd5dfe8596f0 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3677,37 +3677,37 @@ DEFHEADING(Character device options:)
 
 DEF("chardev", HAS_ARG, QEMU_OPTION_chardev,
 "-chardev help\n"
-"-chardev null,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
+"-chardev 
null,id=id[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n"
 "-chardev 
socket,id=id[,host=host],port=port[,to=to][,ipv4=on|off][,ipv6=on|off][,nodelay=on|off]\n"
-" 
[,server=on|off][,wait=on|off][,telnet=on|off][,websocket=on|off][,reconnect=seconds][,mux=on|off]\n"
+" 
[,server=on|off][,wait=on|off][,telnet=on|off][,websocket=on|off][,reconnect=seconds][,mux=on|off][,mux-be-id=id]\n"
 " [,logfile=PATH][,logappend=on|off][,tls-creds=ID][,tls-authz=ID] 
(tcp)\n"
 "-chardev 
socket,id=id,path=path[,server=on|off][,wait=on|off][,telnet=on|off][,websocket=on|off][,reconnect=seconds]\n"
-" 
[,mux=on|off][,logfile=PATH][,logappend=on|off][,abstract=on|off][,tight=on|off]
 (unix)\n"
+" 
[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off][,abstract=on|off][,tight=on|off]
 (unix)\n"
 "-chardev udp,id=id[,host=host],port=port[,localaddr=localaddr]\n"
-" 
[,localport=localport][,ipv4=on|off][,ipv6=on|off][,mux=on|off]\n"
+" 
[,localport=localport][,ipv4=on|off][,ipv6=on|off][,mux=on|off][,mux-be-id=id]\n"
 " [,logfile=PATH][,logappend=on|off]\n"
-"-chardev msmouse,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
+"-chardev 
msmouse,id=id[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n"
 "-chardev 
vc,id=id[[,width=width][,height=height]][[,cols=cols][,rows=rows]]\n"
-" [,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
+" [,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n"
 "-chardev ringbuf,id=id[,size=size][,logfile=PATH][,logappend=on|off]\n"
-"-chardev 
file,id=id,path=path[,input-path=input-file][,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
-"-chardev 
pipe,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
+"-chardev 
file,id=id,path=path[,input-path=input-file][,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n"
+"-chardev 
pipe,id=id,path=path[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n"
 #ifdef _WIN32
-"-chardev console,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
-"-chardev 
serial,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
+"-chardev 
console,id=id[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n"
+"-chardev 
serial,id=id,path=path[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n"
 #else
-"-chardev 
pty,id=id[,path=path][,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
-"-chardev 
stdio,id=id[,mux=on|off][,signal=on|off][,logfile=PATH][,logappend=on|off]\n"
+"-chardev 
pty,id=id[,path=path][,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n"
+"-chardev 
stdio,id=id[,mux=on|off][,mux-be-id=id][,signal=on|off][,logfile=PATH][,logappend=on|off]\n"
 #endif
 #ifdef CONFIG_BRLAPI
-"-chardev braille,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
+"-chardev 
braille,id=id[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n"
 #endif
 #if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \
 || defined(__NetBSD__) || defined(__OpenBSD__) || 
defined(__DragonFly__)
-"-chardev 
serial,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
+"-chardev 
serial,id=id,path=path[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n"
 #endif
 #if defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__)
-"-chardev 
parallel,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
+"-chardev 
parallel,id=id,path=path[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n"
 #endif
 #if defined(CONFIG_SPICE)
 "-chardev 
spicevmc,id=id,name=name[,debug=debug][,logfile=PATH][,logappend=on|off]\n"
@@ -3719,8 +3719,8 @@ DEF("chardev", HAS_ARG, QEMU_OPTION_chardev,
 SRST
 The general form of a character device option is:
 
-``-chardev backend,id=id[,mux=on|off][,options]``
-Backend is one of: ``null``, ``socket``, ``udp``, ``msmouse``,
+``-chardev backend,id=id[,mux=on|off][,mux-be-id=id][,options]``
+Backend is one of: ``null``, ``socket``, ``udp``, ``msmouse``, ``mux-be``,
 ``vc``, ``ringbuf``, ``file``, ``pipe``, ``console`

[PATCH v4 4/8] chardev/char: rename frontend mux calls

2024-10-16 Thread Roman Penyaev
This patch renames calls in the frontend mux implementation
to reflect its frontend nature. Patch does the following:

  s/mux_chr/mux_fe_chr/g

No functional changes are made.

Signed-off-by: Roman Penyaev 
Cc: "Marc-André Lureau" 
Cc: qemu-devel@nongnu.org
---
 chardev/char-fe.c  |  6 ++--
 chardev/char-mux-fe.c  | 68 +++---
 chardev/chardev-internal.h |  8 ++---
 3 files changed, 41 insertions(+), 41 deletions(-)

diff --git a/chardev/char-fe.c b/chardev/char-fe.c
index 7b1ae16c62a4..a2b5bff39fd9 100644
--- a/chardev/char-fe.c
+++ b/chardev/char-fe.c
@@ -197,7 +197,7 @@ bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error 
**errp)
 if (CHARDEV_IS_MUX_FE(s)) {
 MuxFeChardev *d = MUX_FE_CHARDEV(s);
 
-if (!mux_chr_attach_frontend(d, b, &tag, errp)) {
+if (!mux_fe_chr_attach_frontend(d, b, &tag, errp)) {
 return false;
 }
 } else if (s->be) {
@@ -225,7 +225,7 @@ void qemu_chr_fe_deinit(CharBackend *b, bool del)
 }
 if (CHARDEV_IS_MUX_FE(b->chr)) {
 MuxFeChardev *d = MUX_FE_CHARDEV(b->chr);
-mux_chr_detach_frontend(d, b->tag);
+mux_fe_chr_detach_frontend(d, b->tag);
 }
 if (del) {
 Object *obj = OBJECT(b->chr);
@@ -306,7 +306,7 @@ void qemu_chr_fe_take_focus(CharBackend *b)
 }
 
 if (CHARDEV_IS_MUX_FE(b->chr)) {
-mux_set_focus(b->chr, b->tag);
+mux_fe_chr_set_focus(b->chr, b->tag);
 }
 }
 
diff --git a/chardev/char-mux-fe.c b/chardev/char-mux-fe.c
index 6a195390a3c9..dcfce099ea9a 100644
--- a/chardev/char-mux-fe.c
+++ b/chardev/char-mux-fe.c
@@ -35,7 +35,7 @@
 /* MUX driver for serial I/O splitting */
 
 /* Called with chr_write_lock held.  */
-static int mux_chr_write(Chardev *chr, const uint8_t *buf, int len)
+static int mux_fe_chr_write(Chardev *chr, const uint8_t *buf, int len)
 {
 MuxFeChardev *d = MUX_FE_CHARDEV(chr);
 int ret;
@@ -118,8 +118,8 @@ static void mux_print_help(Chardev *chr)
 }
 }
 
-static void mux_chr_send_event(MuxFeChardev *d, unsigned int mux_nr,
-   QEMUChrEvent event)
+static void mux_fe_chr_send_event(MuxFeChardev *d, unsigned int mux_nr,
+  QEMUChrEvent event)
 {
 CharBackend *be = d->backends[mux_nr];
 
@@ -128,12 +128,12 @@ static void mux_chr_send_event(MuxFeChardev *d, unsigned 
int mux_nr,
 }
 }
 
-static void mux_chr_be_event(Chardev *chr, QEMUChrEvent event)
+static void mux_fe_chr_be_event(Chardev *chr, QEMUChrEvent event)
 {
 MuxFeChardev *d = MUX_FE_CHARDEV(chr);
 
 if (d->focus != -1) {
-mux_chr_send_event(d, d->focus, event);
+mux_fe_chr_send_event(d, d->focus, event);
 }
 }
 
@@ -172,7 +172,7 @@ static int mux_proc_byte(Chardev *chr, MuxFeChardev *d, int 
ch)
 if (bit >= MAX_MUX) {
 bit = find_next_bit(&d->mux_bitset, MAX_MUX, 0);
 }
-mux_set_focus(chr, bit);
+mux_fe_chr_set_focus(chr, bit);
 break;
 } case 't':
 d->timestamps = !d->timestamps;
@@ -189,7 +189,7 @@ static int mux_proc_byte(Chardev *chr, MuxFeChardev *d, int 
ch)
 return 0;
 }
 
-static void mux_chr_accept_input(Chardev *chr)
+static void mux_fe_chr_accept_input(Chardev *chr)
 {
 MuxFeChardev *d = MUX_FE_CHARDEV(chr);
 int m = d->focus;
@@ -202,7 +202,7 @@ static void mux_chr_accept_input(Chardev *chr)
 }
 }
 
-static int mux_chr_can_read(void *opaque)
+static int mux_fe_chr_can_read(void *opaque)
 {
 MuxFeChardev *d = MUX_FE_CHARDEV(opaque);
 int m = d->focus;
@@ -219,7 +219,7 @@ static int mux_chr_can_read(void *opaque)
 return 0;
 }
 
-static void mux_chr_read(void *opaque, const uint8_t *buf, int size)
+static void mux_fe_chr_read(void *opaque, const uint8_t *buf, int size)
 {
 Chardev *chr = CHARDEV(opaque);
 MuxFeChardev *d = MUX_FE_CHARDEV(opaque);
@@ -227,7 +227,7 @@ static void mux_chr_read(void *opaque, const uint8_t *buf, 
int size)
 CharBackend *be = d->backends[m];
 int i;
 
-mux_chr_accept_input(opaque);
+mux_fe_chr_accept_input(opaque);
 
 for (i = 0; i < size; i++)
 if (mux_proc_byte(chr, d, buf[i])) {
@@ -248,16 +248,16 @@ void mux_fe_chr_send_all_event(MuxFeChardev *d, 
QEMUChrEvent event)
 /* Send the event to all registered listeners */
 bit = -1;
 while ((bit = find_next_bit(&d->mux_bitset, MAX_MUX, bit + 1)) < MAX_MUX) {
-mux_chr_send_event(d, bit, event);
+mux_fe_chr_send_event(d, bit, event);
 }
 }
 
-static void mux_chr_event(void *opaque, QEMUChrEvent event)
+static void mux_fe_chr_event(void *opaque, QEMUChrEvent event)
 {
 mux_chr_send_all_event(CHARDEV(opaque), event);
 }
 
-static GSource *mux_chr_add_watch(Chardev *s, GIOCondition cond)
+static GSource *mux_fe_chr_add_watch(Chardev *s, GIOCondition cond)
 {
 MuxFeChardev *d = MUX_FE_CHARDE

[PATCH v4 3/8] chardev/char: move away mux suspend/resume calls

2024-10-16 Thread Roman Penyaev
The suspend/resume open multiplexer calls are generic
and will be used for frontend (current mux) and backend
(will follow) implementations. Move them away from the
`char-mux-fe.c` to more generic `char.c` file. Also
for the sake of clarity these renames were made:

  s/suspend_mux_open/mux_suspend_open/g
  s/resume_mux_open/mux_resume_open/g

No functional changes are made.

Signed-off-by: Roman Penyaev 
Cc: "Marc-André Lureau" 
Cc: qemu-devel@nongnu.org
---
 chardev/char-mux-fe.c  | 63 ++---
 chardev/char.c | 72 ++
 chardev/chardev-internal.h |  3 ++
 include/chardev/char.h |  5 +--
 system/vl.c|  4 +--
 5 files changed, 82 insertions(+), 65 deletions(-)

diff --git a/chardev/char-mux-fe.c b/chardev/char-mux-fe.c
index dfaea5aefac3..6a195390a3c9 100644
--- a/chardev/char-mux-fe.c
+++ b/chardev/char-mux-fe.c
@@ -34,13 +34,6 @@
 
 /* MUX driver for serial I/O splitting */
 
-/*
- * Set to false by suspend_mux_open.  Open events are delayed until
- * resume_mux_open.  Usually suspend_mux_open is called before
- * command line processing and resume_mux_open afterwards.
- */
-static bool muxes_opened = true;
-
 /* Called with chr_write_lock held.  */
 static int mux_chr_write(Chardev *chr, const uint8_t *buf, int len)
 {
@@ -248,15 +241,10 @@ static void mux_chr_read(void *opaque, const uint8_t 
*buf, int size)
 }
 }
 
-void mux_chr_send_all_event(Chardev *chr, QEMUChrEvent event)
+void mux_fe_chr_send_all_event(MuxFeChardev *d, QEMUChrEvent event)
 {
-MuxFeChardev *d = MUX_FE_CHARDEV(chr);
 int bit;
 
-if (!muxes_opened) {
-return;
-}
-
 /* Send the event to all registered listeners */
 bit = -1;
 while ((bit = find_next_bit(&d->mux_bitset, MAX_MUX, bit + 1)) < MAX_MUX) {
@@ -381,7 +369,7 @@ static void qemu_chr_open_mux(Chardev *chr,
 /* only default to opened state if we've realized the initial
  * set of muxes
  */
-*be_opened = muxes_opened;
+*be_opened = mux_is_opened();
 qemu_chr_fe_init(&d->chr, drv, errp);
 }
 
@@ -401,53 +389,6 @@ static void qemu_chr_parse_mux(QemuOpts *opts, 
ChardevBackend *backend,
 mux->chardev = g_strdup(chardev);
 }
 
-/**
- * Called after processing of default and command-line-specified
- * chardevs to deliver CHR_EVENT_OPENED events to any FEs attached
- * to a mux chardev. This is done here to ensure that
- * output/prompts/banners are only displayed for the FE that has
- * focus when initial command-line processing/machine init is
- * completed.
- *
- * After this point, any new FE attached to any new or existing
- * mux will receive CHR_EVENT_OPENED notifications for the BE
- * immediately.
- */
-static void open_muxes(Chardev *chr)
-{
-/* send OPENED to all already-attached FEs */
-mux_chr_send_all_event(chr, CHR_EVENT_OPENED);
-
-/*
- * mark mux as OPENED so any new FEs will immediately receive
- * OPENED event
- */
-chr->be_open = 1;
-}
-
-void suspend_mux_open(void)
-{
-muxes_opened = false;
-}
-
-static int chardev_options_parsed_cb(Object *child, void *opaque)
-{
-Chardev *chr = (Chardev *)child;
-
-if (!chr->be_open && CHARDEV_IS_MUX_FE(chr)) {
-open_muxes(chr);
-}
-
-return 0;
-}
-
-void resume_mux_open(void)
-{
-muxes_opened = true;
-object_child_foreach(get_chardevs_root(),
- chardev_options_parsed_cb, NULL);
-}
-
 static void char_mux_class_init(ObjectClass *oc, void *data)
 {
 ChardevClass *cc = CHARDEV_CLASS(oc);
diff --git a/chardev/char.c b/chardev/char.c
index e03cdece..d8dbdb6f84f1 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -43,6 +43,13 @@
 
 #include "chardev-internal.h"
 
+/*
+ * Set to false by mux_suspend_open().  Open events are delayed until
+ * mux_resume_open().  Usually mux_suspend_open() is called before
+ * command line processing and mux_resume_open() afterwards.
+ */
+static bool muxes_opened = true;
+
 /***/
 /* character device */
 
@@ -1259,6 +1266,71 @@ void qemu_chr_cleanup(void)
 object_unparent(get_chardevs_root());
 }
 
+/**
+ * Called after processing of default and command-line-specified
+ * chardevs to deliver CHR_EVENT_OPENED events to any FEs attached
+ * to a mux chardev. This is done here to ensure that
+ * output/prompts/banners are only displayed for the FE that has
+ * focus when initial command-line processing/machine init is
+ * completed.
+ *
+ * After this point, any new FE attached to any new or existing
+ * mux will receive CHR_EVENT_OPENED notifications for the BE
+ * immediately.
+ */
+static void open_muxes(Chardev *chr)
+{
+/* send OPENED to all already-attached FEs */
+mux_chr_send_all_event(chr, CHR_EVENT_OPENED);
+
+/*
+ * mark mux as OPENED so any new FEs will immediately receive
+ * OPENED event
+ */
+chr->be_open = 1;
+}
+
+void mux_suspend_open(void

Fwd: Re: [PATCH] hw/char/riscv_htif: Fix htif_mm_write that causes infinite loop in ACT.

2024-10-16 Thread Trd thg
Sorry about the email style, I'm not familiar with it yet

> It's probably worth including this in the commit message.
Agree, I'll do it.

> It would be good to reference the sail implementation and the
justification for the change there

Sail implementation is probably here:
https://github.com/riscv/sail-riscv/blob/master/model/riscv_platform.sail#L340
- related commit:
https://github.com/riscv/sail-riscv/commit/848312ce7c59fa08c304cab4b4e8060c67d5dfc9

The following is the "infinite loop" part is exported by objdump from
the test ELF of the add instruction generated from ACT
```txt
800082a0 :
800082a0:   1f17auipc   t5,0x1
800082a4:   d61f2023sw  ra,-672(t5) # 80009000 
800082a8:   ff9ff06fj   800082a0 
```
QEMU cannot respond to the above `sw` behavior, It makes no
distinction regarding the size written,
I guess that currently qemu will only respond to the writing to the
high 32 bits and low 32 bits of tohost twice in succession.
I think the behavior here is very strange, and you can find
aswaterman's description of HTIF(include RV32) at:
https://github.com/riscv-software-src/riscv-isa-sim/issues/364#issuecomment-607657754
So this patch try to distinguish these cases based on size and addr.

About the sail impl, there are some related discussions at:
https://github.com/riscv/sail-riscv/issues/218
I made some summaries:
- The implementation of sail as a workaround is not very ideal; we
should follow the experience of spike
  I checked the impl of spike. Although spike handles tohost in a
syscall manner, I don't think this means that spike is better.
  Compared to sail, it does not distinguish whether the write to
tohost is 4 bytes or 8 bytes, but at least in act, it always works
properly.
  - spike code:
https://github.com/riscv-software-src/riscv-isa-sim/blob/master/fesvr/htif.cc#L265
- HTIF has been deprecated
  I don't know if this is true or not, because I haven't found any
official comment.
  However, since ACT is still using htif and is not expected to change
for quite a long time, and no new solutions have emerged, we should go
ahead and implement it
- What are the advantages of QEMU supporting ACT
  - do cross validation with sail/spike, and contributors can use ACT
to verify the correctness when adding new instructions to QEMU. (we do
have this need.)
  > If you think that the benefits of supporting ACT are not obvious,
then I think we can remove all the code related to supporting ACT
(should be the commit mentioned above)

What do you think about this? Thank you!

Alistair Francis  于2024年10月16日周三 13:27写道:
>
> On Mon, Oct 14, 2024 at 8:08 PM 阎明铸  wrote:
> >
> > Thank you for your reply and I'm sorry that I didn't explain it clearly.
> >
> > - ACT is an official riscv test suite to check the riscv support of the 
> > DUT(device under test).
>
> It's probably worth including this in the commit message.
>
> > - Currently ACT support using 
> > [sail-riscv](https://github.com/riscv/sail-riscv)(default) or 
> > [spike](https://github.com/riscv-software-src/riscv-isa-sim)
> > - QEMU is not supported yet,but someone made a commit: 
> > [commit](https://github.com/qemu/qemu/commit/66247edc8b6fb36d6b905babcd795068ea989ad5)
> >
> > But there are still problems, so I'm trying to fix it. After debugging, I 
> > found that it's a htif problem, and the idea of fixing it is referenced 
> > from the sail-riscv implementation
>
> It would be good to reference the sail implementation and the
> justification for the change there
>
> Alistair
>
> >
> > "Alistair Francis" 写道:
> > > On Fri, Sep 27, 2024 at 11:26 PM MingZhu Yan  
> > wrote:
> > > >
> > > > Applications sometimes only write the lower 32-bit payload bytes, 
> > this is used
> > > > in ACT tests. As a workaround, this refers to the solution of 
> > sail-riscv.
> > >
> > > I'm not sure what ACT is, but this feels like a guest bug, not a QEMU 
> > issue.
> > >
> > > Alistair
> > >
> > > > if the payload is written a few times with the same value, we 
> > process the whole
> > > > htif command anyway.
> > > >
> > > > Signed-off-by: MingZhu Yan 
> > > > ---
> > > >  hw/char/riscv_htif.c | 35 +++
> > > >  1 file changed, 19 insertions(+), 16 deletions(-)
> > > >
> > > > diff --git a/hw/char/riscv_htif.c b/hw/char/riscv_htif.c
> > > > index 9bef60def1..d74cce3bef 100644
> > > > --- a/hw/char/riscv_htif.c
> > > > +++ b/hw/char/riscv_htif.c
> > > > @@ -65,16 +65,8 @@ void htif_symbol_callback(const char *st_name, 
> > int st_info, uint64_t st_value,
> > > >  {
> > > >  if (strcmp("fromhost", st_name) == 0) {
> > > >  fromhost_addr = st_value;
> > > > -if (st_size != 8) {
> > > > -error_report("HTIF fromhost must be 8 bytes");
> > > > -exit(1);
> > > > -}
> > > >  } else if (strcmp("tohost", st_name) == 0) {
> > > >  tohost_addr = st_value;
> > > > -if (st_size

Re: [PATCH] tests/functional: Convert most Aspeed machine tests

2024-10-16 Thread Daniel P . Berrangé
On Wed, Oct 16, 2024 at 11:07:41AM +0200, Cédric Le Goater wrote:
> This is a simple conversion of the tests with some cleanups and
> adjustments to match the new test framework. Replace the zephyr image
> MD5 hashes with SHA256 hashes while at it.
> 
> The SDK tests depend on a ssh class from avocado.utils which is
> difficult to replace. To be addressed separately.
> 
> Signed-off-by: Cédric Le Goater 
> ---
>  tests/avocado/machine_aspeed.py | 252 --
>  tests/functional/meson.build|   2 +
>  tests/functional/test_arm_aspeed.py | 269 
>  3 files changed, 271 insertions(+), 252 deletions(-)
>  create mode 100644 tests/functional/test_arm_aspeed.py
> 
> diff --git a/tests/functional/test_arm_aspeed.py 
> b/tests/functional/test_arm_aspeed.py
> new file mode 100644
> index ..2f9a90f64d8f
> --- /dev/null
> +++ b/tests/functional/test_arm_aspeed.py
> @@ -0,0 +1,269 @@
> +#!/usr/bin/env python3
> +#
> +# Functional test that boots the ASPEED SoCs with firmware
> +#
> +# Copyright (C) 2022 ASPEED Technology Inc
> +#
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +
> +import os
> +import time
> +import subprocess
> +import tempfile
> +
> +from qemu_test import QemuSystemTest, Asset
> +from qemu_test import wait_for_console_pattern
> +from qemu_test import exec_command_and_wait_for_pattern
> +from qemu_test import interrupt_interactive_console_until_pattern
> +from qemu_test import exec_command
> +from qemu_test import has_cmd
> +from qemu_test.utils import archive_extract
> +from zipfile import ZipFile
> +from unittest import skipUnless
> +
> +class AST1030Machine(QemuSystemTest):
> +
> +def test_ast1030_zephyros_1_04(self):
> +asset_url = Asset(
> +('https://github.com/AspeedTech-BMC'
> + '/zephyr/releases/download/v00.01.04/ast1030-evb-demo.zip'),
> +
> '4ac6210adcbc61294927918707c6762483fd844dde5e07f3ba834ad1f91434d3')

Don't instantiate assets inline to test code, as this makes them
invisible to the logic that pre-downloads assets prior to running
tests. As a result you're liable to have test timeouts if the
on-the-fly asset download takes too long.

Instead You should use a class level varible with an "ASSET_" name
prefix eg

   ASSET_ = Asset()

See other converted tests for examples of the pattern.

> +kernel_name = "ast1030-evb-demo/zephyr.elf"
> +zip_file = asset_url.fetch()
> +with ZipFile(zip_file, 'r') as zf:
> + zf.extract(kernel_name, path=self.workdir)
> +kernel_file = os.path.join(self.workdir, kernel_name)
> +
> +self.set_machine('ast1030-evb')
> +self.vm.set_console()
> +self.vm.add_args('-kernel', kernel_file, '-nographic')
> +self.vm.launch()
> +wait_for_console_pattern(self, "Booting Zephyr OS")
> +exec_command_and_wait_for_pattern(self, "help",
> +  "Available commands")
> +

With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




Re: [PATCH v3 1/8] target/riscv: Add Ssdbltrp CSRs handling

2024-10-16 Thread LIU Zhiwei



On 2024/10/14 19:22, Clément Léger wrote:

Add ext_ssdbltrp in RISCVCPUConfig and implement MSTATUS.SDT,
{H|M}ENVCFG.DTE and modify the availability of MTVAL2 based on the
presence of the Ssdbltrp ISA extension.

Signed-off-by: Clément Léger 
Reviewed-by: Alistair Francis 
---
  target/riscv/cpu.h|  1 +
  target/riscv/cpu_bits.h   |  6 ++
  target/riscv/cpu_cfg.h|  1 +
  target/riscv/cpu_helper.c | 20 +
  target/riscv/csr.c| 45 ++-
  5 files changed, 63 insertions(+), 10 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index a84e719d3f..ee984bf270 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -553,6 +553,7 @@ void riscv_cpu_set_geilen(CPURISCVState *env, target_ulong 
geilen);
  bool riscv_cpu_vector_enabled(CPURISCVState *env);
  void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable);
  int riscv_env_mmu_index(CPURISCVState *env, bool ifetch);
+bool riscv_env_smode_dbltrp_enabled(CPURISCVState *env, bool virt);
  G_NORETURN void  riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
 MMUAccessType access_type,
 int mmu_idx, uintptr_t 
retaddr);
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index da1723496c..3a5588d4df 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -558,6 +558,7 @@
  #define MSTATUS_TVM 0x0010 /* since: priv-1.10 */
  #define MSTATUS_TW  0x0020 /* since: priv-1.10 */
  #define MSTATUS_TSR 0x0040 /* since: priv-1.10 */
+#define MSTATUS_SDT 0x0100
  #define MSTATUS_GVA 0x40ULL
  #define MSTATUS_MPV 0x80ULL
  
@@ -588,6 +589,7 @@ typedef enum {

  #define SSTATUS_XS  0x00018000
  #define SSTATUS_SUM 0x0004 /* since: priv-1.10 */
  #define SSTATUS_MXR 0x0008
+#define SSTATUS_SDT 0x0100
  
  #define SSTATUS64_UXL   0x0003ULL
  
@@ -777,11 +779,13 @@ typedef enum RISCVException {

  #define MENVCFG_CBIE   (3UL << 4)
  #define MENVCFG_CBCFE  BIT(6)
  #define MENVCFG_CBZE   BIT(7)
+#define MENVCFG_DTE(1ULL << 59)
  #define MENVCFG_ADUE   (1ULL << 61)
  #define MENVCFG_PBMTE  (1ULL << 62)
  #define MENVCFG_STCE   (1ULL << 63)
  
  /* For RV32 */

+#define MENVCFGH_DTE   BIT(27)
  #define MENVCFGH_ADUE  BIT(29)
  #define MENVCFGH_PBMTE BIT(30)
  #define MENVCFGH_STCE  BIT(31)
@@ -795,11 +799,13 @@ typedef enum RISCVException {
  #define HENVCFG_CBIE   MENVCFG_CBIE
  #define HENVCFG_CBCFE  MENVCFG_CBCFE
  #define HENVCFG_CBZE   MENVCFG_CBZE
+#define HENVCFG_DTEMENVCFG_DTE
  #define HENVCFG_ADUE   MENVCFG_ADUE
  #define HENVCFG_PBMTE  MENVCFG_PBMTE
  #define HENVCFG_STCE   MENVCFG_STCE
  
  /* For RV32 */

+#define HENVCFGH_DTEMENVCFGH_DTE
  #define HENVCFGH_ADUE   MENVCFGH_ADUE
  #define HENVCFGH_PBMTE  MENVCFGH_PBMTE
  #define HENVCFGH_STCE   MENVCFGH_STCE
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index ae2a945b5f..dd804f95d4 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -77,6 +77,7 @@ struct RISCVCPUConfig {
  bool ext_smstateen;
  bool ext_sstc;
  bool ext_smcntrpmf;
+bool ext_ssdbltrp;
  bool ext_svadu;
  bool ext_svinval;
  bool ext_svnapot;
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 9d0400035f..77e7736d8a 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -63,6 +63,22 @@ int riscv_env_mmu_index(CPURISCVState *env, bool ifetch)
  #endif
  }
  
+bool riscv_env_smode_dbltrp_enabled(CPURISCVState *env, bool virt)

+{
+#ifdef CONFIG_USER_ONLY
+return false;
+#else
+if (!riscv_cpu_cfg(env)->ext_ssdbltrp) {
+return false;
+}


As we have guard the write to henvcfg and menvcfg by ext_ssdbltrp, I 
think it is enough only check henvcfg or menvcfg.


The only miss is we don't guard the writhe to henvcfgh. I think we can 
add the guard there.



+if (virt) {
+return (env->henvcfg & HENVCFG_DTE) != 0;
+} else {
+return (env->menvcfg & MENVCFG_DTE) != 0;
+}
+#endif
+}
+
  void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
uint64_t *cs_base, uint32_t *pflags)
  {
@@ -562,6 +578,10 @@ void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env)
  
  g_assert(riscv_has_ext(env, RVH));
  
+if (riscv_env_smode_dbltrp_enabled(env, current_virt)) {

+mstatus_mask |= MST

Re: [PATCH] linux-headers: loongarch: add kvm_para.h and unistd_64.h

2024-10-16 Thread maobibo

ping.

@Song

Could you give some comments since it is LoongArch specific?

Regards
Bibo Mao

On 2024/9/29 下午3:22, Bibo Mao wrote:

KVM LBT supports on LoongArch requires the linux-header kvm_para.h,
also unistd_64.h is required by unistd.h on LoongArch since 6.11

Signed-off-by: Bibo Mao 
---
  scripts/update-linux-headers.sh | 4 
  1 file changed, 4 insertions(+)

diff --git a/scripts/update-linux-headers.sh b/scripts/update-linux-headers.sh
index c34ac6454e..3c411f0318 100755
--- a/scripts/update-linux-headers.sh
+++ b/scripts/update-linux-headers.sh
@@ -186,6 +186,10 @@ EOF
  if [ $arch = riscv ]; then
  cp "$hdrdir/include/asm/ptrace.h" "$output/linux-headers/asm-riscv/"
  fi
+if [ $arch = loongarch ]; then
+cp "$hdrdir/include/asm/kvm_para.h" 
"$output/linux-headers/asm-loongarch/"
+cp "$hdrdir/include/asm/unistd_64.h" 
"$output/linux-headers/asm-loongarch/"
+fi
  done
  arch=
  


base-commit: 3b14a767eaca3df5534a162851f04787b363670e






[PATCH] vhost-user: fix shared object return values

2024-10-16 Thread Albert Esteve
VHOST_USER_BACKEND_SHARED_OBJECT_ADD and
VHOST_USER_BACKEND_SHARED_OBJECT_REMOVE state
in the spec that they return 0 for successful
operations, non-zero otherwise. However,
implementation relies on the return types
of the virtio-dmabuf library, with opposite
semantics (true if everything is correct,
false otherwise). Therefore, current implementaion
violates the specification.

Revert the logic so that the implementation
of the vhost-user handling methods matches
the specification.

Fixes: 043e127a126bb3ceb5fc753deee27d261fd0c5ce
Fixes: 160947666276c5b7f6bca4d746bcac2966635d79
Signed-off-by: Albert Esteve 
---
 hw/virtio/vhost-user.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 00561daa06..90917352a4 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -1607,7 +1607,7 @@ vhost_user_backend_handle_shared_object_add(struct 
vhost_dev *dev,
 QemuUUID uuid;
 
 memcpy(uuid.data, object->uuid, sizeof(object->uuid));
-return virtio_add_vhost_device(&uuid, dev);
+return !virtio_add_vhost_device(&uuid, dev);
 }
 
 static int
@@ -1623,16 +1623,16 @@ vhost_user_backend_handle_shared_object_remove(struct 
vhost_dev *dev,
 struct vhost_dev *owner = virtio_lookup_vhost_device(&uuid);
 if (dev != owner) {
 /* Not allowed to remove non-owned entries */
-return 0;
+return -EPERM;
 }
 break;
 }
 default:
 /* Not allowed to remove non-owned entries */
-return 0;
+return -EPERM;
 }
 
-return virtio_remove_resource(&uuid);
+return !virtio_remove_resource(&uuid);
 }
 
 static bool vhost_user_send_resp(QIOChannel *ioc, VhostUserHeader *hdr,
-- 
2.46.1




[PATCH] tests/functional: Convert most Aspeed machine tests

2024-10-16 Thread Cédric Le Goater
This is a simple conversion of the tests with some cleanups and
adjustments to match the new test framework. Replace the zephyr image
MD5 hashes with SHA256 hashes while at it.

The SDK tests depend on a ssh class from avocado.utils which is
difficult to replace. To be addressed separately.

Signed-off-by: Cédric Le Goater 
---
 tests/avocado/machine_aspeed.py | 252 --
 tests/functional/meson.build|   2 +
 tests/functional/test_arm_aspeed.py | 269 
 3 files changed, 271 insertions(+), 252 deletions(-)
 create mode 100644 tests/functional/test_arm_aspeed.py

diff --git a/tests/avocado/machine_aspeed.py b/tests/avocado/machine_aspeed.py
index 4e144bde9131..cb163e3a1106 100644
--- a/tests/avocado/machine_aspeed.py
+++ b/tests/avocado/machine_aspeed.py
@@ -19,258 +19,6 @@
 from avocado_qemu import has_cmd
 from avocado.utils import archive
 from avocado import skipUnless
-from avocado import skipUnless
-
-
-class AST1030Machine(QemuSystemTest):
-"""Boots the zephyr os and checks that the console is operational"""
-
-timeout = 10
-
-def test_ast1030_zephyros_1_04(self):
-"""
-:avocado: tags=arch:arm
-:avocado: tags=machine:ast1030-evb
-:avocado: tags=os:zephyr
-"""
-tar_url = ('https://github.com/AspeedTech-BMC'
-   '/zephyr/releases/download/v00.01.04/ast1030-evb-demo.zip')
-tar_hash = '4c6a8ce3a8ba76ef1a65dae419ae3409343c4b20'
-tar_path = self.fetch_asset(tar_url, asset_hash=tar_hash)
-archive.extract(tar_path, self.workdir)
-kernel_file = self.workdir + "/ast1030-evb-demo/zephyr.elf"
-self.vm.set_console()
-self.vm.add_args('-kernel', kernel_file,
- '-nographic')
-self.vm.launch()
-wait_for_console_pattern(self, "Booting Zephyr OS")
-exec_command_and_wait_for_pattern(self, "help",
-  "Available commands")
-
-def test_ast1030_zephyros_1_07(self):
-"""
-:avocado: tags=arch:arm
-:avocado: tags=machine:ast1030-evb
-:avocado: tags=os:zephyr
-"""
-tar_url = ('https://github.com/AspeedTech-BMC'
-   '/zephyr/releases/download/v00.01.07/ast1030-evb-demo.zip')
-tar_hash = '40ac87eabdcd3b3454ce5aad11fedc72a33ecda2'
-tar_path = self.fetch_asset(tar_url, asset_hash=tar_hash)
-archive.extract(tar_path, self.workdir)
-kernel_file = self.workdir + "/ast1030-evb-demo/zephyr.bin"
-self.vm.set_console()
-self.vm.add_args('-kernel', kernel_file,
- '-nographic')
-self.vm.launch()
-wait_for_console_pattern(self, "Booting Zephyr OS")
-for shell_cmd in [
-'kernel stacks',
-'otp info conf',
-'otp info scu',
-'hwinfo devid',
-'crypto aes256_cbc_vault',
-'random get',
-'jtag JTAG1 sw_xfer high TMS',
-'adc ADC0 resolution 12',
-'adc ADC0 read 42',
-'adc ADC1 read 69',
-'i2c scan I2C_0',
-'i3c attach I3C_0',
-'hash test',
-'kernel uptime',
-'kernel reboot warm',
-'kernel uptime',
-'kernel reboot cold',
-'kernel uptime',
-]: exec_command_and_wait_for_pattern(self, shell_cmd, "uart:~$")
-
-class AST2x00Machine(QemuSystemTest):
-
-timeout = 180
-
-def wait_for_console_pattern(self, success_message, vm=None):
-wait_for_console_pattern(self, success_message,
- failure_message='Kernel panic - not syncing',
- vm=vm)
-
-def do_test_arm_aspeed(self, image):
-self.vm.set_console()
-self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw',
- '-net', 'nic')
-self.vm.launch()
-
-self.wait_for_console_pattern("U-Boot 2016.07")
-self.wait_for_console_pattern("## Loading kernel from FIT Image at 
2008")
-self.wait_for_console_pattern("Starting kernel ...")
-self.wait_for_console_pattern("Booting Linux on physical CPU 0x0")
-wait_for_console_pattern(self,
-"aspeed-smc 1e62.spi: read control register: 203b0641")
-self.wait_for_console_pattern("ftgmac100 1e66.ethernet eth0: irq ")
-self.wait_for_console_pattern("systemd[1]: Set hostname to")
-
-def test_arm_ast2400_palmetto_openbmc_v2_9_0(self):
-"""
-:avocado: tags=arch:arm
-:avocado: tags=machine:palmetto-bmc
-"""
-
-image_url = 
('https://github.com/openbmc/openbmc/releases/download/2.9.0/'
- 'obmc-phosphor-image-palmetto.static.mtd')
-image_hash = 
('3e13bbbc28e424865dc42f35ad672b10f2e82c

[PATCH v3 2/2] tpm_emulator: Read control channel response in 2 passes

2024-10-16 Thread Stefan Berger
Error responses from swtpm are typically only 4 bytes long with the
exception of a few commands that return more bytes. Therefore, read the
entire response in 2 passes and stop if the first few bytes indicate an
error response with no subsequent bytes readable. Read the rest in a 2nd
pass, if needed. This avoids getting stuck while waiting for too many
bytes. The 'getting stuck' condition has not been observed in practice so
far, though.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2615
Signed-off-by: Stefan Berger 
---
 backends/tpm/tpm_emulator.c | 65 -
 1 file changed, 49 insertions(+), 16 deletions(-)

diff --git a/backends/tpm/tpm_emulator.c b/backends/tpm/tpm_emulator.c
index b0e2fb3fc7..dfb298a16d 100644
--- a/backends/tpm/tpm_emulator.c
+++ b/backends/tpm/tpm_emulator.c
@@ -123,12 +123,17 @@ static const char *tpm_emulator_strerror(uint32_t 
tpm_result)
 }
 
 static int tpm_emulator_ctrlcmd(TPMEmulator *tpm, unsigned long cmd, void *msg,
-size_t msg_len_in, size_t msg_len_out)
+size_t msg_len_in, size_t msg_len_out_err,
+size_t msg_len_out_total)
 {
 CharBackend *dev = &tpm->ctrl_chr;
 uint32_t cmd_no = cpu_to_be32(cmd);
 ssize_t n = sizeof(uint32_t) + msg_len_in;
+size_t left_to_read = msg_len_out_total;
 uint8_t *buf = NULL;
+ptm_res res;
+off_t o = 0;
+int to_read;
 
 WITH_QEMU_LOCK_GUARD(&tpm->mutex) {
 buf = g_alloca(n);
@@ -140,11 +145,28 @@ static int tpm_emulator_ctrlcmd(TPMEmulator *tpm, 
unsigned long cmd, void *msg,
 return -1;
 }
 
-if (msg_len_out != 0) {
-n = qemu_chr_fe_read_all(dev, msg, msg_len_out);
+if (msg_len_out_err > 0) {
+to_read = msg_len_out_err;
+} else {
+to_read = left_to_read;
+}
+while (to_read > 0) {
+n = qemu_chr_fe_read_all(dev, (uint8_t *)msg + o, to_read);
 if (n <= 0) {
 return -1;
 }
+left_to_read -= n;
+if (left_to_read == 0) {
+return 0;
+}
+/* result error code is always in the first 4 bytes */
+memcpy(&res, msg, sizeof(res));
+if (res) {
+return 0;
+}
+
+o = to_read;
+to_read = left_to_read;
 }
 }
 
@@ -204,7 +226,8 @@ static int tpm_emulator_set_locality(TPMEmulator *tpm_emu, 
uint8_t locty_number,
 memset(&loc, 0, sizeof(loc));
 loc.u.req.loc = locty_number;
 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_LOCALITY, &loc,
- sizeof(loc), sizeof(loc)) < 0) {
+ sizeof(loc), sizeof(loc.u.resp.tpm_result),
+ sizeof(loc)) < 0) {
 error_setg(errp, "tpm-emulator: could not set locality : %s",
strerror(errno));
 return -1;
@@ -241,8 +264,9 @@ static int tpm_emulator_probe_caps(TPMEmulator *tpm_emu)
 {
 ptm_cap_n cap_n;
 
-if (tpm_emulator_ctrlcmd(tpm_emu, CMD_GET_CAPABILITY,
- &cap_n, 0, sizeof(cap_n)) < 0) {
+if (tpm_emulator_ctrlcmd(tpm_emu, CMD_GET_CAPABILITY, &cap_n, 0,
+ sizeof(cap_n.u.resp.tpm_result),
+ sizeof(cap_n)) < 0) {
 error_report("tpm-emulator: probing failed : %s", strerror(errno));
 return -1;
 }
@@ -292,7 +316,8 @@ static int tpm_emulator_stop_tpm(TPMBackend *tb)
 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
 ptm_res res;
 
-if (tpm_emulator_ctrlcmd(tpm_emu, CMD_STOP, &res, 0, sizeof(res)) < 0) {
+if (tpm_emulator_ctrlcmd(tpm_emu, CMD_STOP, &res, 0,
+ sizeof(ptm_res), sizeof(res)) < 0) {
 error_report("tpm-emulator: Could not stop TPM: %s",
  strerror(errno));
 return -1;
@@ -319,8 +344,9 @@ static int tpm_emulator_lock_storage(TPMEmulator *tpm_emu)
 
 /* give failing side 300 * 10ms time to release lock */
 pls.u.req.retries = cpu_to_be32(300);
-if (tpm_emulator_ctrlcmd(tpm_emu, CMD_LOCK_STORAGE, &pls,
- sizeof(pls.u.req), sizeof(pls.u.resp)) < 0) {
+if (tpm_emulator_ctrlcmd(tpm_emu, CMD_LOCK_STORAGE, &pls, 
sizeof(pls.u.req),
+ sizeof(pls.u.resp.tpm_result),
+ sizeof(pls.u.resp)) < 0) {
 error_report("tpm-emulator: Could not lock storage within 3 seconds: "
  "%s", strerror(errno));
 return -1;
@@ -351,7 +377,8 @@ static int tpm_emulator_set_buffer_size(TPMBackend *tb,
 psbs.u.req.buffersize = cpu_to_be32(wanted_size);
 
 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_BUFFERSIZE, &psbs,
- sizeof(psbs.u.req), sizeof(psbs.u.resp)) < 0) {
+ sizeof(psbs.u.req), 
siz

[PATCH v3 1/2] tpm: Use new ptm_cap_n structure for PTM_GET_CAPABILITY

2024-10-16 Thread Stefan Berger
Use the new ptm_cap_n structure for getting the PTM_GET_CAPABILITY response
from swtpm. Previously only 17 bits could possibly have been set in ptm_cap
(=uint64_t) in big endian order and those bits are now found in the 2nd
32bit word in the response in the caps field.

This data structure makes it now clear that the 1st 32bit word carries the
tpm_result like all the other response structures of all other commands
do.

Signed-off-by: Stefan Berger 
---
 backends/tpm/tpm_emulator.c | 14 --
 backends/tpm/tpm_ioctl.h| 13 -
 backends/tpm/trace-events   |  2 +-
 3 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/backends/tpm/tpm_emulator.c b/backends/tpm/tpm_emulator.c
index 5a8fba9bde..b0e2fb3fc7 100644
--- a/backends/tpm/tpm_emulator.c
+++ b/backends/tpm/tpm_emulator.c
@@ -72,7 +72,7 @@ struct TPMEmulator {
 CharBackend ctrl_chr;
 QIOChannel *data_ioc;
 TPMVersion tpm_version;
-ptm_cap caps; /* capabilities of the TPM */
+uint32_t caps; /* capabilities of the TPM */
 uint8_t cur_locty_number; /* last set locality */
 Error *migration_blocker;
 
@@ -239,13 +239,15 @@ static void tpm_emulator_handle_request(TPMBackend *tb, 
TPMBackendCmd *cmd,
 
 static int tpm_emulator_probe_caps(TPMEmulator *tpm_emu)
 {
+ptm_cap_n cap_n;
+
 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_GET_CAPABILITY,
- &tpm_emu->caps, 0, sizeof(tpm_emu->caps)) < 0) {
+ &cap_n, 0, sizeof(cap_n)) < 0) {
 error_report("tpm-emulator: probing failed : %s", strerror(errno));
 return -1;
 }
 
-tpm_emu->caps = be64_to_cpu(tpm_emu->caps);
+tpm_emu->caps = be32_to_cpu(cap_n.u.resp.caps);
 
 trace_tpm_emulator_probe_caps(tpm_emu->caps);
 
@@ -254,7 +256,7 @@ static int tpm_emulator_probe_caps(TPMEmulator *tpm_emu)
 
 static int tpm_emulator_check_caps(TPMEmulator *tpm_emu)
 {
-ptm_cap caps = 0;
+uint32_t caps = 0;
 const char *tpm = NULL;
 
 /* check for min. required capabilities */
@@ -527,8 +529,8 @@ static size_t tpm_emulator_get_buffer_size(TPMBackend *tb)
 static int tpm_emulator_block_migration(TPMEmulator *tpm_emu)
 {
 Error *err = NULL;
-ptm_cap caps = PTM_CAP_GET_STATEBLOB | PTM_CAP_SET_STATEBLOB |
-   PTM_CAP_STOP;
+uint32_t caps = PTM_CAP_GET_STATEBLOB | PTM_CAP_SET_STATEBLOB |
+PTM_CAP_STOP;
 
 if (!TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(tpm_emu, caps)) {
 error_setg(&tpm_emu->migration_blocker,
diff --git a/backends/tpm/tpm_ioctl.h b/backends/tpm/tpm_ioctl.h
index 1933ab6855..ee2dd15d35 100644
--- a/backends/tpm/tpm_ioctl.h
+++ b/backends/tpm/tpm_ioctl.h
@@ -29,6 +29,16 @@
 
 typedef uint32_t ptm_res;
 
+/* PTM_GET_CAPABILITY: Get supported capabilities (ioctl's) */
+struct ptm_cap_n {
+union {
+struct {
+ptm_res tpm_result; /* will always be TPM_SUCCESS (0) */
+uint32_t caps;
+} resp; /* response */
+} u;
+};
+
 /* PTM_GET_TPMESTABLISHED: get the establishment bit */
 struct ptm_est {
 union {
@@ -242,7 +252,8 @@ struct ptm_lockstorage {
 } u;
 };
 
-typedef uint64_t ptm_cap;
+typedef uint64_t ptm_cap; /* CUSE-only; use ptm_cap_n otherwise */
+typedef struct ptm_cap_n ptm_cap_n;
 typedef struct ptm_est ptm_est;
 typedef struct ptm_reset_est ptm_reset_est;
 typedef struct ptm_loc ptm_loc;
diff --git a/backends/tpm/trace-events b/backends/tpm/trace-events
index cb5cfa6510..05e30533ce 100644
--- a/backends/tpm/trace-events
+++ b/backends/tpm/trace-events
@@ -16,7 +16,7 @@ tpm_util_show_buffer_content(const char *buf) "%s"
 # tpm_emulator.c
 tpm_emulator_set_locality(uint8_t locty) "setting locality to %d"
 tpm_emulator_handle_request(void) "processing TPM command"
-tpm_emulator_probe_caps(uint64_t caps) "capabilities: 0x%"PRIx64
+tpm_emulator_probe_caps(uint32_t caps) "capabilities: 0x%x"
 tpm_emulator_set_buffer_size(uint32_t buffersize, uint32_t minsize, uint32_t 
maxsize) "buffer size: %u, min: %u, max: %u"
 tpm_emulator_startup_tpm_resume(bool is_resume, size_t buffersize) "is_resume: 
%d, buffer size: %zu"
 tpm_emulator_get_tpm_established_flag(uint8_t flag) "got established flag: %d"
-- 
2.47.0




[PATCH v3 0/2] tpm: Resolve potential blocking-forever issue

2024-10-16 Thread Stefan Berger
In case swtpm was to return a control channel message with an error code it
would often return less bytes than the full response. In some cases the
current reading of the returned bytes would get stuck since more bytes are
expected. Therefore, pass a separate parameter indicating how many bytes to
expect in case of an error and read that many bytes in a first pass. Check
for an error code in the first 4 bytes. Read the rest in a 2nd pass.

   Stefan

v3:
  - 2/2: Pass size of return response for error as parameter

v2:
  - 2/2: Added special handling of CMD_GET_STATEBLOB



Stefan Berger (2):
  tpm: Use new ptm_cap_n structure for PTM_GET_CAPABILITY
  tpm_emulator: Read control channel response in 2 passes

 backends/tpm/tpm_emulator.c | 77 +++--
 backends/tpm/tpm_ioctl.h| 13 ++-
 backends/tpm/trace-events   |  2 +-
 3 files changed, 69 insertions(+), 23 deletions(-)

-- 
2.47.0




Re: [PATCH v3 1/2] tpm: Use new ptm_cap_n structure for PTM_GET_CAPABILITY

2024-10-16 Thread Daniel P . Berrangé
On Wed, Oct 16, 2024 at 10:57:07AM -0400, Stefan Berger wrote:
> Use the new ptm_cap_n structure for getting the PTM_GET_CAPABILITY response
> from swtpm. Previously only 17 bits could possibly have been set in ptm_cap
> (=uint64_t) in big endian order and those bits are now found in the 2nd
> 32bit word in the response in the caps field.
> 
> This data structure makes it now clear that the 1st 32bit word carries the
> tpm_result like all the other response structures of all other commands
> do.
> 
> Signed-off-by: Stefan Berger 
> ---
>  backends/tpm/tpm_emulator.c | 14 --
>  backends/tpm/tpm_ioctl.h| 13 -
>  backends/tpm/trace-events   |  2 +-
>  3 files changed, 21 insertions(+), 8 deletions(-)
> 

> diff --git a/backends/tpm/tpm_ioctl.h b/backends/tpm/tpm_ioctl.h
> index 1933ab6855..ee2dd15d35 100644
> --- a/backends/tpm/tpm_ioctl.h
> +++ b/backends/tpm/tpm_ioctl.h
> @@ -29,6 +29,16 @@
>  
>  typedef uint32_t ptm_res;
>  
> +/* PTM_GET_CAPABILITY: Get supported capabilities (ioctl's) */
> +struct ptm_cap_n {
> +union {
> +struct {
> +ptm_res tpm_result; /* will always be TPM_SUCCESS (0) */
> +uint32_t caps;
> +} resp; /* response */
> +} u;
> +};

The union here is pointless surely, since it only has one entry and
the following patch doesn't add a 2nd either ? 


With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




Re: [PATCH 14/14] qtest/xive: Add test of pool interrupts

2024-10-16 Thread Mike Kowal

On 10/16/2024 3:33 AM, Thomas Huth wrote:

On 15/10/2024 23.13, Michael Kowal wrote:

From: Glenn Miles 

Added new test for pool interrupts.

Signed-off-by: Glenn Miles 
Signed-off-by: Michael Kowal 
---
  tests/qtest/pnv-xive2-test.c | 77 
  1 file changed, 77 insertions(+)

diff --git a/tests/qtest/pnv-xive2-test.c b/tests/qtest/pnv-xive2-test.c
index a6008bc053..6e7e7f0d9b 100644
--- a/tests/qtest/pnv-xive2-test.c
+++ b/tests/qtest/pnv-xive2-test.c
@@ -4,6 +4,7 @@
   *  - Test 'Pull Thread Context to Odd Thread Reporting Line'
   *  - Test irq to hardware group
   *  - Test irq to hardware group going through backlog
+ *  - Test irq to pool thread
   *
   * Copyright (c) 2024, IBM Corporation.
   *



Just an FYI that I forgot to rebase the the Group 3 XIVE qtest changes 
into these patch sets...  and will be done for version 2.


MAK



@@ -267,6 +268,79 @@ static void test_hw_irq(QTestState *qts)
  g_assert_cmphex(cppr, ==, 0xFF);
  }
  +static void test_pool_irq(QTestState *qts)
+{
+    uint32_t irq = 2;
+    uint32_t irq_data = 0x600d0d06;
+    uint32_t end_index = 5;
+    uint32_t target_pir = 1;
+    uint32_t target_nvp = 0x100 + target_pir;
+    uint8_t priority = 5;
+    uint32_t reg32;
+    uint16_t reg16;
+    uint8_t pq, nsr, cppr, ipb;
+
+    printf("# 
\n");

+    printf("# Testing irq %d to pool thread %d\n", irq, target_pir);


Please don't use direct printfs in the qtest framework. If you really 
have to log stuff, use g_test_message() instead.


 Thomas





Re: [PATCH v3 1/4] migration: Move cpu-throttole.c from system to migration

2024-10-16 Thread Peter Xu
On Wed, Oct 16, 2024 at 03:56:42PM +0800, yong.hu...@smartx.com wrote:
> From: Hyman Huang 
> 
> Move cpu-throttle.c from system to migration since it's
> only used for migration; this makes us avoid exporting the
> util functions and variables in misc.h but export them in
> migration.h when implementing the background ramblock dirty
> sync feature in the upcoming commits.
> 
> Additionally, make the two modifications below:
> 
> 1. Delay the timer registering of CPU throttle until
>migration starts since it is only used in migration.
> 
> 2. Stop CPU throttle if auto converge capability is
>enabled since it only happens with auto converge.
> 
> 3. Remove the unused header file reference in
>accel/tcg/icount-common.c.

Please consider split the things into smaller patches, especially when it
involves file movements.

> 
> Signed-off-by: Hyman Huang 
> ---
>  accel/tcg/icount-common.c|  1 -
>  {system => migration}/cpu-throttle.c |  2 +-
>  {include/sysemu => migration}/cpu-throttle.h |  0
>  migration/meson.build|  1 +
>  migration/migration.c| 11 +--
>  migration/ram.c  |  2 +-
>  migration/trace-events   |  3 +++
>  system/cpu-timers.c  |  3 ---
>  system/meson.build   |  1 -
>  system/trace-events  |  3 ---
>  10 files changed, 15 insertions(+), 12 deletions(-)
>  rename {system => migration}/cpu-throttle.c (99%)
>  rename {include/sysemu => migration}/cpu-throttle.h (100%)
> 
> diff --git a/accel/tcg/icount-common.c b/accel/tcg/icount-common.c
> index 8d3d3a7e9d..30bf8500dc 100644
> --- a/accel/tcg/icount-common.c
> +++ b/accel/tcg/icount-common.c
> @@ -36,7 +36,6 @@
>  #include "sysemu/runstate.h"
>  #include "hw/core/cpu.h"
>  #include "sysemu/cpu-timers.h"
> -#include "sysemu/cpu-throttle.h"
>  #include "sysemu/cpu-timers-internal.h"
>  
>  /*
> diff --git a/system/cpu-throttle.c b/migration/cpu-throttle.c
> similarity index 99%
> rename from system/cpu-throttle.c
> rename to migration/cpu-throttle.c
> index 7632dc6143..fa47ee2e21 100644
> --- a/system/cpu-throttle.c
> +++ b/migration/cpu-throttle.c
> @@ -27,7 +27,7 @@
>  #include "hw/core/cpu.h"
>  #include "qemu/main-loop.h"
>  #include "sysemu/cpus.h"
> -#include "sysemu/cpu-throttle.h"
> +#include "cpu-throttle.h"
>  #include "trace.h"
>  
>  /* vcpu throttling controls */
> diff --git a/include/sysemu/cpu-throttle.h b/migration/cpu-throttle.h
> similarity index 100%
> rename from include/sysemu/cpu-throttle.h
> rename to migration/cpu-throttle.h
> diff --git a/migration/meson.build b/migration/meson.build
> index 66d3de86f0..d53cf3417a 100644
> --- a/migration/meson.build
> +++ b/migration/meson.build
> @@ -13,6 +13,7 @@ system_ss.add(files(
>'block-dirty-bitmap.c',
>'channel.c',
>'channel-block.c',
> +  'cpu-throttle.c',
>'dirtyrate.c',
>'exec.c',
>'fd.c',
> diff --git a/migration/migration.c b/migration/migration.c
> index 021faee2f3..7e71184257 100644
> --- a/migration/migration.c
> +++ b/migration/migration.c
> @@ -24,7 +24,7 @@
>  #include "socket.h"
>  #include "sysemu/runstate.h"
>  #include "sysemu/sysemu.h"
> -#include "sysemu/cpu-throttle.h"
> +#include "cpu-throttle.h"
>  #include "rdma.h"
>  #include "ram.h"
>  #include "migration/global_state.h"
> @@ -3289,7 +3289,9 @@ static MigIterateState 
> migration_iteration_run(MigrationState *s)
>  static void migration_iteration_finish(MigrationState *s)
>  {
>  /* If we enabled cpu throttling for auto-converge, turn it off. */
> -cpu_throttle_stop();
> +if (migrate_auto_converge()) {
> +cpu_throttle_stop();
> +}
>  
>  bql_lock();
>  switch (s->state) {
> @@ -3508,6 +3510,11 @@ static void *migration_thread(void *opaque)
>  qemu_savevm_send_colo_enable(s->to_dst_file);
>  }
>  
> +if (migrate_auto_converge()) {
> +/* Start cpu throttle timers */
> +cpu_throttle_init();
> +}

Might this leak the timer object? 

I think it perhaps needs to be moved to migration_object_init().

> +
>  bql_lock();
>  ret = qemu_savevm_state_setup(s->to_dst_file, &local_err);
>  bql_unlock();
> diff --git a/migration/ram.c b/migration/ram.c
> index 326ce7eb79..54d352b152 100644
> --- a/migration/ram.c
> +++ b/migration/ram.c
> @@ -52,7 +52,7 @@
>  #include "exec/target_page.h"
>  #include "qemu/rcu_queue.h"
>  #include "migration/colo.h"
> -#include "sysemu/cpu-throttle.h"
> +#include "cpu-throttle.h"
>  #include "savevm.h"
>  #include "qemu/iov.h"
>  #include "multifd.h"
> diff --git a/migration/trace-events b/migration/trace-events
> index c65902f042..9a19599804 100644
> --- a/migration/trace-events
> +++ b/migration/trace-events
> @@ -378,3 +378,6 @@ migration_block_progression(unsigned percent) "Completed 
> %u%%"
>  # page_cache.c
>  migration_pagecache_init(int64_t max_num_items) "Setting c

Re: [PATCH v3 2/4] migration: Remove "rs" parameter in migration_bitmap_sync_precopy

2024-10-16 Thread Peter Xu
On Wed, Oct 16, 2024 at 03:56:43PM +0800, yong.hu...@smartx.com wrote:
> From: Hyman Huang 
> 
> The global static variable ram_state in fact is referred to by the
> "rs" parameter in migration_bitmap_sync_precopy. For ease of calling
> by the callees, use the global variable directly in
> migration_bitmap_sync_precopy and remove "rs" parameter.
> 
> The migration_bitmap_sync_precopy will be exported in the next commit.
> 
> Signed-off-by: Hyman Huang 

Reviewed-by: Peter Xu 

-- 
Peter Xu




Re: [PATCH v3 2/2] tpm_emulator: Read control channel response in 2 passes

2024-10-16 Thread Daniel P . Berrangé
On Wed, Oct 16, 2024 at 10:57:08AM -0400, Stefan Berger wrote:
> Error responses from swtpm are typically only 4 bytes long with the
> exception of a few commands that return more bytes. Therefore, read the
> entire response in 2 passes and stop if the first few bytes indicate an
> error response with no subsequent bytes readable. Read the rest in a 2nd
> pass, if needed. This avoids getting stuck while waiting for too many
> bytes. The 'getting stuck' condition has not been observed in practice so
> far, though.
> 
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2615
> Signed-off-by: Stefan Berger 
> ---
>  backends/tpm/tpm_emulator.c | 65 -
>  1 file changed, 49 insertions(+), 16 deletions(-)
> 
> diff --git a/backends/tpm/tpm_emulator.c b/backends/tpm/tpm_emulator.c
> index b0e2fb3fc7..dfb298a16d 100644
> --- a/backends/tpm/tpm_emulator.c
> +++ b/backends/tpm/tpm_emulator.c
> @@ -123,12 +123,17 @@ static const char *tpm_emulator_strerror(uint32_t 
> tpm_result)
>  }
>  
>  static int tpm_emulator_ctrlcmd(TPMEmulator *tpm, unsigned long cmd, void 
> *msg,
> -size_t msg_len_in, size_t msg_len_out)
> +size_t msg_len_in, size_t msg_len_out_err,
> +size_t msg_len_out_total)
>  {
>  CharBackend *dev = &tpm->ctrl_chr;
>  uint32_t cmd_no = cpu_to_be32(cmd);
>  ssize_t n = sizeof(uint32_t) + msg_len_in;
> +size_t left_to_read = msg_len_out_total;
>  uint8_t *buf = NULL;
> +ptm_res res;
> +off_t o = 0;
> +int to_read;
>  
>  WITH_QEMU_LOCK_GUARD(&tpm->mutex) {
>  buf = g_alloca(n);
> @@ -140,11 +145,28 @@ static int tpm_emulator_ctrlcmd(TPMEmulator *tpm, 
> unsigned long cmd, void *msg,
>  return -1;
>  }
>  
> -if (msg_len_out != 0) {
> -n = qemu_chr_fe_read_all(dev, msg, msg_len_out);
> +if (msg_len_out_err > 0) {
> +to_read = msg_len_out_err;
> +} else {
> +to_read = left_to_read;
> +}
> +while (to_read > 0) {
> +n = qemu_chr_fe_read_all(dev, (uint8_t *)msg + o, to_read);
>  if (n <= 0) {
>  return -1;
>  }
> +left_to_read -= n;
> +if (left_to_read == 0) {
> +return 0;
> +}
> +/* result error code is always in the first 4 bytes */
> +memcpy(&res, msg, sizeof(res));
> +if (res) {
> +return 0;
> +}
> +
> +o = to_read;
> +to_read = left_to_read;
>  }

Using qemu_chr_fe_read_all in a loop feels like an anti-pattern, since
it will always read exactly the full amount you ask, or return an error.

IOW, there code here is a rather confusing way to do exactly 2 reads
of the required size.  I think it'd be much clearer to just read in
two steps, without a loop like this:

  n = qemu_chr_fe_read_all(dev, (uint8_t *)msg, msg_len_out_err);
  if (n != msg_len_out_err) {
return -1;
  }
 
  /* result error code is always in the first 4 bytes */
  memcpy(&res, msg, sizeof(res));
  if (res) {
 return 0;
  }

  assert(msg_len_out_err <= msg_len_out_total);
  msg_len_out_total -= msg_len_out_err;
  n = qemu_chr_fe_read_all(dev, (uint8_t *)msg + msg_len_out_err,
   msg_len_out_total);
  if (n != msg_len_out_total) {
return -1;
  }

  return 0;

With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




[PATCH] tests: Wait for migration completion on destination QEMU to avoid failures

2024-10-16 Thread Stefan Berger
Rather than waiting for the completion of migration on the source side,
wait for it on the destination QEMU side to avoid accessing the TPM TIS
memory mapped registers before QEMU could restore their state. This
error condition could be triggered on busy systems where the destination
QEMU did not have enough time to restore the TIS state while the test case
was already reading its registers. The test case was for example reading
the STS register and received an unexpected value (0x), which
lead to a segmentation fault later on due to trying to read 0x bytes
from the TIS into a buffer.

Cc: qemu-sta...@nongnu.org
Reported-by: Fabiano Rosas 
Signed-off-by: Stefan Berger 
---
 tests/qtest/tpm-tests.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/qtest/tpm-tests.c b/tests/qtest/tpm-tests.c
index fb94496bbd..197714f8d9 100644
--- a/tests/qtest/tpm-tests.c
+++ b/tests/qtest/tpm-tests.c
@@ -114,7 +114,7 @@ void tpm_test_swtpm_migration_test(const char *src_tpm_path,
  sizeof(tpm_pcrread_resp));
 
 tpm_util_migrate(src_qemu, uri);
-tpm_util_wait_for_migration_complete(src_qemu);
+tpm_util_wait_for_migration_complete(dst_qemu);
 
 tpm_util_pcrread(dst_qemu, tx, tpm_pcrread_resp,
  sizeof(tpm_pcrread_resp));
-- 
2.47.0




Re: [PATCH] tests: Wait for migration completion on destination QEMU to avoid failures

2024-10-16 Thread Daniel P . Berrangé
On Wed, Oct 16, 2024 at 11:21:59AM -0400, Stefan Berger wrote:
> Rather than waiting for the completion of migration on the source side,
> wait for it on the destination QEMU side to avoid accessing the TPM TIS
> memory mapped registers before QEMU could restore their state. This
> error condition could be triggered on busy systems where the destination
> QEMU did not have enough time to restore the TIS state while the test case
> was already reading its registers. The test case was for example reading
> the STS register and received an unexpected value (0x), which
> lead to a segmentation fault later on due to trying to read 0x bytes
> from the TIS into a buffer.
> 
> Cc: qemu-sta...@nongnu.org
> Reported-by: Fabiano Rosas 
> Signed-off-by: Stefan Berger 
> ---
>  tests/qtest/tpm-tests.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Reviewed-by: Daniel P. Berrangé 


With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




Re: [PATCH] migration/dirtyrate: Silence warning about strcpy() on OpenBSD

2024-10-16 Thread Daniel P . Berrangé
On Wed, Oct 16, 2024 at 06:07:12PM +0200, Thomas Huth wrote:
> The linker on OpenBSD complains:
> 
>  ld: warning: dirtyrate.c:447 (../src/migration/dirtyrate.c:447)(...):
>  warning: strcpy() is almost always misused, please use strlcpy()

Is that the only place it complains ?  We use 'strcpy' in almost
100 places across the codebase

> It's currently not a real problem in this case since both arrays
> have the same size (256 bytes). But just in case somebody changes
> the size of the source array in the future, let's better play safe
> and use g_strlcpy() here instead.
> 
> Signed-off-by: Thomas Huth 
> ---
>  migration/dirtyrate.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/migration/dirtyrate.c b/migration/dirtyrate.c
> index 233acb0855..090c76e934 100644
> --- a/migration/dirtyrate.c
> +++ b/migration/dirtyrate.c
> @@ -444,7 +444,7 @@ static void get_ramblock_dirty_info(RAMBlock *block,
>  info->ramblock_pages = qemu_ram_get_used_length(block) >>
> qemu_target_page_bits();
>  info->ramblock_addr = qemu_ram_get_host_addr(block);
> -strcpy(info->idstr, qemu_ram_get_idstr(block));
> +g_strlcpy(info->idstr, qemu_ram_get_idstr(block), sizeof(info->idstr));
>  }

Reviewed-by: Daniel P. Berrangé 


Is it worth also adding

  G_STATIC_ASSERT(sizeof((struct RamblockDirtyInfo){}.idstr) ==
  sizeof((struct RAMBlock){}.idstr));

at the top of this file, since both of these fields are expected to
be the same size by this code, to avoid truncation.


With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




[PATCH 0/1] Insert LibSPDM in QEMU enabling in-tree compilation

2024-10-16 Thread htafr
(I) Summary
===

This patch is the beginning of the support of the Security Protocol and 
Data Model (SPDM). There are some known issues (see II), but it's
usable and not many users are going to use this functionality for now,
but for those who will it may facilitate the development.

There are some people working with LibSPDM to implement the SPDM on 
emulated devices, however current works that use QEMU compile LibSPDM
out-of-tree [1][2][3]. This patch enables the compilation of LibSPDM when 
user pass the parameter '--enable-libspdm' to configure file, this option 
is disabled by default. The following parameters were also added:

  --libspdm-crypto=CHOICE  set LibSPDM crypto algorithm [mbedtls] (choices:
   mbedtls/openssl)
  --libspdm-toolchain=VALUE
   toolchain to use for LibSPDM compilation [GCC]

In order to facilitate future code development using LibSPDM API, this
patch also provides the definition of the macro 'CONFIG_LIBSPDM'.


(II) Known Limitations
===

1. This patch enables LibSPDM in-tree compilation for Linux systems only.
2. LibSPDM compilation uses CMake, so meson build system is making use
   of the CMake module [4].
3. Some problems may occur when compiling LibSPDM with MbedTls such as:
error: "_GNU_SOURCE" redefined [-Werror]
  10 | #define _GNU_SOURCE

   It's possible to compile using --disable-werror.

(III) Sample configuration
===

../configure \
  --disable-werror \
  --enable-libspdm \
  --libspdm-crypto=mbedtls \
  --enable-gcov

References:
[1] riscv-spdm 
  Link: https://github.com/htafr/riscv-spdm
[2] spdm-benchmark 
  Link: https://github.com/rcaalves/spdm-benchmark
[3] qemu-spdm-emulation-guide
  Link: https://github.com/twilfredo/qemu-spdm-emulation-guide
[4] The Meson Build System: CMake module
  Link: https://mesonbuild.com/CMake-module.html

htafr (1):
  libspdm: insert LibSPDM as subproject

 .gitmodules   |  3 ++
 Kconfig.host  |  3 ++
 meson.build   | 84 +++
 meson_options.txt |  8 
 scripts/make-config-poison.sh | 19 
 scripts/meson-buildoptions.sh |  9 
 6 files changed, 117 insertions(+), 9 deletions(-)

-- 
2.43.0




[PATCH 1/1] libspdm: insert LibSPDM as subproject

2024-10-16 Thread htafr
Signed-off-by: htafr 
---
 .gitmodules   |  3 ++
 Kconfig.host  |  3 ++
 meson.build   | 84 +++
 meson_options.txt |  8 
 scripts/make-config-poison.sh | 19 
 scripts/meson-buildoptions.sh |  9 
 6 files changed, 117 insertions(+), 9 deletions(-)

diff --git a/.gitmodules b/.gitmodules
index 73cae4cd4d..1bf93427ad 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -43,3 +43,6 @@
 [submodule "tests/lcitool/libvirt-ci"]
path = tests/lcitool/libvirt-ci
url = https://gitlab.com/libvirt/libvirt-ci.git
+[submodule "subprojects/libspdm"]
+   path = subprojects/libspdm
+   url = https://github.com/DMTF/libspdm.git
diff --git a/Kconfig.host b/Kconfig.host
index 4ade7899d6..80bde9eb3d 100644
--- a/Kconfig.host
+++ b/Kconfig.host
@@ -23,6 +23,9 @@ config IVSHMEM
 config TPM
 bool
 
+config SPDM
+bool
+
 config FDT
 bool
 
diff --git a/meson.build b/meson.build
index d26690ce20..40bef9a5cc 100644
--- a/meson.build
+++ b/meson.build
@@ -17,6 +17,7 @@ not_found = dependency('', required: false)
 keyval = import('keyval')
 ss = import('sourceset')
 fs = import('fs')
+cmake = import('cmake')
 
 host_os = host_machine.system()
 config_host = keyval.load(meson.current_build_dir() / 'config-host.mak')
@@ -163,6 +164,10 @@ have_tpm = get_option('tpm') \
   .require(host_os != 'windows', error_message: 'TPM emulation only available 
on POSIX systems') \
   .allowed()
 
+have_libspdm = get_option('libspdm') \
+  .require(host_os == 'linux', error_message: 'LibSPDM is supported only on 
Linux') \
+  .allowed()
+
 # vhost
 have_vhost_user = get_option('vhost_user') \
   .disable_auto_if(host_os != 'linux') \
@@ -280,6 +285,65 @@ if host_os != 'darwin'
   modular_tcg = ['i386-softmmu', 'x86_64-softmmu']
 endif
 
+libspdm_dep_targets = [
+  'debuglib',
+  'malloclib',
+  'memlib',
+  'platform_lib',
+  'rnglib',
+  'spdm_cert_verify_callback_sample',
+  'spdm_common_lib',
+  'spdm_crypt_ext_lib',
+  'spdm_crypt_lib',
+  'spdm_device_secret_lib_sample',
+  'spdm_requester_lib',
+  'spdm_responder_lib',
+  'spdm_secured_message_lib',
+  'spdm_transport_mctp_lib',
+  'spdm_transport_pcidoe_lib',
+  ]
+
+if cpu not in supported_cpus
+  libspdm_host_arch = 'unknown'
+  message(f'LibSPDM will not compile with CMake defines: 
-DARCH=@libspdm_host_arch@')
+elif cpu == 'x86_64'
+  libspdm_host_arch = 'x64'
+elif cpu == 'x86'
+  libspdm_host_arch = 'ia32'
+elif cpu == 'arm'
+  libspdm_host_arch = 'arm'
+elif cpu == 'aarch64'
+  libspdm_host_arch = 'aarch64'
+else
+  libspdm_host_arch = cpu
+endif
+
+if get_option('debug')
+  libspdm_target = 'Debug'
+else 
+  libspdm_target = 'Release'
+endif
+
+if get_option('libspdm-crypto') == 'openssl'
+  libspdm_dep_targets += [
+'cryptlib_openssl',
+'openssllib',
+  ]
+elif get_option('libspdm-crypto') == 'mbedtls'
+  libspdm_dep_targets += [
+'cryptlib_mbedtls',
+'mbedcrypto',
+'mbedtls',
+'mbedx509',
+  ]
+endif
+
+if get_option('b_coverage')
+  libspdm_gcov = 'ON'
+else 
+  libspdm_gcov = 'OFF'
+endif
+
 ##
 # Compiler flags #
 ##
@@ -2409,6 +2473,7 @@ if get_option('tcg').allowed()
   config_host_data.set('CONFIG_TCG', 1)
   config_host_data.set('CONFIG_TCG_INTERPRETER', tcg_arch == 'tci')
 endif
+config_host_data.set('CONFIG_LIBSPDM', have_libspdm)
 config_host_data.set('CONFIG_TPM', have_tpm)
 config_host_data.set('CONFIG_TSAN', get_option('tsan'))
 config_host_data.set('CONFIG_USB_LIBUSB', libusb.found())
@@ -3310,6 +3375,23 @@ if have_libvduse
   libvduse = libvduse_proj.get_variable('libvduse_dep')
 endif
 
+spdm = []
+if have_libspdm
+  libspdm_opt = cmake.subproject_options()
+  libspdm_opt.add_cmake_defines({'ARCH': libspdm_host_arch, \
+ 'TOOLCHAIN': get_option('libspdm-toolchain'), 
\
+ 'TARGET': libspdm_target, \
+ 'CRYPTO': get_option('libspdm-crypto'), \
+ 'DISABLE_TESTS': 1, \
+ 'GCOV': libspdm_gcov, \
+ 'BUILD_LINUX_SHARED_LIB': 'ON'})
+  libspdm_proj = cmake.subproject('libspdm', options: libspdm_opt)
+
+  foreach dep : libspdm_dep_targets
+spdm += libspdm_proj.dependency(dep)
+  endforeach
+endif
+
 #
 # Generated sources #
 #
@@ -3892,6 +3974,7 @@ common_ss.add(hwcore)
 ###
 
 system_ss.add(authz, blockdev, chardev, crypto, io, qmp)
+system_ss.add(when: spdm, if_true: spdm)
 common_ss.add(qom, qemuutil)
 
 common_ss.add_all(when: 'CONFIG_SYSTEM_ONLY', if_true: [system_ss])
@@ -4574,6 +4657,7 @@ summary_info += {'AF_ALG support':have_afalg}
 summary_info += {'rng-none':  get_option('rng_none')}
 summary_info += {'Linux keyring': have_keyring}
 summary_info += {'Linux keyutils':keyutils}
+summary_info += {'LibSPDM algorithm': get_op

Re: [PULL 13/25] target/i386: convert CMPXCHG8B/CMPXCHG16B to new decoder

2024-10-16 Thread Philippe Mathieu-Daudé

Hi,

On 15/10/24 11:16, Paolo Bonzini wrote:

The gen_cmpxchg8b and gen_cmpxchg16b functions even have the correct
prototype already; the only thing that needs to be done is removing the
gen_lea_modrm() call.

This moves the last LOCK-enabled instructions to the new decoder.  It is
now possible to assume that gen_multi0F is called only after checking
that PREFIX_LOCK was not specified.

Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
  target/i386/tcg/decode-new.h |   2 +
  target/i386/tcg/translate.c  | 121 +--
  target/i386/tcg/decode-new.c.inc |  34 ++---
  target/i386/tcg/emit.c.inc   |  96 
  4 files changed, 124 insertions(+), 129 deletions(-)




+static void gen_CMPXCHG8B(DisasContext *s, X86DecodedInsn *decode)
+{
+TCGv_i64 cmp, val, old;
+TCGv Z;
+
+cmp = tcg_temp_new_i64();
+val = tcg_temp_new_i64();
+old = tcg_temp_new_i64();
+
+/* Construct the comparison values from the register pair. */
+tcg_gen_concat_tl_i64(cmp, cpu_regs[R_EAX], cpu_regs[R_EDX]);
+tcg_gen_concat_tl_i64(val, cpu_regs[R_EBX], cpu_regs[R_ECX]);
+
+/* Only require atomic with LOCK; non-parallel handled in generator. */
+if (s->prefix & PREFIX_LOCK) {
+tcg_gen_atomic_cmpxchg_i64(old, s->A0, cmp, val, s->mem_index, 
MO_TEUQ);
+} else {
+tcg_gen_nonatomic_cmpxchg_i64(old, s->A0, cmp, val,
+  s->mem_index, MO_TEUQ);
+}
+
+/* Set tmp0 to match the required value of Z. */
+tcg_gen_setcond_i64(TCG_COND_EQ, cmp, old, cmp);
+Z = tcg_temp_new();
+tcg_gen_trunc_i64_tl(Z, cmp);
+
+/*
+ * Extract the result values for the register pair.
+ * For 32-bit, we may do this unconditionally, because on success (Z=1),
+ * the old value matches the previous value in EDX:EAX.  For x86_64,
+ * the store must be conditional, because we must leave the source
+ * registers unchanged on success, and zero-extend the writeback
+ * on failure (Z=0).
+ */
+if (TARGET_LONG_BITS == 32) {
+tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], old);
+} else {
+TCGv zero = tcg_constant_tl(0);
+
+tcg_gen_extr_i64_tl(s->T0, s->T1, old);
+tcg_gen_movcond_tl(TCG_COND_EQ, cpu_regs[R_EAX], Z, zero,
+   s->T0, cpu_regs[R_EAX]);
+tcg_gen_movcond_tl(TCG_COND_EQ, cpu_regs[R_EDX], Z, zero,
+   s->T1, cpu_regs[R_EDX]);
+}
+
+/* Update Z. */
+gen_compute_eflags(s);
+tcg_gen_deposit_tl(cpu_cc_src, cpu_cc_src, Z, ctz32(CC_Z), 1);
+}


On s390x the cdrom-test generates:

tcg/s390x/tcg-target.c.inc:1284:tgen_cmp2: code should not be reached



Re: [PATCH v6 3/3] Add support for RAPL MSRs in KVM/Qemu

2024-10-16 Thread Igor Mammedov
On Wed, 22 May 2024 17:34:52 +0200
Anthony Harivel  wrote:

> Starting with the "Sandy Bridge" generation, Intel CPUs provide a RAPL
> interface (Running Average Power Limit) for advertising the accumulated
> energy consumption of various power domains (e.g. CPU packages, DRAM,
> etc.).
> 
> The consumption is reported via MSRs (model specific registers) like
> MSR_PKG_ENERGY_STATUS for the CPU package power domain. These MSRs are
> 64 bits registers that represent the accumulated energy consumption in
> micro Joules. They are updated by microcode every ~1ms.
> 
> For now, KVM always returns 0 when the guest requests the value of
> these MSRs. Use the KVM MSR filtering mechanism to allow QEMU handle
> these MSRs dynamically in userspace.
> 
> To limit the amount of system calls for every MSR call, create a new
> thread in QEMU that updates the "virtual" MSR values asynchronously.
> 
> Each vCPU has its own vMSR to reflect the independence of vCPUs. The
> thread updates the vMSR values with the ratio of energy consumed of
> the whole physical CPU package the vCPU thread runs on and the
> thread's utime and stime values.
> 
> All other non-vCPU threads are also taken into account. Their energy
> consumption is evenly distributed among all vCPUs threads running on
> the same physical CPU package.
> 
> To overcome the problem that reading the RAPL MSR requires priviliged
> access, a socket communication between QEMU and the qemu-vmsr-helper is
> mandatory. You can specified the socket path in the parameter.
> 
> This feature is activated with -accel kvm,rapl=true,path=/path/sock.sock
> 
> Actual limitation:
> - Works only on Intel host CPU because AMD CPUs are using different MSR
>   adresses.
> 
> - Only the Package Power-Plane (MSR_PKG_ENERGY_STATUS) is reported at
>   the moment.
> 
> Signed-off-by: Anthony Harivel 
> ---
>  accel/kvm/kvm-all.c   |  27 +++
>  docs/specs/index.rst  |   1 +
>  docs/specs/rapl-msr.rst   | 155 
>  include/sysemu/kvm_int.h  |  32 +++
>  target/i386/cpu.h |   8 +
>  target/i386/kvm/kvm.c | 431 +-
>  target/i386/kvm/meson.build   |   1 +
>  target/i386/kvm/vmsr_energy.c | 344 +++
>  target/i386/kvm/vmsr_energy.h |  99 
>  9 files changed, 1097 insertions(+), 1 deletion(-)
>  create mode 100644 docs/specs/rapl-msr.rst
>  create mode 100644 target/i386/kvm/vmsr_energy.c
>  create mode 100644 target/i386/kvm/vmsr_energy.h
> 


> diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
> index c0be9f5eedb8..f455e6b987b4 100644
> --- a/accel/kvm/kvm-all.c
> +++ b/accel/kvm/kvm-all.c
> @@ -3745,6 +3745,21 @@ static void kvm_set_device(Object *obj,
>  s->device = g_strdup(value);
>  }
>  
> +static void kvm_set_kvm_rapl(Object *obj, bool value, Error **errp)
> +{
> +KVMState *s = KVM_STATE(obj);
> +s->msr_energy.enable = value;
> +}
> +
> +static void kvm_set_kvm_rapl_socket_path(Object *obj,
> + const char *str,
> + Error **errp)
> +{
> +KVMState *s = KVM_STATE(obj);
> +g_free(s->msr_energy.socket_path);
> +s->msr_energy.socket_path = g_strdup(str);
> +}
> +
>  static void kvm_accel_instance_init(Object *obj)
>  {
>  KVMState *s = KVM_STATE(obj);
> @@ -3764,6 +3779,7 @@ static void kvm_accel_instance_init(Object *obj)
>  s->xen_gnttab_max_frames = 64;
>  s->xen_evtchn_max_pirq = 256;
>  s->device = NULL;
> +s->msr_energy.enable = false;
>  }
>  
>  /**
> @@ -3808,6 +3824,17 @@ static void kvm_accel_class_init(ObjectClass *oc, void 
> *data)
>  object_class_property_set_description(oc, "device",
>  "Path to the device node to use (default: /dev/kvm)");
>  
> +object_class_property_add_bool(oc, "rapl",
> +   NULL,
> +   kvm_set_kvm_rapl);
> +object_class_property_set_description(oc, "rapl",
> +"Allow energy related MSRs for RAPL interface in Guest");
> +
> +object_class_property_add_str(oc, "rapl-helper-socket", NULL,
> +  kvm_set_kvm_rapl_socket_path);
> +object_class_property_set_description(oc, "rapl-helper-socket",
> +"Socket Path for comminucating with the Virtual MSR helper daemon");
> +
>  kvm_arch_accel_class_init(oc);
>  }

it seems, RAPL is x86 specific feature, so why it is in generic KVM code 
instead of
target/i386/kvm/kvm.c: kvm_arch_accel_class_init()

>  
> diff --git a/docs/specs/index.rst b/docs/specs/index.rst
> index 1484e3e76077..e738ea7d102f 100644
> --- a/docs/specs/index.rst
> +++ b/docs/specs/index.rst
> @@ -33,3 +33,4 @@ guest hardware that is specific to QEMU.
> virt-ctlr
> vmcoreinfo
> vmgenid
> +   rapl-msr
> diff --git a/docs/specs/rapl-msr.rst b/docs/specs/rapl-msr.rst
> new file mode 100644
> index ..1202ee89bee0
> --- /dev/null
> +++ b/docs/specs/rapl-ms

Re: [PATCH v6 0/3] Add support for the RAPL MSRs series

2024-10-16 Thread Igor Mammedov
On Wed, 22 May 2024 17:34:49 +0200
Anthony Harivel  wrote:

> Dear maintainers, 
> 
> First of all, thank you very much for your review of my patch 
> [1].

I've tried to play with this feature and have a few questions about it

 1. trying to start with non accessible or not existent socket
-accel kvm,rapl=on,rapl-helper-socket=/tmp/socket 
I get:
  qemu-system-x86_64: -accel kvm,rapl=on,rapl-helper-socket=/tmp/socks: 
vmsr socket opening failed
  qemu-system-x86_64: -accel kvm,rapl=on,rapl-helper-socket=/tmp/socks: kvm 
: error RAPL feature requirement not met
* is it possible to report actual OS error that happened during 
open/connect,
  instead of unhelpful 'socket opening failed'?

  What I see in vmsr_open_socket() error is ignored
  and btw it's error leak as well

* 2nd line shouldn't be there if the 1st error already present.

 2.  getting periodic error on console where QEMU has been starter
  # ./qemu-vmsr-helper -k /tmp/sock
 ./qemu-system-x86_64 -snapshot -m 4G -accel 
kvm,rapl=on,rapl-helper-socket=/tmp/sock rhel90.img  -vnc :0 -cpu host
 and let it run

  it appears rdmsr works (well, it returns some values at least)
  however there are recurring errors in qemu's stderr(or out)
  
  qemu-system-x86_64: Error opening /proc/2496093/task/2496109/stat
  qemu-system-x86_64: Error opening /proc/2496093/task/2496095/stat

  My guess it's some temporary threads, that come and go, but still
  they shouldn't cause errors if it's normal operation.

  Also on daemon side, I a few times got while guest was running:
qemu-vmsr-helper: Failed to open /proc at /proc/2496026/task/2496044
qemu-vmsr-helper: Requested TID not in peer PID: 2496026 2496044
  though I can't reproduce it reliably

 3. when starting daemon not as root, it starts 'fine' but later on complains
  qemu-vmsr-helper: Failed to open MSR file at /dev/cpu/0/msr
perhaps it would be better to fail at start daemon if it doesn't have
access to necessary files.

 4. in case #3, guest also fails to start with errors:
  qemu-system-x86_64: -accel kvm,rapl=on,rapl-helper-socket=/tmp/sock: 
can't read any virtual msr
  qemu-system-x86_64: -accel kvm,rapl=on,rapl-helper-socket=/tmp/sock: kvm 
: error RAPL feature requirement not met
 again line #2 is not useful and probably not needed (maybe make it 
tracepoint)
 and #1 is unhelpful - it would be better if it directed user to check 
qemu-vmsr-helper

 5. does AMD have similar MSRs that we could use to make this feature complete?

 6. What happens to power accounting if host constantly migrates
vcpus between sockets, are values we are getting still correct/meaningful?
Or do we need to pin vcpus to get 'accurate' values?

 7. do we have to have a dedicated thread for pooling data from daemon?

Can we fetch data from vcpu thread that have accessed msr
(with some caching and rate limiting access to the daemon)?

> In this version (v6), I have attempted to address all the problems 
> addressed by Daniel and Paolo during the last review. 
> 
> However, two open questions remains unanswered that would require the 
> attention of a x86 maintainers: 
> 
> 1)Should I move from -kvm to -cpu the rapl feature ? [2]
> 
> 2)Should I already rename to "rapl_vmsr_*" in order to anticipate the 
>   futur TMPI architecture ? [end of 3] 
> 
> Thank you again for your continued guidance. 
> 
> v5 -> v6
> 
> - Better error consistency in qio_channel_get_peerpid()
> - Memory leak g_strdup_printf/g_build_filename corrected
> - Renaming several struct with "vmsr_*" for better namespace
> - Renamed several struct with "guest_*" for better comprehension
> - Optimization suggerate from Daniel
> - Crash problem solved [4]
> 
> v4 -> v5
> 
> 
> - correct qio_channel_get_peerpid: return pid = -1 in case of error
> - Vmsr_helper: compile only for x86
> - Vmsr_helper: use qio_channel_read/write_all
> - Vmsr_helper: abandon user/group
> - Vmsr_energy.c: correct all error_report
> - Vmsr thread: compute default socket path only once
> - Vmsr thread: open socket only once
> - Pass relevant QEMU CI
> 
> v3 -> v4
> 
> 
> - Correct memory leaks with AddressSanitizer  
> - Add sanity check for QEMU and qemu-vmsr-helper for checking if host is 
>   INTEL and if RAPL is activated.
> - Rename poor variables naming for easier comprehension
> - Move code that checks Host before creating the VMSR thread
> - Get rid of libnuma: create function that read sysfs for reading the 
>   Host topology instead
> 
> v2 -> v3
> 
> 
> - Move all memory allocations from Clib to Glib
> - Compile on *BSD (working on Linux only)
> - No more limitation on the virtual package: each vCPU that belongs to 
>   the same virtual package is giving the same results like expected on 
>   a real CPU.
>   This has been tested topology like:
>  -smp 4,sockets=2
>  -smp 16,sockets=4,cores=2,th

Re: [PATCH] tests/functional: Convert most Aspeed machine tests

2024-10-16 Thread Philippe Mathieu-Daudé

On 16/10/24 06:30, Daniel P. Berrangé wrote:

On Wed, Oct 16, 2024 at 11:07:41AM +0200, Cédric Le Goater wrote:

This is a simple conversion of the tests with some cleanups and
adjustments to match the new test framework. Replace the zephyr image
MD5 hashes with SHA256 hashes while at it.

The SDK tests depend on a ssh class from avocado.utils which is
difficult to replace. To be addressed separately.

Signed-off-by: Cédric Le Goater 
---
  tests/avocado/machine_aspeed.py | 252 --
  tests/functional/meson.build|   2 +
  tests/functional/test_arm_aspeed.py | 269 
  3 files changed, 271 insertions(+), 252 deletions(-)
  create mode 100644 tests/functional/test_arm_aspeed.py

diff --git a/tests/functional/test_arm_aspeed.py 
b/tests/functional/test_arm_aspeed.py
new file mode 100644
index ..2f9a90f64d8f
--- /dev/null
+++ b/tests/functional/test_arm_aspeed.py
@@ -0,0 +1,269 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots the ASPEED SoCs with firmware
+#
+# Copyright (C) 2022 ASPEED Technology Inc
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+import os
+import time
+import subprocess
+import tempfile
+
+from qemu_test import QemuSystemTest, Asset
+from qemu_test import wait_for_console_pattern
+from qemu_test import exec_command_and_wait_for_pattern
+from qemu_test import interrupt_interactive_console_until_pattern
+from qemu_test import exec_command
+from qemu_test import has_cmd
+from qemu_test.utils import archive_extract
+from zipfile import ZipFile
+from unittest import skipUnless
+
+class AST1030Machine(QemuSystemTest):
+
+def test_ast1030_zephyros_1_04(self):
+asset_url = Asset(
+('https://github.com/AspeedTech-BMC'
+ '/zephyr/releases/download/v00.01.04/ast1030-evb-demo.zip'),
+'4ac6210adcbc61294927918707c6762483fd844dde5e07f3ba834ad1f91434d3')


Don't instantiate assets inline to test code, as this makes them
invisible to the logic that pre-downloads assets prior to running
tests. As a result you're liable to have test timeouts if the
on-the-fly asset download takes too long.

Instead You should use a class level varible with an "ASSET_" name
prefix eg

ASSET_ = Asset()


This is somehow documented in docs/devel/testing/functional.rst but
could be clarified:

  The second problem with downloading files from the internet are time
  constraints. The time for downloading files should not be taken into
  account when the test is running and the timeout of the test is
  ticking (since downloading can be very slow, depending on the network
  bandwidth).
  This problem is solved by downloading the assets ahead of time, before
  the tests are run. This pre-caching is done with the qemu_test.Asset
  class. To use it in your test, declare an asset in your test class
  with its URL and SHA256 checksum like this::

  ASSET_somename = (
  ('https://www.qemu.org/assets/images/qemu_head_200.png'),

'34b74cad46ea28a2966c1d04e102510daf1fd73e6582b6b74523940d5da029dd')




See other converted tests for examples of the pattern.


+kernel_name = "ast1030-evb-demo/zephyr.elf"
+zip_file = asset_url.fetch()
+with ZipFile(zip_file, 'r') as zf:
+ zf.extract(kernel_name, path=self.workdir)
+kernel_file = os.path.join(self.workdir, kernel_name)
+
+self.set_machine('ast1030-evb')
+self.vm.set_console()
+self.vm.add_args('-kernel', kernel_file, '-nographic')
+self.vm.launch()
+wait_for_console_pattern(self, "Booting Zephyr OS")
+exec_command_and_wait_for_pattern(self, "help",
+  "Available commands")
+


With regards,
Daniel





Re: [QEMU PATCH] cxl/cxl-mailbox-utils: Fix size check for cmd_firmware_update_get_info

2024-10-16 Thread Fan Ni
On Wed, Oct 16, 2024 at 05:01:38PM +0100, Jonathan Cameron wrote:
> On Tue, 8 Oct 2024 20:01:07 -0700
> Davidlohr Bueso  wrote:
> 
> > On Tue, 08 Oct 2024, nifan@gmail.com wrote:\n
> > >From: Fan Ni 
> > >
> > >In the function cmd_firmware_update_get_info for handling Get FW info
> > >command (0x0200h), the vmem, pmem and DC capacity size check were
> > >incorrect. The size should be aligned to 256MiB, not smaller than
> > >256MiB.  
> > 
> > Can get rid of a level of parenthesis (other cmds as well), otherwise:
> > 
> > Reviewed-by: Davidlohr Bueso 
> I missed this one when gathering up fixes the other day.
> I'll queue it up now with the excess brackets dropped.
> 
> Jonathan
Thanks Jonathan,
Please also take a look the following patch, it is a fix for dcd.

https://lore.kernel.org/linux-cxl/20241015190224.251293-1-nifan@gmail.com/T/#u

Fan

> 
> > 
> > >
> > >Signed-off-by: Fan Ni 
> > >---
> > > hw/cxl/cxl-mailbox-utils.c | 6 +++---
> > > 1 file changed, 3 insertions(+), 3 deletions(-)
> > >
> > >diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
> > >index 9258e48f95..c82ad50ac8 100644
> > >--- a/hw/cxl/cxl-mailbox-utils.c
> > >+++ b/hw/cxl/cxl-mailbox-utils.c
> > >@@ -649,9 +649,9 @@ static CXLRetCode cmd_firmware_update_get_info(const 
> > >struct cxl_cmd *cmd,
> > > } QEMU_PACKED *fw_info;
> > > QEMU_BUILD_BUG_ON(sizeof(*fw_info) != 0x50);
> > >
> > >-if ((cxl_dstate->vmem_size < CXL_CAPACITY_MULTIPLIER) ||
> > >-(cxl_dstate->pmem_size < CXL_CAPACITY_MULTIPLIER) ||
> > >-(ct3d->dc.total_capacity < CXL_CAPACITY_MULTIPLIER)) {
> > >+if ((!QEMU_IS_ALIGNED(cxl_dstate->vmem_size, 
> > >CXL_CAPACITY_MULTIPLIER)) ||
> > >+(!QEMU_IS_ALIGNED(cxl_dstate->pmem_size, 
> > >CXL_CAPACITY_MULTIPLIER)) ||
> > >+(!QEMU_IS_ALIGNED(ct3d->dc.total_capacity, 
> > >CXL_CAPACITY_MULTIPLIER))) {
> > > return CXL_MBOX_INTERNAL_ERROR;
> > > }
> > >
> > >--
> > >2.43.0
> > >  
> 

-- 
Fan Ni



Re: [PATCH v6 0/3] Add support for the RAPL MSRs series

2024-10-16 Thread Anthony Harivel
Hi Igor,

Igor Mammedov, Oct 16, 2024 at 13:52:
> On Wed, 22 May 2024 17:34:49 +0200
> Anthony Harivel  wrote:
>
>> Dear maintainers, 
>> 
>> First of all, thank you very much for your review of my patch 
>> [1].
>
> I've tried to play with this feature and have a few questions about it
>

Thanks for testing this new feature. 

>  1. trying to start with non accessible or not existent socket
> -accel kvm,rapl=on,rapl-helper-socket=/tmp/socket 
> I get:
>   qemu-system-x86_64: -accel kvm,rapl=on,rapl-helper-socket=/tmp/socks: 
> vmsr socket opening failed
>   qemu-system-x86_64: -accel kvm,rapl=on,rapl-helper-socket=/tmp/socks: 
> kvm : error RAPL feature requirement not met
> * is it possible to report actual OS error that happened during 
> open/connect,
>   instead of unhelpful 'socket opening failed'?
>
>   What I see in vmsr_open_socket() error is ignored
>   and btw it's error leak as well
>

Shame you missed the 6 iterations of that patch that last for a year. 
I would have changed that directly !
Anyway I take note on that comment and will send a modification.

> * 2nd line shouldn't be there if the 1st error already present.
>
>  2.  getting periodic error on console where QEMU has been starter
>   # ./qemu-vmsr-helper -k /tmp/sock
>  ./qemu-system-x86_64 -snapshot -m 4G -accel 
> kvm,rapl=on,rapl-helper-socket=/tmp/sock rhel90.img  -vnc :0 -cpu host
>  and let it run
>
>   it appears rdmsr works (well, it returns some values at least)
>   however there are recurring errors in qemu's stderr(or out)
>   
>   qemu-system-x86_64: Error opening /proc/2496093/task/2496109/stat
>   qemu-system-x86_64: Error opening /proc/2496093/task/2496095/stat
>
>   My guess it's some temporary threads, that come and go, but still
>   they shouldn't cause errors if it's normal operation.
>

There a patch in WIP that change this into a Tracepoint. Maybe you can 
SSH to the VM in meanwhile ?

>   Also on daemon side, I a few times got while guest was running:
> qemu-vmsr-helper: Failed to open /proc at /proc/2496026/task/2496044
> qemu-vmsr-helper: Requested TID not in peer PID: 2496026 2496044
>   though I can't reproduce it reliably

This could happen only when a vCPU thread ID has changed between the 
call of a rdmsr throught the socket and the hepler that read the msr.
No idea how a vCPU can change TID or shutdown that fast.

>
>  3. when starting daemon not as root, it starts 'fine' but later on complains
>   qemu-vmsr-helper: Failed to open MSR file at /dev/cpu/0/msr
> perhaps it would be better to fail at start daemon if it doesn't have
> access to necessary files.
>

Right taking a note on that as well.


>  4. in case #3, guest also fails to start with errors:
>   qemu-system-x86_64: -accel kvm,rapl=on,rapl-helper-socket=/tmp/sock: 
> can't read any virtual msr
>   qemu-system-x86_64: -accel kvm,rapl=on,rapl-helper-socket=/tmp/sock: 
> kvm : error RAPL feature requirement not met
>  again line #2 is not useful and probably not needed (maybe make it 
> tracepoint)
>  and #1 is unhelpful - it would be better if it directed user to check 
> qemu-vmsr-helper
>

I will try to see how to improve that part. 
Thanks for your valuable feedback.

>  5. does AMD have similar MSRs that we could use to make this feature 
> complete?
>

Yes but the address are completely different. However, this in my ToDo 
list. First I need way more feedback like yours to move on extending 
this feature.

>  6. What happens to power accounting if host constantly migrates
> vcpus between sockets, are values we are getting still correct/meaningful?
> Or do we need to pin vcpus to get 'accurate' values?
>

It's taken into account during the ratio calculation which socket the 
vCPU has just been scheduled. But yes the value are more 'accurate' when 
the vCPU is pinned.

>  7. do we have to have a dedicated thread for pooling data from daemon?
>
> Can we fetch data from vcpu thread that have accessed msr
> (with some caching and rate limiting access to the daemon)?
>

This feature is revolving around a thread. Please look at the 
documentation is not already done:

https://www.qemu.org/docs/master/specs/rapl-msr.html#high-level-implementation

If we only fetch from vCPU thread, we won't have the consumption of the 
non-vcpu thread. They are taken into account in the total.



Thanks again for your feedback. 

Anthony


>> In this version (v6), I have attempted to address all the problems 
>> addressed by Daniel and Paolo during the last review. 
>> 
>> However, two open questions remains unanswered that would require the 
>> attention of a x86 maintainers: 
>> 
>> 1)Should I move from -kvm to -cpu the rapl feature ? [2]
>> 
>> 2)Should I already rename to "rapl_vmsr_*" in order to anticipate the 
>>   futur TMPI architecture ? [end of 3] 
>> 
>> Thank you again for your continued guidance. 
>> 
>> v

Re: [QEMU PATCH] cxl/cxl-mailbox-utils: Fix size check for cmd_firmware_update_get_info

2024-10-16 Thread Jonathan Cameron via
On Tue, 8 Oct 2024 20:01:07 -0700
Davidlohr Bueso  wrote:

> On Tue, 08 Oct 2024, nifan@gmail.com wrote:\n
> >From: Fan Ni 
> >
> >In the function cmd_firmware_update_get_info for handling Get FW info
> >command (0x0200h), the vmem, pmem and DC capacity size check were
> >incorrect. The size should be aligned to 256MiB, not smaller than
> >256MiB.  
> 
> Can get rid of a level of parenthesis (other cmds as well), otherwise:
> 
> Reviewed-by: Davidlohr Bueso 
I missed this one when gathering up fixes the other day.
I'll queue it up now with the excess brackets dropped.

Jonathan

> 
> >
> >Signed-off-by: Fan Ni 
> >---
> > hw/cxl/cxl-mailbox-utils.c | 6 +++---
> > 1 file changed, 3 insertions(+), 3 deletions(-)
> >
> >diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
> >index 9258e48f95..c82ad50ac8 100644
> >--- a/hw/cxl/cxl-mailbox-utils.c
> >+++ b/hw/cxl/cxl-mailbox-utils.c
> >@@ -649,9 +649,9 @@ static CXLRetCode cmd_firmware_update_get_info(const 
> >struct cxl_cmd *cmd,
> > } QEMU_PACKED *fw_info;
> > QEMU_BUILD_BUG_ON(sizeof(*fw_info) != 0x50);
> >
> >-if ((cxl_dstate->vmem_size < CXL_CAPACITY_MULTIPLIER) ||
> >-(cxl_dstate->pmem_size < CXL_CAPACITY_MULTIPLIER) ||
> >-(ct3d->dc.total_capacity < CXL_CAPACITY_MULTIPLIER)) {
> >+if ((!QEMU_IS_ALIGNED(cxl_dstate->vmem_size, CXL_CAPACITY_MULTIPLIER)) 
> >||
> >+(!QEMU_IS_ALIGNED(cxl_dstate->pmem_size, CXL_CAPACITY_MULTIPLIER)) 
> >||
> >+(!QEMU_IS_ALIGNED(ct3d->dc.total_capacity, 
> >CXL_CAPACITY_MULTIPLIER))) {
> > return CXL_MBOX_INTERNAL_ERROR;
> > }
> >
> >--
> >2.43.0
> >  




[PATCH] migration/dirtyrate: Silence warning about strcpy() on OpenBSD

2024-10-16 Thread Thomas Huth
The linker on OpenBSD complains:

 ld: warning: dirtyrate.c:447 (../src/migration/dirtyrate.c:447)(...):
 warning: strcpy() is almost always misused, please use strlcpy()

It's currently not a real problem in this case since both arrays
have the same size (256 bytes). But just in case somebody changes
the size of the source array in the future, let's better play safe
and use g_strlcpy() here instead.

Signed-off-by: Thomas Huth 
---
 migration/dirtyrate.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/migration/dirtyrate.c b/migration/dirtyrate.c
index 233acb0855..090c76e934 100644
--- a/migration/dirtyrate.c
+++ b/migration/dirtyrate.c
@@ -444,7 +444,7 @@ static void get_ramblock_dirty_info(RAMBlock *block,
 info->ramblock_pages = qemu_ram_get_used_length(block) >>
qemu_target_page_bits();
 info->ramblock_addr = qemu_ram_get_host_addr(block);
-strcpy(info->idstr, qemu_ram_get_idstr(block));
+g_strlcpy(info->idstr, qemu_ram_get_idstr(block), sizeof(info->idstr));
 }
 
 static void free_ramblock_dirty_info(struct RamblockDirtyInfo *infos, int 
count)
-- 
2.47.0




Re: [PATCH v2 0/2] tpm: Resolve potential blocking-forever issue

2024-10-16 Thread Stefan Berger




On 10/16/24 9:34 AM, Stefan Berger wrote:

In case swtpm was to return a control channel message with an error code it
would only return 4 bytes. However, some of the commands expect a response
with more bytes and QEMU would get stuck in qemu_chr_fe_read_all() waiting
for bytes following the error code. Therefore, read the response in 2
passes stopping if an error code is received in the first 4 bytes to avoid
getting stuck. Implement an exception for CMD_GET_STATEBLOB that has always
been sending the header in case of error.

Stefan

v2:
   -


Please disregard v2. v3 coming shortly.



Stefan Berger (2):
   tpm: Use new ptm_cap_n structure for PTM_GET_CAPABILITY
   tpm_emulator: Read control channel response in 2 passes

  backends/tpm/tpm_emulator.c | 45 ++---
  backends/tpm/tpm_ioctl.h| 13 ++-
  backends/tpm/trace-events   |  2 +-
  3 files changed, 50 insertions(+), 10 deletions(-)





Re: tpm-tis-device-swtpm-test timeout

2024-10-16 Thread Fabiano Rosas
Stefan Berger  writes:

> On 10/15/24 6:02 PM, Fabiano Rosas wrote:
>> Stefan Berger  writes:
>> 
>>> On 10/15/24 3:57 PM, Fabiano Rosas wrote:
 Stefan Berger  writes:

>>>
>
> So this here is failing for you every time?
>
> QTEST_QEMU_BINARY=build/qemu-system-aarch64
> ./build/tests/qtest/tpm-tis-device-swtpm-test

 Sorry, I was unclear. No, that runs for about 30 iterations before it
 fails. I just ran each of these in a terminal window:

 $ for i in $(seq 1 999); do echo "$i =";  
 QTEST_QEMU_BINARY=./qemu-system-aarch64 
 ./tests/qtest/tpm-tis-device-swtpm-test || break ; done
>>>
>>> On my Fedora 40 host this command line here alone has been running for
>>> 250 loop iterations now and is still continuing.
>>>
 $ make -j$(nproc) check
>>>
>>> So this needs to be run in parallel to the above command line to cause
>>> the failure?
>>>
>> 
>> Yes, I've been using that method to reproduce live migration race
>> conditions as well. It's quite effective.
>> 
>> If you don't think you'll be able to find the root cause due to the
>> unreproducibility on your side, maybe we could at least add an assert
>> that bcount is not larger than rsp_size. I think that would at least
>> give an explicit error instead of a buffer overflow.
>> 
>> I can also try to dig deeper into this when I get some time. At the
>> moment I know nothing about the tpm device emulation.
>> 
>
> The loop has run 3000 times by itself so that part is stable. However, 
> it seems there is some other test case that the loop cannot run in 
> parallel with. So, yes there is 'something'. ... ... Just having all 
> CPUs in a system busy requires waiting for migration to be complete on 
> the dst_qemu side as well. Can you try it with this patch:
>
> diff --git a/tests/qtest/tpm-tests.c b/tests/qtest/tpm-tests.c
> index fb94496bbd..b52cd44841 100644
> --- a/tests/qtest/tpm-tests.c
> +++ b/tests/qtest/tpm-tests.c
> @@ -115,6 +115,7 @@ void tpm_test_swtpm_migration_test(const char 
> *src_tpm_path,
>
>   tpm_util_migrate(src_qemu, uri);
>   tpm_util_wait_for_migration_complete(src_qemu);
> +tpm_util_wait_for_migration_complete(dst_qemu);
>
>   tpm_util_pcrread(dst_qemu, tx, tpm_pcrread_resp,
>sizeof(tpm_pcrread_resp));
>
>
> For me this fixes the issue I had seen where reading the STS register 
> was done too early before all the TPM TIS state was completely restored. 
> The active locality was -1 and STS return 0x and from then on 
> things went bad.

Thanks, that fixes the issue. Could you send a patch please?



Re: [PATCH RFC V5 00/30] Support of Virtual CPU Hotplug for ARMv8 Arch

2024-10-16 Thread Miguel Luis
Hi Salil,

> On 15 Oct 2024, at 09:59, Salil Mehta  wrote:
> 
> PROLOGUE
> 
> 
> To assist in review and set the right expectations from this RFC, please first
> read the sections *APPENDED AT THE END* of this cover letter:
> 
> 1. Important *DISCLAIMER* [Section (X)]
> 2. Work presented at KVMForum Conference (slides available) [Section (V)F]
> 3. Organization of patches [Section (XI)]
> 4. References [Section (XII)]
> 5. Detailed TODO list of leftover work or work-in-progress [Section (IX)]
> 6. Repositories [Section (VII)]
> 
> The architecture-agnostic patch set was merged into the mainline during the
> last Qemu cycle. This patch is specific to the ARM architecture and is
> compatible with the latest Qemu mainline version.
> 
> SECTIONS [I - XIII] are as follows:
> 
> (I) Summary of `Recent` Key Changes [details in last section (XIV)]
> ===
> 
> RFC V4 -> RFC V5
> 
> 1. Dropped patches [PATCH RFC V4 {2,12,19}/33] 
> 2. Separated architecture agnostic ACPI/migration changes in separate 
> patch-set.
>   Link: 
> https://lore.kernel.org/qemu-devel/20241014192205.253479-1-salil.me...@huawei.com/#t
> 3. Dropped qemu{present,enabled}_cpu() APIs. 
> 4. Dropped the `CPUState::disabled` flag
> 
> RFC V3 -> RFC V4
> 
> 1. Fixes for TCG. It has been lightly tested but seem to work!
> 2. Migration related fixes [Both KVM & TCG]. 
> 3. Introduction of `gicc_accessble` flag for GICv3 CPU interface
> 4. Addressed comments from Gavin Shan (RedHat), Nicholas Piggin (IBM), 
>   Alex Bennée's & Gustavo Romero (Linaro) 
> 5. Misc fixes and refatoring.
> 
> 
> (II) Summary
> 
> 
> This patch set introduces virtual CPU hotplug support for the ARMv8 
> architecture
> in QEMU. The idea is to be able to hotplug and hot-unplug vCPUs while the 
> guest
> VM is running, without requiring a reboot. This does *not* make any 
> assumptions
> about the physical CPU hotplug availability within the host system but rather
> tries to solve the problem at the virtualizer/QEMU layer. It introduces ACPI 
> CPU
> hotplug hooks and event handling to interface with the guest kernel, and code 
> to
> initialize, plug, and unplug CPUs. No changes are required within the host
> kernel/KVM except the support of hypercall exit handling in the 
> user-space/Qemu,
> which has recently been added to the kernel. Corresponding guest kernel 
> changes
> were posted on the mailing list [3] [4] by James Morse (ARM) and have been
> recently accepted and are now part of v6.11 mainline kernel.
> 
> (III) Motivation
> 
> 
> This allows scaling the guest VM compute capacity on-demand, which would be
> useful for the following example scenarios:
> 
> 1. Vertical Pod Autoscaling [9][10] in the cloud: Part of the orchestration
>   framework that could adjust resource requests (CPU and Mem requests) for
>   the containers in a pod, based on usage.
> 2. Pay-as-you-grow Business Model: Infrastructure providers could allocate and
>   restrict the total number of compute resources available to the guest VM
>   according to the SLA (Service Level Agreement). VM owners could request more
>   compute to be hot-plugged for some cost.
> 
> For example, Kata Container VM starts with a minimum amount of resources 
> (i.e.,
> hotplug everything approach). Why?
> 
> 1. Allowing faster *boot time* and
> 2. Reduction in *memory footprint*
> 
> Kata Container VM can boot with just 1 vCPU, and then later more vCPUs can be
> hot-plugged as needed. Reducing the number of vCPUs in VM can in general
> reduce the boot times of the VM esepcially when number of cores are 
> increasing.
> 
> **[UPCOMING]**
> I've been working on enhancing the boot times of ARM/VMs using the hotplug
> infrastructure proposed in this patch set. Stay tuned for upcoming patches 
> that
> leverage this infrastructure to significantly reduce boot times for
> *non-hotplug* scenarios. Expect these updates in the next few weeks!
> 
> (IV) Terminology
> 
> 
> (*) Possible CPUs: Total vCPUs that could ever exist in the VM. This includes
>   any cold-booted CPUs plus any CPUs that could be later
>   hot-plugged.
>   - Qemu parameter (-smp maxcpus=N)
> (*) Present CPUs:  Possible CPUs that are ACPI 'present'. These might or might
>   not be ACPI 'enabled'. 
>   - Present vCPUs = Possible vCPUs (Always on ARM Arch)
> (*) Enabled CPUs:  Possible CPUs that are ACPI 'present' and 'enabled' and can
>   now be ‘onlined’ (PSCI) for use by the Guest Kernel. All 
> cold-
>   booted vCPUs are ACPI 'enabled' at boot. Later, using
>   device_add, more vCPUs can be hotplugged and made ACPI
>   'enabled'.
>   - Qemu parameter (-smp cpus=N). Can be used to specify some
>   cold-booted vCPUs during VM init. Some can be added using the
>   '-device' option.
> 
> 

[PATCH v2 1/2] tpm: Use new ptm_cap_n structure for PTM_GET_CAPABILITY

2024-10-16 Thread Stefan Berger
Use the new ptm_cap_n structure for getting the PTM_GET_CAPABILITY response
from swtpm. Previously only 17 bits could possibly have been set in ptm_cap
(=uint64_t) in big endian order and those bits are now found in the 2nd
32bit word in the response in the caps field.

This data structure makes it now clear that the 1st 32bit word carries the
tpm_result like all the other response structures of all other commands
do.

Signed-off-by: Stefan Berger 
---
 backends/tpm/tpm_emulator.c | 14 --
 backends/tpm/tpm_ioctl.h| 13 -
 backends/tpm/trace-events   |  2 +-
 3 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/backends/tpm/tpm_emulator.c b/backends/tpm/tpm_emulator.c
index 5a8fba9bde..b0e2fb3fc7 100644
--- a/backends/tpm/tpm_emulator.c
+++ b/backends/tpm/tpm_emulator.c
@@ -72,7 +72,7 @@ struct TPMEmulator {
 CharBackend ctrl_chr;
 QIOChannel *data_ioc;
 TPMVersion tpm_version;
-ptm_cap caps; /* capabilities of the TPM */
+uint32_t caps; /* capabilities of the TPM */
 uint8_t cur_locty_number; /* last set locality */
 Error *migration_blocker;
 
@@ -239,13 +239,15 @@ static void tpm_emulator_handle_request(TPMBackend *tb, 
TPMBackendCmd *cmd,
 
 static int tpm_emulator_probe_caps(TPMEmulator *tpm_emu)
 {
+ptm_cap_n cap_n;
+
 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_GET_CAPABILITY,
- &tpm_emu->caps, 0, sizeof(tpm_emu->caps)) < 0) {
+ &cap_n, 0, sizeof(cap_n)) < 0) {
 error_report("tpm-emulator: probing failed : %s", strerror(errno));
 return -1;
 }
 
-tpm_emu->caps = be64_to_cpu(tpm_emu->caps);
+tpm_emu->caps = be32_to_cpu(cap_n.u.resp.caps);
 
 trace_tpm_emulator_probe_caps(tpm_emu->caps);
 
@@ -254,7 +256,7 @@ static int tpm_emulator_probe_caps(TPMEmulator *tpm_emu)
 
 static int tpm_emulator_check_caps(TPMEmulator *tpm_emu)
 {
-ptm_cap caps = 0;
+uint32_t caps = 0;
 const char *tpm = NULL;
 
 /* check for min. required capabilities */
@@ -527,8 +529,8 @@ static size_t tpm_emulator_get_buffer_size(TPMBackend *tb)
 static int tpm_emulator_block_migration(TPMEmulator *tpm_emu)
 {
 Error *err = NULL;
-ptm_cap caps = PTM_CAP_GET_STATEBLOB | PTM_CAP_SET_STATEBLOB |
-   PTM_CAP_STOP;
+uint32_t caps = PTM_CAP_GET_STATEBLOB | PTM_CAP_SET_STATEBLOB |
+PTM_CAP_STOP;
 
 if (!TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(tpm_emu, caps)) {
 error_setg(&tpm_emu->migration_blocker,
diff --git a/backends/tpm/tpm_ioctl.h b/backends/tpm/tpm_ioctl.h
index 1933ab6855..ee2dd15d35 100644
--- a/backends/tpm/tpm_ioctl.h
+++ b/backends/tpm/tpm_ioctl.h
@@ -29,6 +29,16 @@
 
 typedef uint32_t ptm_res;
 
+/* PTM_GET_CAPABILITY: Get supported capabilities (ioctl's) */
+struct ptm_cap_n {
+union {
+struct {
+ptm_res tpm_result; /* will always be TPM_SUCCESS (0) */
+uint32_t caps;
+} resp; /* response */
+} u;
+};
+
 /* PTM_GET_TPMESTABLISHED: get the establishment bit */
 struct ptm_est {
 union {
@@ -242,7 +252,8 @@ struct ptm_lockstorage {
 } u;
 };
 
-typedef uint64_t ptm_cap;
+typedef uint64_t ptm_cap; /* CUSE-only; use ptm_cap_n otherwise */
+typedef struct ptm_cap_n ptm_cap_n;
 typedef struct ptm_est ptm_est;
 typedef struct ptm_reset_est ptm_reset_est;
 typedef struct ptm_loc ptm_loc;
diff --git a/backends/tpm/trace-events b/backends/tpm/trace-events
index cb5cfa6510..05e30533ce 100644
--- a/backends/tpm/trace-events
+++ b/backends/tpm/trace-events
@@ -16,7 +16,7 @@ tpm_util_show_buffer_content(const char *buf) "%s"
 # tpm_emulator.c
 tpm_emulator_set_locality(uint8_t locty) "setting locality to %d"
 tpm_emulator_handle_request(void) "processing TPM command"
-tpm_emulator_probe_caps(uint64_t caps) "capabilities: 0x%"PRIx64
+tpm_emulator_probe_caps(uint32_t caps) "capabilities: 0x%x"
 tpm_emulator_set_buffer_size(uint32_t buffersize, uint32_t minsize, uint32_t 
maxsize) "buffer size: %u, min: %u, max: %u"
 tpm_emulator_startup_tpm_resume(bool is_resume, size_t buffersize) "is_resume: 
%d, buffer size: %zu"
 tpm_emulator_get_tpm_established_flag(uint8_t flag) "got established flag: %d"
-- 
2.47.0




[PATCH v2 0/2] tpm: Resolve potential blocking-forever issue

2024-10-16 Thread Stefan Berger
In case swtpm was to return a control channel message with an error code it
would only return 4 bytes. However, some of the commands expect a response
with more bytes and QEMU would get stuck in qemu_chr_fe_read_all() waiting
for bytes following the error code. Therefore, read the response in 2
passes stopping if an error code is received in the first 4 bytes to avoid
getting stuck. Implement an exception for CMD_GET_STATEBLOB that has always
been sending the header in case of error.

   Stefan

v2:
  - 


Stefan Berger (2):
  tpm: Use new ptm_cap_n structure for PTM_GET_CAPABILITY
  tpm_emulator: Read control channel response in 2 passes

 backends/tpm/tpm_emulator.c | 45 ++---
 backends/tpm/tpm_ioctl.h| 13 ++-
 backends/tpm/trace-events   |  2 +-
 3 files changed, 50 insertions(+), 10 deletions(-)

-- 
2.47.0




Re: [PATCH v2 0/3] crypto: fix regression in hash result buffer handling

2024-10-16 Thread Dorjoy Chowdhury
On Wed, Oct 16, 2024 at 4:20 PM Daniel P. Berrangé  wrote:
>
>
>
> Daniel P. Berrangé (3):
>   crypto/hash: avoid overwriting user supplied result pointer
>   tests: correctly validate result buffer in hash/hmac tests
>   include/crypto: clarify @result/@result_len for hash/hmac APIs
>
>  crypto/hash-gcrypt.c  | 15 ---
>  crypto/hash-glib.c| 11 +--
>  crypto/hash-gnutls.c  | 16 +---
>  crypto/hash-nettle.c  | 14 +++---
>  include/crypto/hash.h | 30 +++---
>  include/crypto/hmac.h | 17 -
>  tests/unit/test-crypto-hash.c |  7 ---
>  tests/unit/test-crypto-hmac.c |  6 --
>  8 files changed, 88 insertions(+), 28 deletions(-)
>

Reviewed-by: Dorjoy Chowdhury 


@Daniel the api documentation for "qcrypto_hash_bytesv" also needs to
be updated.

Regards,
Dorjoy



[PATCH v2 2/2] tpm_emulator: Read control channel response in 2 passes

2024-10-16 Thread Stefan Berger
Error responses from swtpm are always only 4 bytes long with the exception
of CMD_GET_STATEBLOB that returns more bytes. Therefore, read the entire
response in 2 passes and stop if the first 4 bytes indicate an error
response with no subsequent bytes readable. Read the rest in a 2nd pass, if
needed. This avoids getting stuck while waiting for too many bytes if only
4 bytes were sent due to an error message. The 'getting stuck' condition
has not been observed in practice so far, though.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2615
Signed-off-by: Stefan Berger 
---
 backends/tpm/tpm_emulator.c | 31 +--
 1 file changed, 29 insertions(+), 2 deletions(-)

diff --git a/backends/tpm/tpm_emulator.c b/backends/tpm/tpm_emulator.c
index b0e2fb3fc7..8f5d31be09 100644
--- a/backends/tpm/tpm_emulator.c
+++ b/backends/tpm/tpm_emulator.c
@@ -129,6 +129,9 @@ static int tpm_emulator_ctrlcmd(TPMEmulator *tpm, unsigned 
long cmd, void *msg,
 uint32_t cmd_no = cpu_to_be32(cmd);
 ssize_t n = sizeof(uint32_t) + msg_len_in;
 uint8_t *buf = NULL;
+ptm_res res;
+off_t o = 0;
+int to_read;
 
 WITH_QEMU_LOCK_GUARD(&tpm->mutex) {
 buf = g_alloca(n);
@@ -140,11 +143,35 @@ static int tpm_emulator_ctrlcmd(TPMEmulator *tpm, 
unsigned long cmd, void *msg,
 return -1;
 }
 
-if (msg_len_out != 0) {
-n = qemu_chr_fe_read_all(dev, msg, msg_len_out);
+/*
+ * Any response will be at least 4 bytes long. Error responses are only
+ * 4 bytes (=sizeof(ptm_res)), with exception by CMD_GET_STATEBLOB.
+ * Therefore, read response in 2 passes, returning when an error
+ * response is encountered.
+ */
+if (cmd == CMD_GET_STATEBLOB) {
+to_read = msg_len_out;
+} else {
+to_read = sizeof(res);
+}
+
+while (msg_len_out > 0) {
+n = qemu_chr_fe_read_all(dev, (uint8_t *)msg + o, to_read);
 if (n <= 0) {
 return -1;
 }
+msg_len_out -= to_read;
+if (msg_len_out == 0) {
+return 0;
+}
+
+memcpy(&res, msg, sizeof(res));
+if (res) {
+return 0;
+}
+
+o = to_read;
+to_read = msg_len_out;
 }
 }
 
-- 
2.47.0




Re: [PATCH v4 6/8] chardev/char-mux: implement backend chardev multiplexing

2024-10-16 Thread Roman Penyaev
Hi,

On Wed, Oct 16, 2024 at 1:14 PM Marc-André Lureau
 wrote:
>
> Hi
>
> On Wed, Oct 16, 2024 at 2:29 PM Roman Penyaev  wrote:
>>
>> This patch implements multiplexing capability of several backend
>> devices, which opens up an opportunity to use a single frontend
>> device on the guest, which can be manipulated from several
>> backend devices.
>>
>> The idea of the change is trivial: keep list of backend devices
>> (up to 4), init them on demand and forward data buffer back and
>> forth.
>>
>> Patch implements another multiplexer type `mux-be`. The following
>> is QEMU command line example:
>>
>>-chardev mux-be,id=mux0 \
>>-chardev socket,path=/tmp/sock,server=on,wait=off,id=sock0,mux-be-id=mux0 
>> \
>>-chardev vc,id=vc0,mux-be-id=mux0 \
>
>
> I am not sure about adding "mux-be-id" to all chardev. It avoids the issue of 
> expressing a list of ids in mux-be though (while it may have potential loop!)

Loop is a good point, but actually can be easily fixed by forbidding
the use of stacked muxes and a reference on itself. Do you think that
would be enough?

--
Roman



Re: [PATCH v4 7/8] tests/unit/test-char: add unit test for the `mux-be` multiplexer

2024-10-16 Thread Marc-André Lureau
Hi

On Wed, Oct 16, 2024 at 2:28 PM Roman Penyaev  wrote:
>
> The test is trivial: several backends, 1 `mux-be`, 1 frontend
> do the buffer write and read. Pipe is used for EAGAIN verification.
>
> Signed-off-by: Roman Penyaev 
> Cc: "Marc-André Lureau" 
> Cc: qemu-devel@nongnu.org
> ---
>  tests/unit/test-char.c | 306 -
>  1 file changed, 304 insertions(+), 2 deletions(-)

please fix the few leaks (found with --enable-asan)

>
> diff --git a/tests/unit/test-char.c b/tests/unit/test-char.c
> index a1c6bb874c8e..3eb0692b199f 100644
> --- a/tests/unit/test-char.c
> +++ b/tests/unit/test-char.c
> @@ -178,7 +178,7 @@ static void char_ringbuf_test(void)
>  qemu_opts_del(opts);
>  }
>
> -static void char_mux_test(void)
> +static void char_mux_fe_test(void)
>  {
>  QemuOpts *opts;
>  Chardev *chr, *base;
> @@ -359,6 +359,307 @@ static void char_mux_test(void)
>  qmp_chardev_remove("mux-label", &error_abort);
>  }
>
> +static void char_mux_be_test(void)
> +{
> +QemuOpts *opts;
> +Chardev *mux_be, *chr1, *chr2, *base;
> +char *data;
> +FeHandler h = { 0, false, 0, false, };
> +Error *error = NULL;
> +CharBackend chr_be;
> +int ret, i;
> +
> +#define RB_SIZE 128
> +
> +/* Create mux-be */
> +opts = qemu_opts_create(qemu_find_opts("chardev"), "mux0",
> +1, &error_abort);
> +qemu_opt_set(opts, "backend", "mux-be", &error_abort);
> +mux_be = qemu_chr_new_from_opts(opts, NULL, &error_abort);
> +g_assert_nonnull(mux_be);
> +qemu_opts_del(opts);
> +
> +/* Check maximum allowed backends */
> +for (i = 0; true; i++) {
> +char name[8];
> +
> +snprintf(name, sizeof(name), "chr%d", i);
> +opts = qemu_opts_create(qemu_find_opts("chardev"), name,
> +1, &error_abort);
> +qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
> +qemu_opt_set(opts, "size", stringify(RB_SIZE), &error_abort);
> +qemu_opt_set(opts, "mux-be-id", "mux0", &error_abort);
> +base = qemu_chr_new_from_opts(opts, NULL, &error);
> +if (error) {
> +const char *err_fmt =
> +"too many uses of multiplexed chardev 'mux0' (maximum is 
> %u)";
> +unsigned n;
> +
> +ret = sscanf(error_get_pretty(error), err_fmt, &n);
> +error_free(error);
> +error = NULL;
> +g_assert_cmpint(ret, ==, 1);
> +g_assert_cmpint(i, ==, n);
> +break;
> +}
> +g_assert_nonnull(base);
> +qemu_opts_del(opts);
> +}
> +/* Finalize mux0 */
> +qmp_chardev_remove("mux0", &error_abort);
> +
> +/* Finalize all backends */
> +while (i--) {
> +char name[8];
> +snprintf(name, sizeof(name), "chr%d", i);
> +qmp_chardev_remove(name, &error_abort);
> +}
> +
> +/* Create mux-be */
> +opts = qemu_opts_create(qemu_find_opts("chardev"), "mux0",
> +1, &error_abort);
> +qemu_opt_set(opts, "backend", "mux-be", &error_abort);
> +mux_be = qemu_chr_new_from_opts(opts, NULL, &error_abort);
> +g_assert_nonnull(mux_be);
> +qemu_opts_del(opts);
> +
> +/* Create chardev which fails */
> +opts = qemu_opts_create(qemu_find_opts("chardev"), "chr1",
> +1, &error_abort);
> +qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
> +qemu_opt_set(opts, "size", stringify(RB_SIZE), &error_abort);
> +qemu_opt_set(opts, "mux-be-id", "mux0", &error_abort);
> +qemu_opt_set(opts, "mux", "on", &error_abort);
> +chr1 = qemu_chr_new_from_opts(opts, NULL, &error);
> +g_assert_cmpstr(error_get_pretty(error), ==, "chardev: mux and mux-be "
> +"can't be used for the same device");
> +error_free(error);
> +error = NULL;
> +qemu_opts_del(opts);
> +
> +/* Create first chardev */
> +opts = qemu_opts_create(qemu_find_opts("chardev"), "chr1",
> +1, &error_abort);
> +qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
> +qemu_opt_set(opts, "size", stringify(RB_SIZE), &error_abort);
> +qemu_opt_set(opts, "mux-be-id", "mux0", &error_abort);
> +chr1 = qemu_chr_new_from_opts(opts, NULL, &error_abort);
> +g_assert_nonnull(chr1);
> +qemu_opts_del(opts);
> +
> +/* Create second chardev */
> +opts = qemu_opts_create(qemu_find_opts("chardev"), "chr2",
> +1, &error_abort);
> +qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
> +qemu_opt_set(opts, "size", stringify(RB_SIZE), &error_abort);
> +qemu_opt_set(opts, "mux-be-id", "mux0", &error_abort);
> +chr2 = qemu_chr_new_from_opts(opts, NULL, &error_abort);
> +g_assert_nonnull(chr2);
> +qemu_opts_del(opts);
> +
> +/* Attach mux-be to a frontend */
> +qemu_chr_fe_init(&chr_be, mux_be, &error_abort);
> +qemu_chr_fe_set_

Re: [PATCH v6 3/3] Add support for RAPL MSRs in KVM/Qemu

2024-10-16 Thread Anthony Harivel
Hi Igor,

I will let Paolo or Daniel answering those architecture questions, they 
are more qualified than me. 

Thanks
Anthony


Igor Mammedov, Oct 16, 2024 at 14:17:
> On Wed, 22 May 2024 17:34:52 +0200
> Anthony Harivel  wrote:
>
>> Starting with the "Sandy Bridge" generation, Intel CPUs provide a RAPL
>> interface (Running Average Power Limit) for advertising the accumulated
>> energy consumption of various power domains (e.g. CPU packages, DRAM,
>> etc.).
>> 
>> The consumption is reported via MSRs (model specific registers) like
>> MSR_PKG_ENERGY_STATUS for the CPU package power domain. These MSRs are
>> 64 bits registers that represent the accumulated energy consumption in
>> micro Joules. They are updated by microcode every ~1ms.
>> 
>> For now, KVM always returns 0 when the guest requests the value of
>> these MSRs. Use the KVM MSR filtering mechanism to allow QEMU handle
>> these MSRs dynamically in userspace.
>> 
>> To limit the amount of system calls for every MSR call, create a new
>> thread in QEMU that updates the "virtual" MSR values asynchronously.
>> 
>> Each vCPU has its own vMSR to reflect the independence of vCPUs. The
>> thread updates the vMSR values with the ratio of energy consumed of
>> the whole physical CPU package the vCPU thread runs on and the
>> thread's utime and stime values.
>> 
>> All other non-vCPU threads are also taken into account. Their energy
>> consumption is evenly distributed among all vCPUs threads running on
>> the same physical CPU package.
>> 
>> To overcome the problem that reading the RAPL MSR requires priviliged
>> access, a socket communication between QEMU and the qemu-vmsr-helper is
>> mandatory. You can specified the socket path in the parameter.
>> 
>> This feature is activated with -accel kvm,rapl=true,path=/path/sock.sock
>> 
>> Actual limitation:
>> - Works only on Intel host CPU because AMD CPUs are using different MSR
>>   adresses.
>> 
>> - Only the Package Power-Plane (MSR_PKG_ENERGY_STATUS) is reported at
>>   the moment.
>> 
>> Signed-off-by: Anthony Harivel 
>> ---
>>  accel/kvm/kvm-all.c   |  27 +++
>>  docs/specs/index.rst  |   1 +
>>  docs/specs/rapl-msr.rst   | 155 
>>  include/sysemu/kvm_int.h  |  32 +++
>>  target/i386/cpu.h |   8 +
>>  target/i386/kvm/kvm.c | 431 +-
>>  target/i386/kvm/meson.build   |   1 +
>>  target/i386/kvm/vmsr_energy.c | 344 +++
>>  target/i386/kvm/vmsr_energy.h |  99 
>>  9 files changed, 1097 insertions(+), 1 deletion(-)
>>  create mode 100644 docs/specs/rapl-msr.rst
>>  create mode 100644 target/i386/kvm/vmsr_energy.c
>>  create mode 100644 target/i386/kvm/vmsr_energy.h
>> 
>
>
>> diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
>> index c0be9f5eedb8..f455e6b987b4 100644
>> --- a/accel/kvm/kvm-all.c
>> +++ b/accel/kvm/kvm-all.c
>> @@ -3745,6 +3745,21 @@ static void kvm_set_device(Object *obj,
>>  s->device = g_strdup(value);
>>  }
>>  
>> +static void kvm_set_kvm_rapl(Object *obj, bool value, Error **errp)
>> +{
>> +KVMState *s = KVM_STATE(obj);
>> +s->msr_energy.enable = value;
>> +}
>> +
>> +static void kvm_set_kvm_rapl_socket_path(Object *obj,
>> + const char *str,
>> + Error **errp)
>> +{
>> +KVMState *s = KVM_STATE(obj);
>> +g_free(s->msr_energy.socket_path);
>> +s->msr_energy.socket_path = g_strdup(str);
>> +}
>> +
>>  static void kvm_accel_instance_init(Object *obj)
>>  {
>>  KVMState *s = KVM_STATE(obj);
>> @@ -3764,6 +3779,7 @@ static void kvm_accel_instance_init(Object *obj)
>>  s->xen_gnttab_max_frames = 64;
>>  s->xen_evtchn_max_pirq = 256;
>>  s->device = NULL;
>> +s->msr_energy.enable = false;
>>  }
>>  
>>  /**
>> @@ -3808,6 +3824,17 @@ static void kvm_accel_class_init(ObjectClass *oc, 
>> void *data)
>>  object_class_property_set_description(oc, "device",
>>  "Path to the device node to use (default: /dev/kvm)");
>>  
>> +object_class_property_add_bool(oc, "rapl",
>> +   NULL,
>> +   kvm_set_kvm_rapl);
>> +object_class_property_set_description(oc, "rapl",
>> +"Allow energy related MSRs for RAPL interface in Guest");
>> +
>> +object_class_property_add_str(oc, "rapl-helper-socket", NULL,
>> +  kvm_set_kvm_rapl_socket_path);
>> +object_class_property_set_description(oc, "rapl-helper-socket",
>> +"Socket Path for comminucating with the Virtual MSR helper daemon");
>> +
>>  kvm_arch_accel_class_init(oc);
>>  }
>
> it seems, RAPL is x86 specific feature, so why it is in generic KVM code 
> instead of
> target/i386/kvm/kvm.c: kvm_arch_accel_class_init()
>
>>  
>> diff --git a/docs/specs/index.rst b/docs/specs/index.rst
>> index 1484e3e76077..e738ea7d102f 100644
>> --- a/docs/specs/index.rst
>> +++ b/docs/specs/ind

Re: [PATCH v8 0/6] AWS Nitro Enclave emulation support

2024-10-16 Thread Dorjoy Chowdhury
Ping

This patch series has been reviewed by Alex. I am not sure if it needs
more review. If not, maybe this can be picked up for merging. Thanks!

Regards,
Dorjoy



Re: [PATCH 1/2] gdbstub: Fix wrong CPUState pointer in breakpoint functions

2024-10-16 Thread Roque Arcudia Hernandez
Hello Philippe,

The Google-Bug-Id is an internal ID and should have been removed. The
information in the bug was mostly transcribed in the cover letter of
this patch series.

Thanks

Roque

On Mon, Oct 7, 2024 at 1:06 PM Philippe Mathieu-Daudé  wrote:
>
> Hi Roque,
>
> On 6/9/24 19:54, Roque Arcudia Hernandez wrote:
> > In the context of using the remote gdb with multiple
> > processes/inferiors (multiple cluster machine) a given breakpoint
> > will target an specific inferior. If needed the remote protocol will
> > use the packet 'H op thread-id' with op = 'g' to change focus to the
> > inferior we want to insert/remove the breakpoint to, for instance
> > 'Hgp3.3' and not 'Hcp3.3'.
> >
> > This is supported by the documentation of the H packets:
> >
> >   > 'H op thread-id'
> >   > Set thread for subsequent operations ('m', 'M', 'g', 'G',
> >   > et.al.). Depending on the operation to be performed, op should be
> >   > 'c' for step and continue operations (note that this is
> >   > deprecated, supporting the 'vCont' command is a better option),
> >   > and 'g' for other operations.
> >
> > This can also be verified in the GDB source code file gdb/remote.c.
> > Functions remote_target::insert_breakpoint and
> > remote_target::remove_breakpoint will eventually call
> > remote_target::set_general_thread if it needs to change the process
> > focus and not remote_target::set_continue_thread.
> >
> > This can be seen around a comment that says:
> >
> >/* Make sure the remote is pointing at the right process, if
> >   necessary.  */
> >
> > Google-Bug-Id: 355027002
>
> Where can we find more information on this bug ID?
> I tried various query in the Google public tracker but
> couldn't find anything.
> (i.e. https://issuetracker.google.com/issues?q=canonicalid:355027002)
>
> > Signed-off-by: Roque Arcudia Hernandez 
> > ---
> >   gdbstub/gdbstub.c | 4 ++--
> >   1 file changed, 2 insertions(+), 2 deletions(-)
>



Re: [PATCH v3 1/2] tpm: Use new ptm_cap_n structure for PTM_GET_CAPABILITY

2024-10-16 Thread Stefan Berger




On 10/16/24 11:03 AM, Daniel P. Berrangé wrote:

On Wed, Oct 16, 2024 at 10:57:07AM -0400, Stefan Berger wrote:

Use the new ptm_cap_n structure for getting the PTM_GET_CAPABILITY response
from swtpm. Previously only 17 bits could possibly have been set in ptm_cap
(=uint64_t) in big endian order and those bits are now found in the 2nd
32bit word in the response in the caps field.

This data structure makes it now clear that the 1st 32bit word carries the
tpm_result like all the other response structures of all other commands
do.

Signed-off-by: Stefan Berger 
---
  backends/tpm/tpm_emulator.c | 14 --
  backends/tpm/tpm_ioctl.h| 13 -
  backends/tpm/trace-events   |  2 +-
  3 files changed, 21 insertions(+), 8 deletions(-)




diff --git a/backends/tpm/tpm_ioctl.h b/backends/tpm/tpm_ioctl.h
index 1933ab6855..ee2dd15d35 100644
--- a/backends/tpm/tpm_ioctl.h
+++ b/backends/tpm/tpm_ioctl.h
@@ -29,6 +29,16 @@
  
  typedef uint32_t ptm_res;
  
+/* PTM_GET_CAPABILITY: Get supported capabilities (ioctl's) */

+struct ptm_cap_n {
+union {
+struct {
+ptm_res tpm_result; /* will always be TPM_SUCCESS (0) */
+uint32_t caps;
+} resp; /* response */
+} u;
+};


The union here is pointless surely, since it only has one entry and
the following patch doesn't add a 2nd either ?


I did this because all commands have a union.



With regards,
Daniel




Re: [PATCH 10/16] rust: introduce alternative implementation of offset_of!

2024-10-16 Thread Junjie Mao


Paolo Bonzini  writes:

> offset_of! was stabilized in Rust 1.77.0.  Use an alternative implemenation
> that was found on the Rust forums, and whose author agreed to license as
> MIT for use in QEMU.
>
> The alternative allows only one level of field access, but apart
> from this can be used just by replacing core::mem::offset_of! with
> qemu_api::offset_of!.

How about a macro like this (which essentially comes from memoffset
crate [1])? It has the same use as core::mem::offset_of! (except the
same single-level limitation) and does not need wrapping structures with
with_offsets!.

macro_rules! offset_of {
($parent:ty, $field:tt) => {{
let uninit = std::mem::MaybeUninit::<$parent>::uninit();
let base = uninit.as_ptr();
// SAFETY:
//
// MaybeUninit<$parent> has the same size and alignment as $parent, so
// projection to $field is in bound.
//
// addr_of! does not create intermediate references to the uninitialized
// memory, thus no UB is involved.
let field = unsafe { std::ptr::addr_of!((*base).$field) };
// SAFETY:
//
// Both base and field point to the MaybeUninit<$parent> and are casted
// to u8 for calculating their distance.
unsafe { field.cast::().offset_from(base.cast::()) as usize }
}};
}

[1] https://docs.rs/memoffset/latest/memoffset/

--
Best Regards
Junjie Mao



Re: [PATCH v2 6/7] hw/intc/openpic: Improve errors for out of bounds property values

2024-10-16 Thread Markus Armbruster
Philippe Mathieu-Daudé  writes:

> On 10/10/24 12:01, Markus Armbruster wrote:
>> The error message doesn't matter much, as the "openpic" device isn't
>> user-creatable.  But it's the last use of
>> QERR_PROPERTY_VALUE_OUT_OF_RANGE, which has to go.  Change the message
>> just like the previous commit did for x86 CPUs.
>>
>> Signed-off-by: Markus Armbruster 
>> ---
>>   hw/intc/openpic.c | 5 +
>>   1 file changed, 1 insertion(+), 4 deletions(-)
>>
>> diff --git a/hw/intc/openpic.c b/hw/intc/openpic.c
>> index 32bd880dfa..cd3d87768e 100644
>> --- a/hw/intc/openpic.c
>> +++ b/hw/intc/openpic.c
>> @@ -41,7 +41,6 @@
>>  #include "hw/pci/msi.h"
>>  #include "qapi/error.h"
>>  #include "qemu/bitops.h"
>> -#include "qapi/qmp/qerror.h"
>>  #include "qemu/module.h"
>>  #include "qemu/timer.h"
>>  #include "qemu/error-report.h"
>> @@ -1535,9 +1534,7 @@ static void openpic_realize(DeviceState *dev, Error 
>> **errp)
>>  };
>>
>>  if (opp->nb_cpus > MAX_CPU) {
>> -error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
>> -   TYPE_OPENPIC, "nb_cpus", (uint64_t)opp->nb_cpus,
>> -   (uint64_t)0, (uint64_t)MAX_CPU);
>> +error_setg(errp, "property 'nb_cpus' can be at most %d", MAX_CPU);
>>  return;
>>  }
>>   
>
> As another cleanup we could convert MAX_CPU to unsigned.

Existing uses are all fine as is.  Perhaps the maintainer has a
preference.

> Reviewed-by: Philippe Mathieu-Daudé 

Thanks!




Re: [PATCH 0/7] virtio-net fixes

2024-10-16 Thread Jason Wang
Hi Michael:

On Wed, Oct 16, 2024 at 1:58 AM Michael Tokarev  wrote:
>
> On 15.09.2024 04:06, Akihiko Odaki wrote:
> > Most of this series are fixes for software RSS and hash reporting, which
> > should have no production user.
> >
> > However there is one exception; patch "virtio-net: Fix size check in
> > dhclient workaround" fixes an out-of-bound access that can be triggered
> > for anyone who don't use vhost. It has Cc: qemu-sta...@nongnu.org and
> > can be applied independently.
> >
> > Signed-off-by: Akihiko Odaki 
> > ---
> > Akihiko Odaki (7):
> >net: checksum: Convert data to void *
> >virtio-net: Fix size check in dhclient workaround
> >virtio-net: Do not check for the queue before RSS
> >virtio-net: Fix hash reporting when the queue changes
> >virtio-net: Initialize hash reporting values
> >virtio-net: Copy received header to buffer
> >virtio-net: Fix num_buffers for version 1
> >
> >   include/net/checksum.h |   2 +-
> >   hw/net/virtio-net.c| 109 
> > -
> >   net/checksum.c |   4 +-
> >   3 files changed, 65 insertions(+), 50 deletions(-)
>
> Hi!
>
> Has this patchset been forgotten, or does it wait for some
> R-b's ?

Thanks for the reminder.

I would go through this series.

Thanks

>
> Thanks,
>
> /mjt
>




Re: [PATCH] crypto/hash-afalg: Fix broken build

2024-10-16 Thread Cédric Le Goater

On 10/17/24 08:47, Markus Armbruster wrote:

Fux build broken by semantic conflict with commit
8f525028bc6 (qapi/crypto: Rename QCryptoAFAlg to QCryptoAFAlgo).

Fixes: 90c3dc60735a (crypto/hash-afalg: Implement new hash API)
Signed-off-by: Markus Armbruster 


My bad :/ Obviously, I didn't catch this at compile time, nor did CI.

Reviewed-by: Cédric Le Goater 

Thanks,

C.



---
  crypto/hash-afalg.c | 10 +-
  1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/crypto/hash-afalg.c b/crypto/hash-afalg.c
index 06e1e4699c..8c0ce5b520 100644
--- a/crypto/hash-afalg.c
+++ b/crypto/hash-afalg.c
@@ -142,7 +142,7 @@ QCryptoHash *qcrypto_afalg_hash_new(QCryptoHashAlgo alg, 
Error **errp)
  static
  void qcrypto_afalg_hash_free(QCryptoHash *hash)
  {
-QCryptoAFAlg *ctx = hash->opaque;
+QCryptoAFAlgo *ctx = hash->opaque;
  
  if (ctx) {

  qcrypto_afalg_comm_free(ctx);
@@ -159,7 +159,7 @@ void qcrypto_afalg_hash_free(QCryptoHash *hash)
   * be provided to calculate the final hash.
   */
  static
-int qcrypto_afalg_send_to_kernel(QCryptoAFAlg *afalg,
+int qcrypto_afalg_send_to_kernel(QCryptoAFAlgo *afalg,
   const struct iovec *iov,
   size_t niov,
   bool more_data,
@@ -183,7 +183,7 @@ int qcrypto_afalg_send_to_kernel(QCryptoAFAlg *afalg,
  }
  
  static

-int qcrypto_afalg_recv_from_kernel(QCryptoAFAlg *afalg,
+int qcrypto_afalg_recv_from_kernel(QCryptoAFAlgo *afalg,
 QCryptoHashAlgo alg,
 uint8_t **result,
 size_t *result_len,
@@ -222,7 +222,7 @@ int qcrypto_afalg_hash_update(QCryptoHash *hash,
size_t niov,
Error **errp)
  {
-return qcrypto_afalg_send_to_kernel((QCryptoAFAlg *) hash->opaque,
+return qcrypto_afalg_send_to_kernel((QCryptoAFAlgo *) hash->opaque,
  iov, niov, true, errp);
  }
  
@@ -232,7 +232,7 @@ int qcrypto_afalg_hash_finalize(QCryptoHash *hash,

   size_t *result_len,
   Error **errp)
  {
-return qcrypto_afalg_recv_from_kernel((QCryptoAFAlg *) hash->opaque,
+return qcrypto_afalg_recv_from_kernel((QCryptoAFAlgo *) hash->opaque,
hash->alg, result, result_len, 
errp);
  }
  





Re: [PATCH] migration/dirtyrate: Silence warning about strcpy() on OpenBSD

2024-10-16 Thread Thomas Huth

On 16/10/2024 18.22, Daniel P. Berrangé wrote:

On Wed, Oct 16, 2024 at 06:07:12PM +0200, Thomas Huth wrote:

The linker on OpenBSD complains:

  ld: warning: dirtyrate.c:447 (../src/migration/dirtyrate.c:447)(...):
  warning: strcpy() is almost always misused, please use strlcpy()


Is that the only place it complains ?  We use 'strcpy' in almost
100 places across the codebase


There are only a fistful of other warnings. I guess most of the spots are 
turned into inlined code by the compiler, so the linker never sees those 
other occurrences.



It's currently not a real problem in this case since both arrays
have the same size (256 bytes). But just in case somebody changes
the size of the source array in the future, let's better play safe
and use g_strlcpy() here instead.

Signed-off-by: Thomas Huth 
---
  migration/dirtyrate.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/migration/dirtyrate.c b/migration/dirtyrate.c
index 233acb0855..090c76e934 100644
--- a/migration/dirtyrate.c
+++ b/migration/dirtyrate.c
@@ -444,7 +444,7 @@ static void get_ramblock_dirty_info(RAMBlock *block,
  info->ramblock_pages = qemu_ram_get_used_length(block) >>
 qemu_target_page_bits();
  info->ramblock_addr = qemu_ram_get_host_addr(block);
-strcpy(info->idstr, qemu_ram_get_idstr(block));
+g_strlcpy(info->idstr, qemu_ram_get_idstr(block), sizeof(info->idstr));
  }


Reviewed-by: Daniel P. Berrangé 


Is it worth also adding

   G_STATIC_ASSERT(sizeof((struct RamblockDirtyInfo){}.idstr) ==
   sizeof((struct RAMBlock){}.idstr));

at the top of this file, since both of these fields are expected to
be the same size by this code, to avoid truncation.


... or alternatively check the return value of g_strlcpy() ? ... but that 
wouldn't work if pstrcpy() if we switch to that function instead.


I don't mind either way - Peter, Fabiano, Hyman, what's your opinion here?

 Thomas




Re: Host riscv disas is broken

2024-10-16 Thread LIU Zhiwei



On 2024/10/17 11:52, Richard Henderson wrote:

On 10/16/24 19:57, LIU Zhiwei wrote:

Hi Richard,

On 2024/10/17 02:38, Richard Henderson wrote:

2595: if (dec->cfg->ext_zcmop) {
2690:    if (dec->cfg->ext_zcmp && ((inst >> 12) & 0b01)) {
2716:    if (!dec->cfg->ext_zcmt) {
2726:    if (!dec->cfg->ext_zcmp) {
4028:    if (dec->cfg->ext_zimop) {
5044:    if (dec->cfg->ext_zfinx) {
5051:    if (dec->cfg->ext_zfinx) {
5058:    if (dec->cfg->ext_zfinx) {
5065:    if (dec->cfg->ext_zfinx) {
5371:    if (guard_func(cfg)) {

This structure comes from RISCVCPU, a target structure.

Oops. We missed this.
There is no such structure for the host, causing null pointer 
dereferences.


The zfinx references can be changed to

    dec->cfg && dec->cfg->ext_zfinx

but some of them can simply be removed, e.g. zcmop and zimop, which 
are otherwise reserved encodings.
Yes. Maybe it is better to disassemble them as usual even when there are 
disabled or not supported.


Should we probe the host feature like what we do in tcg backend 
support and then do the right disassemble according to the probe result?


I don't think there's anything that is currently checked in 
disas/riscv.c that needs to know about the host.  And, as I say above, 
some of those checks can be eliminated.


Host disassembly needs are limited to what tcg/riscv/ emits.


Agree.

Thanks,
Zhiwei

Thanks,
Zhiwei




r~




[PATCH] crypto/hash-afalg: Fix broken build

2024-10-16 Thread Markus Armbruster
Fux build broken by semantic conflict with commit
8f525028bc6 (qapi/crypto: Rename QCryptoAFAlg to QCryptoAFAlgo).

Fixes: 90c3dc60735a (crypto/hash-afalg: Implement new hash API)
Signed-off-by: Markus Armbruster 
---
 crypto/hash-afalg.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/crypto/hash-afalg.c b/crypto/hash-afalg.c
index 06e1e4699c..8c0ce5b520 100644
--- a/crypto/hash-afalg.c
+++ b/crypto/hash-afalg.c
@@ -142,7 +142,7 @@ QCryptoHash *qcrypto_afalg_hash_new(QCryptoHashAlgo alg, 
Error **errp)
 static
 void qcrypto_afalg_hash_free(QCryptoHash *hash)
 {
-QCryptoAFAlg *ctx = hash->opaque;
+QCryptoAFAlgo *ctx = hash->opaque;
 
 if (ctx) {
 qcrypto_afalg_comm_free(ctx);
@@ -159,7 +159,7 @@ void qcrypto_afalg_hash_free(QCryptoHash *hash)
  * be provided to calculate the final hash.
  */
 static
-int qcrypto_afalg_send_to_kernel(QCryptoAFAlg *afalg,
+int qcrypto_afalg_send_to_kernel(QCryptoAFAlgo *afalg,
  const struct iovec *iov,
  size_t niov,
  bool more_data,
@@ -183,7 +183,7 @@ int qcrypto_afalg_send_to_kernel(QCryptoAFAlg *afalg,
 }
 
 static
-int qcrypto_afalg_recv_from_kernel(QCryptoAFAlg *afalg,
+int qcrypto_afalg_recv_from_kernel(QCryptoAFAlgo *afalg,
QCryptoHashAlgo alg,
uint8_t **result,
size_t *result_len,
@@ -222,7 +222,7 @@ int qcrypto_afalg_hash_update(QCryptoHash *hash,
   size_t niov,
   Error **errp)
 {
-return qcrypto_afalg_send_to_kernel((QCryptoAFAlg *) hash->opaque,
+return qcrypto_afalg_send_to_kernel((QCryptoAFAlgo *) hash->opaque,
 iov, niov, true, errp);
 }
 
@@ -232,7 +232,7 @@ int qcrypto_afalg_hash_finalize(QCryptoHash *hash,
  size_t *result_len,
  Error **errp)
 {
-return qcrypto_afalg_recv_from_kernel((QCryptoAFAlg *) hash->opaque,
+return qcrypto_afalg_recv_from_kernel((QCryptoAFAlgo *) hash->opaque,
   hash->alg, result, result_len, errp);
 }
 
-- 
2.46.0




Re: [PATCH v2] tests/functional: Convert most Aspeed machine tests

2024-10-16 Thread Thomas Huth

On 16/10/2024 22.38, Cédric Le Goater wrote:

This is a simple conversion of the tests with some cleanups and
adjustments to match the new test framework. Replace the zephyr image
MD5 hashes with SHA256 hashes while at it.

The SDK tests depend on a ssh class from avocado.utils which is
difficult to replace. To be addressed separately.

Signed-off-by: Cédric Le Goater 
---

  Changes in v2:

  - define class level Asset variables

  tests/avocado/machine_aspeed.py | 252 -
  tests/functional/meson.build|   2 +
  tests/functional/test_arm_aspeed.py | 277 
  3 files changed, 279 insertions(+), 252 deletions(-)
  create mode 100644 tests/functional/test_arm_aspeed.py

diff --git a/tests/avocado/machine_aspeed.py b/tests/avocado/machine_aspeed.py
index 4e144bde9131..cb163e3a1106 100644
--- a/tests/avocado/machine_aspeed.py
+++ b/tests/avocado/machine_aspeed.py
@@ -19,258 +19,6 @@
  from avocado_qemu import has_cmd
  from avocado.utils import archive
  from avocado import skipUnless
-from avocado import skipUnless
-
-
-class AST1030Machine(QemuSystemTest):
-"""Boots the zephyr os and checks that the console is operational"""
-
-timeout = 10
-
-def test_ast1030_zephyros_1_04(self):
-"""
-:avocado: tags=arch:arm
-:avocado: tags=machine:ast1030-evb
-:avocado: tags=os:zephyr
-"""
-tar_url = ('https://github.com/AspeedTech-BMC'
-   '/zephyr/releases/download/v00.01.04/ast1030-evb-demo.zip')
-tar_hash = '4c6a8ce3a8ba76ef1a65dae419ae3409343c4b20'
-tar_path = self.fetch_asset(tar_url, asset_hash=tar_hash)
-archive.extract(tar_path, self.workdir)
-kernel_file = self.workdir + "/ast1030-evb-demo/zephyr.elf"
-self.vm.set_console()
-self.vm.add_args('-kernel', kernel_file,
- '-nographic')
-self.vm.launch()
-wait_for_console_pattern(self, "Booting Zephyr OS")
-exec_command_and_wait_for_pattern(self, "help",
-  "Available commands")
-
-def test_ast1030_zephyros_1_07(self):
-"""
-:avocado: tags=arch:arm
-:avocado: tags=machine:ast1030-evb
-:avocado: tags=os:zephyr
-"""
-tar_url = ('https://github.com/AspeedTech-BMC'
-   '/zephyr/releases/download/v00.01.07/ast1030-evb-demo.zip')
-tar_hash = '40ac87eabdcd3b3454ce5aad11fedc72a33ecda2'
-tar_path = self.fetch_asset(tar_url, asset_hash=tar_hash)
-archive.extract(tar_path, self.workdir)
-kernel_file = self.workdir + "/ast1030-evb-demo/zephyr.bin"
-self.vm.set_console()
-self.vm.add_args('-kernel', kernel_file,
- '-nographic')
-self.vm.launch()
-wait_for_console_pattern(self, "Booting Zephyr OS")
-for shell_cmd in [
-'kernel stacks',
-'otp info conf',
-'otp info scu',
-'hwinfo devid',
-'crypto aes256_cbc_vault',
-'random get',
-'jtag JTAG1 sw_xfer high TMS',
-'adc ADC0 resolution 12',
-'adc ADC0 read 42',
-'adc ADC1 read 69',
-'i2c scan I2C_0',
-'i3c attach I3C_0',
-'hash test',
-'kernel uptime',
-'kernel reboot warm',
-'kernel uptime',
-'kernel reboot cold',
-'kernel uptime',
-]: exec_command_and_wait_for_pattern(self, shell_cmd, "uart:~$")
-
-class AST2x00Machine(QemuSystemTest):
-
-timeout = 180
-
-def wait_for_console_pattern(self, success_message, vm=None):
-wait_for_console_pattern(self, success_message,
- failure_message='Kernel panic - not syncing',
- vm=vm)


You're losing the "failure_message='Kernel panic - not syncing'" check in 
your new code. Maybe not worth the effort to copy it over, but still, should 
be mentioned at least in the commit description, I think.


Alternatively, you could also use the LinuxKernelTest base class instead 
which has this wait_for_console_pattern magic included already.



-def do_test_arm_aspeed(self, image):
-self.vm.set_console()
-self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw',
- '-net', 'nic')
-self.vm.launch()
-
-self.wait_for_console_pattern("U-Boot 2016.07")
-self.wait_for_console_pattern("## Loading kernel from FIT Image at 
2008")
-self.wait_for_console_pattern("Starting kernel ...")
-self.wait_for_console_pattern("Booting Linux on physical CPU 0x0")
-wait_for_console_pattern(self,
-"aspeed-smc 1e62.spi: read control register: 203b0641")
-self.wait_for_console_pattern("ftgmac100 1e66.eth

RE: [PATCH] hw/riscv: Add Microblaze V 32bit virt board

2024-10-16 Thread Boddu, Sai Pavan
Hi Daniel,

Thanks for the review, I will send a V2 addressing the comments.

Regards,
Sai Pavan

>-Original Message-
>From: Daniel Henrique Barboza 
>Sent: Wednesday, October 16, 2024 1:28 AM
>To: Boddu, Sai Pavan ; qemu-devel@nongnu.org;
>qemu-ri...@nongnu.org
>Cc: Paolo Bonzini ; Palmer Dabbelt
>; Alistair Francis ; Bin Meng
>; Weiwei Li ; Liu Zhiwei
>; Simek, Michal 
>Subject: Re: [PATCH] hw/riscv: Add Microblaze V 32bit virt board
>
>Hi,
>
>
>The doc file included in the patch will break the build:
>
>/home/danielhb/work/qemu/docs/system/riscv/microblaze-v-virt.rst:document isn't
>included in any toctree
>
>You'll need this extra change:
>
>
>$ git diff
>diff --git a/docs/system/target-riscv.rst b/docs/system/target-riscv.rst index
>ba195f1518..6161f01d21 100644
>--- a/docs/system/target-riscv.rst
>+++ b/docs/system/target-riscv.rst
>@@ -70,6 +70,7 @@ undocumented; you can get a complete list by running
> riscv/shakti-c
> riscv/sifive_u
> riscv/virt
>+   riscv/microblaze-v-virt
>
>  RISC-V CPU firmware
>
>
>More comments below:
>
>On 10/15/24 10:39 AM, Sai Pavan Boddu wrote:
>> Add a basic board with interrupt controller (intc), timer, serial
>> (uartlite), small memory called LMB@0 (128kB) and DDR@0x8000
>> (configured via command line eg. -m 2g).
>> This is basic configuration which matches HW generated out of AMD
>> Vivado (design tools). But initial configuration is going beyond what
>> it is configured by default because validation should be done on other
>> configurations too. That's why wire also additional uart16500, axi
>> ethernet(with axi dma).
>> GPIOs, i2c and qspi is also listed for completeness.
>>
>> IRQ map is: (addr)
>> 0 - timer (0x41c0)
>> 1 - uartlite (0x4060)
>> 2 - i2c (0x4080)
>> 3 - qspi (0x44a0)
>> 4 - uart16550 (0x44a1)
>> 5 - emaclite (0x40e0)
>> 6 - timer2 (0x41c1)
>> 7 - axi emac (0x40c0)
>> 8 - axi dma (0x41e0)
>> 9 - axi dma
>> 10 - gpio (0x4000)
>> 11 - gpio2 (0x4001)
>> 12 - gpio3 (0x4002)
>>
>> Signed-off-by: Sai Pavan Boddu 
>> Signed-off-by: Michal Simek 
>> ---
>>   MAINTAINERS |   6 +
>>   docs/system/riscv/microblaze-v-virt.rst |  39 +
>>   hw/riscv/microblaze-v-virt.c| 182 
>>   hw/riscv/Kconfig|   8 ++
>>   hw/riscv/meson.build|   1 +
>>   5 files changed, 236 insertions(+)
>>   create mode 100644 docs/system/riscv/microblaze-v-virt.rst
>>   create mode 100644 hw/riscv/microblaze-v-virt.c
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS index d7a11fe6017..b104b6d0f7f
>> 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -1274,6 +1274,12 @@ M: Edgar E. Iglesias 
>>   S: Maintained
>>   F: hw/microblaze/petalogix_ml605_mmu.c
>>
>> +amd-microblaze-v-virt
>> +M: Sai Pavan Boddu 
>> +S: Maintained
>> +F: hw/riscv/microblaze-v-virt.c
>> +F: docs/system/riscv/microblaze-v-virt.rst
>> +
>>   MIPS Machines
>>   -
>>   Overall MIPS Machines
>> diff --git a/docs/system/riscv/microblaze-v-virt.rst
>> b/docs/system/riscv/microblaze-v-virt.rst
>> new file mode 100644
>> index 000..42cac9ac475
>> --- /dev/null
>> +++ b/docs/system/riscv/microblaze-v-virt.rst
>> @@ -0,0 +1,39 @@
>> +microblaze-v virt board (``amd-microblaze-v-virt``)
>> +===
>> +The AMD MicroBlaze™ V processor is a soft-core RISC-V processor IP for AMD
>adaptive SoCs and FPGAs.
>> +The MicroBlaze V processor is based on a 32-bit RISC-V instruction set
>architecture (ISA).
>> +
>> +More details here:
>> +https://docs.amd.com/r/en-US/ug1629-microblaze-v-user-guide/MicroBlaz
>> +e-V-Architecture
>> +
>> +The microblaze-v virt board in QEMU is a virtual board with following
>> +supported devices
>> +
>> +Implemented CPU cores:
>> +
>> +1 RISCV32 core
>> +
>> +Implemented devices:
>> +
>> +- timer
>> +- uartlite
>> +- uart16550
>> +- emaclite
>> +- timer2
>> +- axi emac
>> +- axi dma
>> +
>> +Running
>> +"""
>> +Running U-boot
>> +
>> +.. code-block:: bash
>> +
>> +
>> +   $ qemu-system-riscv32 -M amd-microblaze-v-virt \
>> + -display none \
>> + -device loader,addr=0x8000,file=u-boot-spl.bin,cpu-num=0 \
>> + -device loader,addr=0x8020,file=u-boot.img \
>> + -serial mon:stdio \
>> + -device loader,addr=0x8300,file=system.dtb \
>> + -m 2g
>> diff --git a/hw/riscv/microblaze-v-virt.c
>> b/hw/riscv/microblaze-v-virt.c new file mode 100644 index
>> 000..d9cdfe39857
>> --- /dev/null
>> +++ b/hw/riscv/microblaze-v-virt.c
>> @@ -0,0 +1,182 @@
>> +/*
>> + * QEMU model of Microblaze V (32bit version)
>> + *
>> + * based on hw/microblaze/petalogix_ml605_mmu.c
>> + *
>> + * Copyright (c) 2011 Michal Simek 
>> + * Copyright (c) 2011 PetaLogix
>> + * Copyright (c) 2009 Edgar E. Iglesias.
>> + * Copyright (C) 2024, Advanced Micro Devices, Inc.
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + * Written

[PATCH v4 3/6] migration: Move cpu-throttole.c from system to migration

2024-10-16 Thread yong . huang
From: Hyman Huang 

Move cpu-throttle.c from system to migration since it's
only used for migration; this makes us avoid exporting the
util functions and variables in misc.h but export them in
migration.h when implementing the periodic ramblock dirty
sync feature in the upcoming commits.

Since CPU throttle timers are only used in migration, move
their registry to migration_object_init.

Signed-off-by: Hyman Huang 
---
 {system => migration}/cpu-throttle.c | 2 +-
 {include/sysemu => migration}/cpu-throttle.h | 0
 migration/meson.build| 1 +
 migration/migration.c| 5 -
 migration/ram.c  | 2 +-
 migration/trace-events   | 3 +++
 system/cpu-timers.c  | 3 ---
 system/meson.build   | 1 -
 system/trace-events  | 3 ---
 9 files changed, 10 insertions(+), 10 deletions(-)
 rename {system => migration}/cpu-throttle.c (99%)
 rename {include/sysemu => migration}/cpu-throttle.h (100%)

diff --git a/system/cpu-throttle.c b/migration/cpu-throttle.c
similarity index 99%
rename from system/cpu-throttle.c
rename to migration/cpu-throttle.c
index 7632dc6143..fa47ee2e21 100644
--- a/system/cpu-throttle.c
+++ b/migration/cpu-throttle.c
@@ -27,7 +27,7 @@
 #include "hw/core/cpu.h"
 #include "qemu/main-loop.h"
 #include "sysemu/cpus.h"
-#include "sysemu/cpu-throttle.h"
+#include "cpu-throttle.h"
 #include "trace.h"
 
 /* vcpu throttling controls */
diff --git a/include/sysemu/cpu-throttle.h b/migration/cpu-throttle.h
similarity index 100%
rename from include/sysemu/cpu-throttle.h
rename to migration/cpu-throttle.h
diff --git a/migration/meson.build b/migration/meson.build
index 66d3de86f0..d53cf3417a 100644
--- a/migration/meson.build
+++ b/migration/meson.build
@@ -13,6 +13,7 @@ system_ss.add(files(
   'block-dirty-bitmap.c',
   'channel.c',
   'channel-block.c',
+  'cpu-throttle.c',
   'dirtyrate.c',
   'exec.c',
   'fd.c',
diff --git a/migration/migration.c b/migration/migration.c
index 37a200a177..2e10ca77af 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -24,7 +24,7 @@
 #include "socket.h"
 #include "sysemu/runstate.h"
 #include "sysemu/sysemu.h"
-#include "sysemu/cpu-throttle.h"
+#include "cpu-throttle.h"
 #include "rdma.h"
 #include "ram.h"
 #include "migration/global_state.h"
@@ -263,6 +263,9 @@ void migration_object_init(void)
 
 ram_mig_init();
 dirty_bitmap_mig_init();
+
+/* Initialize cpu throttle timers */
+cpu_throttle_init();
 }
 
 typedef struct {
diff --git a/migration/ram.c b/migration/ram.c
index 326ce7eb79..54d352b152 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -52,7 +52,7 @@
 #include "exec/target_page.h"
 #include "qemu/rcu_queue.h"
 #include "migration/colo.h"
-#include "sysemu/cpu-throttle.h"
+#include "cpu-throttle.h"
 #include "savevm.h"
 #include "qemu/iov.h"
 #include "multifd.h"
diff --git a/migration/trace-events b/migration/trace-events
index c65902f042..9a19599804 100644
--- a/migration/trace-events
+++ b/migration/trace-events
@@ -378,3 +378,6 @@ migration_block_progression(unsigned percent) "Completed 
%u%%"
 # page_cache.c
 migration_pagecache_init(int64_t max_num_items) "Setting cache buckets to %" 
PRId64
 migration_pagecache_insert(void) "Error allocating page"
+
+# cpu-throttle.c
+cpu_throttle_set(int new_throttle_pct)  "set guest CPU throttled by %d%%"
diff --git a/system/cpu-timers.c b/system/cpu-timers.c
index 0b31c9a1b6..856e502e34 100644
--- a/system/cpu-timers.c
+++ b/system/cpu-timers.c
@@ -35,7 +35,6 @@
 #include "sysemu/runstate.h"
 #include "hw/core/cpu.h"
 #include "sysemu/cpu-timers.h"
-#include "sysemu/cpu-throttle.h"
 #include "sysemu/cpu-timers-internal.h"
 
 /* clock and ticks */
@@ -272,6 +271,4 @@ void cpu_timers_init(void)
 seqlock_init(&timers_state.vm_clock_seqlock);
 qemu_spin_init(&timers_state.vm_clock_lock);
 vmstate_register(NULL, 0, &vmstate_timers, &timers_state);
-
-cpu_throttle_init();
 }
diff --git a/system/meson.build b/system/meson.build
index a296270cb0..4952f4b2c7 100644
--- a/system/meson.build
+++ b/system/meson.build
@@ -10,7 +10,6 @@ system_ss.add(files(
   'balloon.c',
   'bootdevice.c',
   'cpus.c',
-  'cpu-throttle.c',
   'cpu-timers.c',
   'datadir.c',
   'dirtylimit.c',
diff --git a/system/trace-events b/system/trace-events
index 074d001e90..2ed1d59b1f 100644
--- a/system/trace-events
+++ b/system/trace-events
@@ -44,6 +44,3 @@ dirtylimit_state_finalize(void)
 dirtylimit_throttle_pct(int cpu_index, uint64_t pct, int64_t time_us) "CPU[%d] 
throttle percent: %" PRIu64 ", throttle adjust time %"PRIi64 " us"
 dirtylimit_set_vcpu(int cpu_index, uint64_t quota) "CPU[%d] set dirty page 
rate limit %"PRIu64
 dirtylimit_vcpu_execute(int cpu_index, int64_t sleep_time_us) "CPU[%d] sleep 
%"PRIi64 " us"
-
-# cpu-throttle.c
-cpu_throttle_set(int new_throttle_pct)  "set guest CPU throttled by %d%%"
-- 
2.27.0




[PATCH v4 2/6] migration: Stop CPU throttling conditionally

2024-10-16 Thread yong . huang
From: Hyman Huang 

Since CPU throttling only occurs when auto-converge
is on, stop it conditionally.

Signed-off-by: Hyman Huang 
---
 migration/migration.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/migration/migration.c b/migration/migration.c
index 021faee2f3..37a200a177 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -3289,7 +3289,9 @@ static MigIterateState 
migration_iteration_run(MigrationState *s)
 static void migration_iteration_finish(MigrationState *s)
 {
 /* If we enabled cpu throttling for auto-converge, turn it off. */
-cpu_throttle_stop();
+if (migrate_auto_converge()) {
+cpu_throttle_stop();
+}
 
 bql_lock();
 switch (s->state) {
-- 
2.27.0




[PATCH v4 5/6] migration: Support periodic RAMBlock dirty bitmap sync

2024-10-16 Thread yong . huang
From: Hyman Huang 

When VM is configured with huge memory, the current throttle logic
doesn't look like to scale, because migration_trigger_throttle()
is only called for each iteration, so it won't be invoked for a long
time if one iteration can take a long time.

The periodic dirty sync aims to fix the above issue by synchronizing
the ramblock from remote dirty bitmap and, when necessary, triggering
the CPU throttle multiple times during a long iteration.

This is a trade-off between synchronization overhead and CPU throttle
impact.

Signed-off-by: Hyman Huang 
---
 migration/cpu-throttle.c | 65 +++-
 migration/cpu-throttle.h | 14 +
 migration/migration.c| 14 +++--
 migration/migration.h|  1 +
 migration/ram.c  |  2 +-
 migration/trace-events   |  1 +
 6 files changed, 93 insertions(+), 4 deletions(-)

diff --git a/migration/cpu-throttle.c b/migration/cpu-throttle.c
index fa47ee2e21..342681cdd4 100644
--- a/migration/cpu-throttle.c
+++ b/migration/cpu-throttle.c
@@ -28,16 +28,22 @@
 #include "qemu/main-loop.h"
 #include "sysemu/cpus.h"
 #include "cpu-throttle.h"
+#include "migration.h"
+#include "migration-stats.h"
 #include "trace.h"
 
 /* vcpu throttling controls */
-static QEMUTimer *throttle_timer;
+static QEMUTimer *throttle_timer, *throttle_dirty_sync_timer;
 static unsigned int throttle_percentage;
+static bool throttle_dirty_sync_timer_active;
 
 #define CPU_THROTTLE_PCT_MIN 1
 #define CPU_THROTTLE_PCT_MAX 99
 #define CPU_THROTTLE_TIMESLICE_NS 1000
 
+/* Making sure RAMBlock dirty bitmap is synchronized every five seconds */
+#define CPU_THROTTLE_DIRTY_SYNC_TIMESLICE_MS 5000
+
 static void cpu_throttle_thread(CPUState *cpu, run_on_cpu_data opaque)
 {
 double pct;
@@ -112,6 +118,7 @@ void cpu_throttle_set(int new_throttle_pct)
 void cpu_throttle_stop(void)
 {
 qatomic_set(&throttle_percentage, 0);
+cpu_throttle_dirty_sync_timer(false);
 }
 
 bool cpu_throttle_active(void)
@@ -124,8 +131,64 @@ int cpu_throttle_get_percentage(void)
 return qatomic_read(&throttle_percentage);
 }
 
+void cpu_throttle_dirty_sync_timer_tick(void *opaque)
+{
+static uint64_t prev_sync_cnt;
+uint64_t sync_cnt = stat64_get(&mig_stats.dirty_sync_count);
+
+/*
+ * The first iteration copies all memory anyhow and has no
+ * effect on guest performance, therefore omit it to avoid
+ * paying extra for the sync penalty.
+ */
+if (sync_cnt <= 1) {
+goto end;
+}
+
+if (sync_cnt == prev_sync_cnt) {
+trace_cpu_throttle_dirty_sync();
+WITH_RCU_READ_LOCK_GUARD() {
+migration_bitmap_sync_precopy(false);
+}
+}
+
+end:
+prev_sync_cnt = stat64_get(&mig_stats.dirty_sync_count);
+
+timer_mod(throttle_dirty_sync_timer,
+qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL_RT) +
+CPU_THROTTLE_DIRTY_SYNC_TIMESLICE_MS);
+}
+
+static bool cpu_throttle_dirty_sync_active(void)
+{
+return qatomic_read(&throttle_dirty_sync_timer_active);
+}
+
+void cpu_throttle_dirty_sync_timer(bool enable)
+{
+assert(throttle_dirty_sync_timer);
+
+if (enable) {
+if (!cpu_throttle_dirty_sync_active()) {
+timer_mod(throttle_dirty_sync_timer,
+qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL_RT) +
+CPU_THROTTLE_DIRTY_SYNC_TIMESLICE_MS);
+qatomic_set(&throttle_dirty_sync_timer_active, 1);
+}
+} else {
+if (cpu_throttle_dirty_sync_active()) {
+timer_del(throttle_dirty_sync_timer);
+qatomic_set(&throttle_dirty_sync_timer_active, 0);
+}
+}
+}
+
 void cpu_throttle_init(void)
 {
 throttle_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL_RT,
   cpu_throttle_timer_tick, NULL);
+throttle_dirty_sync_timer =
+timer_new_ms(QEMU_CLOCK_VIRTUAL_RT,
+ cpu_throttle_dirty_sync_timer_tick, NULL);
 }
diff --git a/migration/cpu-throttle.h b/migration/cpu-throttle.h
index d65bdef6d0..420702b8d3 100644
--- a/migration/cpu-throttle.h
+++ b/migration/cpu-throttle.h
@@ -65,4 +65,18 @@ bool cpu_throttle_active(void);
  */
 int cpu_throttle_get_percentage(void);
 
+/**
+ * cpu_throttle_dirty_sync_timer_tick:
+ *
+ * Dirty sync timer hook.
+ */
+void cpu_throttle_dirty_sync_timer_tick(void *opaque);
+
+/**
+ * cpu_throttle_dirty_sync_timer:
+ *
+ * Start or stop the dirty sync timer.
+ */
+void cpu_throttle_dirty_sync_timer(bool enable);
+
 #endif /* SYSEMU_CPU_THROTTLE_H */
diff --git a/migration/migration.c b/migration/migration.c
index 2e10ca77af..f673e30069 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -3291,12 +3291,17 @@ static MigIterateState 
migration_iteration_run(MigrationState *s)
 
 static void migration_iteration_finish(MigrationState *s)
 {
-/* If we enabled cpu throttling for auto-converge, turn it off. */
+bql_lock();
+
+/*
+ * If we enabled cpu throttling for auto-converge, turn it o

[PATCH v4 1/6] accel/tcg/icount-common: Remove the reference to the unused header file

2024-10-16 Thread yong . huang
From: Hyman Huang 

Signed-off-by: Hyman Huang 
---
 accel/tcg/icount-common.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/accel/tcg/icount-common.c b/accel/tcg/icount-common.c
index 8d3d3a7e9d..30bf8500dc 100644
--- a/accel/tcg/icount-common.c
+++ b/accel/tcg/icount-common.c
@@ -36,7 +36,6 @@
 #include "sysemu/runstate.h"
 #include "hw/core/cpu.h"
 #include "sysemu/cpu-timers.h"
-#include "sysemu/cpu-throttle.h"
 #include "sysemu/cpu-timers-internal.h"
 
 /*
-- 
2.27.0




[PATCH v4 4/6] migration: Remove "rs" parameter in migration_bitmap_sync_precopy

2024-10-16 Thread yong . huang
From: Hyman Huang 

The global static variable ram_state in fact is referred to by the
"rs" parameter in migration_bitmap_sync_precopy. For ease of calling
by the callees, use the global variable directly in
migration_bitmap_sync_precopy and remove "rs" parameter.

The migration_bitmap_sync_precopy will be exported in the next commit.

Signed-off-by: Hyman Huang 
Reviewed-by: Peter Xu 
---
 migration/ram.c | 11 ++-
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/migration/ram.c b/migration/ram.c
index 54d352b152..9b5b350405 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -1088,9 +1088,10 @@ static void migration_bitmap_sync(RAMState *rs, bool 
last_stage)
 }
 }
 
-static void migration_bitmap_sync_precopy(RAMState *rs, bool last_stage)
+static void migration_bitmap_sync_precopy(bool last_stage)
 {
 Error *local_err = NULL;
+assert(ram_state);
 
 /*
  * The current notifier usage is just an optimization to migration, so we
@@ -1101,7 +1102,7 @@ static void migration_bitmap_sync_precopy(RAMState *rs, 
bool last_stage)
 local_err = NULL;
 }
 
-migration_bitmap_sync(rs, last_stage);
+migration_bitmap_sync(ram_state, last_stage);
 
 if (precopy_notify(PRECOPY_NOTIFY_AFTER_BITMAP_SYNC, &local_err)) {
 error_report_err(local_err);
@@ -2782,7 +2783,7 @@ static bool ram_init_bitmaps(RAMState *rs, Error **errp)
 if (!ret) {
 goto out_unlock;
 }
-migration_bitmap_sync_precopy(rs, false);
+migration_bitmap_sync_precopy(false);
 }
 }
 out_unlock:
@@ -3248,7 +3249,7 @@ static int ram_save_complete(QEMUFile *f, void *opaque)
 
 WITH_RCU_READ_LOCK_GUARD() {
 if (!migration_in_postcopy()) {
-migration_bitmap_sync_precopy(rs, true);
+migration_bitmap_sync_precopy(true);
 }
 
 ret = rdma_registration_start(f, RAM_CONTROL_FINISH);
@@ -3330,7 +3331,7 @@ static void ram_state_pending_exact(void *opaque, 
uint64_t *must_precopy,
 if (!migration_in_postcopy()) {
 bql_lock();
 WITH_RCU_READ_LOCK_GUARD() {
-migration_bitmap_sync_precopy(rs, false);
+migration_bitmap_sync_precopy(false);
 }
 bql_unlock();
 }
-- 
2.27.0




[PATCH v4 0/6] migration: auto-converge refinements for huge VM

2024-10-16 Thread yong . huang
From: Hyman Huang 

v4:
1. split the [PATCH v3 1/6] into smaller patches.
2. refine some comment and commit message
3. fix race issue for the throttle_dirty_sync_timer
4. refine the util function cpu_throttle_dirty_sync_timer

Thanks Peter for the suggestions.

Please review.

Yong

v3:
1. drop the responsive throttle patchset
2. rename background sync to periodic ramblock dirty sync
3. move the cpu-throttle.* from system to migration
4. remove "rs" parameter in migration_bitmap_sync_precopy
5. implement periodic ramblock dirty sync in cpu-throttle.c
6. move the test change into a separate patch

To simplify the cover letter, i have dropped the test data,
please refer to 
https://lore.kernel.org/qemu-devel/cover.172763.git.yong.hu...@smartx.com/
for more test details.

Thanks Peter and Fabiano for the suggestions and comments.

Please review.

Yong

Hyman Huang (6):
  accel/tcg/icount-common: Remove the reference to the unused header
file
  migration: Stop CPU throttling conditionally
  migration: Move cpu-throttole.c from system to migration
  migration: Remove "rs" parameter in migration_bitmap_sync_precopy
  migration: Support periodic RAMBlock dirty bitmap sync
  tests/migration: Add case for periodic ramblock dirty sync

 accel/tcg/icount-common.c|  1 -
 {system => migration}/cpu-throttle.c | 67 +++-
 {include/sysemu => migration}/cpu-throttle.h | 14 
 migration/meson.build|  1 +
 migration/migration.c| 23 +--
 migration/migration.h|  1 +
 migration/ram.c  | 13 ++--
 migration/trace-events   |  4 ++
 system/cpu-timers.c  |  3 -
 system/meson.build   |  1 -
 system/trace-events  |  3 -
 tests/qtest/migration-test.c | 32 ++
 12 files changed, 143 insertions(+), 20 deletions(-)
 rename {system => migration}/cpu-throttle.c (67%)
 rename {include/sysemu => migration}/cpu-throttle.h (87%)

-- 
2.27.0




[PATCH v4 6/6] tests/migration: Add case for periodic ramblock dirty sync

2024-10-16 Thread yong . huang
From: Hyman Huang 

Signed-off-by: Hyman Huang 
Reviewed-by: Peter Xu 
---
 tests/qtest/migration-test.c | 32 
 1 file changed, 32 insertions(+)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 95e45b5029..e6a2803e71 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -2791,6 +2791,8 @@ static void test_migrate_auto_converge(void)
  * so we need to decrease a bandwidth.
  */
 const int64_t init_pct = 5, inc_pct = 25, max_pct = 95;
+uint64_t prev_dirty_sync_cnt, dirty_sync_cnt;
+int max_try_count, hit = 0;
 
 if (test_migrate_start(&from, &to, uri, &args)) {
 return;
@@ -2827,6 +2829,36 @@ static void test_migrate_auto_converge(void)
 } while (true);
 /* The first percentage of throttling should be at least init_pct */
 g_assert_cmpint(percentage, >=, init_pct);
+
+/*
+ * End the loop when the dirty sync count greater than 1.
+ */
+while ((dirty_sync_cnt = get_migration_pass(from)) < 2) {
+usleep(1000 * 1000);
+}
+
+prev_dirty_sync_cnt = dirty_sync_cnt;
+
+/*
+ * The RAMBlock dirty sync count must changes in 5 seconds, here we set
+ * the timeout to 10 seconds to ensure it changes.
+ *
+ * Note that migrate_ensure_non_converge set the max-bandwidth to 3MB/s,
+ * while the qtest mem is >= 100MB, one iteration takes at least 33s 
(100/3)
+ * to complete; this ensures that the RAMBlock dirty sync occurs.
+ */
+max_try_count = 10;
+while (--max_try_count) {
+dirty_sync_cnt = get_migration_pass(from);
+if (dirty_sync_cnt != prev_dirty_sync_cnt) {
+hit = 1;
+break;
+}
+prev_dirty_sync_cnt = dirty_sync_cnt;
+sleep(1);
+}
+g_assert_cmpint(hit, ==, 1);
+
 /* Now, when we tested that throttling works, let it converge */
 migrate_ensure_converge(from);
 
-- 
2.27.0




Re: [PULL 07/17] crypto/hash-afalg: Implement new hash API

2024-10-16 Thread Markus Armbruster
Daniel P. Berrangé  writes:

> From: Alejandro Zeise 
>
> Updates the afalg hash driver to support the new accumulative
> hashing changes as part of the patch series.
>
> Implements opening/closing of contexts, updating hash data
> and finalizing the hash digest.
>
> In order to support the update function, a flag needs to be passed
> to the kernel via the socket send call (MSG_MORE) to notify it that more
> data is to be expected to calculate the hash correctly.
> As a result, a new function was added to the iov helper utils to allow
> passing a flag to the socket send call.
>
> Signed-off-by: Alejandro Zeise 
> [ clg: - Handled qcrypto_afalg_hash_ctx_new() errors in
>  qcrypto_afalg_hash_new()
>- Freed alg_name in qcrypto_afalg_hash_new()
>- Reworked qcrypto_afalg_recv_from_kernel()
>- Split iov changes from original patch ]
> Signed-off-by: Cédric Le Goater 
> Reviewed-by: Daniel P. Berrangé 
> Signed-off-by: Daniel P. Berrangé 

Semantic conflict with commit 8f525028bc6 broke the build:

../crypto/hash-afalg.c: In function ‘qcrypto_afalg_hash_free’:
../crypto/hash-afalg.c:145:5: error: unknown type name ‘QCryptoAFAlg’; did 
you mean ‘QCryptoAFAlgo’?
  145 | QCryptoAFAlg *ctx = hash->opaque;
  | ^~~~
  | QCryptoAFAlgo


and more of the same.  I'll post a patch.




Re: [PATCH v3 1/4] migration: Move cpu-throttole.c from system to migration

2024-10-16 Thread Yong Huang
On Wed, Oct 16, 2024 at 11:50 PM Peter Xu  wrote:

> On Wed, Oct 16, 2024 at 03:56:42PM +0800, yong.hu...@smartx.com wrote:
> > From: Hyman Huang 
> >
> > Move cpu-throttle.c from system to migration since it's
> > only used for migration; this makes us avoid exporting the
> > util functions and variables in misc.h but export them in
> > migration.h when implementing the background ramblock dirty
> > sync feature in the upcoming commits.
> >
> > Additionally, make the two modifications below:
> >
> > 1. Delay the timer registering of CPU throttle until
> >migration starts since it is only used in migration.
> >
> > 2. Stop CPU throttle if auto converge capability is
> >enabled since it only happens with auto converge.
> >
> > 3. Remove the unused header file reference in
> >accel/tcg/icount-common.c.
>
> Please consider split the things into smaller patches, especially when it
> involves file movements.
>

OK.


> >
> > Signed-off-by: Hyman Huang 
> > ---
> >  accel/tcg/icount-common.c|  1 -
> >  {system => migration}/cpu-throttle.c |  2 +-
> >  {include/sysemu => migration}/cpu-throttle.h |  0
> >  migration/meson.build|  1 +
> >  migration/migration.c| 11 +--
> >  migration/ram.c  |  2 +-
> >  migration/trace-events   |  3 +++
> >  system/cpu-timers.c  |  3 ---
> >  system/meson.build   |  1 -
> >  system/trace-events  |  3 ---
> >  10 files changed, 15 insertions(+), 12 deletions(-)
> >  rename {system => migration}/cpu-throttle.c (99%)
> >  rename {include/sysemu => migration}/cpu-throttle.h (100%)
> >
> > diff --git a/accel/tcg/icount-common.c b/accel/tcg/icount-common.c
> > index 8d3d3a7e9d..30bf8500dc 100644
> > --- a/accel/tcg/icount-common.c
> > +++ b/accel/tcg/icount-common.c
> > @@ -36,7 +36,6 @@
> >  #include "sysemu/runstate.h"
> >  #include "hw/core/cpu.h"
> >  #include "sysemu/cpu-timers.h"
> > -#include "sysemu/cpu-throttle.h"
> >  #include "sysemu/cpu-timers-internal.h"
> >
> >  /*
> > diff --git a/system/cpu-throttle.c b/migration/cpu-throttle.c
> > similarity index 99%
> > rename from system/cpu-throttle.c
> > rename to migration/cpu-throttle.c
> > index 7632dc6143..fa47ee2e21 100644
> > --- a/system/cpu-throttle.c
> > +++ b/migration/cpu-throttle.c
> > @@ -27,7 +27,7 @@
> >  #include "hw/core/cpu.h"
> >  #include "qemu/main-loop.h"
> >  #include "sysemu/cpus.h"
> > -#include "sysemu/cpu-throttle.h"
> > +#include "cpu-throttle.h"
> >  #include "trace.h"
> >
> >  /* vcpu throttling controls */
> > diff --git a/include/sysemu/cpu-throttle.h b/migration/cpu-throttle.h
> > similarity index 100%
> > rename from include/sysemu/cpu-throttle.h
> > rename to migration/cpu-throttle.h
> > diff --git a/migration/meson.build b/migration/meson.build
> > index 66d3de86f0..d53cf3417a 100644
> > --- a/migration/meson.build
> > +++ b/migration/meson.build
> > @@ -13,6 +13,7 @@ system_ss.add(files(
> >'block-dirty-bitmap.c',
> >'channel.c',
> >'channel-block.c',
> > +  'cpu-throttle.c',
> >'dirtyrate.c',
> >'exec.c',
> >'fd.c',
> > diff --git a/migration/migration.c b/migration/migration.c
> > index 021faee2f3..7e71184257 100644
> > --- a/migration/migration.c
> > +++ b/migration/migration.c
> > @@ -24,7 +24,7 @@
> >  #include "socket.h"
> >  #include "sysemu/runstate.h"
> >  #include "sysemu/sysemu.h"
> > -#include "sysemu/cpu-throttle.h"
> > +#include "cpu-throttle.h"
> >  #include "rdma.h"
> >  #include "ram.h"
> >  #include "migration/global_state.h"
> > @@ -3289,7 +3289,9 @@ static MigIterateState
> migration_iteration_run(MigrationState *s)
> >  static void migration_iteration_finish(MigrationState *s)
> >  {
> >  /* If we enabled cpu throttling for auto-converge, turn it off. */
> > -cpu_throttle_stop();
> > +if (migrate_auto_converge()) {
> > +cpu_throttle_stop();
> > +}
> >
> >  bql_lock();
> >  switch (s->state) {
> > @@ -3508,6 +3510,11 @@ static void *migration_thread(void *opaque)
> >  qemu_savevm_send_colo_enable(s->to_dst_file);
> >  }
> >
> > +if (migrate_auto_converge()) {
> > +/* Start cpu throttle timers */
> > +cpu_throttle_init();
> > +}
>
> Might this leak the timer object?


> I think it perhaps needs to be moved to migration_object_init().
>

Ok, I'll fix it in the next version.


>
> > +
> >  bql_lock();
> >  ret = qemu_savevm_state_setup(s->to_dst_file, &local_err);
> >  bql_unlock();
> > diff --git a/migration/ram.c b/migration/ram.c
> > index 326ce7eb79..54d352b152 100644
> > --- a/migration/ram.c
> > +++ b/migration/ram.c
> > @@ -52,7 +52,7 @@
> >  #include "exec/target_page.h"
> >  #include "qemu/rcu_queue.h"
> >  #include "migration/colo.h"
> > -#include "sysemu/cpu-throttle.h"
> > +#include "cpu-throttle.h"
> >  #include "savevm.h"
> >  #include "qemu/iov.h"
> 

Re: Host riscv disas is broken

2024-10-16 Thread Richard Henderson

On 10/16/24 19:57, LIU Zhiwei wrote:

Hi Richard,

On 2024/10/17 02:38, Richard Henderson wrote:

2595: if (dec->cfg->ext_zcmop) {
2690:    if (dec->cfg->ext_zcmp && ((inst >> 12) & 0b01)) {
2716:    if (!dec->cfg->ext_zcmt) {
2726:    if (!dec->cfg->ext_zcmp) {
4028:    if (dec->cfg->ext_zimop) {
5044:    if (dec->cfg->ext_zfinx) {
5051:    if (dec->cfg->ext_zfinx) {
5058:    if (dec->cfg->ext_zfinx) {
5065:    if (dec->cfg->ext_zfinx) {
5371:    if (guard_func(cfg)) {

This structure comes from RISCVCPU, a target structure.

Oops. We missed this.

There is no such structure for the host, causing null pointer dereferences.

The zfinx references can be changed to

    dec->cfg && dec->cfg->ext_zfinx

but some of them can simply be removed, e.g. zcmop and zimop, which are otherwise 
reserved encodings.


Should we probe the host feature like what we do in tcg backend support and then do the 
right disassemble according to the probe result?


I don't think there's anything that is currently checked in disas/riscv.c that needs to 
know about the host.  And, as I say above, some of those checks can be eliminated.


Host disassembly needs are limited to what tcg/riscv/ emits.


r~



Re: [PATCH v3 3/4] migration: Support periodic ramblock dirty sync

2024-10-16 Thread Yong Huang
On Thu, Oct 17, 2024 at 2:49 AM Peter Xu  wrote:

> On Wed, Oct 16, 2024 at 03:56:44PM +0800, yong.hu...@smartx.com wrote:
> > From: Hyman Huang 
> >
> > When VM is configured with huge memory, the current throttle logic
> > doesn't look like to scale, because migration_trigger_throttle()
> > is only called for each iteration, so it won't be invoked for a long
> > time if one iteration can take a long time.
> >
> > The periodic dirty sync aims to fix the above issue by synchronizing
> > the ramblock from remote dirty bitmap and, when necessary, triggering
> > the CPU throttle multiple times during a long iteration.
> >
> > This is a trade-off between synchronization overhead and CPU throttle
> > impact.
> >
> > Signed-off-by: Hyman Huang 
> > ---
> >  migration/cpu-throttle.c | 70 +++-
> >  migration/cpu-throttle.h | 14 
> >  migration/migration.h|  1 +
> >  migration/ram.c  |  9 --
> >  migration/trace-events   |  1 +
> >  5 files changed, 92 insertions(+), 3 deletions(-)
> >
> > diff --git a/migration/cpu-throttle.c b/migration/cpu-throttle.c
> > index fa47ee2e21..784b51ab35 100644
> > --- a/migration/cpu-throttle.c
> > +++ b/migration/cpu-throttle.c
> > @@ -28,16 +28,23 @@
> >  #include "qemu/main-loop.h"
> >  #include "sysemu/cpus.h"
> >  #include "cpu-throttle.h"
> > +#include "migration.h"
> > +#include "migration-stats.h"
> > +#include "options.h"
> >  #include "trace.h"
> >
> >  /* vcpu throttling controls */
> > -static QEMUTimer *throttle_timer;
> > +static QEMUTimer *throttle_timer, *throttle_dirty_sync_timer;
> >  static unsigned int throttle_percentage;
> > +static bool throttle_dirty_sync_timer_active;
> >
> >  #define CPU_THROTTLE_PCT_MIN 1
> >  #define CPU_THROTTLE_PCT_MAX 99
> >  #define CPU_THROTTLE_TIMESLICE_NS 1000
> >
> > +/* RAMBlock dirty sync trigger every five seconds */
>
> Maybe enrich it to say "making sure it is synchronized every five seconds"?
> Because it can synchronize faster if each iteration runs faster than 5sec,
> so just to emphasize it's a fallback sync, and only with auto converge.
>

Agree, I'll refine the comment in the next version.


>
> > +#define CPU_THROTTLE_DIRTY_SYNC_TIMESLICE_MS 5000
> > +
> >  static void cpu_throttle_thread(CPUState *cpu, run_on_cpu_data opaque)
> >  {
> >  double pct;
> > @@ -112,6 +119,7 @@ void cpu_throttle_set(int new_throttle_pct)
> >  void cpu_throttle_stop(void)
> >  {
> >  qatomic_set(&throttle_percentage, 0);
> > +cpu_throttle_dirty_sync_timer(false);
> >  }
> >
> >  bool cpu_throttle_active(void)
> > @@ -124,8 +132,68 @@ int cpu_throttle_get_percentage(void)
> >  return qatomic_read(&throttle_percentage);
> >  }
> >
> > +void cpu_throttle_dirty_sync_timer_tick(void *opaque)
> > +{
> > +static uint64_t prev_sync_cnt = 2;
>
> IIUC the hard coded "2" isn't needed, as long as it's guaranteed to be
> updated for each timer call, and you special cased "1" anyway below.
>

Ok.


>
> > +uint64_t sync_cnt = stat64_get(&mig_stats.dirty_sync_count);
> > +
> > +if (!migrate_auto_converge()) {
> > +/* Stop the timer when auto converge is disabled */
> > +return;
>
> I think we can try to make sure this never starts if !auto-converge, so
> assuming this path will never trigger in real life.
>

Indeed, this makes the code cleaner.


> > +}
> > +
> > +/*
> > + * The first iteration copies all memory anyhow and has no
> > + * effect on guest performance, therefore omit it to avoid
> > + * paying extra for the sync penalty.
> > + */
> > +if (sync_cnt <= 1) {
> > +goto end;
> > +}
> > +
> > +if (sync_cnt == prev_sync_cnt) {
> > +trace_cpu_throttle_dirty_sync();
> > +WITH_RCU_READ_LOCK_GUARD() {
> > +migration_bitmap_sync_precopy(false);
> > +}
> > +}
> > +
> > +end:
> > +prev_sync_cnt = stat64_get(&mig_stats.dirty_sync_count);
> > +
> > +timer_mod(throttle_dirty_sync_timer,
> > +qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL_RT) +
> > +CPU_THROTTLE_DIRTY_SYNC_TIMESLICE_MS);
> > +}
> > +
> > +static bool cpu_throttle_dirty_sync_active(void)
> > +{
> > +return qatomic_read(&throttle_dirty_sync_timer_active);
> > +}
> > +
> > +void cpu_throttle_dirty_sync_timer(bool enable)
> > +{
> > +if (enable) {
> > +assert(throttle_dirty_sync_timer);
> > +if (!cpu_throttle_dirty_sync_active()) {
>
> I suppose this can be logically racy? As I think after this patch this path
> can be invoked both in main thread and migration thread.
>

Indeed, thanks for pointing this out.


>
> The simplest way to do is to move cpu_throttle_stop() call to be under
> bql_lock(), so that this will be serialized by BQL.  Then we can add an
> assertion at the entry of the function for bql_locked().


> > +timer_mod(throttle_dirty_sync_timer,
> > +qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL_RT) +
> > +CPU_THROTTL

Re: [PATCH v6 00/14] tcg/riscv: Add support for vector

2024-10-16 Thread TangTianCheng

Signed-off-by: Huang Shiyuan
Co-authored-by: TANG Tiancheng
Signed-off-by: TANG Tiancheng
Reviewed-by: Liu Zhiwei
Reviewed-by: Richard Henderson
Signed-off-by: Swung0x48

Hi,

We should remove the tag "Signed-off-by: swung0x48swung0...@outlook.com" since the 
author's real name, Huang Shiyuan, is already correctly included as "Signed-off-by: Huang 
shiyuanswung0...@outlook.com".

Thanks,
TianCheng.

Message-ID: <20241007025700.47259-3-zhiwei_...@linux.alibaba.com 
>
Signed-off-by: Richard Henderson


Re: Re: [PATCH] hw/char/riscv_htif: Fix htif_mm_write that causes infinite loop in ACT.

2024-10-16 Thread Alistair Francis
On Wed, Oct 16, 2024 at 8:32 PM Trd thg  wrote:
>
> Sorry about the email style, I'm not familiar with it yet

No worries! It takes some getting used to. Mostly just plain text
emails and reply inline :)

Alistair

>
> > It's probably worth including this in the commit message.
> Agree, I'll do it.
>
> > It would be good to reference the sail implementation and the
> justification for the change there
>
> Sail implementation is probably here:
> https://github.com/riscv/sail-riscv/blob/master/model/riscv_platform.sail#L340
> - related commit:
> https://github.com/riscv/sail-riscv/commit/848312ce7c59fa08c304cab4b4e8060c67d5dfc9
>
> The following is the "infinite loop" part is exported by objdump from
> the test ELF of the add instruction generated from ACT
> ```txt
> 800082a0 :
> 800082a0:   1f17auipc   t5,0x1
> 800082a4:   d61f2023sw  ra,-672(t5) # 80009000 
> 
> 800082a8:   ff9ff06fj   800082a0 
> ```
> QEMU cannot respond to the above `sw` behavior, It makes no
> distinction regarding the size written,
> I guess that currently qemu will only respond to the writing to the
> high 32 bits and low 32 bits of tohost twice in succession.
> I think the behavior here is very strange, and you can find
> aswaterman's description of HTIF(include RV32) at:
> https://github.com/riscv-software-src/riscv-isa-sim/issues/364#issuecomment-607657754
> So this patch try to distinguish these cases based on size and addr.
>
> About the sail impl, there are some related discussions at:
> https://github.com/riscv/sail-riscv/issues/218
> I made some summaries:
> - The implementation of sail as a workaround is not very ideal; we
> should follow the experience of spike
>   I checked the impl of spike. Although spike handles tohost in a
> syscall manner, I don't think this means that spike is better.
>   Compared to sail, it does not distinguish whether the write to
> tohost is 4 bytes or 8 bytes, but at least in act, it always works
> properly.
>   - spike code:
> https://github.com/riscv-software-src/riscv-isa-sim/blob/master/fesvr/htif.cc#L265
> - HTIF has been deprecated
>   I don't know if this is true or not, because I haven't found any
> official comment.
>   However, since ACT is still using htif and is not expected to change
> for quite a long time, and no new solutions have emerged, we should go
> ahead and implement it
> - What are the advantages of QEMU supporting ACT
>   - do cross validation with sail/spike, and contributors can use ACT
> to verify the correctness when adding new instructions to QEMU. (we do
> have this need.)
>   > If you think that the benefits of supporting ACT are not obvious,
> then I think we can remove all the code related to supporting ACT
> (should be the commit mentioned above)
>
> What do you think about this? Thank you!
>
> Alistair Francis  于2024年10月16日周三 13:27写道:
> >
> > On Mon, Oct 14, 2024 at 8:08 PM 阎明铸  wrote:
> > >
> > > Thank you for your reply and I'm sorry that I didn't explain it clearly.
> > >
> > > - ACT is an official riscv test suite to check the riscv support of the 
> > > DUT(device under test).
> >
> > It's probably worth including this in the commit message.
> >
> > > - Currently ACT support using 
> > > [sail-riscv](https://github.com/riscv/sail-riscv)(default) or 
> > > [spike](https://github.com/riscv-software-src/riscv-isa-sim)
> > > - QEMU is not supported yet,but someone made a commit: 
> > > [commit](https://github.com/qemu/qemu/commit/66247edc8b6fb36d6b905babcd795068ea989ad5)
> > >
> > > But there are still problems, so I'm trying to fix it. After debugging, I 
> > > found that it's a htif problem, and the idea of fixing it is referenced 
> > > from the sail-riscv implementation
> >
> > It would be good to reference the sail implementation and the
> > justification for the change there
> >
> > Alistair
> >
> > >
> > > "Alistair Francis" 写道:
> > > > On Fri, Sep 27, 2024 at 11:26 PM MingZhu Yan  
> > > wrote:
> > > > >
> > > > > Applications sometimes only write the lower 32-bit payload 
> > > bytes, this is used
> > > > > in ACT tests. As a workaround, this refers to the solution of 
> > > sail-riscv.
> > > >
> > > > I'm not sure what ACT is, but this feels like a guest bug, not a 
> > > QEMU issue.
> > > >
> > > > Alistair
> > > >
> > > > > if the payload is written a few times with the same value, we 
> > > process the whole
> > > > > htif command anyway.
> > > > >
> > > > > Signed-off-by: MingZhu Yan 
> > > > > ---
> > > > >  hw/char/riscv_htif.c | 35 +++
> > > > >  1 file changed, 19 insertions(+), 16 deletions(-)
> > > > >
> > > > > diff --git a/hw/char/riscv_htif.c b/hw/char/riscv_htif.c
> > > > > index 9bef60def1..d74cce3bef 100644
> > > > > --- a/hw/char/riscv_htif.c
> > > > > +++ b/hw/char/riscv_htif.c
> > > > > @@ -65,16 +65,8 @@ void htif_symbol_callback(const char 
> > > *st_name, int st_info, uint64_t st_value,
> > > > >

Re: [PATCH 0/1] Insert LibSPDM in QEMU enabling in-tree compilation

2024-10-16 Thread Alistair Francis
On Thu, Oct 17, 2024 at 2:35 AM htafr  wrote:
>
> (I) Summary
> ===
>
> This patch is the beginning of the support of the Security Protocol and
> Data Model (SPDM). There are some known issues (see II), but it's
> usable and not many users are going to use this functionality for now,
> but for those who will it may facilitate the development.
>
> There are some people working with LibSPDM to implement the SPDM on
> emulated devices, however current works that use QEMU compile LibSPDM
> out-of-tree [1][2][3]. This patch enables the compilation of LibSPDM when
> user pass the parameter '--enable-libspdm' to configure file, this option
> is disabled by default. The following parameters were also added:
>
>   --libspdm-crypto=CHOICE  set LibSPDM crypto algorithm [mbedtls] (choices:
>mbedtls/openssl)
>   --libspdm-toolchain=VALUE
>toolchain to use for LibSPDM compilation [GCC]
>
> In order to facilitate future code development using LibSPDM API, this
> patch also provides the definition of the macro 'CONFIG_LIBSPDM'.

We have talked about this before, see
https://patchew.org/QEMU/cover.1691509717.git.alistair.fran...@wdc.com/

The general agreement seemed to be that it will be hard to do SPDM
configuration inside QEMU, hence the external library (like the QEMU
TPM support).

>
>
> (II) Known Limitations
> ===
>
> 1. This patch enables LibSPDM in-tree compilation for Linux systems only.
> 2. LibSPDM compilation uses CMake, so meson build system is making use
>of the CMake module [4].
> 3. Some problems may occur when compiling LibSPDM with MbedTls such as:
> error: "_GNU_SOURCE" redefined [-Werror]
>   10 | #define _GNU_SOURCE
>
>It's possible to compile using --disable-werror.
>
> (III) Sample configuration
> ===
>
> ../configure \
>   --disable-werror \
>   --enable-libspdm \
>   --libspdm-crypto=mbedtls \
>   --enable-gcov
>
> References:
> [1] riscv-spdm
>   Link: https://github.com/htafr/riscv-spdm
> [2] spdm-benchmark
>   Link: https://github.com/rcaalves/spdm-benchmark
> [3] qemu-spdm-emulation-guide
>   Link: https://github.com/twilfredo/qemu-spdm-emulation-guide

This one has been merged upstream and mainline QEMU supports it now:

https://www.qemu.org/docs/master/specs/spdm.html

Alistair



Re: [PATCH v2 3/8] target/riscv: Implement Ssdbltrp exception handling

2024-10-16 Thread Alistair Francis
On Mon, Oct 14, 2024 at 5:43 PM Clément Léger  wrote:
>
>
>
> On 11/10/2024 05:22, Alistair Francis wrote:
> > On Wed, Sep 25, 2024 at 9:59 PM Clément Léger  wrote:
> >>
> >> When the Ssdbltrp ISA extension is enabled, if a trap happens in S-mode
> >> while SSTATUS.SDT isn't cleared, generate a double trap exception to
> >> M-mode.
> >>
> >> Signed-off-by: Clément Léger 
> >> ---
> >>  target/riscv/cpu.c|  2 +-
> >>  target/riscv/cpu_bits.h   |  1 +
> >>  target/riscv/cpu_helper.c | 47 ++-
> >>  3 files changed, 43 insertions(+), 7 deletions(-)
> >>
> >> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> >> index cf06cd741a..65347ccd5a 100644
> >> --- a/target/riscv/cpu.c
> >> +++ b/target/riscv/cpu.c
> >> @@ -284,7 +284,7 @@ static const char * const riscv_excp_names[] = {
> >>  "load_page_fault",
> >>  "reserved",
> >>  "store_page_fault",
> >> -"reserved",
> >> +"double_trap",
> >>  "reserved",
> >>  "reserved",
> >>  "reserved",
> >> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> >> index 3a5588d4df..5557a86348 100644
> >> --- a/target/riscv/cpu_bits.h
> >> +++ b/target/riscv/cpu_bits.h
> >> @@ -699,6 +699,7 @@ typedef enum RISCVException {
> >>  RISCV_EXCP_INST_PAGE_FAULT = 0xc, /* since: priv-1.10.0 */
> >>  RISCV_EXCP_LOAD_PAGE_FAULT = 0xd, /* since: priv-1.10.0 */
> >>  RISCV_EXCP_STORE_PAGE_FAULT = 0xf, /* since: priv-1.10.0 */
> >> +RISCV_EXCP_DOUBLE_TRAP = 0x10,
> >>  RISCV_EXCP_SW_CHECK = 0x12, /* since: priv-1.13.0 */
> >>  RISCV_EXCP_HW_ERR = 0x13, /* since: priv-1.13.0 */
> >>  RISCV_EXCP_INST_GUEST_PAGE_FAULT = 0x14,
> >> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> >> index 395d8235ce..69da3c3384 100644
> >> --- a/target/riscv/cpu_helper.c
> >> +++ b/target/riscv/cpu_helper.c
> >> @@ -575,7 +575,9 @@ void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env)
> >>  mstatus_mask |= MSTATUS_FS;
> >>  }
> >>  bool current_virt = env->virt_enabled;
> >> -
> >> +if (riscv_env_smode_dbltrp_enabled(env, current_virt)) {
> >> +mstatus_mask |= MSTATUS_SDT;
> >> +}
> >>  g_assert(riscv_has_ext(env, RVH));
> >>
> >>  if (current_virt) {
> >> @@ -1707,6 +1709,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> >>  CPURISCVState *env = &cpu->env;
> >>  bool virt = env->virt_enabled;
> >>  bool write_gva = false;
> >> +bool vsmode_exc;
> >>  uint64_t s;
> >>  int mode;
> >>
> >> @@ -1721,6 +1724,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> >>  !(env->mip & (1 << cause));
> >>  bool vs_injected = env->hvip & (1 << cause) & env->hvien &&
> >>  !(env->mip & (1 << cause));
> >> +bool smode_double_trap = false;
> >> +uint64_t hdeleg = async ? env->hideleg : env->hedeleg;
> >>  target_ulong tval = 0;
> >>  target_ulong tinst = 0;
> >>  target_ulong htval = 0;
> >> @@ -1837,13 +1842,35 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> >>  !async &&
> >>  mode == PRV_M;
> >>
> >> +vsmode_exc = env->virt_enabled && (((hdeleg >> cause) & 1) || 
> >> vs_injected);
> >> +/*
> >> + * Check double trap condition only if already in S-mode and targeting
> >> + * S-mode
> >> + */
> >> +if (cpu->cfg.ext_ssdbltrp && env->priv == PRV_S && mode == PRV_S) {
> >> +bool dte = (env->menvcfg & MENVCFG_DTE) != 0;
> >> +bool sdt = (env->mstatus & MSTATUS_SDT) != 0;
> >> +/* In VS or HS */
> >> +if (riscv_has_ext(env, RVH)) {
> >> +if (vsmode_exc) {
> >> +/* VS -> VS */
> >> +/* Stay in VS mode, use henvcfg instead of menvcfg*/
> >> +dte = (env->henvcfg & HENVCFG_DTE) != 0;
> >> +} else if (env->virt_enabled) {
> >> +/* VS -> HS */
> >> +dte = false;
> >
> > I don't follow why this is false
>
> Hi Alistair,
>
> It's indeed probably lacking some comments here. The rationale is that
> if you are trapping from VS to HS, then at some point, you returned to
> VS using a sret/mret and thus cleared DTE, so rather than checking the

Why not just clear it at sret/mret? Instead of having this assumption

Alistair

> value of mstatus_hs, just assume it is false.
>
> Thanks,
>
> Clément
>
> >
> > Alistair
>



Re: [PATCH v2 2/8] target/riscv: Implement Ssdbltrp sret, mret and mnret behavior

2024-10-16 Thread Alistair Francis
On Sat, Oct 12, 2024 at 4:52 AM Ved Shanbhogue  wrote:
>
> Alistair Francis wrote:
> >> When the Ssdbltrp extension is enabled, SSTATUS.SDT field is cleared
> >> when executing sret. When executing mret/mnret, SSTATUS.SDT is cleared
> >> when returning to U, VS or VU and VSSTATUS.SDT is cleared when returning
> >> to VU from HS.
> >
> >I don't see mret being mentioned in the spec. Where do you see that
> >V/SSTATUS.SDT should be cleared?
> >
>
> Ssdbltrp specifies:
> In S-mode, the SRET instruction sets sstatus.SDT to 0,
> and if the new privilege mode is VU, it also sets
> vsstatus.SDT to 0. However, in VS-mode, only vsstatus.SDT
> is set to to 0.

I cannot find this

$ git show --shortstat
commit ef2ec9dc9afd003d0dab6d5ca36db59864c8483c (HEAD -> main, tag:
riscv-isa-release-ef2ec9d-2024-10-16, origin/main)
Author: Andrew Waterman 
Date:   Wed Oct 16 12:09:41 2024 -0700

   Remove future tense from description of now-ratified text (#1685)

2 files changed, 8 insertions(+), 15 deletions(-)

$ grep -r sstatus.SDT | grep SRET
src/hypervisor.adoc:if the new privilege mode is VU, the `SRET`
instruction sets `vsstatus.SDT`

What am I missing here?

Alistair

>
> The MRET instructions sets sstatus.SDT to 0, if the new
> privilege mode is U, VS, or VU. Additionally, if it is
> VU, then vsstatus.SDT is also set to 0.
>
> Smdbltrp specifies:
> The MRET and SRET instructions, when executed in M-mode,
> set the MDT bit to 0. If the new privilege mode is U, VS,
> or VU, then sstatus.SDT is also set to 0. Additionally,
> if it is VU, then vsstatus.SDT is also set to 0.
>
> The MNRET instruction sets the MDT bit to 0 if the new
> privilege mode is not M. If it is U, VS, or VU, then
> sstatus.SDT is also set to 0. Additionally, if it is VU,
> then vsstatus.SDT is also set to 0.
>
> regards
> ved



[PATCH v4 2/2] tpm_emulator: Read control channel response in 2 passes

2024-10-16 Thread Stefan Berger
Error responses from swtpm are typically only 4 bytes long with the
exception of a few commands that return more bytes. Therefore, read the
entire response in 2 steps and stop if the first few bytes indicate an
error response with no subsequent bytes readable. Read the rest in a 2nd
step, if needed. This avoids getting stuck while waiting for too many
bytes in case of an error. The 'getting stuck' condition has not been
observed in practice so far, though.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2615
Signed-off-by: Stefan Berger 
---
 backends/tpm/tpm_emulator.c | 61 +++--
 1 file changed, 45 insertions(+), 16 deletions(-)

diff --git a/backends/tpm/tpm_emulator.c b/backends/tpm/tpm_emulator.c
index b0e2fb3fc7..8ad54f49a5 100644
--- a/backends/tpm/tpm_emulator.c
+++ b/backends/tpm/tpm_emulator.c
@@ -123,12 +123,14 @@ static const char *tpm_emulator_strerror(uint32_t 
tpm_result)
 }
 
 static int tpm_emulator_ctrlcmd(TPMEmulator *tpm, unsigned long cmd, void *msg,
-size_t msg_len_in, size_t msg_len_out)
+size_t msg_len_in, size_t msg_len_out_err,
+size_t msg_len_out_total)
 {
 CharBackend *dev = &tpm->ctrl_chr;
 uint32_t cmd_no = cpu_to_be32(cmd);
 ssize_t n = sizeof(uint32_t) + msg_len_in;
 uint8_t *buf = NULL;
+ptm_res res;
 
 WITH_QEMU_LOCK_GUARD(&tpm->mutex) {
 buf = g_alloca(n);
@@ -140,8 +142,24 @@ static int tpm_emulator_ctrlcmd(TPMEmulator *tpm, unsigned 
long cmd, void *msg,
 return -1;
 }
 
-if (msg_len_out != 0) {
-n = qemu_chr_fe_read_all(dev, msg, msg_len_out);
+if (msg_len_out_total > 0) {
+assert(msg_len_out_total >= msg_len_out_err);
+
+n = qemu_chr_fe_read_all(dev, (uint8_t *)msg, msg_len_out_err);
+if (n <= 0) {
+return -1;
+}
+if (msg_len_out_err == msg_len_out_total) {
+return 0;
+}
+/* result error code is always in the first 4 bytes */
+memcpy(&res, msg, sizeof(res));
+if (res) {
+return 0;
+}
+
+n = qemu_chr_fe_read_all(dev, (uint8_t *)msg + msg_len_out_err,
+ msg_len_out_total - msg_len_out_err);
 if (n <= 0) {
 return -1;
 }
@@ -204,7 +222,8 @@ static int tpm_emulator_set_locality(TPMEmulator *tpm_emu, 
uint8_t locty_number,
 memset(&loc, 0, sizeof(loc));
 loc.u.req.loc = locty_number;
 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_LOCALITY, &loc,
- sizeof(loc), sizeof(loc)) < 0) {
+ sizeof(loc), sizeof(loc.u.resp.tpm_result),
+ sizeof(loc)) < 0) {
 error_setg(errp, "tpm-emulator: could not set locality : %s",
strerror(errno));
 return -1;
@@ -241,8 +260,9 @@ static int tpm_emulator_probe_caps(TPMEmulator *tpm_emu)
 {
 ptm_cap_n cap_n;
 
-if (tpm_emulator_ctrlcmd(tpm_emu, CMD_GET_CAPABILITY,
- &cap_n, 0, sizeof(cap_n)) < 0) {
+if (tpm_emulator_ctrlcmd(tpm_emu, CMD_GET_CAPABILITY, &cap_n, 0,
+ sizeof(cap_n.u.resp.tpm_result),
+ sizeof(cap_n)) < 0) {
 error_report("tpm-emulator: probing failed : %s", strerror(errno));
 return -1;
 }
@@ -292,7 +312,8 @@ static int tpm_emulator_stop_tpm(TPMBackend *tb)
 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
 ptm_res res;
 
-if (tpm_emulator_ctrlcmd(tpm_emu, CMD_STOP, &res, 0, sizeof(res)) < 0) {
+if (tpm_emulator_ctrlcmd(tpm_emu, CMD_STOP, &res, 0,
+ sizeof(ptm_res), sizeof(res)) < 0) {
 error_report("tpm-emulator: Could not stop TPM: %s",
  strerror(errno));
 return -1;
@@ -319,8 +340,9 @@ static int tpm_emulator_lock_storage(TPMEmulator *tpm_emu)
 
 /* give failing side 300 * 10ms time to release lock */
 pls.u.req.retries = cpu_to_be32(300);
-if (tpm_emulator_ctrlcmd(tpm_emu, CMD_LOCK_STORAGE, &pls,
- sizeof(pls.u.req), sizeof(pls.u.resp)) < 0) {
+if (tpm_emulator_ctrlcmd(tpm_emu, CMD_LOCK_STORAGE, &pls, 
sizeof(pls.u.req),
+ sizeof(pls.u.resp.tpm_result),
+ sizeof(pls.u.resp)) < 0) {
 error_report("tpm-emulator: Could not lock storage within 3 seconds: "
  "%s", strerror(errno));
 return -1;
@@ -351,7 +373,8 @@ static int tpm_emulator_set_buffer_size(TPMBackend *tb,
 psbs.u.req.buffersize = cpu_to_be32(wanted_size);
 
 if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_BUFFERSIZE, &psbs,
- sizeof(psbs.u.req), sizeof(psbs.u.resp)) < 0) {
+ sizeof(psbs.u.req), 
sizeof(psb

  1   2   >