Re: [PATCH v4 09/14] ppc/xive2: Change context/ring specific functions to be generic

2024-09-15 Thread Cédric Le Goater

On 9/13/24 18:16, Michael Kowal wrote:

Some the functions that have been created are specific to a ring or context. 
Some
of these same functions are being changed to operate on any ring/context. This  
will
simplify the next patch sets that are adding additional ring/context operations.

Signed-off-by: Michael Kowal 



Reviewed-by: Cédric Le Goater 

Thanks,

C.



---
  include/hw/ppc/xive.h |  2 +-
  hw/intc/xive.c|  6 +++---
  hw/intc/xive2.c   | 20 ++--
  3 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h
index 28c181faa2..31242f0406 100644
--- a/include/hw/ppc/xive.h
+++ b/include/hw/ppc/xive.h
@@ -533,7 +533,7 @@ Object *xive_tctx_create(Object *cpu, XivePresenter *xptr, 
Error **errp);
  void xive_tctx_reset(XiveTCTX *tctx);
  void xive_tctx_destroy(XiveTCTX *tctx);
  void xive_tctx_ipb_update(XiveTCTX *tctx, uint8_t ring, uint8_t ipb);
-void xive_tctx_reset_os_signal(XiveTCTX *tctx);
+void xive_tctx_reset_signal(XiveTCTX *tctx, uint8_t ring);
  
  /*

   * KVM XIVE device helpers
diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index 5b66a3aec5..f1d007d9a6 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -114,7 +114,7 @@ static void xive_tctx_notify(XiveTCTX *tctx, uint8_t ring)
  }
  }
  
-void xive_tctx_reset_os_signal(XiveTCTX *tctx)

+void xive_tctx_reset_signal(XiveTCTX *tctx, uint8_t ring)
  {
  /*
   * Lower the External interrupt. Used when pulling an OS
@@ -122,7 +122,7 @@ void xive_tctx_reset_os_signal(XiveTCTX *tctx)
   * context. It should be raised again when re-pushing the OS
   * context.
   */
-qemu_irq_lower(xive_tctx_output(tctx, TM_QW1_OS));
+qemu_irq_lower(xive_tctx_output(tctx, ring));
  }
  
  static void xive_tctx_set_cppr(XiveTCTX *tctx, uint8_t ring, uint8_t cppr)

@@ -424,7 +424,7 @@ static uint64_t xive_tm_pull_os_ctx(XivePresenter *xptr, 
XiveTCTX *tctx,
  qw1w2_new = xive_set_field32(TM_QW1W2_VO, qw1w2, 0);
  xive_tctx_set_os_cam(tctx, qw1w2_new);
  
-xive_tctx_reset_os_signal(tctx);

+xive_tctx_reset_signal(tctx, TM_QW1_OS);
  return qw1w2;
  }
  
diff --git a/hw/intc/xive2.c b/hw/intc/xive2.c

index 8d3d69a0db..c5aa784fe8 100644
--- a/hw/intc/xive2.c
+++ b/hw/intc/xive2.c
@@ -270,13 +270,14 @@ static void xive2_end_enqueue(Xive2End *end, uint32_t 
data)
   * the NVP by changing the H bit while the context is enabled
   */
  
-static void xive2_tctx_save_os_ctx(Xive2Router *xrtr, XiveTCTX *tctx,

-   uint8_t nvp_blk, uint32_t nvp_idx)
+static void xive2_tctx_save_ctx(Xive2Router *xrtr, XiveTCTX *tctx,
+uint8_t nvp_blk, uint32_t nvp_idx,
+uint8_t ring)
  {
  CPUPPCState *env = &POWERPC_CPU(tctx->cs)->env;
  uint32_t pir = env->spr_cb[SPR_PIR].default_value;
  Xive2Nvp nvp;
-uint8_t *regs = &tctx->regs[TM_QW1_OS];
+uint8_t *regs = &tctx->regs[ring];
  
  if (xive2_router_get_nvp(xrtr, nvp_blk, nvp_idx, &nvp)) {

  qemu_log_mask(LOG_GUEST_ERROR, "XIVE: No NVP %x/%x\n",
@@ -321,8 +322,8 @@ static void xive2_tctx_save_os_ctx(Xive2Router *xrtr, 
XiveTCTX *tctx,
  xive2_router_write_nvp(xrtr, nvp_blk, nvp_idx, &nvp, 1);
  }
  
-static void xive2_os_cam_decode(uint32_t cam, uint8_t *nvp_blk,

-uint32_t *nvp_idx, bool *vo, bool *ho)
+static void xive2_cam_decode(uint32_t cam, uint8_t *nvp_blk,
+ uint32_t *nvp_idx, bool *vo, bool *ho)
  {
  *nvp_blk = xive2_nvp_blk(cam);
  *nvp_idx = xive2_nvp_idx(cam);
@@ -330,7 +331,6 @@ static void xive2_os_cam_decode(uint32_t cam, uint8_t 
*nvp_blk,
  *ho = !!(cam & TM2_QW1W2_HO);
  }
  
-

  /*
   * Encode the HW CAM line with 7bit or 8bit thread id. The thread id
   * width and block id width is configurable at the IC level.
@@ -363,7 +363,7 @@ uint64_t xive2_tm_pull_os_ctx(XivePresenter *xptr, XiveTCTX 
*tctx,
  bool vo;
  bool do_save;
  
-xive2_os_cam_decode(cam, &nvp_blk, &nvp_idx, &vo, &do_save);

+xive2_cam_decode(cam, &nvp_blk, &nvp_idx, &vo, &do_save);
  
  if (!vo) {

  qemu_log_mask(LOG_GUEST_ERROR, "XIVE: pulling invalid NVP %x/%x !?\n",
@@ -375,10 +375,10 @@ uint64_t xive2_tm_pull_os_ctx(XivePresenter *xptr, 
XiveTCTX *tctx,
  memcpy(&tctx->regs[TM_QW1_OS + TM_WORD2], &qw1w2_new, 4);
  
  if (xive2_router_get_config(xrtr) & XIVE2_VP_SAVE_RESTORE && do_save) {

-xive2_tctx_save_os_ctx(xrtr, tctx, nvp_blk, nvp_idx);
+xive2_tctx_save_ctx(xrtr, tctx, nvp_blk, nvp_idx, TM_QW1_OS);
  }
  
-xive_tctx_reset_os_signal(tctx);

+xive_tctx_reset_signal(tctx, TM_QW1_OS);
  return qw1w2;
  }
  
@@ -573,7 +573,7 @@ void xive2_tm_push_os_ctx(XivePresenter *xptr, XiveTCTX *tctx,

  bool vo;
  bool do_restore;
  
-xive2_os_cam_decode(cam, &nvp_blk, &nvp_idx, &vo, &do_restore);

+xive2_cam_decode(cam, &nvp_blk, &nvp_idx

[PATCH] hw/display: Fix mirrored output in dm163

2024-09-15 Thread Inès Varhol
DM163 is an emulated 8x8 LED matrix. This commit flips the image
horizontally so it's rendered the same way as on the hardware.

Signed-off-by: Inès Varhol 
---
 hw/display/dm163.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/display/dm163.c b/hw/display/dm163.c
index f92aee371d..75a91f62bd 100644
--- a/hw/display/dm163.c
+++ b/hw/display/dm163.c
@@ -271,7 +271,7 @@ static uint32_t *update_display_of_row(DM163State *s, 
uint32_t *dest,
unsigned row)
 {
 for (unsigned _ = 0; _ < LED_SQUARE_SIZE; _++) {
-for (int x = 0; x < RGB_MATRIX_NUM_COLS * LED_SQUARE_SIZE; x++) {
+for (int x = RGB_MATRIX_NUM_COLS * LED_SQUARE_SIZE - 1; x >= 0; x--) {
 /* UI layer guarantees that there's 32 bits per pixel (Mar 2024) */
 *dest++ = s->buffer[s->buffer_idx_of_row[row]][x / 
LED_SQUARE_SIZE];
 }
-- 
2.45.2




[PATCH v6 00/17] bsd-user: Comprehensive RISCV Support

2024-09-15 Thread Ajeet Singh
Key Changes Compared to Version 5:
In target_arch_sigtramp.h removed static const,
as there was a compile-time constant issue

Mark Corbin (15):
  bsd-user: Implement RISC-V CPU initialization and main loop
  bsd-user: Add RISC-V CPU execution loop and syscall handling
  bsd-user: Implement RISC-V CPU register cloning and reset functions
  bsd-user: Implement RISC-V TLS register setup
  bsd-user: Add RISC-V ELF definitions and hardware capability detection
  bsd-user: Define RISC-V register structures and register copying
  bsd-user: Add RISC-V signal trampoline setup function
  bsd-user: Implement RISC-V sysarch system call emulation
  bsd-user: Add RISC-V thread setup and initialization support
  bsd-user: Define RISC-V VM parameters and helper functions
  bsd-user: Define RISC-V system call structures and constants
  bsd-user: Define RISC-V signal handling structures and constants
  bsd-user: Implement RISC-V signal trampoline setup functions
  bsd-user: Implement 'get_mcontext' for RISC-V
  bsd-user: Implement set_mcontext and get_ucontext_sigreturn for RISCV

Warner Losh (2):
  bsd-user: Add generic RISC-V64 target definitions
  bsd-user: Add RISC-V 64-bit Target Configuration and Debug XML Files

 bsd-user/riscv/signal.c   | 170 ++
 bsd-user/riscv/target.h   |  20 +++
 bsd-user/riscv/target_arch.h  |  27 
 bsd-user/riscv/target_arch_cpu.c  |  29 +
 bsd-user/riscv/target_arch_cpu.h  | 147 ++
 bsd-user/riscv/target_arch_elf.h  |  42 +++
 bsd-user/riscv/target_arch_reg.h  |  88 +
 bsd-user/riscv/target_arch_signal.h   |  75 
 bsd-user/riscv/target_arch_sigtramp.h |  41 +++
 bsd-user/riscv/target_arch_sysarch.h  |  41 +++
 bsd-user/riscv/target_arch_thread.h   |  47 +++
 bsd-user/riscv/target_arch_vmparam.h  |  53 
 bsd-user/riscv/target_syscall.h   |  38 ++
 configs/targets/riscv64-bsd-user.mak  |   4 +
 14 files changed, 822 insertions(+)
 create mode 100644 bsd-user/riscv/signal.c
 create mode 100644 bsd-user/riscv/target.h
 create mode 100644 bsd-user/riscv/target_arch.h
 create mode 100644 bsd-user/riscv/target_arch_cpu.c
 create mode 100644 bsd-user/riscv/target_arch_cpu.h
 create mode 100644 bsd-user/riscv/target_arch_elf.h
 create mode 100644 bsd-user/riscv/target_arch_reg.h
 create mode 100644 bsd-user/riscv/target_arch_signal.h
 create mode 100644 bsd-user/riscv/target_arch_sigtramp.h
 create mode 100644 bsd-user/riscv/target_arch_sysarch.h
 create mode 100644 bsd-user/riscv/target_arch_thread.h
 create mode 100644 bsd-user/riscv/target_arch_vmparam.h
 create mode 100644 bsd-user/riscv/target_syscall.h
 create mode 100644 configs/targets/riscv64-bsd-user.mak

-- 
2.34.1




[PATCH v6 05/17] bsd-user: Add RISC-V ELF definitions and hardware capability detection

2024-09-15 Thread Ajeet Singh
From: Mark Corbin 

Introduced RISC-V specific ELF definitions and hardware capability
detection.
Additionally, a function to retrieve hardware capabilities
('get_elf_hwcap') is implemented, which returns the common bits set in
each CPU's ISA strings.

Signed-off-by: Mark Corbin 
Signed-off-by: Ajeet Singh 
Co-authored-by: Kyle Evans 
Reviewed-by: Richard Henderson 
---
 bsd-user/riscv/target_arch_elf.h | 42 
 1 file changed, 42 insertions(+)
 create mode 100644 bsd-user/riscv/target_arch_elf.h

diff --git a/bsd-user/riscv/target_arch_elf.h b/bsd-user/riscv/target_arch_elf.h
new file mode 100644
index 00..4eb915e61e
--- /dev/null
+++ b/bsd-user/riscv/target_arch_elf.h
@@ -0,0 +1,42 @@
+/*
+ *  RISC-V ELF definitions
+ *
+ *  Copyright (c) 2019 Mark Corbin
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see .
+ */
+
+#ifndef TARGET_ARCH_ELF_H
+#define TARGET_ARCH_ELF_H
+
+#define elf_check_arch(x) ((x) == EM_RISCV)
+#define ELF_START_MMAP 0x8000
+#define ELF_ET_DYN_LOAD_ADDR0x10
+#define ELF_CLASS   ELFCLASS64
+
+#define ELF_DATAELFDATA2LSB
+#define ELF_ARCHEM_RISCV
+
+#define ELF_HWCAP get_elf_hwcap()
+static uint32_t get_elf_hwcap(void)
+{
+RISCVCPU *cpu = RISCV_CPU(thread_cpu);
+
+return cpu->env.misa_ext_mask;
+}
+
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE4096
+
+#endif /* TARGET_ARCH_ELF_H */
-- 
2.34.1




[PATCH v6 13/17] bsd-user: Define RISC-V signal handling structures and constants

2024-09-15 Thread Ajeet Singh
From: Mark Corbin 

Added definitions for RISC-V signal handling, including structures
and constants for managing signal frames and context

Signed-off-by: Mark Corbin 
Signed-off-by: Ajeet Singh 
Co-authored-by: Warner Losh 
Reviewed-by: Richard Henderson 
---
 bsd-user/riscv/target_arch_signal.h | 75 +
 1 file changed, 75 insertions(+)
 create mode 100644 bsd-user/riscv/target_arch_signal.h

diff --git a/bsd-user/riscv/target_arch_signal.h 
b/bsd-user/riscv/target_arch_signal.h
new file mode 100644
index 00..1a634b865b
--- /dev/null
+++ b/bsd-user/riscv/target_arch_signal.h
@@ -0,0 +1,75 @@
+/*
+ *  RISC-V signal definitions
+ *
+ *  Copyright (c) 2019 Mark Corbin
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see .
+ */
+
+#ifndef TARGET_ARCH_SIGNAL_H
+#define TARGET_ARCH_SIGNAL_H
+
+#include "cpu.h"
+
+
+#define TARGET_INSN_SIZE 4  /* riscv instruction size */
+
+/* Size of the signal trampoline code placed on the stack. */
+#define TARGET_SZSIGCODE((abi_ulong)(7 * TARGET_INSN_SIZE))
+
+/* Compare with riscv/include/_limits.h */
+#define TARGET_MINSIGSTKSZ  (1024 * 4)
+#define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
+
+struct target_gpregs {
+uint64_tgp_ra;
+uint64_tgp_sp;
+uint64_tgp_gp;
+uint64_tgp_tp;
+uint64_tgp_t[7];
+uint64_tgp_s[12];
+uint64_tgp_a[8];
+uint64_tgp_sepc;
+uint64_tgp_sstatus;
+};
+
+struct target_fpregs {
+uint64_tfp_x[32][2];
+uint64_tfp_fcsr;
+uint32_tfp_flags;
+uint32_tpad;
+};
+
+typedef struct target_mcontext {
+struct target_gpregs   mc_gpregs;
+struct target_fpregs   mc_fpregs;
+uint32_t   mc_flags;
+#define TARGET_MC_FP_VALID 0x01
+uint32_t   mc_pad;
+uint64_t   mc_spare[8];
+} target_mcontext_t;
+
+#define TARGET_MCONTEXT_SIZE 864
+#define TARGET_UCONTEXT_SIZE 936
+
+#include "target_os_ucontext.h"
+
+struct target_sigframe {
+target_ucontext_t   sf_uc; /* = *sf_uncontext */
+target_siginfo_tsf_si; /* = *sf_siginfo (SA_SIGINFO case)*/
+};
+
+#define TARGET_SIGSTACK_ALIGN 16
+
+#endif /* TARGET_ARCH_SIGNAL_H */
-- 
2.34.1




[PATCH v6 10/17] bsd-user: Define RISC-V VM parameters and helper functions

2024-09-15 Thread Ajeet Singh
From: Mark Corbin 

Added definitions for RISC-V VM parameters, including maximum and
default sizes for text, data, and stack, as well as address space
limits.
Implemented helper functions for retrieving and setting specific
values in the CPU state, such as stack pointer and return values.

Signed-off-by: Mark Corbin 
Signed-off-by: Ajeet Singh 
Reviewed-by: Richard Henderson 
---
 bsd-user/riscv/target_arch_vmparam.h | 53 
 1 file changed, 53 insertions(+)
 create mode 100644 bsd-user/riscv/target_arch_vmparam.h

diff --git a/bsd-user/riscv/target_arch_vmparam.h 
b/bsd-user/riscv/target_arch_vmparam.h
new file mode 100644
index 00..0f2486def1
--- /dev/null
+++ b/bsd-user/riscv/target_arch_vmparam.h
@@ -0,0 +1,53 @@
+/*
+ *  RISC-V VM parameters definitions
+ *
+ *  Copyright (c) 2019 Mark Corbin
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see .
+ */
+
+#ifndef TARGET_ARCH_VMPARAM_H
+#define TARGET_ARCH_VMPARAM_H
+
+#include "cpu.h"
+
+/* Compare with riscv/include/vmparam.h */
+#define TARGET_MAXTSIZ  (1 * GiB)   /* max text size */
+#define TARGET_DFLDSIZ  (128 * MiB) /* initial data size limit */
+#define TARGET_MAXDSIZ  (1 * GiB)   /* max data size */
+#define TARGET_DFLSSIZ  (128 * MiB) /* initial stack size limit */
+#define TARGET_MAXSSIZ  (1 * GiB)   /* max stack size */
+#define TARGET_SGROWSIZ (128 * KiB) /* amount to grow stack */
+
+#define TARGET_VM_MINUSER_ADDRESS   (0xUL)
+#define TARGET_VM_MAXUSER_ADDRESS   (0x0040UL)
+
+#define TARGET_USRSTACK (TARGET_VM_MAXUSER_ADDRESS - TARGET_PAGE_SIZE)
+
+static inline abi_ulong get_sp_from_cpustate(CPURISCVState *state)
+{
+return state->gpr[xSP];
+}
+
+static inline void set_second_rval(CPURISCVState *state, abi_ulong retval2)
+{
+state->gpr[xA1] = retval2;
+}
+
+static inline abi_ulong get_second_rval(CPURISCVState *state)
+{
+return state->gpr[xA1];
+}
+
+#endif /* TARGET_ARCH_VMPARAM_H */
-- 
2.34.1




[PATCH v6 06/17] bsd-user: Define RISC-V register structures and register copying

2024-09-15 Thread Ajeet Singh
From: Mark Corbin 

Added definitions for RISC-V register structures, including
general-purpose registers and floating-point registers, in
'target_arch_reg.h'. Implemented the 'target_copy_regs' function to
copy register values from the CPU state to the target register
structure, ensuring proper endianness handling using 'tswapreg'.

Signed-off-by: Mark Corbin 
Signed-off-by: Ajeet Singh 
Reviewed-by: Richard Henderson 
---
 bsd-user/riscv/target_arch_reg.h | 88 
 1 file changed, 88 insertions(+)
 create mode 100644 bsd-user/riscv/target_arch_reg.h

diff --git a/bsd-user/riscv/target_arch_reg.h b/bsd-user/riscv/target_arch_reg.h
new file mode 100644
index 00..12b1c96b61
--- /dev/null
+++ b/bsd-user/riscv/target_arch_reg.h
@@ -0,0 +1,88 @@
+/*
+ *  RISC-V register structures
+ *
+ *  Copyright (c) 2019 Mark Corbin
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see .
+ */
+
+#ifndef TARGET_ARCH_REG_H
+#define TARGET_ARCH_REG_H
+
+/* Compare with riscv/include/reg.h */
+typedef struct target_reg {
+uint64_t ra;/* return address */
+uint64_t sp;/* stack pointer */
+uint64_t gp;/* global pointer */
+uint64_t tp;/* thread pointer */
+uint64_t t[7];  /* temporaries */
+uint64_t s[12]; /* saved registers */
+uint64_t a[8];  /* function arguments */
+uint64_t sepc;  /* exception program counter */
+uint64_t sstatus;   /* status register */
+} target_reg_t;
+
+typedef struct target_fpreg {
+uint64_tfp_x[32][2];/* Floating point registers */
+uint64_tfp_fcsr;/* Floating point control reg */
+} target_fpreg_t;
+
+#define tswapreg(ptr)   tswapal(ptr)
+
+/* Compare with struct trapframe in riscv/include/frame.h */
+static inline void target_copy_regs(target_reg_t *regs,
+const CPURISCVState *env)
+{
+
+regs->ra = tswapreg(env->gpr[1]);
+regs->sp = tswapreg(env->gpr[2]);
+regs->gp = tswapreg(env->gpr[3]);
+regs->tp = tswapreg(env->gpr[4]);
+
+regs->t[0] = tswapreg(env->gpr[5]);
+regs->t[1] = tswapreg(env->gpr[6]);
+regs->t[2] = tswapreg(env->gpr[7]);
+regs->t[3] = tswapreg(env->gpr[28]);
+regs->t[4] = tswapreg(env->gpr[29]);
+regs->t[5] = tswapreg(env->gpr[30]);
+regs->t[6] = tswapreg(env->gpr[31]);
+
+regs->s[0] = tswapreg(env->gpr[8]);
+regs->s[1] = tswapreg(env->gpr[9]);
+regs->s[2] = tswapreg(env->gpr[18]);
+regs->s[3] = tswapreg(env->gpr[19]);
+regs->s[4] = tswapreg(env->gpr[20]);
+regs->s[5] = tswapreg(env->gpr[21]);
+regs->s[6] = tswapreg(env->gpr[22]);
+regs->s[7] = tswapreg(env->gpr[23]);
+regs->s[8] = tswapreg(env->gpr[24]);
+regs->s[9] = tswapreg(env->gpr[25]);
+regs->s[10] = tswapreg(env->gpr[26]);
+regs->s[11] = tswapreg(env->gpr[27]);
+
+regs->a[0] = tswapreg(env->gpr[10]);
+regs->a[1] = tswapreg(env->gpr[11]);
+regs->a[2] = tswapreg(env->gpr[12]);
+regs->a[3] = tswapreg(env->gpr[13]);
+regs->a[4] = tswapreg(env->gpr[14]);
+regs->a[5] = tswapreg(env->gpr[15]);
+regs->a[6] = tswapreg(env->gpr[16]);
+regs->a[7] = tswapreg(env->gpr[17]);
+
+regs->sepc = tswapreg(env->pc);
+}
+
+#undef tswapreg
+
+#endif /* TARGET_ARCH_REG_H */
-- 
2.34.1




[PATCH v6 09/17] bsd-user: Add RISC-V thread setup and initialization support

2024-09-15 Thread Ajeet Singh
From: Mark Corbin 

Implemented functions for setting up and initializing threads in the
RISC-V architecture.
The 'target_thread_set_upcall' function sets up the stack pointer,
program counter, and function argument for new threads.
The 'target_thread_init' function initializes thread registers based on
the provided image information.

Signed-off-by: Mark Corbin 
Signed-off-by: Ajeet Singh 
Co-authored-by: Jessica Clarke 
Co-authored-by: Kyle Evans 
Reviewed-by: Richard Henderson 
---
 bsd-user/riscv/target_arch_thread.h | 47 +
 1 file changed, 47 insertions(+)
 create mode 100644 bsd-user/riscv/target_arch_thread.h

diff --git a/bsd-user/riscv/target_arch_thread.h 
b/bsd-user/riscv/target_arch_thread.h
new file mode 100644
index 00..95cd0b6ad7
--- /dev/null
+++ b/bsd-user/riscv/target_arch_thread.h
@@ -0,0 +1,47 @@
+/*
+ *  RISC-V thread support
+ *
+ *  Copyright (c) 2019 Mark Corbin
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see .
+ */
+
+#ifndef TARGET_ARCH_THREAD_H
+#define TARGET_ARCH_THREAD_H
+
+/* Compare with cpu_set_upcall() in riscv/riscv/vm_machdep.c */
+static inline void target_thread_set_upcall(CPURISCVState *regs,
+abi_ulong entry, abi_ulong arg, abi_ulong stack_base,
+abi_ulong stack_size)
+{
+abi_ulong sp;
+
+sp = ROUND_DOWN(stack_base + stack_size, 16);
+
+regs->gpr[xSP] = sp;
+regs->pc = entry;
+regs->gpr[xA0] = arg;
+}
+
+/* Compare with exec_setregs() in riscv/riscv/machdep.c */
+static inline void target_thread_init(struct target_pt_regs *regs,
+struct image_info *infop)
+{
+regs->sepc = infop->entry;
+regs->regs[xRA] = infop->entry;
+regs->regs[xA0] = infop->start_stack;
+regs->regs[xSP] = ROUND_DOWN(infop->start_stack, 16);
+}
+
+#endif /* TARGET_ARCH_THREAD_H */
-- 
2.34.1




[PATCH v6 01/17] bsd-user: Implement RISC-V CPU initialization and main loop

2024-09-15 Thread Ajeet Singh
From: Mark Corbin 

Added the initial implementation for RISC-V CPU initialization and main
loop. This includes setting up the general-purpose registers and
program counter based on the provided target architecture definitions.

Signed-off-by: Mark Corbin 
Signed-off-by: Ajeet Singh 
Co-authored-by: Jessica Clarke 
Reviewed-by: Richard Henderson 
---
 bsd-user/riscv/target_arch_cpu.h | 39 
 1 file changed, 39 insertions(+)
 create mode 100644 bsd-user/riscv/target_arch_cpu.h

diff --git a/bsd-user/riscv/target_arch_cpu.h b/bsd-user/riscv/target_arch_cpu.h
new file mode 100644
index 00..e17c910ae9
--- /dev/null
+++ b/bsd-user/riscv/target_arch_cpu.h
@@ -0,0 +1,39 @@
+/*
+ *  RISC-V CPU init and loop
+ *
+ *  Copyright (c) 2019 Mark Corbin
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see .
+ */
+
+#ifndef TARGET_ARCH_CPU_H
+#define TARGET_ARCH_CPU_H
+
+#include "target_arch.h"
+
+#define TARGET_DEFAULT_CPU_MODEL "max"
+
+static inline void target_cpu_init(CPURISCVState *env,
+struct target_pt_regs *regs)
+{
+int i;
+
+for (i = 1; i < 32; i++) {
+env->gpr[i] = regs->regs[i];
+}
+
+env->pc = regs->sepc;
+}
+
+#endif /* TARGET_ARCH_CPU_H */
-- 
2.34.1




[PATCH v6 11/17] bsd-user: Define RISC-V system call structures and constants

2024-09-15 Thread Ajeet Singh
From: Mark Corbin 

Introduced definitions for the RISC-V system call interface, including
the 'target_pt_regs' structure that outlines the register storage
layout during a system call.
Added constants for hardware machine identifiers.

Signed-off-by: Mark Corbin 
Signed-off-by: Ajeet Singh 
Co-authored-by: Jessica Clarke 
Reviewed-by: Richard Henderson 
---
 bsd-user/riscv/target_syscall.h | 38 +
 1 file changed, 38 insertions(+)
 create mode 100644 bsd-user/riscv/target_syscall.h

diff --git a/bsd-user/riscv/target_syscall.h b/bsd-user/riscv/target_syscall.h
new file mode 100644
index 00..e7e5231309
--- /dev/null
+++ b/bsd-user/riscv/target_syscall.h
@@ -0,0 +1,38 @@
+/*
+ *  RISC-V system call definitions
+ *
+ *  Copyright (c) Mark Corbin
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see .
+ */
+
+#ifndef BSD_USER_RISCV_TARGET_SYSCALL_H
+#define BSD_USER_RISCV_TARGET_SYSCALL_H
+
+/*
+ * struct target_pt_regs defines the way the registers are stored on the stack
+ * during a system call.
+ */
+
+struct target_pt_regs {
+abi_ulong regs[32];
+abi_ulong sepc;
+};
+
+#define UNAME_MACHINE "riscv64"
+
+#define TARGET_HW_MACHINE   "riscv"
+#define TARGET_HW_MACHINE_ARCH  UNAME_MACHINE
+
+#endif /* BSD_USER_RISCV_TARGET_SYSCALL_H */
-- 
2.34.1




[PATCH v6 08/17] bsd-user: Implement RISC-V sysarch system call emulation

2024-09-15 Thread Ajeet Singh
From: Mark Corbin 

Added the 'do_freebsd_arch_sysarch' function to emulate the 'sysarch'
system call for the RISC-V architecture.
Currently, this function returns '-TARGET_EOPNOTSUPP' to indicate that
the operation is not supported.

Signed-off-by: Mark Corbin 
Signed-off-by: Ajeet Singh 
Reviewed-by: Richard Henderson 
---
 bsd-user/riscv/target_arch_sysarch.h | 41 
 1 file changed, 41 insertions(+)
 create mode 100644 bsd-user/riscv/target_arch_sysarch.h

diff --git a/bsd-user/riscv/target_arch_sysarch.h 
b/bsd-user/riscv/target_arch_sysarch.h
new file mode 100644
index 00..9af42331b4
--- /dev/null
+++ b/bsd-user/riscv/target_arch_sysarch.h
@@ -0,0 +1,41 @@
+/*
+ *  RISC-V sysarch() system call emulation
+ *
+ *  Copyright (c) 2019 Mark Corbin
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see .
+ */
+
+#ifndef TARGET_ARCH_SYSARCH_H
+#define TARGET_ARCH_SYSARCH_H
+
+#include "target_syscall.h"
+#include "target_arch.h"
+
+static inline abi_long do_freebsd_arch_sysarch(CPURISCVState *env, int op,
+abi_ulong parms)
+{
+
+return -TARGET_EOPNOTSUPP;
+}
+
+static inline void do_freebsd_arch_print_sysarch(
+const struct syscallname *name, abi_long arg1, abi_long arg2,
+abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6)
+{
+
+gemu_log("UNKNOWN OP: %d, " TARGET_ABI_FMT_lx ")", (int)arg1, arg2);
+}
+
+#endif /* TARGET_ARCH_SYSARCH_H */
-- 
2.34.1




[PATCH v6 02/17] bsd-user: Add RISC-V CPU execution loop and syscall handling

2024-09-15 Thread Ajeet Singh
From: Mark Corbin 

Implemented the RISC-V CPU execution loop, including handling various
exceptions and system calls. The loop continuously executes CPU
instructions,processes exceptions, and handles system calls by invoking
FreeBSD syscall handlers.

Signed-off-by: Mark Corbin 
Signed-off-by: Ajeet Singh 
Co-authored-by: Jessica Clarke 
Co-authored-by: Kyle Evans 
Reviewed-by: Richard Henderson 
---
 bsd-user/riscv/target_arch_cpu.h | 94 
 1 file changed, 94 insertions(+)

diff --git a/bsd-user/riscv/target_arch_cpu.h b/bsd-user/riscv/target_arch_cpu.h
index e17c910ae9..ea2a8d1ace 100644
--- a/bsd-user/riscv/target_arch_cpu.h
+++ b/bsd-user/riscv/target_arch_cpu.h
@@ -36,4 +36,98 @@ static inline void target_cpu_init(CPURISCVState *env,
 env->pc = regs->sepc;
 }
 
+static inline void target_cpu_loop(CPURISCVState *env)
+{
+CPUState *cs = env_cpu(env);
+int trapnr;
+abi_long ret;
+unsigned int syscall_num;
+int32_t signo, code;
+
+for (;;) {
+cpu_exec_start(cs);
+trapnr = cpu_exec(cs);
+cpu_exec_end(cs);
+process_queued_cpu_work(cs);
+
+signo = 0;
+
+switch (trapnr) {
+case EXCP_INTERRUPT:
+/* just indicate that signals should be handled asap */
+break;
+case EXCP_ATOMIC:
+cpu_exec_step_atomic(cs);
+break;
+case RISCV_EXCP_U_ECALL:
+syscall_num = env->gpr[xT0];
+env->pc += TARGET_INSN_SIZE;
+/* Compare to cpu_fetch_syscall_args() in riscv/riscv/trap.c */
+if (TARGET_FREEBSD_NR___syscall == syscall_num ||
+TARGET_FREEBSD_NR_syscall == syscall_num) {
+ret = do_freebsd_syscall(env,
+ env->gpr[xA0],
+ env->gpr[xA1],
+ env->gpr[xA2],
+ env->gpr[xA3],
+ env->gpr[xA4],
+ env->gpr[xA5],
+ env->gpr[xA6],
+ env->gpr[xA7],
+ 0);
+} else {
+ret = do_freebsd_syscall(env,
+ syscall_num,
+ env->gpr[xA0],
+ env->gpr[xA1],
+ env->gpr[xA2],
+ env->gpr[xA3],
+ env->gpr[xA4],
+ env->gpr[xA5],
+ env->gpr[xA6],
+ env->gpr[xA7]
+);
+}
+
+/*
+ * Compare to cpu_set_syscall_retval() in
+ * riscv/riscv/vm_machdep.c
+ */
+if (ret >= 0) {
+env->gpr[xA0] = ret;
+env->gpr[xT0] = 0;
+} else if (ret == -TARGET_ERESTART) {
+env->pc -= TARGET_INSN_SIZE;
+} else if (ret != -TARGET_EJUSTRETURN) {
+env->gpr[xA0] = -ret;
+env->gpr[xT0] = 1;
+}
+break;
+case RISCV_EXCP_ILLEGAL_INST:
+signo = TARGET_SIGILL;
+code = TARGET_ILL_ILLOPC;
+break;
+case RISCV_EXCP_BREAKPOINT:
+signo = TARGET_SIGTRAP;
+code = TARGET_TRAP_BRKPT;
+break;
+case EXCP_DEBUG:
+signo = TARGET_SIGTRAP;
+code = TARGET_TRAP_BRKPT;
+break;
+default:
+fprintf(stderr, "qemu: unhandled CPU exception "
+"0x%x - aborting\n", trapnr);
+cpu_dump_state(cs, stderr, 0);
+abort();
+}
+
+if (signo) {
+force_sig_fault(signo, code, env->pc);
+}
+
+process_pending_signals(env);
+}
+}
+
 #endif /* TARGET_ARCH_CPU_H */
-- 
2.34.1




[PATCH v6 16/17] bsd-user: Implement set_mcontext and get_ucontext_sigreturn for RISCV

2024-09-15 Thread Ajeet Singh
From: Mark Corbin 

Added implementations for 'set_mcontext' and 'get_ucontext_sigreturn'
functions for RISC-V architecture,
Both functions ensure that the CPU state and user context are properly
managed.

Signed-off-by: Mark Corbin 
Signed-off-by: Warner Losh 
Signed-off-by: Ajeet Singh 
Co-authored-by: Warner Losh 
Reviewed-by: Richard Henderson 
---
 bsd-user/riscv/signal.c | 54 +
 1 file changed, 54 insertions(+)

diff --git a/bsd-user/riscv/signal.c b/bsd-user/riscv/signal.c
index 072ad821d2..10c940cd49 100644
--- a/bsd-user/riscv/signal.c
+++ b/bsd-user/riscv/signal.c
@@ -114,3 +114,57 @@ abi_long get_mcontext(CPURISCVState *regs, 
target_mcontext_t *mcp,
 
 return 0;
 }
+
+/* Compare with set_mcontext() in riscv/riscv/exec_machdep.c */
+abi_long set_mcontext(CPURISCVState *regs, target_mcontext_t *mcp,
+int srflag)
+{
+
+regs->gpr[5] = tswap64(mcp->mc_gpregs.gp_t[0]);
+regs->gpr[6] = tswap64(mcp->mc_gpregs.gp_t[1]);
+regs->gpr[7] = tswap64(mcp->mc_gpregs.gp_t[2]);
+regs->gpr[28] = tswap64(mcp->mc_gpregs.gp_t[3]);
+regs->gpr[29] = tswap64(mcp->mc_gpregs.gp_t[4]);
+regs->gpr[30] = tswap64(mcp->mc_gpregs.gp_t[5]);
+regs->gpr[31] = tswap64(mcp->mc_gpregs.gp_t[6]);
+
+regs->gpr[8] = tswap64(mcp->mc_gpregs.gp_s[0]);
+regs->gpr[9] = tswap64(mcp->mc_gpregs.gp_s[1]);
+regs->gpr[18] = tswap64(mcp->mc_gpregs.gp_s[2]);
+regs->gpr[19] = tswap64(mcp->mc_gpregs.gp_s[3]);
+regs->gpr[20] = tswap64(mcp->mc_gpregs.gp_s[4]);
+regs->gpr[21] = tswap64(mcp->mc_gpregs.gp_s[5]);
+regs->gpr[22] = tswap64(mcp->mc_gpregs.gp_s[6]);
+regs->gpr[23] = tswap64(mcp->mc_gpregs.gp_s[7]);
+regs->gpr[24] = tswap64(mcp->mc_gpregs.gp_s[8]);
+regs->gpr[25] = tswap64(mcp->mc_gpregs.gp_s[9]);
+regs->gpr[26] = tswap64(mcp->mc_gpregs.gp_s[10]);
+regs->gpr[27] = tswap64(mcp->mc_gpregs.gp_s[11]);
+
+regs->gpr[10] = tswap64(mcp->mc_gpregs.gp_a[0]);
+regs->gpr[11] = tswap64(mcp->mc_gpregs.gp_a[1]);
+regs->gpr[12] = tswap64(mcp->mc_gpregs.gp_a[2]);
+regs->gpr[13] = tswap64(mcp->mc_gpregs.gp_a[3]);
+regs->gpr[14] = tswap64(mcp->mc_gpregs.gp_a[4]);
+regs->gpr[15] = tswap64(mcp->mc_gpregs.gp_a[5]);
+regs->gpr[16] = tswap64(mcp->mc_gpregs.gp_a[6]);
+regs->gpr[17] = tswap64(mcp->mc_gpregs.gp_a[7]);
+
+
+regs->gpr[1] = tswap64(mcp->mc_gpregs.gp_ra);
+regs->gpr[2] = tswap64(mcp->mc_gpregs.gp_sp);
+regs->gpr[3] = tswap64(mcp->mc_gpregs.gp_gp);
+regs->gpr[4] = tswap64(mcp->mc_gpregs.gp_tp);
+regs->pc = tswap64(mcp->mc_gpregs.gp_sepc);
+
+return 0;
+}
+
+/* Compare with sys_sigreturn() in riscv/riscv/machdep.c */
+abi_long get_ucontext_sigreturn(CPURISCVState *regs,
+abi_ulong target_sf, abi_ulong *target_uc)
+{
+
+*target_uc = target_sf;
+return 0;
+}
-- 
2.34.1




[PATCH v6 04/17] bsd-user: Implement RISC-V TLS register setup

2024-09-15 Thread Ajeet Singh
From: Mark Corbin 

Included the prototype for the 'target_cpu_set_tls' function in the
'target_arch.h' header file. This function is responsible for setting
the Thread Local Storage (TLS) register for RISC-V architecture.

Signed-off-by: Mark Corbin 
Signed-off-by: Ajeet Singh 
Reviewed-by: Richard Henderson 
---
 bsd-user/riscv/target_arch.h | 27 +++
 bsd-user/riscv/target_arch_cpu.c | 29 +
 2 files changed, 56 insertions(+)
 create mode 100644 bsd-user/riscv/target_arch.h
 create mode 100644 bsd-user/riscv/target_arch_cpu.c

diff --git a/bsd-user/riscv/target_arch.h b/bsd-user/riscv/target_arch.h
new file mode 100644
index 00..26ce07f343
--- /dev/null
+++ b/bsd-user/riscv/target_arch.h
@@ -0,0 +1,27 @@
+/*
+ * RISC-V specific prototypes
+ *
+ * Copyright (c) 2019 Mark Corbin 
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+
+#ifndef TARGET_ARCH_H
+#define TARGET_ARCH_H
+
+#include "qemu.h"
+
+void target_cpu_set_tls(CPURISCVState *env, target_ulong newtls);
+
+#endif /* TARGET_ARCH_H */
diff --git a/bsd-user/riscv/target_arch_cpu.c b/bsd-user/riscv/target_arch_cpu.c
new file mode 100644
index 00..44e25d2ddf
--- /dev/null
+++ b/bsd-user/riscv/target_arch_cpu.c
@@ -0,0 +1,29 @@
+/*
+ *  RISC-V CPU related code
+ *
+ *  Copyright (c) 2019 Mark Corbin
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see .
+ */
+#include "qemu/osdep.h"
+
+#include "target_arch.h"
+
+#define TP_OFFSET   16
+
+/* Compare with cpu_set_user_tls() in riscv/riscv/vm_machdep.c */
+void target_cpu_set_tls(CPURISCVState *env, target_ulong newtls)
+{
+env->gpr[xTP] = newtls + TP_OFFSET;
+}
-- 
2.34.1




[PATCH v6 17/17] bsd-user: Add RISC-V 64-bit Target Configuration and Debug XML Files

2024-09-15 Thread Ajeet Singh
From: Warner Losh 

Added configuration for RISC-V 64-bit target to the build system.

Signed-off-by: Warner Losh 
Signed-off-by: Ajeet Singh 
Reviewed-by: Richard Henderson 
---
 configs/targets/riscv64-bsd-user.mak | 4 
 1 file changed, 4 insertions(+)
 create mode 100644 configs/targets/riscv64-bsd-user.mak

diff --git a/configs/targets/riscv64-bsd-user.mak 
b/configs/targets/riscv64-bsd-user.mak
new file mode 100644
index 00..191c2c483f
--- /dev/null
+++ b/configs/targets/riscv64-bsd-user.mak
@@ -0,0 +1,4 @@
+TARGET_ARCH=riscv64
+TARGET_BASE_ARCH=riscv
+TARGET_ABI_DIR=riscv
+TARGET_XML_FILES= gdb-xml/riscv-64bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml 
gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-64bit-virtual.xml
-- 
2.34.1




[PATCH v6 15/17] bsd-user: Implement 'get_mcontext' for RISC-V

2024-09-15 Thread Ajeet Singh
From: Mark Corbin 

Added the 'get_mcontext' function to extract and populate
the RISC-V machine context from the CPU state.
This function is used to gather the current state of the
general-purpose registers and store it in a 'target_mcontext_'
structure.

Signed-off-by: Mark Corbin 
Signed-off-by: Ajeet Singh 
Signed-off-by: Warner Losh 
Co-authored-by: Warner Losh 
Reviewed-by: Richard Henderson 
---
 bsd-user/riscv/signal.c | 53 +
 1 file changed, 53 insertions(+)

diff --git a/bsd-user/riscv/signal.c b/bsd-user/riscv/signal.c
index 2597fec2fd..072ad821d2 100644
--- a/bsd-user/riscv/signal.c
+++ b/bsd-user/riscv/signal.c
@@ -61,3 +61,56 @@ abi_long setup_sigframe_arch(CPURISCVState *env, abi_ulong 
frame_addr,
 get_mcontext(env, mcp, flags);
 return 0;
 }
+
+/*
+ * Compare with get_mcontext() in riscv/riscv/machdep.c
+ * Assumes that the memory is locked if mcp points to user memory.
+ */
+abi_long get_mcontext(CPURISCVState *regs, target_mcontext_t *mcp,
+int flags)
+{
+
+mcp->mc_gpregs.gp_t[0] = tswap64(regs->gpr[5]);
+mcp->mc_gpregs.gp_t[1] = tswap64(regs->gpr[6]);
+mcp->mc_gpregs.gp_t[2] = tswap64(regs->gpr[7]);
+mcp->mc_gpregs.gp_t[3] = tswap64(regs->gpr[28]);
+mcp->mc_gpregs.gp_t[4] = tswap64(regs->gpr[29]);
+mcp->mc_gpregs.gp_t[5] = tswap64(regs->gpr[30]);
+mcp->mc_gpregs.gp_t[6] = tswap64(regs->gpr[31]);
+
+mcp->mc_gpregs.gp_s[0] = tswap64(regs->gpr[8]);
+mcp->mc_gpregs.gp_s[1] = tswap64(regs->gpr[9]);
+mcp->mc_gpregs.gp_s[2] = tswap64(regs->gpr[18]);
+mcp->mc_gpregs.gp_s[3] = tswap64(regs->gpr[19]);
+mcp->mc_gpregs.gp_s[4] = tswap64(regs->gpr[20]);
+mcp->mc_gpregs.gp_s[5] = tswap64(regs->gpr[21]);
+mcp->mc_gpregs.gp_s[6] = tswap64(regs->gpr[22]);
+mcp->mc_gpregs.gp_s[7] = tswap64(regs->gpr[23]);
+mcp->mc_gpregs.gp_s[8] = tswap64(regs->gpr[24]);
+mcp->mc_gpregs.gp_s[9] = tswap64(regs->gpr[25]);
+mcp->mc_gpregs.gp_s[10] = tswap64(regs->gpr[26]);
+mcp->mc_gpregs.gp_s[11] = tswap64(regs->gpr[27]);
+
+mcp->mc_gpregs.gp_a[0] = tswap64(regs->gpr[10]);
+mcp->mc_gpregs.gp_a[1] = tswap64(regs->gpr[11]);
+mcp->mc_gpregs.gp_a[2] = tswap64(regs->gpr[12]);
+mcp->mc_gpregs.gp_a[3] = tswap64(regs->gpr[13]);
+mcp->mc_gpregs.gp_a[4] = tswap64(regs->gpr[14]);
+mcp->mc_gpregs.gp_a[5] = tswap64(regs->gpr[15]);
+mcp->mc_gpregs.gp_a[6] = tswap64(regs->gpr[16]);
+mcp->mc_gpregs.gp_a[7] = tswap64(regs->gpr[17]);
+
+if (flags & TARGET_MC_GET_CLEAR_RET) {
+mcp->mc_gpregs.gp_a[0] = 0; /* a0 */
+mcp->mc_gpregs.gp_a[1] = 0; /* a1 */
+mcp->mc_gpregs.gp_t[0] = 0; /* clear syscall error */
+}
+
+mcp->mc_gpregs.gp_ra = tswap64(regs->gpr[1]);
+mcp->mc_gpregs.gp_sp = tswap64(regs->gpr[2]);
+mcp->mc_gpregs.gp_gp = tswap64(regs->gpr[3]);
+mcp->mc_gpregs.gp_tp = tswap64(regs->gpr[4]);
+mcp->mc_gpregs.gp_sepc = tswap64(regs->pc);
+
+return 0;
+}
-- 
2.34.1




[PATCH v6 03/17] bsd-user: Implement RISC-V CPU register cloning and reset functions

2024-09-15 Thread Ajeet Singh
From: Mark Corbin 

Added functions for cloning CPU registers and resetting the CPU state
for RISC-V architecture.

Signed-off-by: Mark Corbin 
Signed-off-by: Ajeet Singh 
Reviewed-by: Richard Henderson 
---
 bsd-user/riscv/target_arch_cpu.h | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/bsd-user/riscv/target_arch_cpu.h b/bsd-user/riscv/target_arch_cpu.h
index ea2a8d1ace..57abfbd556 100644
--- a/bsd-user/riscv/target_arch_cpu.h
+++ b/bsd-user/riscv/target_arch_cpu.h
@@ -130,4 +130,18 @@ static inline void target_cpu_loop(CPURISCVState *env)
 }
 }
 
+static inline void target_cpu_clone_regs(CPURISCVState *env, target_ulong 
newsp)
+{
+if (newsp) {
+env->gpr[xSP] = newsp;
+}
+
+env->gpr[xA0] = 0;
+env->gpr[xT0] = 0;
+}
+
+static inline void target_cpu_reset(CPUArchState *env)
+{
+}
+
 #endif /* TARGET_ARCH_CPU_H */
-- 
2.34.1




[PATCH v6 14/17] bsd-user: Implement RISC-V signal trampoline setup functions

2024-09-15 Thread Ajeet Singh
From: Mark Corbin 

Added functions for setting up the RISC-V signal trampoline and signal
frame:

'set_sigtramp_args()': Configures the RISC-V CPU state with arguments
for the signal handler. It sets up the registers with the signal
number,pointers to the signal info and user context, the signal handler
address, and the signal frame pointer.

'setup_sigframe_arch()': Initializes the signal frame with the current
machine context.This function copies the context from the CPU state to
the signal frame, preparing it for the signal handler.

Signed-off-by: Mark Corbin 
Signed-off-by: Ajeet Singh 
Signed-off-by: Warner Losh 
Co-authored-by: Warner Losh 
Reviewed-by: Richard Henderson 
---
 bsd-user/riscv/signal.c | 63 +
 1 file changed, 63 insertions(+)
 create mode 100644 bsd-user/riscv/signal.c

diff --git a/bsd-user/riscv/signal.c b/bsd-user/riscv/signal.c
new file mode 100644
index 00..2597fec2fd
--- /dev/null
+++ b/bsd-user/riscv/signal.c
@@ -0,0 +1,63 @@
+/*
+ *  RISC-V signal definitions
+ *
+ *  Copyright (c) 2019 Mark Corbin
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see .
+ */
+#include "qemu/osdep.h"
+
+#include "qemu.h"
+
+/*
+ * Compare with sendsig() in riscv/riscv/exec_machdep.c
+ * Assumes that target stack frame memory is locked.
+ */
+abi_long
+set_sigtramp_args(CPURISCVState *regs, int sig, struct target_sigframe *frame,
+abi_ulong frame_addr, struct target_sigaction *ka)
+{
+/*
+ * Arguments to signal handler:
+ *  a0 (10) = signal number
+ *  a1 (11) = siginfo pointer
+ *  a2 (12) = ucontext pointer
+ *  pc  = signal pointer handler
+ *  sp (2)  = sigframe pointer
+ *  ra (1)  = sigtramp at base of user stack
+ */
+
+ regs->gpr[xA0] = sig;
+ regs->gpr[xA1] = frame_addr +
+ offsetof(struct target_sigframe, sf_si);
+ regs->gpr[xA2] = frame_addr +
+ offsetof(struct target_sigframe, sf_uc);
+ regs->pc = ka->_sa_handler;
+ regs->gpr[xSP] = frame_addr;
+ regs->gpr[xRA] = TARGET_PS_STRINGS - TARGET_SZSIGCODE;
+ return 0;
+}
+
+/*
+ * Compare to riscv/riscv/exec_machdep.c sendsig()
+ * Assumes that the memory is locked if frame points to user memory.
+ */
+abi_long setup_sigframe_arch(CPURISCVState *env, abi_ulong frame_addr,
+ struct target_sigframe *frame, int flags)
+{
+target_mcontext_t *mcp = &frame->sf_uc.uc_mcontext;
+
+get_mcontext(env, mcp, flags);
+return 0;
+}
-- 
2.34.1




[PATCH v6 12/17] bsd-user: Add generic RISC-V64 target definitions

2024-09-15 Thread Ajeet Singh
From: Warner Losh 

Added a generic definition for RISC-V64 target-specific details.
Implemented the 'regpairs_aligned' function,which returns 'false'
to indicate that register pairs are not aligned in the RISC-V64 ABI.

Signed-off-by: Warner Losh 
Signed-off-by: Ajeet Singh 
Reviewed-by: Richard Henderson 
---
 bsd-user/riscv/target.h | 20 
 1 file changed, 20 insertions(+)
 create mode 100644 bsd-user/riscv/target.h

diff --git a/bsd-user/riscv/target.h b/bsd-user/riscv/target.h
new file mode 100644
index 00..036ddd185e
--- /dev/null
+++ b/bsd-user/riscv/target.h
@@ -0,0 +1,20 @@
+/*
+ * Riscv64 general target stuff that's common to all aarch details
+ *
+ * Copyright (c) 2022 M. Warner Losh 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef TARGET_H
+#define TARGET_H
+
+/*
+ * riscv64 ABI does not 'lump' the registers for 64-bit args.
+ */
+static inline bool regpairs_aligned(void *cpu_env)
+{
+return false;
+}
+
+#endif /* TARGET_H */
-- 
2.34.1




[PATCH v6 07/17] bsd-user: Add RISC-V signal trampoline setup function

2024-09-15 Thread Ajeet Singh
From: Mark Corbin 

Implemented the 'setup_sigtramp' function for setting up the signal
trampoline code in the RISC-V architecture.

Signed-off-by: Mark Corbin 
Signed-off-by: Ajeet Singh 
Reviewed-by: Richard Henderson 
---
 bsd-user/riscv/target_arch_sigtramp.h | 41 +++
 1 file changed, 41 insertions(+)
 create mode 100644 bsd-user/riscv/target_arch_sigtramp.h

diff --git a/bsd-user/riscv/target_arch_sigtramp.h 
b/bsd-user/riscv/target_arch_sigtramp.h
new file mode 100644
index 00..dfe5076739
--- /dev/null
+++ b/bsd-user/riscv/target_arch_sigtramp.h
@@ -0,0 +1,41 @@
+/*
+ * RISC-V sigcode
+ *
+ * Copyright (c) 2019 Mark Corbin
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+
+#ifndef TARGET_ARCH_SIGTRAMP_H
+#define TARGET_ARCH_SIGTRAMP_H
+
+/* Compare with sigcode() in riscv/riscv/locore.S */
+static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc,
+unsigned sys_sigreturn)
+{
+uint32_t sys_exit = TARGET_FREEBSD_NR_exit;
+
+uint32_t sigtramp_code[] = {
+/*1*/ const_le32(0x00010513),/*mv a0, sp*/
+/*2*/ const_le32(0x00050513 + (sigf_uc << 20)),  /*addi a0,a0,sigf_uc*/
+/*3*/ const_le32(0x0293 + (sys_sigreturn << 20)),/*li 
t0,sys_sigreturn*/
+/*4*/ const_le32(0x0073),/*ecall*/
+/*5*/ const_le32(0x0293 + (sys_exit << 20)), /*li t0,sys_exit*/
+/*6*/ const_le32(0x0073),/*ecall*/
+/*7*/ const_le32(0xFF1FF06F) /*b -16*/
+};
+
+return memcpy_to_target(offset, sigtramp_code, TARGET_SZSIGCODE);
+}
+#endif /* TARGET_ARCH_SIGTRAMP_H */
-- 
2.34.1




[PATCH v1 1/7] migration: Introduce structs for background sync

2024-09-15 Thread Hyman Huang
shadow_bmap, iter_bmap and iter_dirty_pages are introduced
to satisfy the need for background sync.

Meanwhile, introduce enumeration of sync method.

Signed-off-by: Hyman Huang 
---
 include/exec/ramblock.h | 45 +
 migration/ram.c |  6 ++
 2 files changed, 51 insertions(+)

diff --git a/include/exec/ramblock.h b/include/exec/ramblock.h
index 0babd105c0..0e327bc0ae 100644
--- a/include/exec/ramblock.h
+++ b/include/exec/ramblock.h
@@ -24,6 +24,30 @@
 #include "qemu/rcu.h"
 #include "exec/ramlist.h"
 
+/* Possible bits for cpu_physical_memory_sync_dirty_bitmap */
+
+/*
+ * The old-fashioned sync, which is, in turn, used for CPU
+ * throttle and memory transfer.
+ */
+#define RAMBLOCK_SYN_LEGACY_ITER   (1U << 0)
+
+/*
+ * The modern sync, which is, in turn, used for CPU throttle
+ * and memory transfer.
+ */
+#define RAMBLOCK_SYN_MODERN_ITER   (1U << 1)
+
+/* The modern sync, which is used for CPU throttle only */
+#define RAMBLOCK_SYN_MODERN_BACKGROUND(1U << 2)
+
+#define RAMBLOCK_SYN_MASK  (0x7)
+
+typedef enum RAMBlockSynMode {
+RAMBLOCK_SYN_LEGACY, /* Old-fashined mode */
+RAMBLOCK_SYN_MODERN, /* Background-sync-supported mode */
+} RAMBlockSynMode;
+
 struct RAMBlock {
 struct rcu_head rcu;
 struct MemoryRegion *mr;
@@ -89,6 +113,27 @@ struct RAMBlock {
  * could not have been valid on the source.
  */
 ram_addr_t postcopy_length;
+
+/*
+ * Used to backup the bmap during background sync to see whether any dirty
+ * pages were sent during that time.
+ */
+unsigned long *shadow_bmap;
+
+/*
+ * The bitmap "bmap," which was initially used for both sync and memory
+ * transfer, will be replaced by two bitmaps: the previously used "bmap"
+ * and the recently added "iter_bmap." Only the memory transfer is
+ * conducted with the previously used "bmap"; the recently added
+ * "iter_bmap" is utilized for dirty bitmap sync.
+ */
+unsigned long *iter_bmap;
+
+/* Number of new dirty pages during iteration */
+uint64_t iter_dirty_pages;
+
+/* If background sync has shown up during iteration */
+bool background_sync_shown_up;
 };
 #endif
 #endif
diff --git a/migration/ram.c b/migration/ram.c
index 67ca3d5d51..f29faa82d6 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -2362,6 +2362,10 @@ static void ram_bitmaps_destroy(void)
 block->bmap = NULL;
 g_free(block->file_bmap);
 block->file_bmap = NULL;
+g_free(block->shadow_bmap);
+block->shadow_bmap = NULL;
+g_free(block->iter_bmap);
+block->iter_bmap = NULL;
 }
 }
 
@@ -2753,6 +2757,8 @@ static void ram_list_init_bitmaps(void)
 }
 block->clear_bmap_shift = shift;
 block->clear_bmap = bitmap_new(clear_bmap_size(pages, shift));
+block->shadow_bmap = bitmap_new(pages);
+block->iter_bmap = bitmap_new(pages);
 }
 }
 }
-- 
2.39.1




[PATCH v1 5/7] migration: Support background dirty bitmap sync and throttle

2024-09-15 Thread 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 background sync and throttle aim to fix the above issue by
synchronizing the remote dirty bitmap and triggering the throttle
once detect that iteration lasts a long time.

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

Signed-off-by: Hyman Huang 
---
 migration/migration.c| 12 +++
 tests/qtest/migration-test.c | 39 
 2 files changed, 51 insertions(+)

diff --git a/migration/migration.c b/migration/migration.c
index 055d527ff6..af8b22fa15 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -1416,6 +1416,7 @@ static void migrate_fd_cleanup(MigrationState *s)
 
 trace_migrate_fd_cleanup();
 bql_unlock();
+migration_background_sync_cleanup();
 if (s->migration_thread_running) {
 qemu_thread_join(&s->thread);
 s->migration_thread_running = false;
@@ -3263,6 +3264,7 @@ static MigIterateState 
migration_iteration_run(MigrationState *s)
 
 if ((!pending_size || pending_size < s->threshold_size) && can_switchover) 
{
 trace_migration_thread_low_pending(pending_size);
+migration_background_sync_cleanup();
 migration_completion(s);
 return MIG_ITERATE_BREAK;
 }
@@ -3508,6 +3510,16 @@ static void *migration_thread(void *opaque)
 ret = qemu_savevm_state_setup(s->to_dst_file, &local_err);
 bql_unlock();
 
+if (!migrate_dirty_limit()) {
+/*
+ * Initiate the background sync watcher in order to guarantee
+ * that the CPU throttling acts appropriately. Dirty Limit
+ * doesn't use CPU throttle to make guest down, so ignore that
+ * case.
+ */
+migration_background_sync_setup();
+}
+
 qemu_savevm_wait_unplug(s, MIGRATION_STATUS_SETUP,
MIGRATION_STATUS_ACTIVE);
 
diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index b796a90cad..e0e94d26be 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -281,6 +281,11 @@ static uint64_t get_migration_pass(QTestState *who)
 return read_ram_property_int(who, "iteration-count");
 }
 
+static uint64_t get_dirty_sync_count(QTestState *who)
+{
+return read_ram_property_int(who, "dirty-sync-count");
+}
+
 static void read_blocktime(QTestState *who)
 {
 QDict *rsp_return;
@@ -468,6 +473,12 @@ static void migrate_ensure_converge(QTestState *who)
 migrate_set_parameter_int(who, "downtime-limit", 30 * 1000);
 }
 
+static void migrate_ensure_iteration_last_long(QTestState *who)
+{
+/* Set 10Byte/s bandwidth limit to make the iteration last long enough */
+migrate_set_parameter_int(who, "max-bandwidth", 10);
+}
+
 /*
  * Our goal is to ensure that we run a single full migration
  * iteration, and also dirty memory, ensuring that at least
@@ -2791,6 +2802,10 @@ 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_iter_cnt = 0, iter_cnt;
+uint64_t iter_cnt_changes = 0;
+uint64_t prev_dirty_sync_cnt = 0, dirty_sync_cnt;
+uint64_t dirty_sync_cnt_changes = 0;
 
 if (test_migrate_start(&from, &to, uri, &args)) {
 return;
@@ -2827,6 +2842,30 @@ 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);
+
+/* Make sure the iteration take a long time enough */
+migrate_ensure_iteration_last_long(from);
+
+/*
+ * End the loop when the dirty sync count or iteration count changes.
+ */
+while (iter_cnt_changes < 2 && dirty_sync_cnt_changes < 2) {
+usleep(1000 * 1000);
+iter_cnt = get_migration_pass(from);
+iter_cnt_changes += (iter_cnt != prev_iter_cnt);
+prev_iter_cnt = iter_cnt;
+
+dirty_sync_cnt = get_dirty_sync_count(from);
+dirty_sync_cnt_changes += (dirty_sync_cnt != prev_dirty_sync_cnt);
+prev_dirty_sync_cnt = dirty_sync_cnt;
+}
+
+/*
+ * The dirty sync count must have changed because we are in the same
+ * iteration.
+ */
+g_assert_cmpint(iter_cnt_changes , < , dirty_sync_cnt_changes);
+
 /* Now, when we tested that throttling works, let it converge */
 migrate_ensure_converge(from);
 
-- 
2.39.1




[PATCH v1 2/7] migration: Refine util functions to support background sync

2024-09-15 Thread Hyman Huang
Supply the migration_bitmap_sync function along with the
background argument. Introduce the sync_mode global variable
to track the sync mode and support background sync while
keeping backward compatibility.

Signed-off-by: Hyman Huang 
---
 include/exec/ram_addr.h | 107 +---
 migration/ram.c |  53 
 2 files changed, 144 insertions(+), 16 deletions(-)

diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
index 891c44cf2d..d0d123ac60 100644
--- a/include/exec/ram_addr.h
+++ b/include/exec/ram_addr.h
@@ -472,17 +472,68 @@ static inline void 
cpu_physical_memory_clear_dirty_range(ram_addr_t start,
 cpu_physical_memory_test_and_clear_dirty(start, length, DIRTY_MEMORY_CODE);
 }
 
+static void ramblock_clear_iter_bmap(RAMBlock *rb,
+ ram_addr_t start,
+ ram_addr_t length)
+{
+ram_addr_t addr;
+unsigned long *bmap = rb->bmap;
+unsigned long *shadow_bmap = rb->shadow_bmap;
+unsigned long *iter_bmap = rb->iter_bmap;
+
+for (addr = 0; addr < length; addr += TARGET_PAGE_SIZE) {
+long k = (start + addr) >> TARGET_PAGE_BITS;
+if (test_bit(k, shadow_bmap) && !test_bit(k, bmap)) {
+/* Page has been sent, clear the iter bmap */
+clear_bit(k, iter_bmap);
+}
+}
+}
+
+static void ramblock_update_iter_bmap(RAMBlock *rb,
+  ram_addr_t start,
+  ram_addr_t length)
+{
+ram_addr_t addr;
+unsigned long *bmap = rb->bmap;
+unsigned long *iter_bmap = rb->iter_bmap;
+
+for (addr = 0; addr < length; addr += TARGET_PAGE_SIZE) {
+long k = (start + addr) >> TARGET_PAGE_BITS;
+if (test_bit(k, iter_bmap)) {
+if (!test_bit(k, bmap)) {
+set_bit(k, bmap);
+rb->iter_dirty_pages++;
+}
+}
+}
+}
 
 /* Called with RCU critical section */
 static inline
 uint64_t cpu_physical_memory_sync_dirty_bitmap(RAMBlock *rb,
ram_addr_t start,
-   ram_addr_t length)
+   ram_addr_t length,
+   unsigned int flag)
 {
 ram_addr_t addr;
 unsigned long word = BIT_WORD((start + rb->offset) >> TARGET_PAGE_BITS);
 uint64_t num_dirty = 0;
 unsigned long *dest = rb->bmap;
+unsigned long *shadow_bmap = rb->shadow_bmap;
+unsigned long *iter_bmap = rb->iter_bmap;
+
+assert(flag && !(flag & (~RAMBLOCK_SYN_MASK)));
+
+/*
+ * We must remove the sent dirty page from the iter_bmap in order to
+ * minimize redundant page transfers if background sync has appeared
+ * during this iteration.
+ */
+if (rb->background_sync_shown_up &&
+(flag & (RAMBLOCK_SYN_MODERN_ITER | RAMBLOCK_SYN_MODERN_BACKGROUND))) {
+ramblock_clear_iter_bmap(rb, start, length);
+}
 
 /* start address and length is aligned at the start of a word? */
 if (((word * BITS_PER_LONG) << TARGET_PAGE_BITS) ==
@@ -503,8 +554,20 @@ uint64_t cpu_physical_memory_sync_dirty_bitmap(RAMBlock 
*rb,
 if (src[idx][offset]) {
 unsigned long bits = qatomic_xchg(&src[idx][offset], 0);
 unsigned long new_dirty;
+if (flag & (RAMBLOCK_SYN_MODERN_ITER |
+RAMBLOCK_SYN_MODERN_BACKGROUND)) {
+/* Back-up bmap for the next iteration */
+iter_bmap[k] |= bits;
+if (flag == RAMBLOCK_SYN_MODERN_BACKGROUND) {
+/* Back-up bmap to detect pages has been sent */
+shadow_bmap[k] = dest[k];
+}
+}
 new_dirty = ~dest[k];
-dest[k] |= bits;
+if (flag == RAMBLOCK_SYN_LEGACY_ITER) {
+dest[k] |= bits;
+}
+
 new_dirty &= bits;
 num_dirty += ctpopl(new_dirty);
 }
@@ -534,18 +597,50 @@ uint64_t cpu_physical_memory_sync_dirty_bitmap(RAMBlock 
*rb,
 ram_addr_t offset = rb->offset;
 
 for (addr = 0; addr < length; addr += TARGET_PAGE_SIZE) {
-if (cpu_physical_memory_test_and_clear_dirty(
+bool dirty = false;
+long k = (start + addr) >> TARGET_PAGE_BITS;
+if (flag == RAMBLOCK_SYN_MODERN_BACKGROUND) {
+if (test_bit(k, dest)) {
+/* Back-up bmap to detect pages has been sent */
+set_bit(k, shadow_bmap);
+}
+}
+
+dirty = cpu_physical_memory_test_and_clear_dirty(
 start + addr + offset,
 TARGET_PAGE_SIZE,
-DIRTY_MEMORY_MIGRATION)) {
-l

[PATCH v1 4/7] migration: Implment background sync watcher

2024-09-15 Thread Hyman Huang
The background sync watcher is used to detect that if the
iteration lasts a long time, if so, trigger the background
sync.

Signed-off-by: Hyman Huang 
---
 migration/ram.c| 110 +
 migration/ram.h|   3 ++
 migration/trace-events |   3 ++
 3 files changed, 116 insertions(+)

diff --git a/migration/ram.c b/migration/ram.c
index ca5a1b5f16..799eaa0382 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -416,6 +416,11 @@ struct RAMState {
  * RAM migration.
  */
 unsigned int postcopy_bmap_sync_requested;
+
+/* Background throttle information */
+bool background_sync_running;
+QemuThread background_sync_thread;
+QemuSemaphore quit_sem;
 };
 typedef struct RAMState RAMState;
 
@@ -1125,6 +1130,111 @@ static void migration_bitmap_sync(RAMState *rs,
 }
 }
 
+/*
+ * Iteration lasting more than five seconds is undesirable;
+ * launch a background dirty bitmap sync.
+ */
+#define MIGRATION_MAX_ITERATION_DURATION  5
+
+static void *migration_background_sync_watcher(void *opaque)
+{
+RAMState *rs = opaque;
+uint64_t iter_cnt, prev_iter_cnt = 2;
+bool iter_cnt_unchanged = false;
+int max_pct = migrate_max_cpu_throttle();
+
+trace_migration_background_sync_watcher_start();
+rcu_register_thread();
+
+while (qatomic_read(&rs->background_sync_running)) {
+int cur_pct = cpu_throttle_get_percentage();
+if ((cur_pct == max_pct) || (!migration_is_active())) {
+break;
+}
+
+if (qemu_sem_timedwait(&rs->quit_sem, 1000) == 0) {
+/* We were woken by background_sync_cleanup, quit */
+break;
+}
+
+/*
+ * 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.
+ */
+iter_cnt = stat64_get(&mig_stats.iteration_count);
+if (iter_cnt <= 1) {
+continue;
+}
+
+iter_cnt_unchanged = (iter_cnt == prev_iter_cnt);
+prev_iter_cnt = iter_cnt;
+
+if (iter_cnt_unchanged) {
+int64_t curr_time, iter_duration;
+
+curr_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
+iter_duration = curr_time - rs->time_last_bitmap_sync;
+
+if (iter_duration >
+MIGRATION_MAX_ITERATION_DURATION * 1000) {
+sync_mode = RAMBLOCK_SYN_MODERN;
+bql_lock();
+trace_migration_background_sync();
+WITH_RCU_READ_LOCK_GUARD() {
+migration_bitmap_sync(rs, false, true);
+}
+bql_unlock();
+}
+}
+}
+
+qatomic_set(&rs->background_sync_running, 0);
+
+rcu_unregister_thread();
+trace_migration_background_sync_watcher_end();
+
+return NULL;
+}
+
+void migration_background_sync_setup(void)
+{
+RAMState *rs = ram_state;
+
+if (!rs) {
+return;
+}
+
+if (qatomic_read(&rs->background_sync_running)) {
+return;
+}
+
+qemu_sem_init(&rs->quit_sem, 0);
+qatomic_set(&rs->background_sync_running, 1);
+
+qemu_thread_create(&rs->background_sync_thread,
+   NULL, migration_background_sync_watcher,
+   rs, QEMU_THREAD_JOINABLE);
+}
+
+void migration_background_sync_cleanup(void)
+{
+RAMState *rs = ram_state;
+
+if (!rs) {
+return;
+}
+
+if (!qatomic_read(&rs->background_sync_running)) {
+return;
+}
+
+qatomic_set(&rs->background_sync_running, 0);
+qemu_sem_post(&rs->quit_sem);
+qemu_thread_join(&rs->background_sync_thread);
+qemu_sem_destroy(&rs->quit_sem);
+}
+
 static void migration_bitmap_sync_precopy(RAMState *rs, bool last_stage)
 {
 Error *local_err = NULL;
diff --git a/migration/ram.h b/migration/ram.h
index bc0318b834..0315d22a66 100644
--- a/migration/ram.h
+++ b/migration/ram.h
@@ -93,4 +93,7 @@ void ram_write_tracking_prepare(void);
 int ram_write_tracking_start(void);
 void ram_write_tracking_stop(void);
 
+/* Migration background sync */
+void migration_background_sync_setup(void);
+void migration_background_sync_cleanup(void);
 #endif
diff --git a/migration/trace-events b/migration/trace-events
index c65902f042..4f95f9fe14 100644
--- a/migration/trace-events
+++ b/migration/trace-events
@@ -92,6 +92,9 @@ qemu_file_fclose(void) ""
 # ram.c
 get_queued_page(const char *block_name, uint64_t tmp_offset, unsigned long 
page_abs) "%s/0x%" PRIx64 " page_abs=0x%lx"
 get_queued_page_not_dirty(const char *block_name, uint64_t tmp_offset, 
unsigned long page_abs) "%s/0x%" PRIx64 " page_abs=0x%lx"
+migration_background_sync(void) ""
+migration_background_sync_watcher_start(void) ""
+migration_background_sync_watcher_end(void) ""
 migration_bitmap_sync_start(void) ""
 migration_bitmap_sync_end(uint64_t dirty_pages) "dirty_pages %" PRIu64
 migration_bitmap_clear

[PATCH v1 0/7] migration: auto-converge refinements for huge VM

2024-09-15 Thread Hyman Huang
This is the first version for auto-converge refinements; refer to the
following link for details about the RFC version:
https://patchew.org/QEMU/cover.1725891841.git.yong.hu...@smartx.com/

This series introduces two refinements called "background sync" and
"responsive throttle," respectively.

1. background sync:

   The original auto-converge throttle logic doesn't look like it will
   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 background sync would fix this issue by implementing the background
   dirty bitmap sync and throttle automatically once detect that
   the iteration lasts a long time during the migration.

   The background sync is implemented transparently, and there is no
   new-added interface for upper apps.

2. responsive throttle: 

   The original auto-converge throttle logic determines if the migration
   is convergent by one criteria, and if the iteration fits twice, then
   launch the CPU throttle or increase the throttle percentage. This
   results in that the migration_trigger_throttle() won't be invoked for
   a long time if one iteration can take a long time too.

   The responsive throttle introduce one more criteria to assist detecting
   the convergence of the migration, if either of the two criteria is
   met, migration_trigger_throttle() would be called. This also makes it
   more likely that the CPU throttle will be activated, thereby
   accelerating the migration process.

   The responsive throttle provides the 'cpu-responsive-throttle' option
   to enable this feature. 

We test this two features with the following environment:

a. Test tool:
guestperf

Refer to the following link to see details:
https://github.com/qemu/qemu/tree/master/tests/migration/guestperf

b. Test VM scale:
CPU: 16; Memory: 100GB

c. Average bandwidth between source and destination for migration:
1.59 Gbits/sec

We use stress tool contained in the initrd-stress.img to update
ramsize MB on every CPU in guest, refer to the following link to
see the source code:
https://github.com/qemu/qemu/blob/master/tests/migration/stress.c

The following command is executed to compare our refined QEMU with the
original QEMU:
# python3.6 guestperf.py --binary /path/to/qemu-kvm --cpus 16 \
--mem 100 --max-iters 200 --max-time 1200  --dst-host {dst_ip} \
--kernel /path/to/vmlinuz --initrd /path/to/initrd-stress.img \
--transport tcp --downtime 500 --auto-converge --auto-converge-step 10 \
--verbose --stress-mem {ramsize} 

We set ramsize to 150MB to simulate the light load, 3000MB as moderate
load and 5000MB as heavy load. Test cases were executed three times in
each scenario.  

The following data shows the migration test results with an increase in
stress.

ramsize: 150MB
|+---+--+---+--|
|| totaltime | downtime | iteration | max throttle |
|| (ms)  | (ms) | count | percent  |
|+---+--+---+--|
| original   | 123685| 490  | 87| 99%  |
|| 116249| 542  | 45| 60%  |  
|| 107772| 587  | 8 | 0%   | 
|+---+--+---+--|
| background | 113744| 1654 | 16| 20%  | 
| sync   | 122623| 758  | 60| 80%  | 
|| 112668| 547  | 23| 20%  | 
|+---+--+---+--|
| background | 113660| 573  | 5 | 0%   | 
| sync + | 109357| 576  | 6 | 0%   | 
| responsive | 126792| 494  | 37| 99%  | 
| throttle   |   |  |   |  | 
|+---+--+---+--|

ramsize: 3000MB
|+---+--+---+--|
|| totaltime | downtime | iteration | max throttle |
|| (ms)  | (ms) | count | percent  |
|+---+--+---+--|
| original   | 404398| 515  | 26| 99%  |
|| 392552| 528  | 25| 99%  | 
|| 400113| 447  | 24| 99%  | 
|+---+--+---+--|
| background | 239151| 681  | 25| 99%  | 
| sync   | 295047| 587  | 41| 99%  | 
|| 289936| 681  | 34| 99%  | 
|+---+--+---+--|
| background | 212786| 487  | 22| 99%  | 
| sync + | 225246| 666  | 23| 99%  | 
| responsive | 244053| 572  | 27| 99%  | 
| throttle   |   |  | 

[PATCH v1 6/7] qapi/migration: Introduce cpu-responsive-throttle parameter

2024-09-15 Thread Hyman Huang
To enable the responsive throttle that will be implemented
in the next commit, introduce the cpu-responsive-throttle
parameter.

Signed-off-by: Hyman Huang 
---
 migration/migration-hmp-cmds.c |  8 
 migration/options.c| 20 
 migration/options.h|  1 +
 qapi/migration.json| 16 +++-
 4 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/migration/migration-hmp-cmds.c b/migration/migration-hmp-cmds.c
index 28165cfc9e..1fe6c74d66 100644
--- a/migration/migration-hmp-cmds.c
+++ b/migration/migration-hmp-cmds.c
@@ -264,6 +264,10 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict 
*qdict)
 monitor_printf(mon, "%s: %s\n",
 MigrationParameter_str(MIGRATION_PARAMETER_CPU_THROTTLE_TAILSLOW),
 params->cpu_throttle_tailslow ? "on" : "off");
+assert(params->has_cpu_responsive_throttle);
+monitor_printf(mon, "%s: %s\n",
+
MigrationParameter_str(MIGRATION_PARAMETER_CPU_RESPONSIVE_THROTTLE),
+params->cpu_responsive_throttle ? "on" : "off");
 assert(params->has_max_cpu_throttle);
 monitor_printf(mon, "%s: %u\n",
 MigrationParameter_str(MIGRATION_PARAMETER_MAX_CPU_THROTTLE),
@@ -512,6 +516,10 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict 
*qdict)
 p->has_cpu_throttle_tailslow = true;
 visit_type_bool(v, param, &p->cpu_throttle_tailslow, &err);
 break;
+case MIGRATION_PARAMETER_CPU_RESPONSIVE_THROTTLE:
+p->has_cpu_responsive_throttle = true;
+visit_type_bool(v, param, &p->cpu_responsive_throttle, &err);
+break;
 case MIGRATION_PARAMETER_MAX_CPU_THROTTLE:
 p->has_max_cpu_throttle = true;
 visit_type_uint8(v, param, &p->max_cpu_throttle, &err);
diff --git a/migration/options.c b/migration/options.c
index 147cd2b8fd..b4c269bf1d 100644
--- a/migration/options.c
+++ b/migration/options.c
@@ -111,6 +111,8 @@ Property migration_properties[] = {
   DEFAULT_MIGRATE_CPU_THROTTLE_INCREMENT),
 DEFINE_PROP_BOOL("x-cpu-throttle-tailslow", MigrationState,
   parameters.cpu_throttle_tailslow, false),
+DEFINE_PROP_BOOL("x-cpu-responsive-throttle", MigrationState,
+  parameters.cpu_responsive_throttle, false),
 DEFINE_PROP_SIZE("x-max-bandwidth", MigrationState,
   parameters.max_bandwidth, MAX_THROTTLE),
 DEFINE_PROP_SIZE("avail-switchover-bandwidth", MigrationState,
@@ -705,6 +707,13 @@ uint8_t migrate_cpu_throttle_initial(void)
 return s->parameters.cpu_throttle_initial;
 }
 
+bool migrate_responsive_throttle(void)
+{
+MigrationState *s = migrate_get_current();
+
+return s->parameters.cpu_responsive_throttle;
+}
+
 bool migrate_cpu_throttle_tailslow(void)
 {
 MigrationState *s = migrate_get_current();
@@ -891,6 +900,8 @@ MigrationParameters *qmp_query_migrate_parameters(Error 
**errp)
 params->cpu_throttle_increment = s->parameters.cpu_throttle_increment;
 params->has_cpu_throttle_tailslow = true;
 params->cpu_throttle_tailslow = s->parameters.cpu_throttle_tailslow;
+params->has_cpu_responsive_throttle = true;
+params->cpu_responsive_throttle = s->parameters.cpu_responsive_throttle;
 params->tls_creds = g_strdup(s->parameters.tls_creds);
 params->tls_hostname = g_strdup(s->parameters.tls_hostname);
 params->tls_authz = g_strdup(s->parameters.tls_authz ?
@@ -959,6 +970,7 @@ void migrate_params_init(MigrationParameters *params)
 params->has_cpu_throttle_initial = true;
 params->has_cpu_throttle_increment = true;
 params->has_cpu_throttle_tailslow = true;
+params->has_cpu_responsive_throttle = true;
 params->has_max_bandwidth = true;
 params->has_downtime_limit = true;
 params->has_x_checkpoint_delay = true;
@@ -1191,6 +1203,10 @@ static void 
migrate_params_test_apply(MigrateSetParameters *params,
 dest->cpu_throttle_tailslow = params->cpu_throttle_tailslow;
 }
 
+if (params->has_cpu_responsive_throttle) {
+dest->cpu_responsive_throttle = params->cpu_responsive_throttle;
+}
+
 if (params->tls_creds) {
 assert(params->tls_creds->type == QTYPE_QSTRING);
 dest->tls_creds = params->tls_creds->u.s;
@@ -1302,6 +1318,10 @@ static void migrate_params_apply(MigrateSetParameters 
*params, Error **errp)
 s->parameters.cpu_throttle_tailslow = params->cpu_throttle_tailslow;
 }
 
+if (params->has_cpu_responsive_throttle) {
+s->parameters.cpu_responsive_throttle = 
params->cpu_responsive_throttle;
+}
+
 if (params->tls_creds) {
 g_free(s->parameters.tls_creds);
 assert(params->tls_creds->type == QTYPE_QSTRING);
diff --git a/migration/options.h b/migration/options.h
index a0bd6edc06..80d0fcdaf9 100644
--- a/migration/options.h
+++ b/migration/options.h
@@ -68,6 +68,7 @@ bool migrate_has_block_bitmap_mapping(void);
 uin

[PATCH v1 3/7] qapi/migration: Introduce the iteration-count

2024-09-15 Thread Hyman Huang
The original migration information dirty-sync-count could
no longer reflect iteration count due to the introduction
of background synchronization in the next commit;
add the iteration count to compensate.

Signed-off-by: Hyman Huang 
---
 migration/migration-stats.h  |  4 
 migration/migration.c|  1 +
 migration/ram.c  | 12 
 qapi/migration.json  |  6 +-
 tests/qtest/migration-test.c |  2 +-
 5 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/migration/migration-stats.h b/migration/migration-stats.h
index 05290ade76..43ee0f4f05 100644
--- a/migration/migration-stats.h
+++ b/migration/migration-stats.h
@@ -50,6 +50,10 @@ typedef struct {
  * Number of times we have synchronized guest bitmaps.
  */
 Stat64 dirty_sync_count;
+/*
+ * Number of migration iteration processed.
+ */
+Stat64 iteration_count;
 /*
  * Number of times zero copy failed to send any page using zero
  * copy.
diff --git a/migration/migration.c b/migration/migration.c
index 3dea06d577..055d527ff6 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -1197,6 +1197,7 @@ static void populate_ram_info(MigrationInfo *info, 
MigrationState *s)
 info->ram->mbps = s->mbps;
 info->ram->dirty_sync_count =
 stat64_get(&mig_stats.dirty_sync_count);
+info->ram->iteration_count = stat64_get(&mig_stats.iteration_count);
 info->ram->dirty_sync_missed_zero_copy =
 stat64_get(&mig_stats.dirty_sync_missed_zero_copy);
 info->ram->postcopy_requests =
diff --git a/migration/ram.c b/migration/ram.c
index e205806a5f..ca5a1b5f16 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -594,7 +594,7 @@ static void xbzrle_cache_zero_page(ram_addr_t current_addr)
 /* We don't care if this fails to allocate a new cache page
  * as long as it updated an old one */
 cache_insert(XBZRLE.cache, current_addr, XBZRLE.zero_target_page,
- stat64_get(&mig_stats.dirty_sync_count));
+ stat64_get(&mig_stats.iteration_count));
 }
 
 #define ENCODING_FLAG_XBZRLE 0x1
@@ -620,7 +620,7 @@ static int save_xbzrle_page(RAMState *rs, PageSearchStatus 
*pss,
 int encoded_len = 0, bytes_xbzrle;
 uint8_t *prev_cached_page;
 QEMUFile *file = pss->pss_channel;
-uint64_t generation = stat64_get(&mig_stats.dirty_sync_count);
+uint64_t generation = stat64_get(&mig_stats.iteration_count);
 
 if (!cache_is_cached(XBZRLE.cache, current_addr, generation)) {
 xbzrle_counters.cache_miss++;
@@ -1079,6 +1079,10 @@ static void migration_bitmap_sync(RAMState *rs,
 RAMBlock *block;
 int64_t end_time;
 
+if (!background) {
+stat64_add(&mig_stats.iteration_count, 1);
+}
+
 stat64_add(&mig_stats.dirty_sync_count, 1);
 
 if (!rs->time_last_bitmap_sync) {
@@ -1115,8 +1119,8 @@ static void migration_bitmap_sync(RAMState *rs,
 rs->num_dirty_pages_period = 0;
 rs->bytes_xfer_prev = migration_transferred_bytes();
 }
-if (migrate_events()) {
-uint64_t generation = stat64_get(&mig_stats.dirty_sync_count);
+if (!background && migrate_events()) {
+uint64_t generation = stat64_get(&mig_stats.iteration_count);
 qapi_event_send_migration_pass(generation);
 }
 }
diff --git a/qapi/migration.json b/qapi/migration.json
index b66cccf107..95b490706c 100644
--- a/qapi/migration.json
+++ b/qapi/migration.json
@@ -60,6 +60,9 @@
 # between 0 and @dirty-sync-count * @multifd-channels.  (since
 # 7.1)
 #
+# @iteration-count: The number of iterations since migration started.
+# (since 9.2)
+#
 # Since: 0.14
 ##
 { 'struct': 'MigrationStats',
@@ -72,7 +75,8 @@
'multifd-bytes': 'uint64', 'pages-per-second': 'uint64',
'precopy-bytes': 'uint64', 'downtime-bytes': 'uint64',
'postcopy-bytes': 'uint64',
-   'dirty-sync-missed-zero-copy': 'uint64' } }
+   'dirty-sync-missed-zero-copy': 'uint64',
+   'iteration-count' : 'int' } }
 
 ##
 # @XBZRLECacheStats:
diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index d6768d5d71..b796a90cad 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -278,7 +278,7 @@ static int64_t read_migrate_property_int(QTestState *who, 
const char *property)
 
 static uint64_t get_migration_pass(QTestState *who)
 {
-return read_ram_property_int(who, "dirty-sync-count");
+return read_ram_property_int(who, "iteration-count");
 }
 
 static void read_blocktime(QTestState *who)
-- 
2.39.1




[PATCH v1 7/7] migration: Support responsive CPU throttle

2024-09-15 Thread Hyman Huang
Currently, the convergence algorithm determines that the migration
cannot converge according to the following principle:
The dirty pages generated in current iteration exceed a specific
percentage (throttle-trigger-threshold, 50 by default) of the number
of transmissions. Let's refer to this criteria as the "dirty rate".
If this criteria is met more than or equal to twice
(dirty_rate_high_cnt >= 2), the throttle percentage increased.

In most cases, above implementation is appropriate. However, for a
VM with high memory overload, each iteration is time-consuming.
The VM's computing performance may be throttled at a high percentage
and last for a long time due to the repeated confirmation behavior.
Which may be intolerable for some computationally sensitive software
in the VM.

As the comment mentioned in the migration_trigger_throttle function,
in order to avoid erroneous detection, the original algorithm confirms
the criteria repeatedly. Put differently, the criteria does not need
to be validated again once the detection is more reliable.

In the refinement, in order to make the detection more accurate, we
introduce another criteria, called the "dirty ratio" to determine
the migration convergence. The "dirty ratio" is the ratio of
bytes_xfer_period and bytes_dirty_period. When the algorithm
repeatedly detects that the "dirty ratio" of current sync is lower
than the previous, the algorithm determines that the migration cannot
converge. For the "dirty rate" and "dirty ratio", if one of the two
criteria is met, the penalty percentage would be increased. This
makes CPU throttle more responsively and therefor saves the time of
the entire iteration and therefore reduces the time of VM performance
degradation.

In conclusion, this refinement significantly reduces the processing
time required for the throttle percentage step to its maximum while
the VM is under a high memory load.

Signed-off-by: Hyman Huang 
---
 migration/ram.c  | 55 ++--
 migration/trace-events   |  1 +
 tests/qtest/migration-test.c |  1 +
 3 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/migration/ram.c b/migration/ram.c
index 799eaa0382..8d856a89db 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -421,6 +421,12 @@ struct RAMState {
 bool background_sync_running;
 QemuThread background_sync_thread;
 QemuSemaphore quit_sem;
+
+/*
+ * Ratio of bytes_dirty_period and bytes_xfer_period in the
+ * previous sync.
+ */
+uint64_t dirty_ratio_pct;
 };
 typedef struct RAMState RAMState;
 
@@ -1049,6 +1055,43 @@ static void migration_dirty_limit_guest(void)
 trace_migration_dirty_limit_guest(quota_dirtyrate);
 }
 
+static bool migration_dirty_ratio_high(RAMState *rs)
+{
+static int dirty_ratio_high_cnt;
+uint64_t threshold = migrate_throttle_trigger_threshold();
+uint64_t bytes_xfer_period =
+migration_transferred_bytes() - rs->bytes_xfer_prev;
+uint64_t bytes_dirty_period = rs->num_dirty_pages_period * 
TARGET_PAGE_SIZE;
+bool dirty_ratio_high = false;
+uint64_t prev, curr;
+
+/* Calculate the dirty ratio percentage */
+curr = 100 * (bytes_dirty_period * 1.0 / bytes_xfer_period);
+
+prev = rs->dirty_ratio_pct;
+rs->dirty_ratio_pct = curr;
+
+if (prev == 0) {
+return false;
+}
+
+/*
+ * If current dirty ratio is greater than previouse, determine
+ * that the migration do not converge.
+ */
+if (curr > threshold && curr >= prev) {
+trace_migration_dirty_ratio_high(curr, prev);
+dirty_ratio_high_cnt++;
+}
+
+if (dirty_ratio_high_cnt >= 2) {
+dirty_ratio_high = true;
+dirty_ratio_high_cnt = 0;
+}
+
+return dirty_ratio_high;
+}
+
 static void migration_trigger_throttle(RAMState *rs)
 {
 uint64_t threshold = migrate_throttle_trigger_threshold();
@@ -1056,6 +1099,11 @@ static void migration_trigger_throttle(RAMState *rs)
 migration_transferred_bytes() - rs->bytes_xfer_prev;
 uint64_t bytes_dirty_period = rs->num_dirty_pages_period * 
TARGET_PAGE_SIZE;
 uint64_t bytes_dirty_threshold = bytes_xfer_period * threshold / 100;
+bool dirty_ratio_high = false;
+
+if (migrate_responsive_throttle() && (bytes_xfer_period != 0)) {
+dirty_ratio_high = migration_dirty_ratio_high(rs);
+}
 
 /*
  * The following detection logic can be refined later. For now:
@@ -1065,8 +1113,11 @@ static void migration_trigger_throttle(RAMState *rs)
  * twice, start or increase throttling.
  */
 if ((bytes_dirty_period > bytes_dirty_threshold) &&
-(++rs->dirty_rate_high_cnt >= 2)) {
-rs->dirty_rate_high_cnt = 0;
+((++rs->dirty_rate_high_cnt >= 2) || dirty_ratio_high)) {
+
+rs->dirty_rate_high_cnt =
+rs->dirty_rate_high_cnt >= 2 ? 0 : rs->dirty_rate_high_cnt;
+
 if (migrate_auto_converge()) {
 trace_migration_throttle();
 mig_t

[PATCH] qom: fix NULL pointer in object_initialize_with_type()

2024-09-15 Thread alexjlzheng
From: Jinliang Zheng 

Currently, object_initialize_with_type() calls object_class_property_init_all()
before initializing Object->properties. This may cause Object->properties to
still be NULL when we call object_property_add() on Object.

For exmaple, if we extend DEFINE_PROP_ARRAY() to a version with a default value
other than 0:
#define DEFINE_PROP_ARRAY_EXAMPLE(_name, _state, _field,\
_arrayfield, _arrayprop, _arraytype)\
DEFINE_PROP((PROP_ARRAY_LEN_PREFIX _name),  \
_state, _field, qdev_prop_arraylen_virtio_net,  \
uint32_t,   \
.set_default = true,\
.defval.u = , \
.arrayinfo = &(_arrayprop), \
.arrayfieldsize = sizeof(_arraytype),   \
.arrayoffset = offsetof(_state, _arrayfield))
We should have:
object_initialize_with_type
  object_class_property_init_all
ObjectProperty->init() / object_property_init_defval
  ...
set_prop_arraylen
  object_property_add
object_property_try_add
  g_hash_table_insert(Object->properties)   <- NULL
  obj->properties = g_hash_table_new_full() <- initializing

This patch fixes the above problem by exchanging the order of Ojbect->properties
initialization and object_class_property_init_all().

Signed-off-by: Jinliang Zheng 
---
 qom/object.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/qom/object.c b/qom/object.c
index 157a45c5f8..734b52f048 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -556,9 +556,9 @@ static void object_initialize_with_type(Object *obj, size_t 
size, TypeImpl *type
 memset(obj, 0, type->instance_size);
 obj->class = type->class;
 object_ref(obj);
-object_class_property_init_all(obj);
 obj->properties = g_hash_table_new_full(g_str_hash, g_str_equal,
 NULL, object_property_free);
+object_class_property_init_all(obj);
 object_init_with_type(obj, type);
 object_post_init_with_type(obj, type);
 }
-- 
2.41.1




Re: [PATCH v6 0/8] AWS Nitro Enclave emulation support

2024-09-15 Thread Dorjoy Chowdhury
ping

Requesting for review on this patch series. The first 3 patches have
been merged by Daniel but the rest need to be reviewed. Thanks!
patch URL: 
https://lore.kernel.org/qemu-devel/20240905195735.16911-1-dorjoychy...@gmail.com/T/#t

Regards,
Dorjoy



Re: [PATCH v6 5/8] device/virtio-nsm: Support for Nitro Secure Module device

2024-09-15 Thread Michael S. Tsirkin
On Fri, Sep 06, 2024 at 01:57:32AM +0600, Dorjoy Chowdhury wrote:
> Nitro Secure Module (NSM)[1] device is used in AWS Nitro Enclaves[2]
> for stripped down TPM functionality like cryptographic attestation.
> The requests to and responses from NSM device are CBOR[3] encoded.
> 
> This commit adds support for NSM device in QEMU. Although related to
> AWS Nitro Enclaves, the virito-nsm device is independent and can be
> used in other machine types as well. The libcbor[4] library has been
> used for the CBOR encoding and decoding functionalities.
> 
> [1] https://lists.oasis-open.org/archives/virtio-comment/202310/msg00387.html
> [2] https://docs.aws.amazon.com/enclaves/latest/user/nitro-enclave.html
> [3] http://cbor.io/
> [4] https://libcbor.readthedocs.io/en/latest/
> 
> Signed-off-by: Dorjoy Chowdhury 
> ---
>  MAINTAINERS  |   10 +
>  hw/virtio/Kconfig|5 +
>  hw/virtio/cbor-helpers.c |  326 ++
>  hw/virtio/meson.build|6 +
>  hw/virtio/virtio-nsm-pci.c   |   73 ++
>  hw/virtio/virtio-nsm.c   | 1665 ++
>  include/hw/virtio/cbor-helpers.h |   46 +
>  include/hw/virtio/virtio-nsm.h   |   59 ++
>  meson.build  |2 +
>  9 files changed, 2192 insertions(+)
>  create mode 100644 hw/virtio/cbor-helpers.c
>  create mode 100644 hw/virtio/virtio-nsm-pci.c
>  create mode 100644 hw/virtio/virtio-nsm.c
>  create mode 100644 include/hw/virtio/cbor-helpers.h
>  create mode 100644 include/hw/virtio/virtio-nsm.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index c14ac014e2..b371c24747 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2342,6 +2342,16 @@ F: include/sysemu/rng*.h
>  F: backends/rng*.c
>  F: tests/qtest/virtio-rng-test.c
>  
> +virtio-nsm
> +M: Alexander Graf 
> +M: Dorjoy Chowdhury 
> +S: Maintained
> +F: hw/virtio/cbor-helpers.c
> +F: hw/virtio/virtio-nsm.c
> +F: hw/virtio/virtio-nsm-pci.c
> +F: include/hw/virtio/cbor-helpers.h
> +F: include/hw/virtio/virtio-nsm.h
> +
>  vhost-user-stubs
>  M: Alex Bennée 
>  S: Maintained
> diff --git a/hw/virtio/Kconfig b/hw/virtio/Kconfig
> index aa63ff7fd4..29fee32035 100644
> --- a/hw/virtio/Kconfig
> +++ b/hw/virtio/Kconfig
> @@ -6,6 +6,11 @@ config VIRTIO_RNG
>  default y
>  depends on VIRTIO
>  
> +config VIRTIO_NSM
> +   bool
> +   default y
> +   depends on VIRTIO
> +
>  config VIRTIO_IOMMU
>  bool
>  default y
> diff --git a/hw/virtio/cbor-helpers.c b/hw/virtio/cbor-helpers.c
> new file mode 100644
> index 00..a0e58d6862
> --- /dev/null
> +++ b/hw/virtio/cbor-helpers.c
> @@ -0,0 +1,326 @@
> +/*
> + * QEMU CBOR helpers
> + *
> + * Copyright (c) 2024 Dorjoy Chowdhury 
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or
> + * (at your option) any later version.  See the COPYING file in the
> + * top-level directory.
> + */
> +
> +#include "hw/virtio/cbor-helpers.h"
> +
> +bool qemu_cbor_map_add(cbor_item_t *map, cbor_item_t *key, cbor_item_t 
> *value)
> +{
> +bool success = false;
> +struct cbor_pair pair = (struct cbor_pair) {
> +.key = cbor_move(key),
> +.value = cbor_move(value)
> +};
> +
> +success = cbor_map_add(map, pair);
> +if (!success) {
> +cbor_incref(pair.key);
> +cbor_incref(pair.value);
> +}
> +
> +return success;
> +}
> +
> +bool qemu_cbor_array_push(cbor_item_t *array, cbor_item_t *value)
> +{
> +bool success = false;
> +
> +success = cbor_array_push(array, cbor_move(value));
> +if (!success) {
> +cbor_incref(value);
> +}
> +
> +return success;
> +}
> +
> +bool qemu_cbor_add_bool_to_map(cbor_item_t *map, const char *key, bool value)
> +{
> +cbor_item_t *key_cbor = NULL;
> +cbor_item_t *value_cbor = NULL;
> +
> +key_cbor = cbor_build_string(key);
> +if (!key_cbor) {
> +goto cleanup;
> +}
> +value_cbor = cbor_build_bool(value);
> +if (!value_cbor) {
> +goto cleanup;
> +}
> +if (!qemu_cbor_map_add(map, key_cbor, value_cbor)) {
> +goto cleanup;
> +}
> +
> +return true;
> +
> + cleanup:
> +if (key_cbor) {
> +cbor_decref(&key_cbor);
> +}
> +if (value_cbor) {
> +cbor_decref(&value_cbor);
> +}
> +return false;
> +}
> +
> +bool qemu_cbor_add_uint8_to_map(cbor_item_t *map, const char *key,
> +uint8_t value)
> +{
> +cbor_item_t *key_cbor = NULL;
> +cbor_item_t *value_cbor = NULL;
> +
> +key_cbor = cbor_build_string(key);
> +if (!key_cbor) {
> +goto cleanup;
> +}
> +value_cbor = cbor_build_uint8(value);
> +if (!value_cbor) {
> +goto cleanup;
> +}
> +if (!qemu_cbor_map_add(map, key_cbor, value_cbor)) {
> +goto cleanup;
> +}
> +
> +return true;
> +
> + cleanup:
> +if (key_cbor) {
> +cbor_decref(&key_cbor);
> +}
> +if (value_cbor) {
> +cbor_decref(&value_cbor);
> +

Re: [PATCH v6 5/8] device/virtio-nsm: Support for Nitro Secure Module device

2024-09-15 Thread Dorjoy Chowdhury
On Mon, Sep 16, 2024, 1:26 AM Michael S. Tsirkin  wrote:

> On Fri, Sep 06, 2024 at 01:57:32AM +0600, Dorjoy Chowdhury wrote:
> > Nitro Secure Module (NSM)[1] device is used in AWS Nitro Enclaves[2]
> > for stripped down TPM functionality like cryptographic attestation.
> > The requests to and responses from NSM device are CBOR[3] encoded.
> >
> > This commit adds support for NSM device in QEMU. Although related to
> > AWS Nitro Enclaves, the virito-nsm device is independent and can be
> > used in other machine types as well. The libcbor[4] library has been
> > used for the CBOR encoding and decoding functionalities.
> >
> > [1]
> https://lists.oasis-open.org/archives/virtio-comment/202310/msg00387.html
> > [2] https://docs.aws.amazon.com/enclaves/latest/user/nitro-enclave.html
> > [3] http://cbor.io/
> > [4] https://libcbor.readthedocs.io/en/latest/
> >
> > Signed-off-by: Dorjoy Chowdhury 
> > ---
> >  MAINTAINERS  |   10 +
> >  hw/virtio/Kconfig|5 +
> >  hw/virtio/cbor-helpers.c |  326 ++
> >  hw/virtio/meson.build|6 +
> >  hw/virtio/virtio-nsm-pci.c   |   73 ++
> >  hw/virtio/virtio-nsm.c   | 1665 ++
> >  include/hw/virtio/cbor-helpers.h |   46 +
> >  include/hw/virtio/virtio-nsm.h   |   59 ++
> >  meson.build  |2 +
> >  9 files changed, 2192 insertions(+)
> >  create mode 100644 hw/virtio/cbor-helpers.c
> >  create mode 100644 hw/virtio/virtio-nsm-pci.c
> >  create mode 100644 hw/virtio/virtio-nsm.c
> >  create mode 100644 include/hw/virtio/cbor-helpers.h
> >  create mode 100644 include/hw/virtio/virtio-nsm.h
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index c14ac014e2..b371c24747 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -2342,6 +2342,16 @@ F: include/sysemu/rng*.h
> >  F: backends/rng*.c
> >  F: tests/qtest/virtio-rng-test.c
> >
> > +virtio-nsm
> > +M: Alexander Graf 
> > +M: Dorjoy Chowdhury 
> > +S: Maintained
> > +F: hw/virtio/cbor-helpers.c
> > +F: hw/virtio/virtio-nsm.c
> > +F: hw/virtio/virtio-nsm-pci.c
> > +F: include/hw/virtio/cbor-helpers.h
> > +F: include/hw/virtio/virtio-nsm.h
> > +
> >  vhost-user-stubs
> >  M: Alex Bennée 
> >  S: Maintained
> > diff --git a/hw/virtio/Kconfig b/hw/virtio/Kconfig
> > index aa63ff7fd4..29fee32035 100644
> > --- a/hw/virtio/Kconfig
> > +++ b/hw/virtio/Kconfig
> > @@ -6,6 +6,11 @@ config VIRTIO_RNG
> >  default y
> >  depends on VIRTIO
> >
> > +config VIRTIO_NSM
> > +   bool
> > +   default y
> > +   depends on VIRTIO
> > +
> >  config VIRTIO_IOMMU
> >  bool
> >  default y
> > diff --git a/hw/virtio/cbor-helpers.c b/hw/virtio/cbor-helpers.c
> > new file mode 100644
> > index 00..a0e58d6862
> > --- /dev/null
> > +++ b/hw/virtio/cbor-helpers.c
> > @@ -0,0 +1,326 @@
> > +/*
> > + * QEMU CBOR helpers
> > + *
> > + * Copyright (c) 2024 Dorjoy Chowdhury 
> > + *
> > + * This work is licensed under the terms of the GNU GPL, version 2 or
> > + * (at your option) any later version.  See the COPYING file in the
> > + * top-level directory.
> > + */
> > +
> > +#include "hw/virtio/cbor-helpers.h"
> > +
> > +bool qemu_cbor_map_add(cbor_item_t *map, cbor_item_t *key, cbor_item_t
> *value)
> > +{
> > +bool success = false;
> > +struct cbor_pair pair = (struct cbor_pair) {
> > +.key = cbor_move(key),
> > +.value = cbor_move(value)
> > +};
> > +
> > +success = cbor_map_add(map, pair);
> > +if (!success) {
> > +cbor_incref(pair.key);
> > +cbor_incref(pair.value);
> > +}
> > +
> > +return success;
> > +}
> > +
> > +bool qemu_cbor_array_push(cbor_item_t *array, cbor_item_t *value)
> > +{
> > +bool success = false;
> > +
> > +success = cbor_array_push(array, cbor_move(value));
> > +if (!success) {
> > +cbor_incref(value);
> > +}
> > +
> > +return success;
> > +}
> > +
> > +bool qemu_cbor_add_bool_to_map(cbor_item_t *map, const char *key, bool
> value)
> > +{
> > +cbor_item_t *key_cbor = NULL;
> > +cbor_item_t *value_cbor = NULL;
> > +
> > +key_cbor = cbor_build_string(key);
> > +if (!key_cbor) {
> > +goto cleanup;
> > +}
> > +value_cbor = cbor_build_bool(value);
> > +if (!value_cbor) {
> > +goto cleanup;
> > +}
> > +if (!qemu_cbor_map_add(map, key_cbor, value_cbor)) {
> > +goto cleanup;
> > +}
> > +
> > +return true;
> > +
> > + cleanup:
> > +if (key_cbor) {
> > +cbor_decref(&key_cbor);
> > +}
> > +if (value_cbor) {
> > +cbor_decref(&value_cbor);
> > +}
> > +return false;
> > +}
> > +
> > +bool qemu_cbor_add_uint8_to_map(cbor_item_t *map, const char *key,
> > +uint8_t value)
> > +{
> > +cbor_item_t *key_cbor = NULL;
> > +cbor_item_t *value_cbor = NULL;
> > +
> > +key_cbor = cbor_build_string(key);
> > +if (!key_cbor) {
> > +goto cleanup;
> > +}
> > +va

Re: [PULL 27/47] bsd-user: Add RISC-V CPU execution loop and syscall handling

2024-09-15 Thread Daniel Henrique Barboza




On 9/12/24 2:29 AM, Alistair Francis wrote:

From: Mark Corbin 

Implemented the RISC-V CPU execution loop, including handling various
exceptions and system calls. The loop continuously executes CPU
instructions,processes exceptions, and handles system calls by invoking
FreeBSD syscall handlers.

Signed-off-by: Mark Corbin 
Signed-off-by: Ajeet Singh 
Co-authored-by: Jessica Clarke 
Co-authored-by: Kyle Evans 
Reviewed-by: Richard Henderson 
Message-ID: <20240907031927.1908-3-itac...@freebsd.org>
Signed-off-by: Alistair Francis 
---
  bsd-user/riscv/target_arch_cpu.h | 94 
  1 file changed, 94 insertions(+)

diff --git a/bsd-user/riscv/target_arch_cpu.h b/bsd-user/riscv/target_arch_cpu.h
index e17c910ae9..ea2a8d1ace 100644
--- a/bsd-user/riscv/target_arch_cpu.h
+++ b/bsd-user/riscv/target_arch_cpu.h
@@ -36,4 +36,98 @@ static inline void target_cpu_init(CPURISCVState *env,
  env->pc = regs->sepc;
  }
  


This patch won't build:

In file included from ../bsd-user/main.c:53:
../bsd-user/riscv/target_arch_cpu.h:126:13: error: call to undeclared function 
'force_sig_fault'; ISO C99 and later do not support implicit function 
declarations [-Werror,-Wimplicit-function-declaration]
  126 | force_sig_fault(signo, code, env->pc);
  | ^
../bsd-user/riscv/target_arch_cpu.h:129:9: error: call to undeclared function 
'process_pending_signals'; ISO C99 and later do not support implicit function 
declarations [-Werror,-Wimplicit-function-declaration]
  129 | process_pending_signals(env);
  | ^

You're missing the following header:


diff --git a/bsd-user/riscv/target_arch_cpu.h b/bsd-user/riscv/target_arch_cpu.h
index 57abfbd556..a93ea3915a 100644
--- a/bsd-user/riscv/target_arch_cpu.h
+++ b/bsd-user/riscv/target_arch_cpu.h
@@ -21,6 +21,7 @@
 #define TARGET_ARCH_CPU_H
 
 #include "target_arch.h"

+#include "signal-common.h"
 
 #define TARGET_DEFAULT_CPU_MODEL "max"






This diff will also fix this other build error:


../bsd-user/main.c:608:5: error: call to undeclared function 'signal_init'; ISO 
C99 and later do not support implicit function declarations 
[-Werror,-Wimplicit-function-declaration]
  608 | signal_init();
  | ^
3 errors generated.


Because bsd-user/main.c is including target_arch_cpu.h.





Thanks,

Daniel


+static inline void target_cpu_loop(CPURISCVState *env)
+{
+CPUState *cs = env_cpu(env);
+int trapnr;
+abi_long ret;
+unsigned int syscall_num;
+int32_t signo, code;
+
+for (;;) {
+cpu_exec_start(cs);
+trapnr = cpu_exec(cs);
+cpu_exec_end(cs);
+process_queued_cpu_work(cs);
+
+signo = 0;
+
+switch (trapnr) {
+case EXCP_INTERRUPT:
+/* just indicate that signals should be handled asap */
+break;
+case EXCP_ATOMIC:
+cpu_exec_step_atomic(cs);
+break;
+case RISCV_EXCP_U_ECALL:
+syscall_num = env->gpr[xT0];
+env->pc += TARGET_INSN_SIZE;
+/* Compare to cpu_fetch_syscall_args() in riscv/riscv/trap.c */
+if (TARGET_FREEBSD_NR___syscall == syscall_num ||
+TARGET_FREEBSD_NR_syscall == syscall_num) {
+ret = do_freebsd_syscall(env,
+ env->gpr[xA0],
+ env->gpr[xA1],
+ env->gpr[xA2],
+ env->gpr[xA3],
+ env->gpr[xA4],
+ env->gpr[xA5],
+ env->gpr[xA6],
+ env->gpr[xA7],
+ 0);
+} else {
+ret = do_freebsd_syscall(env,
+ syscall_num,
+ env->gpr[xA0],
+ env->gpr[xA1],
+ env->gpr[xA2],
+ env->gpr[xA3],
+ env->gpr[xA4],
+ env->gpr[xA5],
+ env->gpr[xA6],
+ env->gpr[xA7]
+);
+}
+
+/*
+ * Compare to cpu_set_syscall_retval() in
+ * riscv/riscv/vm_machdep.c
+ */
+if (ret >= 0) {
+env->gpr[xA0] = ret;
+env->gpr[xT0] = 0;
+} else if (ret == -TARGET_ERESTART) {
+env->pc -= TARGET_INSN_SIZE;
+} else if (ret != -TARGET_EJUSTRETURN) {
+env->gpr[xA0] = -ret;
+env->gpr[xT0] = 1;
+}
+break;
+case RISCV_EXCP_ILLEGAL_INST:
+signo = TARGET_SIGILL;
+   

Re: [PULL 32/47] bsd-user: Add RISC-V signal trampoline setup function

2024-09-15 Thread Daniel Henrique Barboza




On 9/12/24 2:29 AM, Alistair Francis wrote:

From: Mark Corbin 

Implemented the 'setup_sigtramp' function for setting up the signal
trampoline code in the RISC-V architecture.

Signed-off-by: Mark Corbin 
Signed-off-by: Ajeet Singh 
Reviewed-by: Richard Henderson 
Message-ID: <20240907031927.1908-8-itac...@freebsd.org>
Signed-off-by: Alistair Francis 
---
  bsd-user/riscv/target_arch_sigtramp.h | 42 +++
  1 file changed, 42 insertions(+)
  create mode 100644 bsd-user/riscv/target_arch_sigtramp.h

diff --git a/bsd-user/riscv/target_arch_sigtramp.h 
b/bsd-user/riscv/target_arch_sigtramp.h
new file mode 100644
index 00..83345f3961
--- /dev/null
+++ b/bsd-user/riscv/target_arch_sigtramp.h
@@ -0,0 +1,42 @@
+/*
+ * RISC-V sigcode
+ *
+ * Copyright (c) 2019 Mark Corbin
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+
+#ifndef TARGET_ARCH_SIGTRAMP_H
+#define TARGET_ARCH_SIGTRAMP_H
+
+/* Compare with sigcode() in riscv/riscv/locore.S */
+static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc,
+unsigned sys_sigreturn)
+{
+int i;


There's no 'i' var being used. This will throw an 'unused variable' warning 
when building.


+uint32_t sys_exit = TARGET_FREEBSD_NR_exit;
+
+static const uint32_t sigtramp_code[] = {
+/*1*/ const_le32(0x00010513),/*mv a0, sp*/
+/*2*/ const_le32(0x00050513 + (sigf_uc << 20)),  /*addi a0,a0,sigf_uc*/
+/*3*/ const_le32(0x0293 + (sys_sigreturn << 20)),/*li 
t0,sys_sigreturn*/
+/*4*/ const_le32(0x0073),/*ecall*/
+/*5*/ const_le32(0x0293 + (sys_exit << 20)), /*li t0,sys_exit*/
+/*6*/ const_le32(0x0073),/*ecall*/
+/*7*/ const_le32(0xFF1FF06F) /*b -16*/
+};



And this will throw the following error:

../bsd-user/riscv/target_arch_sigtramp.h:32:33: error: initializer element is 
not a compile-time constant
   32 | /*2*/ const_le32(0x00050513 + (sigf_uc << 20)),  /*addi 
a0,a0,sigf_uc*/
  ~~~^
/tmp/cirrus-ci-build/include/qemu/bswap.h:168:26: note: expanded from macro 
'const_le32'
  168 | # define const_le32(_x) (_x)
  |  ^~
1 error generated.


One solution is to remove the 'static const' qualifier from the array, like
bsd-user/arm/target_arch_sigtramp.h is doing.


This diff will fix the build:


diff --git a/bsd-user/riscv/target_arch_sigtramp.h 
b/bsd-user/riscv/target_arch_sigtramp.h
index 83345f3961..dfe5076739 100644
--- a/bsd-user/riscv/target_arch_sigtramp.h
+++ b/bsd-user/riscv/target_arch_sigtramp.h
@@ -24,10 +24,9 @@
 static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc,
 unsigned sys_sigreturn)
 {
-int i;
 uint32_t sys_exit = TARGET_FREEBSD_NR_exit;
 
-static const uint32_t sigtramp_code[] = {

+uint32_t sigtramp_code[] = {
 /*1*/ const_le32(0x00010513),/*mv a0, sp*/
 /*2*/ const_le32(0x00050513 + (sigf_uc << 20)),  /*addi a0,a0,sigf_uc*/
 /*3*/ const_le32(0x0293 + (sys_sigreturn << 20)),/*li 
t0,sys_sigreturn*/




Thanks,

Daniel




+
+return memcpy_to_target(offset, sigtramp_code, TARGET_SZSIGCODE);
+}
+#endif /* TARGET_ARCH_SIGTRAMP_H */




Re: [PULL 00/47] riscv-to-apply queue

2024-09-15 Thread Daniel Henrique Barboza

Hi Peter, Alistair,

On 9/14/24 6:15 AM, Alistair Francis wrote:

On Fri, Sep 13, 2024 at 8:37 PM Peter Maydell  wrote:


On Thu, 12 Sept 2024 at 06:30, Alistair Francis  wrote:


The following changes since commit a4eb31c678400472de0b4915b9154a7c20d8332f:

   Merge tag 'pull-testing-gdbstub-oct-100924-1' of 
https://gitlab.com/stsquad/qemu into staging (2024-09-11 13:17:29 +0100)

are available in the Git repository at:

   https://github.com/alistair23/qemu.git tags/pull-riscv-to-apply-20240912-1

for you to fetch changes up to 90d5d3c1115399d8e27621efd69dfa74a35a4932:

   hw/intc: riscv-imsic: Fix interrupt state updates. (2024-09-12 15:05:10 
+1000)


RISC-V PR for 9.2

* Add a property to set vl to ceil(AVL/2)
* Enable numamem testing for RISC-V
* Consider MISA bit choice in implied rule
* Fix the za64rs priv spec requirements
* Enable Bit Manip for OpenTitan Ibex CPU
* Fix the group bit setting of AIA with KVM
* Stop timer with infinite timecmp
* Add 'fcsr' register to QEMU log as a part of F extension
* Fix riscv64 build on musl libc
* Add preliminary textra trigger CSR functions
* RISC-V IOMMU support
* RISC-V bsd-user support
* Respect firmware ELF entry point
* Add Svvptc extension support
* Fix masking of rv32 physical address
* Fix linking problem with semihosting disabled
* Fix IMSIC interrupt state updates


Hi; this fails to build on FreeBSD:

https://gitlab.com/qemu-project/qemu/-/jobs/7817823771


Is this one of those jobs that are only available when running the main 
pipeline? I don't
have this x86-freebsd runner when triggering the gitlab pipeline. I ended up 
installing a
FreeBSD VM and using it to reproduce the problem.

Would be nice to have access to a FreeBSD runner as a regular user, even if 
just for x86_64,
to help detect these build problems before sending a PR.




Ajeet do you mind looking at this failure and sending a new series with a fix



I sent some build fixes in patches 27 and 32 that worked for me. Since they are 
trivial I think
you could just squash them in the PR and send a v2.



Thanks,

Daniel



Alistair



In file included from ../bsd-user/elfload.c:31:
In file included from ../bsd-user/freebsd/target_os_stack.h:24:
../bsd-user/riscv/target_arch_sigtramp.h:32:33: error: initializer
element is not a compile-time constant
32 | /*2*/ const_le32(0x00050513 + (sigf_uc << 20)), /*addi a0,a0,sigf_uc*/
|  ~~~^
/tmp/cirrus-ci-build/include/qemu/bswap.h:168:26: note: expanded from
macro 'const_le32'
168 | # define const_le32(_x) (_x)
 |  ^~


and

In file included from ../bsd-user/main.c:53:
../bsd-user/riscv/target_arch_cpu.h:126:13: error: call to undeclared
function 'force_sig_fault'; ISO C99 and later do not support implicit
function declarations [-Werror,-Wimplicit-function-declaration]
126 | force_sig_fault(signo, code, env->pc);
 | ^
../bsd-user/riscv/target_arch_cpu.h:129:9: error: call to undeclared
function 'process_pending_signals'; ISO C99 and later do not support
implicit function declarations
[-Werror,-Wimplicit-function-declaration]
129 | process_pending_signals(env);
 | ^
../bsd-user/main.c:608:5: error: call to undeclared function
'signal_init'; ISO C99 and later do not support implicit function
declarations [-Werror,-Wimplicit-function-declaration]
608 | signal_init();
 | ^
3 errors generated.

thanks
-- PMM






Re: [PATCH v6 5/8] device/virtio-nsm: Support for Nitro Secure Module device

2024-09-15 Thread Michael S. Tsirkin
On Mon, Sep 16, 2024 at 01:46:52AM +0600, Dorjoy Chowdhury wrote:
> > +    len = cbor_serialize(root, response->iov_base, response->iov_len);
> 
> As far as I can tell, all these also need to be switched to use
> iov_from_buf.
> 
> 
> Sorry I didn't understand this. The iovecs passed in these functions are not
> the iovecs from virtqueue. We make an iovec for the response and then pass it
> down. We do the "iov_from_buf" after calling "get_nsm_request_response" in
> "handle_input" function. Am I missing something?
> 
> Regards,
> Dorjoy


Oh, I misunderstood. Passing in a pointer and length might be clearer.
Not critical.

-- 
MST




Re: [PATCH v6 5/8] device/virtio-nsm: Support for Nitro Secure Module device

2024-09-15 Thread Michael S. Tsirkin
On Fri, Sep 06, 2024 at 01:57:32AM +0600, Dorjoy Chowdhury wrote:
> +const struct nsm_cmd nsm_cmds[] = {
> +{ "GetRandom",   CBOR_ROOT_TYPE_STRING,  handle_GetRandom },
> +{ "DescribeNSM", CBOR_ROOT_TYPE_STRING,  handle_DescribeNSM },
> +{ "DescribePCR", CBOR_ROOT_TYPE_MAP, handle_DescribePCR },
> +{ "ExtendPCR",   CBOR_ROOT_TYPE_MAP, handle_ExtendPCR },
> +{ "LockPCR", CBOR_ROOT_TYPE_MAP, handle_LockPCR },
> +{ "LockPCRs",CBOR_ROOT_TYPE_MAP, handle_LockPCRs },
> +{ "Attestation", CBOR_ROOT_TYPE_MAP, handle_Attestation },
> +};

I think we should stick to the coding style and avoid camel case
for functions. I know, it is tempting to stick to what
some spec says, but they are all inconsistent. Put the spec
name in a code comment before the function, should be
good enough.




[PATCH] hostmem: Apply merge property after the memory region is initialized

2024-09-15 Thread Gavin Shan
The semantic change has been introduced by commit 5becdc0ab0 ("hostmem:
simplify the code for merge and dump properties") even it clarifies that
no senmatic change has been introduced. After the commit, the merge
property can be applied even the corresponding memory region isn't
initialized yet. This leads to crash dump by the following command
lines.

  # /home/gavin/sandbox/qemu.main/build/qemu-system-aarch64  \
-accel kvm  -machine virt -cpu host  \
-object memory-backend-ram,id=mem-memN0,size=4096M,merge=off
:
qemu-system-aarch64: ../system/memory.c:2419: memory_region_get_ram_ptr: \
Assertion `mr->ram_block' failed.

Fix it by applying the merge property only when the memory region is
initialized.

Fixes: 5becdc0ab083 ("hostmem: simplify the code for merge and dump properties")
Reported-by: Zhenyu Zhang 
Signed-off-by: Gavin Shan 
---
 backends/hostmem.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/backends/hostmem.c b/backends/hostmem.c
index 4e5576a4ad..181446626a 100644
--- a/backends/hostmem.c
+++ b/backends/hostmem.c
@@ -178,7 +178,7 @@ static void host_memory_backend_set_merge(Object *obj, bool 
value, Error **errp)
 return;
 }
 
-if (!host_memory_backend_mr_inited(backend) &&
+if (host_memory_backend_mr_inited(backend) &&
 value != backend->merge) {
 void *ptr = memory_region_get_ram_ptr(&backend->mr);
 uint64_t sz = memory_region_size(&backend->mr);
-- 
2.45.2




Re: [RFC v3 3/3] vhost: Allocate memory for packed vring

2024-09-15 Thread Sahil
Hi,

On Thursday, September 12, 2024 3:24:27 PM GMT+5:30 Eugenio Perez Martin wrote:
> On Wed, Sep 11, 2024 at 9:36 PM Sahil  wrote:
> > Hi,
> > 
> > On Monday, September 9, 2024 6:04:45 PM GMT+5:30 Eugenio Perez Martin wrote:
> > > On Sun, Sep 8, 2024 at 9:47 PM Sahil  wrote:
> > > > On Friday, August 30, 2024 4:18:31 PM GMT+5:30 Eugenio Perez Martin 
> > > > wrote:
> > > > > On Fri, Aug 30, 2024 at 12:20 PM Sahil 
> > > > > wrote:
> > > > > [...]
> > > > > vdpa_sim does not support packed vq at the moment. You need to build
> > > > > the use case #3 of the second part of that blog [1]. It's good that
> > > > > you build the vdpa_sim earlier as it is a simpler setup.
> > > > > 
> > > > > If you have problems with the vp_vdpa environment please let me know
> > > > > so we can find alternative setups.
> > > > 
> > > > Thank you for the clarification. I tried setting up the vp_vdpa
> > > > environment (scenario 3) but I ended up running into a problem
> > > > in the L1 VM.
> > > > 
> > > > I verified that nesting is enabled in KVM (L0):
> > > > 
> > > > $ grep -oE "(vmx|svm)" /proc/cpuinfo | sort | uniq
> > > > vmx
> > > > 
> > > > $ cat /sys/module/kvm_intel/parameters/nested
> > > > Y
> > > > 
> > > > There are no issues when booting L1. I start the VM by running:
> > > > 
> > > > $ sudo ./qemu/build/qemu-system-x86_64 \
> > > > -enable-kvm \
> > > > -drive
> > > > file=//home/ig91/fedora_qemu_test_vm/L1.qcow2,media=disk,if=virtio
> > > > \
> > > > -net nic,model=virtio \
> > > > -net user,hostfwd=tcp::-:22 \
> > > > -device intel-iommu,snoop-control=on \
> > > > -device
> > > > virtio-net-pci,netdev=net0,disable-legacy=on,disable-modern=off,iommu_
> > > > pla
> > > > tform=on,event_idx=off,packed=on,bus=pcie.0,addr=0x4 \ -netdev
> > > > tap,id=net0,script=no,downscript=no \
> > > > -nographic \
> > > > -m 2G \
> > > > -smp 2 \
> > > > -M q35 \
> > > > -cpu host \
> > > > 2>&1 | tee vm.log
> > > > 
> > > > Kernel version in L1:
> > > > 
> > > > # uname -a
> > > > Linux fedora 6.8.5-201.fc39.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Apr 11
> > > > 18:25:26 UTC 2024 x86_64 GNU/Linux
> > > 
> > > Did you run the kernels with the arguments "iommu=pt intel_iommu=on"?
> > > You can print them with cat /proc/cmdline.
> > 
> > I missed this while setting up the environment. After setting the kernel
> > params I managed to move past this issue but my environment in virtualbox
> > was very unstable and it kept crashing.
> 
> I've no experience with virtualbox+vdpa, sorry :). Why not use QEMU also for
> L1?

No, I was using virtualbox for L0. I wasn't able to create L1.qcow2 on my
host OS (Arch Linux). "Virt-sysprep" was giving me "resolve.conf is a
dangling symlink" issues. I had a Fedora VM set up on virtualbox and I
managed to create L1.qcow2 and L2.qcow2 there.

So my environment looked something like this:

Host OS (Bare metal) -> L0 (Fedora on virtualbox) -> L1 (QEMU) -> L2 (QEMU)

I learnt that shared folders can be set up between the host and virtualbox
and so I managed to move L1.qcow2 from the Fedora VM to my host OS.

So now my environment looks like this:

L0 (Arch Linux on bare metal) -> L1 (QEMU) -> L2 (QEMU)

> > I managed to get L1 to run on my host OS, so scenario 3 is now up and
> > running. However, the packed bit seems to be disabled in this scenario
> > too.
> > 
> > L0 (host machine) specs:
> > 
> > - kernel version:
> >   6.6.46-1-lts
> > 
> > - QEMU version:
> >   9.0.50 (v8.2.0-5536-g16514611dc)
> > 
> > - vDPA version:
> >   iproute2-6.10.0
> > 
> > L1 specs:
> > 
> > - kernel version:
> >   6.8.5-201.fc39.x86_64
> > 
> > - QEMU version:
> >   9.0.91
> > 
> > - vDPA version:
> >   iproute2-6.10.0
> > 
> > L2 specs:
> > - kernel version
> > 
> >   6.8.7-200.fc39.x86_64
> > 
> > I followed the following steps to set up scenario 3:
> > 
> >  In L0 
> > 
> > $ grep -oE "(vmx|svm)" /proc/cpuinfo | sort | uniq
> > vmx
> > 
> > $ cat /sys/module/kvm_intel/parameters/nested
> > Y
> > 
> > $ sudo ./qemu/build/qemu-system-x86_64 \
> > -enable-kvm \
> > -drive
> > file=//home/valdaarhun/valdaarhun/qcow2_img/L1.qcow2,media=disk,if=virtio
> > \ -net nic,model=virtio \
> > -net user,hostfwd=tcp::-:22 \
> > -device intel-iommu,snoop-control=on \
> > -device
> > virtio-net-pci,netdev=net0,disable-legacy=on,disable-modern=off,iommu_pla
> > tform=on,event_idx=off,packed=on,bus=pcie.0,addr=0x4 \ -netdev
> > tap,id=net0,script=no,downscript=no \
> > -nographic \
> > -m 8G \
> > -smp 4 \
> > -M q35 \
> > -cpu host \
> > 2>&1 | tee vm.log
> > 
> >  In L1 
> > 
> > I verified that the following config variables are set as decribed in the
> > blog [1].
> > 
> > CONFIG_VIRTIO_VDPA=m
> > CONFIG_VDPA=m
> > CONFIG_VP_VDPA=m
> > CONFIG_VHOST_VDPA=m
> > 
> > # modprobe vdpa
> > # modprobe vhost_vdpa
> > # modprobe vp_vdpa
> > 
> > # lsmod | grep -i vdpa
> > vp_vdpa 20480  0
> > vhost_vdpa  32768  0
> > vhost   65536  1 vhost_vdpa
> > vhost_iotlb 1638

Re: [PATCH 12/17] tests/tcg: ensure s390x-softmmu output redirected

2024-09-15 Thread Thomas Huth

On 13/09/2024 19.26, Alex Bennée wrote:

The multiarch system tests output serial data which should be
redirected to the "output" chardev rather than echoed to the console.

Remove the unused EXTFLAGS variable while we are at it.

Signed-off-by: Alex Bennée 
---
  tests/tcg/s390x/Makefile.softmmu-target | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/tcg/s390x/Makefile.softmmu-target 
b/tests/tcg/s390x/Makefile.softmmu-target
index f60f94b090..ad681bbe40 100644
--- a/tests/tcg/s390x/Makefile.softmmu-target
+++ b/tests/tcg/s390x/Makefile.softmmu-target
@@ -1,6 +1,6 @@
  S390X_SRC=$(SRC_PATH)/tests/tcg/s390x
  VPATH+=$(S390X_SRC)
-QEMU_OPTS+=-action panic=exit-failure -nographic $(EXTFLAGS) -kernel
+QEMU_OPTS+=-action panic=exit-failure -nographic -serial chardev:output -kernel
  LINK_SCRIPT=$(S390X_SRC)/softmmu.ld
  CFLAGS+=-ggdb -O0
  LDFLAGS=-nostdlib -static


EXTFLAGS has been added on purpose here, see commit 26a09ead7351f117ae780.

 Thomas




Re: [PULL 00/47] riscv-to-apply queue

2024-09-15 Thread Thomas Huth

On 15/09/2024 21.58, Daniel Henrique Barboza wrote:

Hi Peter, Alistair,

On 9/14/24 6:15 AM, Alistair Francis wrote:
On Fri, Sep 13, 2024 at 8:37 PM Peter Maydell  
wrote:


On Thu, 12 Sept 2024 at 06:30, Alistair Francis  
wrote:


The following changes since commit 
a4eb31c678400472de0b4915b9154a7c20d8332f:


   Merge tag 'pull-testing-gdbstub-oct-100924-1' of https://gitlab.com/ 
stsquad/qemu into staging (2024-09-11 13:17:29 +0100)


are available in the Git repository at:

   https://github.com/alistair23/qemu.git tags/pull-riscv-to- 
apply-20240912-1


for you to fetch changes up to 90d5d3c1115399d8e27621efd69dfa74a35a4932:

   hw/intc: riscv-imsic: Fix interrupt state updates. (2024-09-12 
15:05:10 +1000)



RISC-V PR for 9.2

* Add a property to set vl to ceil(AVL/2)
* Enable numamem testing for RISC-V
* Consider MISA bit choice in implied rule
* Fix the za64rs priv spec requirements
* Enable Bit Manip for OpenTitan Ibex CPU
* Fix the group bit setting of AIA with KVM
* Stop timer with infinite timecmp
* Add 'fcsr' register to QEMU log as a part of F extension
* Fix riscv64 build on musl libc
* Add preliminary textra trigger CSR functions
* RISC-V IOMMU support
* RISC-V bsd-user support
* Respect firmware ELF entry point
* Add Svvptc extension support
* Fix masking of rv32 physical address
* Fix linking problem with semihosting disabled
* Fix IMSIC interrupt state updates


Hi; this fails to build on FreeBSD:

https://gitlab.com/qemu-project/qemu/-/jobs/7817823771


Is this one of those jobs that are only available when running the main 
pipeline? I don't
have this x86-freebsd runner when triggering the gitlab pipeline. I ended up 
installing a

FreeBSD VM and using it to reproduce the problem.

Would be nice to have access to a FreeBSD runner as a regular user, even if 
just for x86_64,

to help detect these build problems before sending a PR.


You can enable this job for your pipelines, too, see 
.gitlab-ci.d/cirrus/README.rst for information how to configure it.


If you have a Linux host with KVM, you could alternatively also use "make 
vm-build-freebsd" on your local machine instead.


 Thomas




Re: [PULL 32/47] bsd-user: Add RISC-V signal trampoline setup function

2024-09-15 Thread Ajeet Singh
Hi, I had already fixed it and sent a patchv6,

I will send another one with the other changes.

On Mon, 16 Sept, 2024, 5:51 am Daniel Henrique Barboza, <
dbarb...@ventanamicro.com> wrote:

>
>
> On 9/12/24 2:29 AM, Alistair Francis wrote:
> > From: Mark Corbin 
> >
> > Implemented the 'setup_sigtramp' function for setting up the signal
> > trampoline code in the RISC-V architecture.
> >
> > Signed-off-by: Mark Corbin 
> > Signed-off-by: Ajeet Singh 
> > Reviewed-by: Richard Henderson 
> > Message-ID: <20240907031927.1908-8-itac...@freebsd.org>
> > Signed-off-by: Alistair Francis 
> > ---
> >   bsd-user/riscv/target_arch_sigtramp.h | 42 +++
> >   1 file changed, 42 insertions(+)
> >   create mode 100644 bsd-user/riscv/target_arch_sigtramp.h
> >
> > diff --git a/bsd-user/riscv/target_arch_sigtramp.h
> b/bsd-user/riscv/target_arch_sigtramp.h
> > new file mode 100644
> > index 00..83345f3961
> > --- /dev/null
> > +++ b/bsd-user/riscv/target_arch_sigtramp.h
> > @@ -0,0 +1,42 @@
> > +/*
> > + * RISC-V sigcode
> > + *
> > + * Copyright (c) 2019 Mark Corbin
> > + *
> > + * This library is free software; you can redistribute it and/or
> > + * modify it under the terms of the GNU Lesser General Public
> > + * License as published by the Free Software Foundation; either
> > + * version 2 of the License, or (at your option) any later version.
> > + *
> > + * This library is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> > + * Lesser General Public License for more details.
> > + *
> > + * You should have received a copy of the GNU Lesser General Public
> > + * License along with this library; if not, see <
> http://www.gnu.org/licenses/>.
> > + */
> > +
> > +#ifndef TARGET_ARCH_SIGTRAMP_H
> > +#define TARGET_ARCH_SIGTRAMP_H
> > +
> > +/* Compare with sigcode() in riscv/riscv/locore.S */
> > +static inline abi_long setup_sigtramp(abi_ulong offset, unsigned
> sigf_uc,
> > +unsigned sys_sigreturn)
> > +{
> > +int i;
>
> There's no 'i' var being used. This will throw an 'unused variable'
> warning when building.
>
> > +uint32_t sys_exit = TARGET_FREEBSD_NR_exit;
> > +
> > +static const uint32_t sigtramp_code[] = {
> > +/*1*/ const_le32(0x00010513),/*mv a0, sp*/
> > +/*2*/ const_le32(0x00050513 + (sigf_uc << 20)),  /*addi
> a0,a0,sigf_uc*/
> > +/*3*/ const_le32(0x0293 + (sys_sigreturn << 20)),/*li
> t0,sys_sigreturn*/
> > +/*4*/ const_le32(0x0073),/*ecall*/
> > +/*5*/ const_le32(0x0293 + (sys_exit << 20)), /*li
> t0,sys_exit*/
> > +/*6*/ const_le32(0x0073),/*ecall*/
> > +/*7*/ const_le32(0xFF1FF06F) /*b -16*/
> > +};
>
>
> And this will throw the following error:
>
> ../bsd-user/riscv/target_arch_sigtramp.h:32:33: error: initializer element
> is not a compile-time constant
> 32 | /*2*/ const_le32(0x00050513 + (sigf_uc << 20)),  /*addi
> a0,a0,sigf_uc*/
>~~~^
> /tmp/cirrus-ci-build/include/qemu/bswap.h:168:26: note: expanded from
> macro 'const_le32'
>168 | # define const_le32(_x) (_x)
>|  ^~
> 1 error generated.
>
>
> One solution is to remove the 'static const' qualifier from the array, like
> bsd-user/arm/target_arch_sigtramp.h is doing.
>
>
> This diff will fix the build:
>
>
> diff --git a/bsd-user/riscv/target_arch_sigtramp.h
> b/bsd-user/riscv/target_arch_sigtramp.h
> index 83345f3961..dfe5076739 100644
> --- a/bsd-user/riscv/target_arch_sigtramp.h
> +++ b/bsd-user/riscv/target_arch_sigtramp.h
> @@ -24,10 +24,9 @@
>   static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc,
>   unsigned sys_sigreturn)
>   {
> -int i;
>   uint32_t sys_exit = TARGET_FREEBSD_NR_exit;
>
> -static const uint32_t sigtramp_code[] = {
> +uint32_t sigtramp_code[] = {
>   /*1*/ const_le32(0x00010513),/*mv a0, sp*/
>   /*2*/ const_le32(0x00050513 + (sigf_uc << 20)),  /*addi
> a0,a0,sigf_uc*/
>   /*3*/ const_le32(0x0293 + (sys_sigreturn << 20)),/*li
> t0,sys_sigreturn*/
>
>
>
>
> Thanks,
>
> Daniel
>
>
>
> > +
> > +return memcpy_to_target(offset, sigtramp_code, TARGET_SZSIGCODE);
> > +}
> > +#endif /* TARGET_ARCH_SIGTRAMP_H */
>


Re: -chardev with a JSON argument (was: [PATCH] chardev: introduce 'reconnect-ms' and deprecate 'reconnect')

2024-09-15 Thread Peter Krempa
On Sat, Sep 14, 2024 at 10:42:36 +0200, Markus Armbruster wrote:
> Peter Krempa  writes:
> 
> > This is a little off-topic:
> >
> > So I wanted to make libvirt use the new parameter to stay ahead
> > deprecation. I've applied this patch to qemu, dumped capabilities and
> > pretty much expected a bunch of test cases in libvirt fail as they'd be
> > using a deprecated field as libvirt is supposed to validate everything.
> >
> > And the test suite passed unexpectedly. I've dug further and noticed
> > that for some reason libvirt doesn't still use JSON parameters for
> > -chardev (which is the pre-requisite for validation).
> >
> > I've also noticed that at some point I attempted to convert it over
> > witnessed by having an (unused) capability named QEMU_CAPS_CHARDEV_JSON
> > that I've introduced.
> >
> > My questions are:
> > 1) Does '-chardev' accept JSON identical to 'chardev-add' QMP command?
> 
> Sadly, no.

Yeah, in the meanwhile I had a look and also remembered that we spoke
about why this was the case. (All the 'wrapper' objects making the
schema of 'chardev-add' extremely unpleasant)

> How badly do you want it?

So the main motivation is to have just one instance of the code
generating the config for qemu. As JSON has type information inside
libvirt always generates JSON internally first. This is the case for
-object, -device, -netdev, -blockdev, ...

For '-chardev' we currently (in tree) have two separate formatters for
'-chardev' and QMP 'chardev-add'. I do have a reasonalby looking rework
in the works which unifies them (with a few quirky  "if (commandline)"
blocks).

In cases when we need to support the old syntax for any reason we do
have a converter that takes JSON and outputs the qemuopts syntax. This
is possible for now as we have mostly flat structures and the only
difference for now is how the arrays are processed in -device vs -netdev
(by callbacks to the converter).

For -chardev this will require a bit more logic as we need to avoid the
extra wrappers for commandline output and few fields have different
names in QMP than on the commandline.

My main goal here is to achieve validation against the QMP schema, and
it's much easier for us to add test cases via XML than hardcoding them
in C.

So honestly I don't think we want it too badly. Definitely not so bad
that having it with bad design. I reckon that doing the refactor will
also simplify things for the future if the QMP design will be changed to
e.g. drop the wrappers.

> > If yes:
> 
> If we implemented it:
> 
> > 2) Since when can that be used? (What can I use as a witness)
> 
> I figure we'd provide a witness the same way we did when we added JSON
> support to -device: add a feature @json-cli to chardev-add.

Yup, that'll always work :)


> > 3) Are there any gotchas?
> 
> Not aware of any.  Can't be 100% sure until we try.
> 
> > I wonder this as I'd love to finish that out, but I really don't fancy
> > digging into qemu to find a gotcha 3/4 of the way there.
> 
> Understandable :)
> 
> > Anyways, as I've already stated, this patch is okay for libvirt, but I
> > didn't review the implementation, thus, on behalf of libvirt:
> >
> > ACKed-by: Peter Krempa 
> 
> Thanks!
> 




Re: [PATCH v3 12/12] qcow2: add discard-subclusters option

2024-09-15 Thread Andrey Drobyshev
On 9/13/24 7:39 PM, Andrey Drobyshev wrote:
> Introduce Qcow2 runtime boolean option "discard-subclusters".  This
> option influences discard alignment value (either cluster_size or
> subcluster_size) and essentially makes subcluster-based discard optional.
> We disable it by default.
> 
> Also tweak iotests/271 to enable this option and really test subcluster
> based discards.
> 
> Signed-off-by: Andrey Drobyshev 
> ---
>  block/qcow2.c  | 21 -
>  block/qcow2.h  |  2 ++
>  tests/qemu-iotests/271 | 10 ++
>  3 files changed, 28 insertions(+), 5 deletions(-)
> 
> diff --git a/block/qcow2.c b/block/qcow2.c
> index c2086d0bd1..7c38a5be41 100644
> --- a/block/qcow2.c
> +++ b/block/qcow2.c
> @@ -685,6 +685,7 @@ static const char *const mutable_opts[] = {
>  QCOW2_OPT_DISCARD_SNAPSHOT,
>  QCOW2_OPT_DISCARD_OTHER,
>  QCOW2_OPT_DISCARD_NO_UNREF,
> +QCOW2_OPT_DISCARD_SUBCLUSTERS,
>  QCOW2_OPT_OVERLAP,
>  QCOW2_OPT_OVERLAP_TEMPLATE,
>  QCOW2_OPT_OVERLAP_MAIN_HEADER,
> @@ -734,6 +735,11 @@ static QemuOptsList qcow2_runtime_opts = {
>  .type = QEMU_OPT_BOOL,
>  .help = "Do not unreference discarded clusters",
>  },
> +{
> +.name = QCOW2_OPT_DISCARD_SUBCLUSTERS,
> +.type = QEMU_OPT_BOOL,
> +.help = "Allow subcluster aligned discard requests",
> +},
>  {
>  .name = QCOW2_OPT_OVERLAP,
>  .type = QEMU_OPT_STRING,
> @@ -978,6 +984,7 @@ typedef struct Qcow2ReopenState {
>  int overlap_check;
>  bool discard_passthrough[QCOW2_DISCARD_MAX];
>  bool discard_no_unref;
> +bool discard_subclusters;
>  uint64_t cache_clean_interval;
>  QCryptoBlockOpenOptions *crypto_opts; /* Disk encryption runtime options 
> */
>  } Qcow2ReopenState;
> @@ -1157,6 +1164,16 @@ qcow2_update_options_prepare(BlockDriverState *bs, 
> Qcow2ReopenState *r,
>  goto fail;
>  }
>  
> +r->discard_subclusters =
> +qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_SUBCLUSTERS, false);
> +if (r->discard_subclusters && !has_subclusters(s)) {
> +error_setg(errp,
> +   "Image doesn't have extended L2 entries, but option "
> +   "'discard-subclusters' is enabled");
> +ret = -EINVAL;
> +goto fail;

I realized that failing here might not be the best course of action,
since non-presence of extended L2 entries in an image is an external
condition which we can't control.  I guess we can just do warn_report()
instead.

> +}
> +
>  switch (s->crypt_method_header) {
>  case QCOW_CRYPT_NONE:
>  if (encryptfmt) {
> @@ -1238,6 +1255,7 @@ static void 
> qcow2_update_options_commit(BlockDriverState *bs,
>  }
>  
>  s->discard_no_unref = r->discard_no_unref;
> +s->discard_subclusters = r->discard_subclusters;
>  
>  if (s->cache_clean_interval != r->cache_clean_interval) {
>  cache_clean_timer_del(bs);
> @@ -1981,7 +1999,8 @@ static void qcow2_refresh_limits(BlockDriverState *bs, 
> Error **errp)
>  bs->bl.request_alignment = qcrypto_block_get_sector_size(s->crypto);
>  }
>  bs->bl.pwrite_zeroes_alignment = s->subcluster_size;
> -bs->bl.pdiscard_alignment = s->subcluster_size;
> +bs->bl.pdiscard_alignment = s->discard_subclusters ?
> +s->subcluster_size : s->cluster_size;
>  }
>  
>  static int GRAPH_UNLOCKED
> diff --git a/block/qcow2.h b/block/qcow2.h
> index a65c185b51..4e91bdde3f 100644
> --- a/block/qcow2.h
> +++ b/block/qcow2.h
> @@ -134,6 +134,7 @@
>  #define QCOW2_OPT_DISCARD_SNAPSHOT "pass-discard-snapshot"
>  #define QCOW2_OPT_DISCARD_OTHER "pass-discard-other"
>  #define QCOW2_OPT_DISCARD_NO_UNREF "discard-no-unref"
> +#define QCOW2_OPT_DISCARD_SUBCLUSTERS "discard-subclusters"
>  #define QCOW2_OPT_OVERLAP "overlap-check"
>  #define QCOW2_OPT_OVERLAP_TEMPLATE "overlap-check.template"
>  #define QCOW2_OPT_OVERLAP_MAIN_HEADER "overlap-check.main-header"
> @@ -387,6 +388,7 @@ typedef struct BDRVQcow2State {
>  bool discard_passthrough[QCOW2_DISCARD_MAX];
>  
>  bool discard_no_unref;
> +bool discard_subclusters;
>  
>  int overlap_check; /* bitmask of Qcow2MetadataOverlap values */
>  bool signaled_corruption;
> diff --git a/tests/qemu-iotests/271 b/tests/qemu-iotests/271
> index 8b80682cff..d7cf3c459b 100755
> --- a/tests/qemu-iotests/271
> +++ b/tests/qemu-iotests/271
> @@ -100,13 +100,14 @@ _filter_trace_fallocate()
>  #  discard  -> discard
>  _run_test()
>  {
> -unset c sc off len cmd opt
> +unset c sc off len cmd trace opt
>  for var in "$@"; do eval "$var"; done
>  case "${cmd:-write}" in
>  zero)
>  cmd="write -q -z";;
>  unmap)
> -opt="--trace enable=file_do_fallocate"
> +trace="--trace enable=file_do_fallocate"
> +opt="-c reopen -o discard-subclusters=on"
>  cmd="wri