Re: [RFC PATCH v2 36/44] target/loongarch: Implement vseq vsle vslt

2023-04-01 Thread Richard Henderson

On 3/27/23 20:06, Song Gao wrote:

+static bool do_cmp(DisasContext *ctx, arg_vvv *a, MemOp mop, TCGCond cond,
+   void (*func)(TCGCond, unsigned, uint32_t, uint32_t,
+uint32_t, uint32_t, uint32_t))
+{
+uint32_t vd_ofs, vj_ofs, vk_ofs;
+
+CHECK_SXE;
+
+vd_ofs = vreg_full_offset(a->vd);
+vj_ofs = vreg_full_offset(a->vj);
+vk_ofs = vreg_full_offset(a->vk);
+
+func(cond, mop, vd_ofs, vj_ofs, vk_ofs, 16, 16);


You always pass tcg_gen_cmp_vec.


+static void do_cmpi_vec(TCGCond cond,
+unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm)
+{
+TCGv_vec t1;
+
+t1 = tcg_temp_new_vec_matching(t);
+tcg_gen_dupi_vec(vece, t1, imm);


tcg_constant_vec_matching.


r~



Re: [RFC PATCH v2 35/44] target/loongarch: Implement LSX fpu fcvt instructions

2023-04-01 Thread Richard Henderson

On 3/27/23 20:06, Song Gao wrote:

This patch includes:
- VFCVT{L/H}.{S.H/D.S};
- VFCVT.{H.S/S.D};
- VFRINT[{RNE/RZ/RP/RM}].{S/D};
- VFTINT[{RNE/RZ/RP/RM}].{W.S/L.D};
- VFTINT[RZ].{WU.S/LU.D};
- VFTINT[{RNE/RZ/RP/RM}].W.D;
- VFTINT[{RNE/RZ/RP/RM}]{L/H}.L.S;
- VFFINT.{S.W/D.L}[U];
- VFFINT.S.L, VFFINT{L/H}.D.W.

Signed-off-by: Song Gao 
---
  fpu/softfloat.c |  55 +++
  include/fpu/softfloat.h |  27 ++
  target/loongarch/disas.c|  56 +++
  target/loongarch/helper.h   |  56 +++
  target/loongarch/insn_trans/trans_lsx.c.inc |  56 +++
  target/loongarch/insns.decode   |  56 +++
  target/loongarch/lsx_helper.c   | 369 
  7 files changed, 675 insertions(+)

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index c7454c3eb1..79975c6b01 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -2988,6 +2988,25 @@ float64 float64_round_to_int(float64 a, float_status *s)
  return float64_round_pack_canonical(&p, s);
  }
  
+#define FRINT_RM(rm, rmode, bits) \

+float ## bits float ## bits ## _round_to_int_ ## rm(  \
+ float ## bits a, float_status *s)\
+{ \
+FloatParts64 pa;   \
+float ## bits ## _unpack_canonical(&pa, a, s); \
+parts_round_to_int(&pa, rmode, 0, s, &float64_params);\
+return float ## bits ## _round_pack_canonical(&pa, s);\
+}
+FRINT_RM(rne, float_round_nearest_even, 32)
+FRINT_RM(rm,  float_round_down, 32)
+FRINT_RM(rp,  float_round_up,   32)
+FRINT_RM(rz,  float_round_to_zero,  32)
+FRINT_RM(rne, float_round_nearest_even, 64)
+FRINT_RM(rm,  float_round_down, 64)
+FRINT_RM(rp,  float_round_up,   64)
+FRINT_RM(rz,  float_round_to_zero,  64)
+#undef FRINT_RM



No, you should simply swap your float_status rounding mode around the operation.
See the arm/tcg gen_set_rmode function.


r~



Re: [RFC PATCH v2 34/44] target/loongarch: Implement LSX fpu arith instructions

2023-04-01 Thread Richard Henderson

On 3/27/23 20:06, Song Gao wrote:

This patch includes:
- VF{ADD/SUB/MUL/DIV}.{S/D};
- VF{MADD/MSUB/NMADD/NMSUB}.{S/D};
- VF{MAX/MIN}.{S/D};
- VF{MAXA/MINA}.{S/D};
- VFLOGB.{S/D};
- VFCLASS.{S/D};
- VF{SQRT/RECIP/RSQRT}.{S/D}.

Signed-off-by: Song Gao
---
  target/loongarch/cpu.h  |   4 +
  target/loongarch/disas.c|  46 +
  target/loongarch/fpu_helper.c   |   2 +-
  target/loongarch/helper.h   |  41 +
  target/loongarch/insn_trans/trans_lsx.c.inc |  55 ++
  target/loongarch/insns.decode   |  43 +
  target/loongarch/internals.h|   1 +
  target/loongarch/lsx_helper.c   | 187 
  8 files changed, 378 insertions(+), 1 deletion(-)


Reviewed-by: Richard Henderson 

r~



Re: [RFC PATCH v2 33/44] target/loongarch: Implement vfrstp

2023-04-01 Thread Richard Henderson

On 3/27/23 20:06, Song Gao wrote:

This patch includes:
- VFRSTP[I].{B/H}.

Signed-off-by: Song Gao
---
  target/loongarch/disas.c|  5 +++
  target/loongarch/helper.h   |  5 +++
  target/loongarch/insn_trans/trans_lsx.c.inc |  5 +++
  target/loongarch/insns.decode   |  5 +++
  target/loongarch/lsx_helper.c   | 41 +
  5 files changed, 61 insertions(+)


This one's obscure.  Find first negative element in Vj,
store that value in Vd element indexed by Vk?

Acked-by: Richard Henderson 


r~



Re: [RFC PATCH v2 32/44] target/loongarch: Implement vbitclr vbitset vbitrev

2023-04-01 Thread Richard Henderson

On 3/27/23 20:06, Song Gao wrote:

+#define DO_BITCLR(a, bit) (a & ~(1ul << bit))
+#define DO_BITSET(a, bit) (a | 1ul << bit)
+#define DO_BITREV(a, bit) (a ^ (1ul << bit))


ul.

Also, the *i versions should always be inline.
And it should be trivial to expand the non-i versions inline, with shl.


r~



Re: [RFC PATCH v2 31/44] target/loongarch: Implement vpcnt

2023-04-01 Thread Richard Henderson

On 3/27/23 20:06, Song Gao wrote:

+static uint64_t do_vpcnt(uint64_t u1)
+{
+u1 = (u1 & 0xULL) + ((u1 >>  1) & 0xULL);
+u1 = (u1 & 0xULL) + ((u1 >>  2) & 0xULL);
+u1 = (u1 & 0x0F0F0F0F0F0F0F0FULL) + ((u1 >>  4) & 0x0F0F0F0F0F0F0F0FULL);
+u1 = (u1 & 0x00FF00FF00FF00FFULL) + ((u1 >>  8) & 0x00FF00FF00FF00FFULL);
+u1 = (u1 & 0xULL) + ((u1 >> 16) & 0xULL);
+u1 = (u1 & 0xULL) + ((u1 >> 32));
+
+return u1;
+}
+
+#define VPCNT(NAME, BIT, E, T)  \
+void HELPER(NAME)(CPULoongArchState *env, uint32_t vd, uint32_t vj) \
+{   \
+int i;  \
+VReg *Vd = &(env->fpr[vd].vreg);\
+VReg *Vj = &(env->fpr[vj].vreg);\
+\
+for (i = 0; i < LSX_LEN/BIT; i++)   \
+{   \
+Vd->E(i) = do_vpcnt((T)Vj->E(i));   \
+}   \
+}
+
+VPCNT(vpcnt_b, 8, B, uint8_t)
+VPCNT(vpcnt_h, 16, H, uint16_t)
+VPCNT(vpcnt_w, 32, W, uint32_t)
+VPCNT(vpcnt_d, 64, D, uint64_t)


host-utils.h has ctpop{8,16,32,64}.


r~



Re: [RFC PATCH v2 30/44] target/loongarch: Implement vclo vclz

2023-04-01 Thread Richard Henderson

On 3/27/23 20:06, Song Gao wrote:

+#define DO_CLO_B(N)  (clz32((uint8_t)~N) - 24)
+#define DO_CLO_H(N)  (clz32((uint16_t)~N) - 16)


I think this is wrong.  You *want* the high bits to be set, so that they are ones, and 
included in the count, which you then subtract off.  You want the "real" count to start 
after the 24th leading 1.



r~



Re: [RFC PATCH v2 29/44] target/loongarch: Implement vssrlrn vssrarn

2023-04-01 Thread Richard Henderson

On 3/27/23 20:06, Song Gao wrote:

+#define SSRLRNS(E1, E2, T1, T2, T3)\
+static T1 do_ssrlrns_ ## E1(T2 e2, int sa, int sh) \
+{  \
+T1 shft_res;   \
+   \
+shft_res = do_vsrlr_ ## E2(e2, sa);\
+T1 mask;   \
+mask = (1ul << sh) -1; \


I've probably missed other instances in review, but "ul" and "l" are *always* 
incorrect.

For 32-bit hosts, this is not wide enough.
If it were, "u" or no suffix would have been sufficient.

For uses like this, MAKE_64BIT_MASK(0, sh) is what you want.
For other kinds of uses, "ull" or "ll" is correct.


r~



Re: [RFC PATCH v2 28/44] target/loongarch: Implement vssrln vssran

2023-04-01 Thread Richard Henderson

On 3/27/23 20:06, Song Gao wrote:

This patch includes:
- VSSRLN.{B.H/H.W/W.D};
- VSSRAN.{B.H/H.W/W.D};
- VSSRLN.{BU.H/HU.W/WU.D};
- VSSRAN.{BU.H/HU.W/WU.D};
- VSSRLNI.{B.H/H.W/W.D/D.Q};
- VSSRANI.{B.H/H.W/W.D/D.Q};
- VSSRLNI.{BU.H/HU.W/WU.D/DU.Q};
- VSSRANI.{BU.H/HU.W/WU.D/DU.Q}.

Signed-off-by: Song Gao
---
  target/loongarch/disas.c|  30 ++
  target/loongarch/helper.h   |  30 ++
  target/loongarch/insn_trans/trans_lsx.c.inc |  30 ++
  target/loongarch/insns.decode   |  30 ++
  target/loongarch/lsx_helper.c   | 383 
  5 files changed, 503 insertions(+)


Reviewed-by: Richard Henderson 

r~



Re: [PATCH v2 6/6] target/ppc: Implement HEIR SPR

2023-04-01 Thread Nicholas Piggin
On Wed Mar 29, 2023 at 3:51 PM AEST, Michael Neuling wrote:
> Nick,
>
> > +case POWERPC_EXCP_HV_EMU:
> > +env->spr[SPR_HEIR] = insn;
> > +if (is_prefix_excp(env, insn)) {
> > +uint32_t insn2 = ppc_ldl_code(env, env->nip + 4);
> > +env->spr[SPR_HEIR] |= (uint64_t)insn2 << 32;
>
> Are inst and inst2 in the right locations here? I think you might need
> insn in the top half and insn2 in the bottom.
>
> I wrote the little test case below. I'd expect GPR0 and GPR1 to end up
> with the same value, but they don't with this code

You're right. I was a bit confused becaue the prefix instructions are
treated as two words, so ld (insn) in little endian doesn't match
HEIR, for example.

The ISA uses the term "image", but that's only really defined for 4
byte instructions AFAIKS. You can deduce though,

  There may be circumstances in which the suffix cannot be loaded [...]
  In such circumstances, bits 32:63 are set to 0s.

So prefix word goes in the high bits. Real P10 agrees, so does
systemsim. I'll fix and re-send.

Is there any better semantics in the ISA or should I raise an issue to
clarify instruction image for prefix?

Thanks,
Nick



Re: [RESEND PATCH v5 4/6] target/riscv: Add support for PC-relative translation

2023-04-01 Thread LIU Zhiwei



On 2023/4/1 20:49, Weiwei Li wrote:

Add a base save_pc For

pc_save for

PC-relative translation(CF_PCREL).
Diable the directly sync pc from tb by riscv_cpu_synchronize_from_tb.
Sync pc before it's used or updated from tb related pc:
real_pc = (old)env->pc + target_pc(from tb) - ctx->save_pc

pc_save in the code.

Use gen_get_target_pc to compute target address of auipc and successor
address of jalr.

Signed-off-by: Weiwei Li 
Signed-off-by: Junqiang Wang 
Reviewed-by: Richard Henderson 
---
  target/riscv/cpu.c  | 29 +-
  target/riscv/insn_trans/trans_rvi.c.inc | 14 +--
  target/riscv/translate.c| 53 +
  3 files changed, 75 insertions(+), 21 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 1e97473af2..646fa31a59 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -658,16 +658,18 @@ static vaddr riscv_cpu_get_pc(CPUState *cs)
  static void riscv_cpu_synchronize_from_tb(CPUState *cs,
const TranslationBlock *tb)
  {
-RISCVCPU *cpu = RISCV_CPU(cs);
-CPURISCVState *env = &cpu->env;
-RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
+if (!(tb_cflags(tb) & CF_PCREL)) {
+RISCVCPU *cpu = RISCV_CPU(cs);
+CPURISCVState *env = &cpu->env;
+RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
  
-tcg_debug_assert(!(cs->tcg_cflags & CF_PCREL));

+tcg_debug_assert(!(cs->tcg_cflags & CF_PCREL));
  
-if (xl == MXL_RV32) {

-env->pc = (int32_t) tb->pc;
-} else {
-env->pc = tb->pc;
+if (xl == MXL_RV32) {
+env->pc = (int32_t) tb->pc;
+} else {
+env->pc = tb->pc;
+}
  }
  }
  
@@ -693,11 +695,18 @@ static void riscv_restore_state_to_opc(CPUState *cs,

  RISCVCPU *cpu = RISCV_CPU(cs);
  CPURISCVState *env = &cpu->env;
  RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
+target_ulong pc;
+
+if (tb_cflags(tb) & CF_PCREL) {
+pc = (env->pc & TARGET_PAGE_MASK) | data[0];
+} else {
+pc = data[0];
+}
  
  if (xl == MXL_RV32) {

-env->pc = (int32_t)data[0];
+env->pc = (int32_t)pc;
  } else {
-env->pc = data[0];
+env->pc = pc;
  }
  env->bins = data[1];
  }
diff --git a/target/riscv/insn_trans/trans_rvi.c.inc 
b/target/riscv/insn_trans/trans_rvi.c.inc
index 48c73cfcfe..52ef260eff 100644
--- a/target/riscv/insn_trans/trans_rvi.c.inc
+++ b/target/riscv/insn_trans/trans_rvi.c.inc
@@ -38,7 +38,9 @@ static bool trans_lui(DisasContext *ctx, arg_lui *a)
  
  static bool trans_auipc(DisasContext *ctx, arg_auipc *a)

  {
-gen_set_gpri(ctx, a->rd, a->imm + ctx->base.pc_next);
+TCGv target_pc = dest_gpr(ctx, a->rd);
+gen_get_target_pc(target_pc, ctx, a->imm + ctx->base.pc_next);
+gen_set_gpr(ctx, a->rd, target_pc);
  return true;
  }
  
@@ -52,6 +54,7 @@ static bool trans_jalr(DisasContext *ctx, arg_jalr *a)

  {
  TCGLabel *misaligned = NULL;
  TCGv target_pc = tcg_temp_new();
+TCGv succ_pc = dest_gpr(ctx, a->rd);
  
  tcg_gen_addi_tl(target_pc, get_gpr(ctx, a->rs1, EXT_NONE), a->imm);

  tcg_gen_andi_tl(target_pc, target_pc, (target_ulong)-2);
@@ -68,7 +71,9 @@ static bool trans_jalr(DisasContext *ctx, arg_jalr *a)
  tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0x0, misaligned);
  }
  
-gen_set_gpri(ctx, a->rd, ctx->pc_succ_insn);

+gen_get_target_pc(succ_pc, ctx, ctx->pc_succ_insn);
+gen_set_gpr(ctx, a->rd, succ_pc);
+
  tcg_gen_mov_tl(cpu_pc, target_pc);
  lookup_and_goto_ptr(ctx);
  
@@ -159,6 +164,7 @@ static bool gen_branch(DisasContext *ctx, arg_b *a, TCGCond cond)

  TCGv src1 = get_gpr(ctx, a->rs1, EXT_SIGN);
  TCGv src2 = get_gpr(ctx, a->rs2, EXT_SIGN);
  target_ulong next_pc;
+target_ulong orig_pc_save = ctx->pc_save;
  
  if (get_xl(ctx) == MXL_RV128) {

  TCGv src1h = get_gprh(ctx, a->rs1);
@@ -175,6 +181,7 @@ static bool gen_branch(DisasContext *ctx, arg_b *a, TCGCond 
cond)
  
  gen_set_label(l); /* branch taken */
  
+ctx->pc_save = orig_pc_save;

  next_pc = ctx->base.pc_next + a->imm;
  if (!has_ext(ctx, RVC) && (next_pc & 0x3)) {
  /* misaligned */
@@ -182,8 +189,9 @@ static bool gen_branch(DisasContext *ctx, arg_b *a, TCGCond 
cond)
  gen_get_target_pc(target_pc, ctx, next_pc);
  gen_exception_inst_addr_mis(ctx, target_pc);
  } else {
-gen_goto_tb(ctx, 0, ctx->base.pc_next + a->imm);
+gen_goto_tb(ctx, 0, next_pc);
  }
+ctx->pc_save = -1;
  ctx->base.is_jmp = DISAS_NORETURN;
  
  return true;

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 7b5223efc2..2dd594ddae 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -59,6 +59,7 @@ typedef struct DisasContext {
  DisasContextBase base;
  /* pc_succ_insn points to the instruction following base.

Re: [PATCH v3 2/6] hw/isa/piix3: Reuse piix3_realize() in piix3_xen_realize()

2023-04-01 Thread Bernhard Beschow



Am 30. März 2023 13:00:25 UTC schrieb Anthony PERARD 
:
>On Sun, Mar 12, 2023 at 01:02:17PM +0100, Bernhard Beschow wrote:
>> This is a preparational patch for the next one to make the following
>> more obvious:
>> 
>> First, pci_bus_irqs() is now called twice in case of Xen where the
>> second call overrides the pci_set_irq_fn with the Xen variant.
>
>pci_bus_irqs() does allocates pci_bus->irq_count, so the second call in
>piix3_xen_realize() will leak `pci_bus->irq_count`. Could you look if
>pci_bus_irqs_cleanup() can be called before the second pci_bus_irqs()
>call, or maybe some other way to avoid the leak?

Thanks for catching this! I'll post a v4.

I think the most fool-proof way to fix this is to free irq_count just before 
the assignment. pci_bus_irqs_cleanup() would then have to NULL the attribute 
such that pci_bus_irqs() can be called afterwards.

BTW: I tried running qemu-system-x86_64 with PIIX4 rather than PIIX3 as Xen 
guest with my pc-piix4 branch without success. This branch essentially just 
provides slightly different PCI IDs for PIIX. Does xl or something else in Xen 
check these? If not then this means I'm still missing something. Under KVM this 
branch works just fine. Any idea?

Thanks,
Bernhard

>
>> Second, pci_bus_set_route_irq_fn() is now also called in Xen mode.
>> 
>> Signed-off-by: Bernhard Beschow 
>> Reviewed-by: Michael S. Tsirkin 
>
>Beside the leak which I think can happen only once, patch is fine:
>Reviewed-by: Anthony PERARD 
>
>Thanks,
>



Re: [PATCH 3/3] accel/tcg: Fix jump cache set in cpu_exec_loop

2023-04-01 Thread Richard Henderson

On 4/1/23 04:03, liweiwei wrote:

  mmap_unlock();
+

Blank line.


Yes, adding separation.


  /*
   * We add the TB in the virtual pc hash table
   * for the fast lookup
   */
  h = tb_jmp_cache_hash_func(pc);
-    /* Use the pc value already stored in tb->pc. */
-    qatomic_set(&cpu->tb_jmp_cache->array[h].tb, tb);
+    jc = cpu->tb_jmp_cache;
+    if (cflags & CF_PCREL) {
+    jc->array[h].pc = pc;
+    /* Ensure pc is written first. */
+    qatomic_store_release(&jc->array[h].tb, tb);


Whether we should add a qatomic_load_require() before this?


The load_acquire is already present in tb_lookup.


r~



Re: [PATCH v12 3/3] tpm: Add support for TPM device over I2C bus

2023-04-01 Thread Ninad Palsule

Hello Corey,


On 4/1/23 12:44 PM, Corey Minyard wrote:

On Fri, Mar 31, 2023 at 11:13:19AM -0500, Ninad Palsule wrote:

From: Ninad Palsule 

Qemu already supports devices attached to ISA and sysbus. This drop adds
support for the I2C bus attached TPM devices. I2C model only supports
TPM2 protocol.

This commit includes changes for the common code.
- Added I2C emulation model. Logic was added in the model to temporarily
   cache the data as I2C interface works per byte basis.
- New tpm type "tpm-tis-i2c" added for I2C support. The user has to
   provide this string on command line.

There is a stray blank line near the end of tpm_tis_i2c_send(), and
above it the if statement

I removed a blank.


+if ((i2cst->offset == 0) ||
+(i2cst->data[0] != TPM_I2C_REG_DATA_FIFO)) {
+i2cst->data[i2cst->offset++] = data;

is a bit hard to read because of the indention.  But those are really
minor nits, I didn't see anything really wrong with this.


Improved a comment to help understand this logic.

Thanks for the review.

Ninad



Reviewed-by: Corey Minyard 



Testing:
   TPM I2C device module is tested using SWTPM (software based TPM
   package). Qemu uses the rainier machine and is connected to swtpm over
   the socket interface.

   The command to start swtpm is as follows:
   $ swtpm socket --tpmstate dir=/tmp/mytpm1\
  --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock  \
  --tpm2 --log level=100

   The command to start qemu is as follows:
   $ qemu-system-arm -M rainier-bmc -nographic \
 -kernel ${IMAGEPATH}/fitImage-linux.bin \
 -dtb ${IMAGEPATH}/aspeed-bmc-ibm-rainier.dtb \
 -initrd ${IMAGEPATH}/obmc-phosphor-initramfs.rootfs.cpio.xz \
 -drive 
file=${IMAGEPATH}/obmc-phosphor-image.rootfs.wic.qcow2,if=sd,index=2 \
 -net nic -net 
user,hostfwd=:127.0.0.1:-:22,hostfwd=:127.0.0.1:2443-:443 \
 -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \
 -tpmdev emulator,id=tpm0,chardev=chrtpm \
 -device tpm-tis-i2c,tpmdev=tpm0,bus=aspeed.i2c.bus.12,address=0x2e

Signed-off-by: Ninad Palsule 
Reviewed-by: Stefan Berger 
Tested-by: Stefan Berger 
Reviewed-by: Cédric Le Goater 
Reviewed-by: Joel Stanley 
Tested-by: Joel Stanley 
---
V2:
Incorporated Stephen's review comments.
- Handled checksum related register in I2C layer
- Defined I2C interface capabilities and return those instead of
   capabilities from TPM TIS. Add required capabilities from TIS.
- Do not cache FIFO data in the I2C layer.
- Make sure that Device address change register is not passed to I2C
   layer as capability indicate that it is not supported.
- Added boundary checks.
- Make sure that bits 26-31 are zeroed for the TPM_STS register on read
- Updated Kconfig files for new define.

---
V3:
- Moved processing of register TPM_I2C_LOC_SEL in the I2C. So I2C layer
   remembers the locality and pass it to TIS on each read/write.
- The write data is no more cached in the I2C layer so the buffer size
   is reduced to 16 bytes.
- Checksum registers are now managed by the I2C layer. Added new
   function in TIS layer to return the checksum and used that to process
   the request.
- Now 2-4 byte register value will be passed to TIS layer in a single
   write call instead of 1 byte at a time. Added functions to convert
   between little endian stream of bytes to single 32 bit unsigned
   integer. Similarly 32  bit integer to stream of bytes.
- Added restriction on device change register.
- Replace few if-else statement with switch statement for clarity.
- Log warning when unknown register is received.
- Moved all register definations to acpi/tmp.h

---
V4:
Incorporated review comments from Cedric and Stefan.
- Reduced data[] size from 16 byte to 5 bytes.
- Added register name in the mapping table which can be used for
   tracing.
- Removed the endian conversion functions instead used simple logic
   provided by Stefan.
- Rename I2C registers to reduce the length.
- Added traces for send, recv and event functions. You can turn on trace
   on command line by using "-trace "tpm_tis_i2c*" option.

---
V5:
Fixed issues reported by Stefan's test.
- Added mask for the INT_ENABLE register.
- Use correct TIS register for reading interrupt capability.
- Cleanup how register is converted from I2C to TIS and also saved
   information like tis_addr and register name in the i2cst so that we
   can only convert it once on i2c_send.
- Trace register number for unknown registers.

---
V6:
Fixed review comments from Stefan.
- Fixed some variable size.
- Removed unused variables.
- Added vmstat backin to handle migration.
- Added post load phase to reload tis address and register name.

---
V7:
Incorporated review comments from Stefan.
- Added tpm_tis_i2c_initfn function
- Set the device catagory DEVICE_CATEGORY_MISC.
- Corrected default locality selection.
- Other cleanup. Include file cleanup.

---
V8:
Incorpora

Re: [PATCH v4] hostmem-file: add offset option

2023-04-01 Thread Stefan Hajnoczi
On Sat, Apr 01, 2023 at 12:42:57PM +, Alexander Graf wrote:
> Add an option for hostmem-file to start the memory object at an offset
> into the target file. This is useful if multiple memory objects reside
> inside the same target file, such as a device node.
> 
> In particular, it's useful to map guest memory directly into /dev/mem
> for experimentation.
> 
> Signed-off-by: Alexander Graf 
> Reviewed-by: Stefan Hajnoczi 
> 
> ---
> 
> v1 -> v2:
> 
>   - add qom documentation
>   - propagate offset into truncate, size and alignment checks
> 
> v2 -> v3:
> 
>   - failed attempt at fixing typo
> 
> v2 -> v4:
> 
>   - fix typo
> ---
>  backends/hostmem-file.c | 40 +++-
>  include/exec/memory.h   |  2 ++
>  include/exec/ram_addr.h |  3 ++-
>  qapi/qom.json   |  5 +
>  qemu-options.hx |  6 +-
>  softmmu/memory.c|  3 ++-
>  softmmu/physmem.c   | 14 ++
>  7 files changed, 65 insertions(+), 8 deletions(-)

Reviewed-by: Stefan Hajnoczi 


signature.asc
Description: PGP signature


Re: [PATCH v12 3/3] tpm: Add support for TPM device over I2C bus

2023-04-01 Thread Corey Minyard
On Fri, Mar 31, 2023 at 11:13:19AM -0500, Ninad Palsule wrote:
> From: Ninad Palsule 
> 
> Qemu already supports devices attached to ISA and sysbus. This drop adds
> support for the I2C bus attached TPM devices. I2C model only supports
> TPM2 protocol.
> 
> This commit includes changes for the common code.
> - Added I2C emulation model. Logic was added in the model to temporarily
>   cache the data as I2C interface works per byte basis.
> - New tpm type "tpm-tis-i2c" added for I2C support. The user has to
>   provide this string on command line.

There is a stray blank line near the end of tpm_tis_i2c_send(), and
above it the if statement

+if ((i2cst->offset == 0) ||
+(i2cst->data[0] != TPM_I2C_REG_DATA_FIFO)) {
+i2cst->data[i2cst->offset++] = data;

is a bit hard to read because of the indention.  But those are really
minor nits, I didn't see anything really wrong with this.

Reviewed-by: Corey Minyard 


> 
> Testing:
>   TPM I2C device module is tested using SWTPM (software based TPM
>   package). Qemu uses the rainier machine and is connected to swtpm over
>   the socket interface.
> 
>   The command to start swtpm is as follows:
>   $ swtpm socket --tpmstate dir=/tmp/mytpm1\
>  --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock  \
>  --tpm2 --log level=100
> 
>   The command to start qemu is as follows:
>   $ qemu-system-arm -M rainier-bmc -nographic \
> -kernel ${IMAGEPATH}/fitImage-linux.bin \
> -dtb ${IMAGEPATH}/aspeed-bmc-ibm-rainier.dtb \
> -initrd ${IMAGEPATH}/obmc-phosphor-initramfs.rootfs.cpio.xz \
> -drive 
> file=${IMAGEPATH}/obmc-phosphor-image.rootfs.wic.qcow2,if=sd,index=2 \
> -net nic -net 
> user,hostfwd=:127.0.0.1:-:22,hostfwd=:127.0.0.1:2443-:443 \
> -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \
> -tpmdev emulator,id=tpm0,chardev=chrtpm \
> -device tpm-tis-i2c,tpmdev=tpm0,bus=aspeed.i2c.bus.12,address=0x2e
> 
> Signed-off-by: Ninad Palsule 
> Reviewed-by: Stefan Berger 
> Tested-by: Stefan Berger 
> Reviewed-by: Cédric Le Goater 
> Reviewed-by: Joel Stanley 
> Tested-by: Joel Stanley 
> ---
> V2:
> Incorporated Stephen's review comments.
> - Handled checksum related register in I2C layer
> - Defined I2C interface capabilities and return those instead of
>   capabilities from TPM TIS. Add required capabilities from TIS.
> - Do not cache FIFO data in the I2C layer.
> - Make sure that Device address change register is not passed to I2C
>   layer as capability indicate that it is not supported.
> - Added boundary checks.
> - Make sure that bits 26-31 are zeroed for the TPM_STS register on read
> - Updated Kconfig files for new define.
> 
> ---
> V3:
> - Moved processing of register TPM_I2C_LOC_SEL in the I2C. So I2C layer
>   remembers the locality and pass it to TIS on each read/write.
> - The write data is no more cached in the I2C layer so the buffer size
>   is reduced to 16 bytes.
> - Checksum registers are now managed by the I2C layer. Added new
>   function in TIS layer to return the checksum and used that to process
>   the request.
> - Now 2-4 byte register value will be passed to TIS layer in a single
>   write call instead of 1 byte at a time. Added functions to convert
>   between little endian stream of bytes to single 32 bit unsigned
>   integer. Similarly 32  bit integer to stream of bytes.
> - Added restriction on device change register.
> - Replace few if-else statement with switch statement for clarity.
> - Log warning when unknown register is received.
> - Moved all register definations to acpi/tmp.h
> 
> ---
> V4:
> Incorporated review comments from Cedric and Stefan.
> - Reduced data[] size from 16 byte to 5 bytes.
> - Added register name in the mapping table which can be used for
>   tracing.
> - Removed the endian conversion functions instead used simple logic
>   provided by Stefan.
> - Rename I2C registers to reduce the length.
> - Added traces for send, recv and event functions. You can turn on trace
>   on command line by using "-trace "tpm_tis_i2c*" option.
> 
> ---
> V5:
> Fixed issues reported by Stefan's test.
> - Added mask for the INT_ENABLE register.
> - Use correct TIS register for reading interrupt capability.
> - Cleanup how register is converted from I2C to TIS and also saved
>   information like tis_addr and register name in the i2cst so that we
>   can only convert it once on i2c_send.
> - Trace register number for unknown registers.
> 
> ---
> V6:
> Fixed review comments from Stefan.
> - Fixed some variable size.
> - Removed unused variables.
> - Added vmstat backin to handle migration.
> - Added post load phase to reload tis address and register name.
> 
> ---
> V7:
> Incorporated review comments from Stefan.
> - Added tpm_tis_i2c_initfn function
> - Set the device catagory DEVICE_CATEGORY_MISC.
> - Corrected default locality selection.
> - Other cleanup. Include file cleanup

Re: [PATCH 00/16] i3c: aspeed: Add I3C support

2023-04-01 Thread Ben Dooks
On Fri, Mar 31, 2023 at 01:01:15AM +, Joe Komlodi wrote:
> Hi all,
> 
> This series adds I3C bus support to QEMU and adds more functionality to the
> Aspeed I3C controller.
> 
> This implementation is a basic implementation that introduces IBIs
> (including hot-join), CCCs, and SDR data transfer. As-is, it doesnt support
> multi-controller buses or HDR transfers.
> 
> First we add the I3C bus and controller model. With that added we
> gradually extend the functionality of the Aspeed I3C controller so it
> can do transfers.
> 
> With that added, we add 2 targets. The first target is a mock I3C
> target. It's intended to be a very simple target just to verify that I3C
> is working on the guest. Internally, we've used it on Linux to verify
> that i3C devices can be probed and can send/receive data and send IBIs.
> 
> The second target is a remote target. The intention of this is to be
> able to communicate to a target that exists outside of QEMU.
> 
> Lastly we add hotplugging support. The hotplugging doesn't do anything too
> complicated, it just adds the device attempting to hotplug to the bus. It is
> the device's responsibility to hot-join and go through the DAA process to
> participate on the bus.
> 
> Thanks!
> Joe
> 
> Joe Komlodi (16):
>   hw/misc/aspeed_i3c: Move to i3c directory
>   hw/i3c: Add bus support
>   hw/i3c/aspeed_i3c: Add more register fields
>   hw/i3c/aspeed_i3c: Add more reset values
>   hw/i3c/aspeed_i3c: Add register RO field masks
>   hw/i3c/aspeed_i3c: Treat more registers as read-as-zero
>   hw/i3c/aspeed_i3c: Use 32 bits on MMIO writes
>   hw/i3c/aspeed_i3c: Add IRQ MMIO behavior
>   hw/i3c/aspeed_i3c: Add data TX and RX
>   hw/i3c/aspeed_i3c: Add IBI handling
>   hw/i3c/aspeed_i3c: Add ctrl MMIO handling
>   hw/i3c/aspeed_i3c: Add controller resets
>   hw/i3c: Add Mock target
>   hw/i3c: remote_i3c: Add model
>   qtest: remote_i3c: Add remote I3C qtest
>   hw/i3c: Add hotplug support

Isn't this the designware i3c ip block, and as such could we name
it so? I was going to send an i2c only version of this but it seems
you've beaten me to it and got the i3c core going.

>  hw/Kconfig|1 +
>  hw/arm/Kconfig|2 +
>  hw/i3c/Kconfig|   17 +
>  hw/i3c/aspeed_i3c.c   | 2044 +
>  hw/i3c/core.c |  646 +++
>  hw/i3c/meson.build|6 +
>  hw/i3c/mock-target.c  |  314 +
>  hw/i3c/remote-i3c.c   |  469 
>  hw/i3c/trace-events   |   52 +
>  hw/i3c/trace.h|1 +
>  hw/meson.build|1 +
>  hw/misc/aspeed_i3c.c  |  384 ---
>  hw/misc/meson.build   |1 -
>  hw/misc/trace-events  |6 -
>  include/hw/arm/aspeed_soc.h   |2 +-
>  include/hw/i3c/aspeed_i3c.h   |  207 
>  include/hw/i3c/i3c.h  |  275 +
>  include/hw/i3c/mock-target.h  |   60 +
>  include/hw/i3c/remote-i3c.h   |   72 ++
>  include/hw/misc/aspeed_i3c.h  |   48 -
>  meson.build   |1 +
>  tests/qtest/meson.build   |1 +
>  tests/qtest/remote-i3c-test.c |  610 ++
>  23 files changed, 4780 insertions(+), 440 deletions(-)
>  create mode 100644 hw/i3c/Kconfig
>  create mode 100644 hw/i3c/aspeed_i3c.c
>  create mode 100644 hw/i3c/core.c
>  create mode 100644 hw/i3c/meson.build
>  create mode 100644 hw/i3c/mock-target.c
>  create mode 100644 hw/i3c/remote-i3c.c
>  create mode 100644 hw/i3c/trace-events
>  create mode 100644 hw/i3c/trace.h
>  delete mode 100644 hw/misc/aspeed_i3c.c
>  create mode 100644 include/hw/i3c/aspeed_i3c.h
>  create mode 100644 include/hw/i3c/i3c.h
>  create mode 100644 include/hw/i3c/mock-target.h
>  create mode 100644 include/hw/i3c/remote-i3c.h
>  delete mode 100644 include/hw/misc/aspeed_i3c.h
>  create mode 100644 tests/qtest/remote-i3c-test.c
> 
> -- 
> 2.40.0.348.gf938b09366-goog
> 
> 

-- 
Ben Dooks, b...@fluff.org, http://www.fluff.org/ben/

Large Hadron Colada: A large Pina Colada that makes the universe disappear.




Re: [PATCH 0/7] bsd-user: remove bitrotted NetBSD and OpenBSD bsd-user support

2023-04-01 Thread Warner Losh
These haven't even compiled in years. Last time I polled the NetBSD and
OpenBSD communities they weren't using this and had no plans to fix.

I'd be happy to work with anybody that wanted to fix that state of affairs.

Warner

On Sat, Apr 1, 2023, 7:00 AM Reinoud Zandijk  wrote:

> Dear Qemu folks,
>
> I'll throw it in the NetBSD group for feedback.
>
> With regards,
> Reinoud
>
> On Fri, Mar 31, 2023 at 08:18:26AM -0600, Warner Losh wrote:
> > The NetBSD and OpenBSD support in bsd-user hasn't built since before the
> meson
> > conversion. It's also out of sync with many of the recent changes in the
> > bsd-user fork and has just been removed there. Remove it from master for
> the
> > same reasons: it generates a number of false positives with grep and has
> > increasingly gotten in the way. The bsd-user fork code is much more
> advanced,
> > and even it doesn't compile and is out of date. Remove this from both
> > branches. If others wish to bring it up to speed, I'm happy to help them.
> >
> > Warner Losh (7):
> >   bsd-user: Remove obsolete prototypes
> >   bsd-user: Remove netbsd system call inclusion and defines
> >   bsd-user: Remove netbsd system call tracing
> >   bsd-user: Remove openbsd system call inclusion and defines
> >   bsd-user: Remove openbsd system call tracing
> >   bsd-user: Remove netbsd directory
> >   bsd-user: Remove openbsd directory
> >
> >  bsd-user/netbsd/host-os.h|  25 --
> >  bsd-user/netbsd/os-strace.h  |   1 -
> >  bsd-user/netbsd/strace.list  | 145 ---
> >  bsd-user/netbsd/syscall_nr.h | 373 ---
> >  bsd-user/netbsd/target_os_elf.h  | 147 ---
> >  bsd-user/netbsd/target_os_siginfo.h  |  82 --
> >  bsd-user/netbsd/target_os_signal.h   |  69 -
> >  bsd-user/netbsd/target_os_stack.h|  56 
> >  bsd-user/netbsd/target_os_thread.h   |  25 --
> >  bsd-user/openbsd/host-os.h   |  25 --
> >  bsd-user/openbsd/os-strace.h |   1 -
> >  bsd-user/openbsd/strace.list | 187 --
> >  bsd-user/openbsd/syscall_nr.h| 225 
> >  bsd-user/openbsd/target_os_elf.h | 147 ---
> >  bsd-user/openbsd/target_os_siginfo.h |  82 --
> >  bsd-user/openbsd/target_os_signal.h  |  69 -
> >  bsd-user/openbsd/target_os_stack.h   |  56 
> >  bsd-user/openbsd/target_os_thread.h  |  25 --
> >  bsd-user/qemu.h  |  16 --
> >  bsd-user/strace.c|  34 ---
> >  bsd-user/syscall_defs.h  |  29 +--
> >  21 files changed, 1 insertion(+), 1818 deletions(-)
> >  delete mode 100644 bsd-user/netbsd/host-os.h
> >  delete mode 100644 bsd-user/netbsd/os-strace.h
> >  delete mode 100644 bsd-user/netbsd/strace.list
> >  delete mode 100644 bsd-user/netbsd/syscall_nr.h
> >  delete mode 100644 bsd-user/netbsd/target_os_elf.h
> >  delete mode 100644 bsd-user/netbsd/target_os_siginfo.h
> >  delete mode 100644 bsd-user/netbsd/target_os_signal.h
> >  delete mode 100644 bsd-user/netbsd/target_os_stack.h
> >  delete mode 100644 bsd-user/netbsd/target_os_thread.h
> >  delete mode 100644 bsd-user/openbsd/host-os.h
> >  delete mode 100644 bsd-user/openbsd/os-strace.h
> >  delete mode 100644 bsd-user/openbsd/strace.list
> >  delete mode 100644 bsd-user/openbsd/syscall_nr.h
> >  delete mode 100644 bsd-user/openbsd/target_os_elf.h
> >  delete mode 100644 bsd-user/openbsd/target_os_siginfo.h
> >  delete mode 100644 bsd-user/openbsd/target_os_signal.h
> >  delete mode 100644 bsd-user/openbsd/target_os_stack.h
> >  delete mode 100644 bsd-user/openbsd/target_os_thread.h
> >
> > --
> > 2.39.2
> >
>


Re: [PATCH 0/7] bsd-user: remove bitrotted NetBSD and OpenBSD bsd-user support

2023-04-01 Thread Reinoud Zandijk
Dear Qemu folks,

I'll throw it in the NetBSD group for feedback.

With regards,
Reinoud

On Fri, Mar 31, 2023 at 08:18:26AM -0600, Warner Losh wrote:
> The NetBSD and OpenBSD support in bsd-user hasn't built since before the meson
> conversion. It's also out of sync with many of the recent changes in the
> bsd-user fork and has just been removed there. Remove it from master for the
> same reasons: it generates a number of false positives with grep and has
> increasingly gotten in the way. The bsd-user fork code is much more advanced,
> and even it doesn't compile and is out of date. Remove this from both
> branches. If others wish to bring it up to speed, I'm happy to help them.
> 
> Warner Losh (7):
>   bsd-user: Remove obsolete prototypes
>   bsd-user: Remove netbsd system call inclusion and defines
>   bsd-user: Remove netbsd system call tracing
>   bsd-user: Remove openbsd system call inclusion and defines
>   bsd-user: Remove openbsd system call tracing
>   bsd-user: Remove netbsd directory
>   bsd-user: Remove openbsd directory
> 
>  bsd-user/netbsd/host-os.h|  25 --
>  bsd-user/netbsd/os-strace.h  |   1 -
>  bsd-user/netbsd/strace.list  | 145 ---
>  bsd-user/netbsd/syscall_nr.h | 373 ---
>  bsd-user/netbsd/target_os_elf.h  | 147 ---
>  bsd-user/netbsd/target_os_siginfo.h  |  82 --
>  bsd-user/netbsd/target_os_signal.h   |  69 -
>  bsd-user/netbsd/target_os_stack.h|  56 
>  bsd-user/netbsd/target_os_thread.h   |  25 --
>  bsd-user/openbsd/host-os.h   |  25 --
>  bsd-user/openbsd/os-strace.h |   1 -
>  bsd-user/openbsd/strace.list | 187 --
>  bsd-user/openbsd/syscall_nr.h| 225 
>  bsd-user/openbsd/target_os_elf.h | 147 ---
>  bsd-user/openbsd/target_os_siginfo.h |  82 --
>  bsd-user/openbsd/target_os_signal.h  |  69 -
>  bsd-user/openbsd/target_os_stack.h   |  56 
>  bsd-user/openbsd/target_os_thread.h  |  25 --
>  bsd-user/qemu.h  |  16 --
>  bsd-user/strace.c|  34 ---
>  bsd-user/syscall_defs.h  |  29 +--
>  21 files changed, 1 insertion(+), 1818 deletions(-)
>  delete mode 100644 bsd-user/netbsd/host-os.h
>  delete mode 100644 bsd-user/netbsd/os-strace.h
>  delete mode 100644 bsd-user/netbsd/strace.list
>  delete mode 100644 bsd-user/netbsd/syscall_nr.h
>  delete mode 100644 bsd-user/netbsd/target_os_elf.h
>  delete mode 100644 bsd-user/netbsd/target_os_siginfo.h
>  delete mode 100644 bsd-user/netbsd/target_os_signal.h
>  delete mode 100644 bsd-user/netbsd/target_os_stack.h
>  delete mode 100644 bsd-user/netbsd/target_os_thread.h
>  delete mode 100644 bsd-user/openbsd/host-os.h
>  delete mode 100644 bsd-user/openbsd/os-strace.h
>  delete mode 100644 bsd-user/openbsd/strace.list
>  delete mode 100644 bsd-user/openbsd/syscall_nr.h
>  delete mode 100644 bsd-user/openbsd/target_os_elf.h
>  delete mode 100644 bsd-user/openbsd/target_os_siginfo.h
>  delete mode 100644 bsd-user/openbsd/target_os_signal.h
>  delete mode 100644 bsd-user/openbsd/target_os_stack.h
>  delete mode 100644 bsd-user/openbsd/target_os_thread.h
> 
> -- 
> 2.39.2
> 


signature.asc
Description: PGP signature


Re: [PATCH v3 0/6] target/riscv: Fix pointer mask related support

2023-04-01 Thread liweiwei



On 2023/4/1 20:39, Weiwei Li wrote:

This patchset tries to fix some problem in current implementation for pointer 
mask, and add support for pointer mask of instruction fetch.

The port is available here:
https://github.com/plctlab/plct-qemu/tree/plct-pm-fix-v5

v2:
* drop some error patchs
* Add patch 2 and 3 to fix the new problems
* Add patch 4 and 5 to use PC-relative translation for pointer mask for 
instruction fetch

v3:
* use target_pc temp instead of cpu_pc to store into badaddr in patch 3
* use dest_gpr instead of tcg_temp_new() for succ_pc in patch 4
* enable CF_PCREL for system mode in seperate patch 5

v4:
* Fix wrong pc_save value for conditional jump in patch 4
* Fix tcg_cflags overwrite problem to make CF_PCREL really work in new patch 5
* Fix tb mis-matched problem in new patch 6

v5:
* use gen_get_target_pc to compute target address of auipc and successor 
address of jalr in patch 4.
* separate tcg related fix patches(5, 6) from this patchset

Weiwei Li (6):
   target/riscv: Fix pointer mask transformation for vector address
   target/riscv: Update cur_pmmask/base when xl changes
   target/riscv: Fix target address to update badaddr
   target/riscv: Add support for PC-relative translation
   target/riscv: Enable PC-relative translation in system mode
   target/riscv: Add pointer mask support for instruction fetch

  target/riscv/cpu.c  | 31 +++
  target/riscv/cpu.h  |  1 +
  target/riscv/cpu_helper.c   | 20 ++-
  target/riscv/csr.c  | 11 ++--
  target/riscv/insn_trans/trans_rvi.c.inc | 37 +
  target/riscv/translate.c| 72 ++---
  target/riscv/vector_helper.c|  2 +-
  7 files changed, 131 insertions(+), 43 deletions(-)


Sorry for the wrong version number in Subject. I have re-sent it.

Regards,

Weiwei Li




[RESEND PATCH v5 2/6] target/riscv: Update cur_pmmask/base when xl changes

2023-04-01 Thread Weiwei Li
write_mstatus() can only change current xl when in debug mode.
And we need update cur_pmmask/base in this case.

Signed-off-by: Weiwei Li 
Signed-off-by: Junqiang Wang 
Reviewed-by: LIU Zhiwei 
---
 target/riscv/csr.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index d522efc0b6..43b9ad4500 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1277,8 +1277,15 @@ static RISCVException write_mstatus(CPURISCVState *env, 
int csrno,
 mstatus = set_field(mstatus, MSTATUS64_SXL, xl);
 }
 env->mstatus = mstatus;
-env->xl = cpu_recompute_xl(env);
 
+/*
+ * Except in debug mode, UXL/SXL can only be modified by higher
+ * privilege mode. So xl will not be changed in normal mode.
+ */
+if (env->debugger) {
+env->xl = cpu_recompute_xl(env);
+riscv_cpu_update_mask(env);
+}
 return RISCV_EXCP_NONE;
 }
 
-- 
2.25.1




[RESEND PATCH v5 0/6] target/riscv: Fix pointer mask related support

2023-04-01 Thread Weiwei Li
This patchset tries to fix some problem in current implementation for pointer 
mask, and add support for pointer mask of instruction fetch.

The port is available here:
https://github.com/plctlab/plct-qemu/tree/plct-pm-fix-v5

v2:
* drop some error patchs
* Add patch 2 and 3 to fix the new problems
* Add patch 4 and 5 to use PC-relative translation for pointer mask for 
instruction fetch

v3:
* use target_pc temp instead of cpu_pc to store into badaddr in patch 3
* use dest_gpr instead of tcg_temp_new() for succ_pc in patch 4
* enable CF_PCREL for system mode in seperate patch 5

v4:
* Fix wrong pc_save value for conditional jump in patch 4
* Fix tcg_cflags overwrite problem to make CF_PCREL really work in new patch 5
* Fix tb mis-matched problem in new patch 6

v5:
* use gen_get_target_pc to compute target address of auipc and successor 
address of jalr in patch 4.
* separate tcg related fix patches(5, 6) from this patchset

Weiwei Li (6):
  target/riscv: Fix pointer mask transformation for vector address
  target/riscv: Update cur_pmmask/base when xl changes
  target/riscv: Fix target address to update badaddr
  target/riscv: Add support for PC-relative translation
  target/riscv: Enable PC-relative translation in system mode
  target/riscv: Add pointer mask support for instruction fetch

 target/riscv/cpu.c  | 31 +++
 target/riscv/cpu.h  |  1 +
 target/riscv/cpu_helper.c   | 20 ++-
 target/riscv/csr.c  | 11 ++--
 target/riscv/insn_trans/trans_rvi.c.inc | 37 +
 target/riscv/translate.c| 72 ++---
 target/riscv/vector_helper.c|  2 +-
 7 files changed, 131 insertions(+), 43 deletions(-)

-- 
2.25.1




[RESEND PATCH v5 1/6] target/riscv: Fix pointer mask transformation for vector address

2023-04-01 Thread Weiwei Li
actual_address = (requested_address & ~mpmmask) | mpmbase.

Signed-off-by: Weiwei Li 
Signed-off-by: Junqiang Wang 
Reviewed-by: Daniel Henrique Barboza 
Reviewed-by: LIU Zhiwei 
---
 target/riscv/vector_helper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
index 2423affe37..a58d82af8c 100644
--- a/target/riscv/vector_helper.c
+++ b/target/riscv/vector_helper.c
@@ -172,7 +172,7 @@ static inline uint32_t vext_get_total_elems(CPURISCVState 
*env, uint32_t desc,
 
 static inline target_ulong adjust_addr(CPURISCVState *env, target_ulong addr)
 {
-return (addr & env->cur_pmmask) | env->cur_pmbase;
+return (addr & ~env->cur_pmmask) | env->cur_pmbase;
 }
 
 /*
-- 
2.25.1




[RESEND PATCH v5 5/6] target/riscv: Enable PC-relative translation in system mode

2023-04-01 Thread Weiwei Li
The existence of CF_PCREL can improve performance with the guest
kernel's address space randomization.  Each guest process maps
libc.so (et al) at a different virtual address, and this allows
those translations to be shared.

Signed-off-by: Weiwei Li 
Signed-off-by: Junqiang Wang 
Reviewed-by: LIU Zhiwei 
Reviewed-by: Richard Henderson 
---
 target/riscv/cpu.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 646fa31a59..3b562d5d9f 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1193,6 +1193,8 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 
 
 #ifndef CONFIG_USER_ONLY
+cs->tcg_cflags |= CF_PCREL;
+
 if (cpu->cfg.ext_sstc) {
 riscv_timer_init(cpu);
 }
-- 
2.25.1




[RESEND PATCH v5 3/6] target/riscv: Fix target address to update badaddr

2023-04-01 Thread Weiwei Li
Compute the target address  before storing it into badaddr
when mis-aligned exception is triggered.
Use a target_pc temp to store the target address to avoid
the confusing operation that udpate target address into
cpu_pc before misalign check, then update it into badaddr
and restore cpu_pc to current pc if exception is triggered.

Signed-off-by: Weiwei Li 
Signed-off-by: Junqiang Wang 
Reviewed-by: Richard Henderson 
---
 target/riscv/insn_trans/trans_rvi.c.inc | 23 ---
 target/riscv/translate.c| 21 ++---
 2 files changed, 26 insertions(+), 18 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rvi.c.inc 
b/target/riscv/insn_trans/trans_rvi.c.inc
index 4ad54e8a49..48c73cfcfe 100644
--- a/target/riscv/insn_trans/trans_rvi.c.inc
+++ b/target/riscv/insn_trans/trans_rvi.c.inc
@@ -51,25 +51,30 @@ static bool trans_jal(DisasContext *ctx, arg_jal *a)
 static bool trans_jalr(DisasContext *ctx, arg_jalr *a)
 {
 TCGLabel *misaligned = NULL;
+TCGv target_pc = tcg_temp_new();
 
-tcg_gen_addi_tl(cpu_pc, get_gpr(ctx, a->rs1, EXT_NONE), a->imm);
-tcg_gen_andi_tl(cpu_pc, cpu_pc, (target_ulong)-2);
+tcg_gen_addi_tl(target_pc, get_gpr(ctx, a->rs1, EXT_NONE), a->imm);
+tcg_gen_andi_tl(target_pc, target_pc, (target_ulong)-2);
+
+if (get_xl(ctx) == MXL_RV32) {
+tcg_gen_ext32s_tl(target_pc, target_pc);
+}
 
-gen_set_pc(ctx, cpu_pc);
 if (!has_ext(ctx, RVC)) {
 TCGv t0 = tcg_temp_new();
 
 misaligned = gen_new_label();
-tcg_gen_andi_tl(t0, cpu_pc, 0x2);
+tcg_gen_andi_tl(t0, target_pc, 0x2);
 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0x0, misaligned);
 }
 
 gen_set_gpri(ctx, a->rd, ctx->pc_succ_insn);
+tcg_gen_mov_tl(cpu_pc, target_pc);
 lookup_and_goto_ptr(ctx);
 
 if (misaligned) {
 gen_set_label(misaligned);
-gen_exception_inst_addr_mis(ctx);
+gen_exception_inst_addr_mis(ctx, target_pc);
 }
 ctx->base.is_jmp = DISAS_NORETURN;
 
@@ -153,6 +158,7 @@ static bool gen_branch(DisasContext *ctx, arg_b *a, TCGCond 
cond)
 TCGLabel *l = gen_new_label();
 TCGv src1 = get_gpr(ctx, a->rs1, EXT_SIGN);
 TCGv src2 = get_gpr(ctx, a->rs2, EXT_SIGN);
+target_ulong next_pc;
 
 if (get_xl(ctx) == MXL_RV128) {
 TCGv src1h = get_gprh(ctx, a->rs1);
@@ -169,9 +175,12 @@ static bool gen_branch(DisasContext *ctx, arg_b *a, 
TCGCond cond)
 
 gen_set_label(l); /* branch taken */
 
-if (!has_ext(ctx, RVC) && ((ctx->base.pc_next + a->imm) & 0x3)) {
+next_pc = ctx->base.pc_next + a->imm;
+if (!has_ext(ctx, RVC) && (next_pc & 0x3)) {
 /* misaligned */
-gen_exception_inst_addr_mis(ctx);
+TCGv target_pc = tcg_temp_new();
+gen_get_target_pc(target_pc, ctx, next_pc);
+gen_exception_inst_addr_mis(ctx, target_pc);
 } else {
 gen_goto_tb(ctx, 0, ctx->base.pc_next + a->imm);
 }
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 0ee8ee147d..7b5223efc2 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -222,21 +222,18 @@ static void decode_save_opc(DisasContext *ctx)
 ctx->insn_start = NULL;
 }
 
-static void gen_set_pc_imm(DisasContext *ctx, target_ulong dest)
+static void gen_get_target_pc(TCGv target, DisasContext *ctx,
+  target_ulong dest)
 {
 if (get_xl(ctx) == MXL_RV32) {
 dest = (int32_t)dest;
 }
-tcg_gen_movi_tl(cpu_pc, dest);
+tcg_gen_movi_tl(target, dest);
 }
 
-static void gen_set_pc(DisasContext *ctx, TCGv dest)
+static void gen_set_pc_imm(DisasContext *ctx, target_ulong dest)
 {
-if (get_xl(ctx) == MXL_RV32) {
-tcg_gen_ext32s_tl(cpu_pc, dest);
-} else {
-tcg_gen_mov_tl(cpu_pc, dest);
-}
+gen_get_target_pc(cpu_pc, ctx, dest);
 }
 
 static void generate_exception(DisasContext *ctx, int excp)
@@ -257,9 +254,9 @@ static void gen_exception_illegal(DisasContext *ctx)
 }
 }
 
-static void gen_exception_inst_addr_mis(DisasContext *ctx)
+static void gen_exception_inst_addr_mis(DisasContext *ctx, TCGv target)
 {
-tcg_gen_st_tl(cpu_pc, cpu_env, offsetof(CPURISCVState, badaddr));
+tcg_gen_st_tl(target, cpu_env, offsetof(CPURISCVState, badaddr));
 generate_exception(ctx, RISCV_EXCP_INST_ADDR_MIS);
 }
 
@@ -551,7 +548,9 @@ static void gen_jal(DisasContext *ctx, int rd, target_ulong 
imm)
 next_pc = ctx->base.pc_next + imm;
 if (!has_ext(ctx, RVC)) {
 if ((next_pc & 0x3) != 0) {
-gen_exception_inst_addr_mis(ctx);
+TCGv target_pc = tcg_temp_new();
+gen_get_target_pc(target_pc, ctx, next_pc);
+gen_exception_inst_addr_mis(ctx, target_pc);
 return;
 }
 }
-- 
2.25.1




[RESEND PATCH v5 4/6] target/riscv: Add support for PC-relative translation

2023-04-01 Thread Weiwei Li
Add a base save_pc For PC-relative translation(CF_PCREL).
Diable the directly sync pc from tb by riscv_cpu_synchronize_from_tb.
Sync pc before it's used or updated from tb related pc:
   real_pc = (old)env->pc + target_pc(from tb) - ctx->save_pc
Use gen_get_target_pc to compute target address of auipc and successor
address of jalr.

Signed-off-by: Weiwei Li 
Signed-off-by: Junqiang Wang 
Reviewed-by: Richard Henderson 
---
 target/riscv/cpu.c  | 29 +-
 target/riscv/insn_trans/trans_rvi.c.inc | 14 +--
 target/riscv/translate.c| 53 +
 3 files changed, 75 insertions(+), 21 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 1e97473af2..646fa31a59 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -658,16 +658,18 @@ static vaddr riscv_cpu_get_pc(CPUState *cs)
 static void riscv_cpu_synchronize_from_tb(CPUState *cs,
   const TranslationBlock *tb)
 {
-RISCVCPU *cpu = RISCV_CPU(cs);
-CPURISCVState *env = &cpu->env;
-RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
+if (!(tb_cflags(tb) & CF_PCREL)) {
+RISCVCPU *cpu = RISCV_CPU(cs);
+CPURISCVState *env = &cpu->env;
+RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
 
-tcg_debug_assert(!(cs->tcg_cflags & CF_PCREL));
+tcg_debug_assert(!(cs->tcg_cflags & CF_PCREL));
 
-if (xl == MXL_RV32) {
-env->pc = (int32_t) tb->pc;
-} else {
-env->pc = tb->pc;
+if (xl == MXL_RV32) {
+env->pc = (int32_t) tb->pc;
+} else {
+env->pc = tb->pc;
+}
 }
 }
 
@@ -693,11 +695,18 @@ static void riscv_restore_state_to_opc(CPUState *cs,
 RISCVCPU *cpu = RISCV_CPU(cs);
 CPURISCVState *env = &cpu->env;
 RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
+target_ulong pc;
+
+if (tb_cflags(tb) & CF_PCREL) {
+pc = (env->pc & TARGET_PAGE_MASK) | data[0];
+} else {
+pc = data[0];
+}
 
 if (xl == MXL_RV32) {
-env->pc = (int32_t)data[0];
+env->pc = (int32_t)pc;
 } else {
-env->pc = data[0];
+env->pc = pc;
 }
 env->bins = data[1];
 }
diff --git a/target/riscv/insn_trans/trans_rvi.c.inc 
b/target/riscv/insn_trans/trans_rvi.c.inc
index 48c73cfcfe..52ef260eff 100644
--- a/target/riscv/insn_trans/trans_rvi.c.inc
+++ b/target/riscv/insn_trans/trans_rvi.c.inc
@@ -38,7 +38,9 @@ static bool trans_lui(DisasContext *ctx, arg_lui *a)
 
 static bool trans_auipc(DisasContext *ctx, arg_auipc *a)
 {
-gen_set_gpri(ctx, a->rd, a->imm + ctx->base.pc_next);
+TCGv target_pc = dest_gpr(ctx, a->rd);
+gen_get_target_pc(target_pc, ctx, a->imm + ctx->base.pc_next);
+gen_set_gpr(ctx, a->rd, target_pc);
 return true;
 }
 
@@ -52,6 +54,7 @@ static bool trans_jalr(DisasContext *ctx, arg_jalr *a)
 {
 TCGLabel *misaligned = NULL;
 TCGv target_pc = tcg_temp_new();
+TCGv succ_pc = dest_gpr(ctx, a->rd);
 
 tcg_gen_addi_tl(target_pc, get_gpr(ctx, a->rs1, EXT_NONE), a->imm);
 tcg_gen_andi_tl(target_pc, target_pc, (target_ulong)-2);
@@ -68,7 +71,9 @@ static bool trans_jalr(DisasContext *ctx, arg_jalr *a)
 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0x0, misaligned);
 }
 
-gen_set_gpri(ctx, a->rd, ctx->pc_succ_insn);
+gen_get_target_pc(succ_pc, ctx, ctx->pc_succ_insn);
+gen_set_gpr(ctx, a->rd, succ_pc);
+
 tcg_gen_mov_tl(cpu_pc, target_pc);
 lookup_and_goto_ptr(ctx);
 
@@ -159,6 +164,7 @@ static bool gen_branch(DisasContext *ctx, arg_b *a, TCGCond 
cond)
 TCGv src1 = get_gpr(ctx, a->rs1, EXT_SIGN);
 TCGv src2 = get_gpr(ctx, a->rs2, EXT_SIGN);
 target_ulong next_pc;
+target_ulong orig_pc_save = ctx->pc_save;
 
 if (get_xl(ctx) == MXL_RV128) {
 TCGv src1h = get_gprh(ctx, a->rs1);
@@ -175,6 +181,7 @@ static bool gen_branch(DisasContext *ctx, arg_b *a, TCGCond 
cond)
 
 gen_set_label(l); /* branch taken */
 
+ctx->pc_save = orig_pc_save;
 next_pc = ctx->base.pc_next + a->imm;
 if (!has_ext(ctx, RVC) && (next_pc & 0x3)) {
 /* misaligned */
@@ -182,8 +189,9 @@ static bool gen_branch(DisasContext *ctx, arg_b *a, TCGCond 
cond)
 gen_get_target_pc(target_pc, ctx, next_pc);
 gen_exception_inst_addr_mis(ctx, target_pc);
 } else {
-gen_goto_tb(ctx, 0, ctx->base.pc_next + a->imm);
+gen_goto_tb(ctx, 0, next_pc);
 }
+ctx->pc_save = -1;
 ctx->base.is_jmp = DISAS_NORETURN;
 
 return true;
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 7b5223efc2..2dd594ddae 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -59,6 +59,7 @@ typedef struct DisasContext {
 DisasContextBase base;
 /* pc_succ_insn points to the instruction following base.pc_next */
 target_ulong pc_succ_insn;
+target_ulong pc_save;
 target_ulong priv_ver;
 RISCVMXL misa_mxl_max;
 RISCVMXL xl;
@@ -2

[RESEND PATCH v5 6/6] target/riscv: Add pointer mask support for instruction fetch

2023-04-01 Thread Weiwei Li
Transform the fetch address in cpu_get_tb_cpu_state() when pointer
mask for instruction is enabled.

Signed-off-by: Weiwei Li 
Signed-off-by: Junqiang Wang 
Reviewed-by: Richard Henderson 
---
 target/riscv/cpu.h|  1 +
 target/riscv/cpu_helper.c | 20 +++-
 target/riscv/csr.c|  2 --
 3 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 638e47c75a..57bd9c3279 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -368,6 +368,7 @@ struct CPUArchState {
 #endif
 target_ulong cur_pmmask;
 target_ulong cur_pmbase;
+bool cur_pminsn;
 
 /* Fields from here on are preserved across CPU reset. */
 QEMUTimer *stimer; /* Internal timer for S-mode interrupt */
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index f88c503cf4..b683a770fe 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -40,6 +40,19 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
 #endif
 }
 
+static target_ulong adjust_pc_address(CPURISCVState *env, target_ulong pc)
+{
+target_ulong adjust_pc = pc;
+
+if (env->cur_pminsn) {
+adjust_pc = (adjust_pc & ~env->cur_pmmask) | env->cur_pmbase;
+} else if (env->xl == MXL_RV32) {
+adjust_pc &= UINT32_MAX;
+}
+
+return adjust_pc;
+}
+
 void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
   target_ulong *cs_base, uint32_t *pflags)
 {
@@ -48,7 +61,7 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong 
*pc,
 
 uint32_t flags = 0;
 
-*pc = env->xl == MXL_RV32 ? env->pc & UINT32_MAX : env->pc;
+*pc = adjust_pc_address(env, env->pc);
 *cs_base = 0;
 
 if (cpu->cfg.ext_zve32f) {
@@ -124,6 +137,7 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong 
*pc,
 void riscv_cpu_update_mask(CPURISCVState *env)
 {
 target_ulong mask = -1, base = 0;
+bool insn = false;
 /*
  * TODO: Current RVJ spec does not specify
  * how the extension interacts with XLEN.
@@ -135,18 +149,21 @@ void riscv_cpu_update_mask(CPURISCVState *env)
 if (env->mmte & M_PM_ENABLE) {
 mask = env->mpmmask;
 base = env->mpmbase;
+insn = env->mmte & MMTE_M_PM_INSN;
 }
 break;
 case PRV_S:
 if (env->mmte & S_PM_ENABLE) {
 mask = env->spmmask;
 base = env->spmbase;
+insn = env->mmte & MMTE_S_PM_INSN;
 }
 break;
 case PRV_U:
 if (env->mmte & U_PM_ENABLE) {
 mask = env->upmmask;
 base = env->upmbase;
+insn = env->mmte & MMTE_U_PM_INSN;
 }
 break;
 default:
@@ -161,6 +178,7 @@ void riscv_cpu_update_mask(CPURISCVState *env)
 env->cur_pmmask = mask;
 env->cur_pmbase = base;
 }
+env->cur_pminsn = insn;
 }
 
 #ifndef CONFIG_USER_ONLY
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 43b9ad4500..0902b64129 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -3518,8 +3518,6 @@ static RISCVException write_mmte(CPURISCVState *env, int 
csrno,
 /* for machine mode pm.current is hardwired to 1 */
 wpri_val |= MMTE_M_PM_CURRENT;
 
-/* hardwiring pm.instruction bit to 0, since it's not supported yet */
-wpri_val &= ~(MMTE_M_PM_INSN | MMTE_S_PM_INSN | MMTE_U_PM_INSN);
 env->mmte = wpri_val | PM_EXT_DIRTY;
 riscv_cpu_update_mask(env);
 
-- 
2.25.1




[PATCH v4] hostmem-file: add offset option

2023-04-01 Thread Alexander Graf
Add an option for hostmem-file to start the memory object at an offset
into the target file. This is useful if multiple memory objects reside
inside the same target file, such as a device node.

In particular, it's useful to map guest memory directly into /dev/mem
for experimentation.

Signed-off-by: Alexander Graf 
Reviewed-by: Stefan Hajnoczi 

---

v1 -> v2:

  - add qom documentation
  - propagate offset into truncate, size and alignment checks

v2 -> v3:

  - failed attempt at fixing typo

v2 -> v4:

  - fix typo
---
 backends/hostmem-file.c | 40 +++-
 include/exec/memory.h   |  2 ++
 include/exec/ram_addr.h |  3 ++-
 qapi/qom.json   |  5 +
 qemu-options.hx |  6 +-
 softmmu/memory.c|  3 ++-
 softmmu/physmem.c   | 14 ++
 7 files changed, 65 insertions(+), 8 deletions(-)

diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c
index 25141283c4..38ea65bec5 100644
--- a/backends/hostmem-file.c
+++ b/backends/hostmem-file.c
@@ -27,6 +27,7 @@ struct HostMemoryBackendFile {
 
 char *mem_path;
 uint64_t align;
+uint64_t offset;
 bool discard_data;
 bool is_pmem;
 bool readonly;
@@ -58,7 +59,8 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error 
**errp)
 ram_flags |= fb->is_pmem ? RAM_PMEM : 0;
 memory_region_init_ram_from_file(&backend->mr, OBJECT(backend), name,
  backend->size, fb->align, ram_flags,
- fb->mem_path, fb->readonly, errp);
+ fb->mem_path, fb->offset, fb->readonly,
+ errp);
 g_free(name);
 #endif
 }
@@ -125,6 +127,36 @@ static void file_memory_backend_set_align(Object *o, 
Visitor *v,
 fb->align = val;
 }
 
+static void file_memory_backend_get_offset(Object *o, Visitor *v,
+  const char *name, void *opaque,
+  Error **errp)
+{
+HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
+uint64_t val = fb->offset;
+
+visit_type_size(v, name, &val, errp);
+}
+
+static void file_memory_backend_set_offset(Object *o, Visitor *v,
+  const char *name, void *opaque,
+  Error **errp)
+{
+HostMemoryBackend *backend = MEMORY_BACKEND(o);
+HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
+uint64_t val;
+
+if (host_memory_backend_mr_inited(backend)) {
+error_setg(errp, "cannot change property '%s' of %s", name,
+   object_get_typename(o));
+return;
+}
+
+if (!visit_type_size(v, name, &val, errp)) {
+return;
+}
+fb->offset = val;
+}
+
 #ifdef CONFIG_LIBPMEM
 static bool file_memory_backend_get_pmem(Object *o, Error **errp)
 {
@@ -197,6 +229,12 @@ file_backend_class_init(ObjectClass *oc, void *data)
 file_memory_backend_get_align,
 file_memory_backend_set_align,
 NULL, NULL);
+object_class_property_add(oc, "offset", "int",
+file_memory_backend_get_offset,
+file_memory_backend_set_offset,
+NULL, NULL);
+object_class_property_set_description(oc, "offset",
+"Offset into the target file (ex: 1G)");
 #ifdef CONFIG_LIBPMEM
 object_class_property_add_bool(oc, "pmem",
 file_memory_backend_get_pmem, file_memory_backend_set_pmem);
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 15ade918ba..3b7295fbe2 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -1318,6 +1318,7 @@ void memory_region_init_resizeable_ram(MemoryRegion *mr,
  * @ram_flags: RamBlock flags. Supported flags: RAM_SHARED, RAM_PMEM,
  * RAM_NORESERVE,
  * @path: the path in which to allocate the RAM.
+ * @offset: offset within the file referenced by path
  * @readonly: true to open @path for reading, false for read/write.
  * @errp: pointer to Error*, to store an error if it happens.
  *
@@ -1331,6 +1332,7 @@ void memory_region_init_ram_from_file(MemoryRegion *mr,
   uint64_t align,
   uint32_t ram_flags,
   const char *path,
+  ram_addr_t offset,
   bool readonly,
   Error **errp);
 
diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
index f4fb6a2111..90a8269290 100644
--- a/include/exec/ram_addr.h
+++ b/include/exec/ram_addr.h
@@ -110,6 +110,7 @@ long qemu_maxrampagesize(void);
  *  @ram_flags: RamBlock flags. Supported flags: RAM_SHARED, RAM_PMEM,
  *  RAM_NORESERVE.
  *  @mem_path or @fd: specify the backing file or device
+ *  @offset: Offset into target file
  *  @readonly: true to open @path for reading, false for read/write.
  *  @errp: pointer to Error*, to store an error if it hap

[PATCH v3] hostmem-file: add offset option

2023-04-01 Thread Alexander Graf
Add an option for hostmem-file to start the memory object at an offset
into the target file. This is useful if multiple memory objects reside
inside the same target file, such as a device node.

In particular, it's useful to map guest memory directly into /dev/mem
for experimentation.

Signed-off-by: Alexander Graf 
Reviewed-by: Stefan Hajnoczi 

---

v1 -> v2:

  - add qom documentation
  - propagate offset into truncate, size and alignment checks

v2 -> v3:

  - fix typo
---
 backends/hostmem-file.c | 40 +++-
 include/exec/memory.h   |  2 ++
 include/exec/ram_addr.h |  3 ++-
 qapi/qom.json   |  5 +
 qemu-options.hx |  6 +-
 softmmu/memory.c|  3 ++-
 softmmu/physmem.c   | 14 ++
 7 files changed, 65 insertions(+), 8 deletions(-)

diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c
index 25141283c4..38ea65bec5 100644
--- a/backends/hostmem-file.c
+++ b/backends/hostmem-file.c
@@ -27,6 +27,7 @@ struct HostMemoryBackendFile {
 
 char *mem_path;
 uint64_t align;
+uint64_t offset;
 bool discard_data;
 bool is_pmem;
 bool readonly;
@@ -58,7 +59,8 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error 
**errp)
 ram_flags |= fb->is_pmem ? RAM_PMEM : 0;
 memory_region_init_ram_from_file(&backend->mr, OBJECT(backend), name,
  backend->size, fb->align, ram_flags,
- fb->mem_path, fb->readonly, errp);
+ fb->mem_path, fb->offset, fb->readonly,
+ errp);
 g_free(name);
 #endif
 }
@@ -125,6 +127,36 @@ static void file_memory_backend_set_align(Object *o, 
Visitor *v,
 fb->align = val;
 }
 
+static void file_memory_backend_get_offset(Object *o, Visitor *v,
+  const char *name, void *opaque,
+  Error **errp)
+{
+HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
+uint64_t val = fb->offset;
+
+visit_type_size(v, name, &val, errp);
+}
+
+static void file_memory_backend_set_offset(Object *o, Visitor *v,
+  const char *name, void *opaque,
+  Error **errp)
+{
+HostMemoryBackend *backend = MEMORY_BACKEND(o);
+HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
+uint64_t val;
+
+if (host_memory_backend_mr_inited(backend)) {
+error_setg(errp, "cannot change property '%s' of %s", name,
+   object_get_typename(o));
+return;
+}
+
+if (!visit_type_size(v, name, &val, errp)) {
+return;
+}
+fb->offset = val;
+}
+
 #ifdef CONFIG_LIBPMEM
 static bool file_memory_backend_get_pmem(Object *o, Error **errp)
 {
@@ -197,6 +229,12 @@ file_backend_class_init(ObjectClass *oc, void *data)
 file_memory_backend_get_align,
 file_memory_backend_set_align,
 NULL, NULL);
+object_class_property_add(oc, "offset", "int",
+file_memory_backend_get_offset,
+file_memory_backend_set_offset,
+NULL, NULL);
+object_class_property_set_description(oc, "offset",
+"Offset into the target file (ex: 1G)");
 #ifdef CONFIG_LIBPMEM
 object_class_property_add_bool(oc, "pmem",
 file_memory_backend_get_pmem, file_memory_backend_set_pmem);
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 15ade918ba..3b7295fbe2 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -1318,6 +1318,7 @@ void memory_region_init_resizeable_ram(MemoryRegion *mr,
  * @ram_flags: RamBlock flags. Supported flags: RAM_SHARED, RAM_PMEM,
  * RAM_NORESERVE,
  * @path: the path in which to allocate the RAM.
+ * @offset: offset within the file referenced by path
  * @readonly: true to open @path for reading, false for read/write.
  * @errp: pointer to Error*, to store an error if it happens.
  *
@@ -1331,6 +1332,7 @@ void memory_region_init_ram_from_file(MemoryRegion *mr,
   uint64_t align,
   uint32_t ram_flags,
   const char *path,
+  ram_addr_t offset,
   bool readonly,
   Error **errp);
 
diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
index f4fb6a2111..90a8269290 100644
--- a/include/exec/ram_addr.h
+++ b/include/exec/ram_addr.h
@@ -110,6 +110,7 @@ long qemu_maxrampagesize(void);
  *  @ram_flags: RamBlock flags. Supported flags: RAM_SHARED, RAM_PMEM,
  *  RAM_NORESERVE.
  *  @mem_path or @fd: specify the backing file or device
+ *  @offset: Offset into target file
  *  @readonly: true to open @path for reading, false for read/write.
  *  @errp: pointer to Error*, to store an error if it happens
  *
@@ -119,7 +120,7 @@ long qemu_maxramp

[PATCH v3 5/6] target/riscv: Enable PC-relative translation in system mode

2023-04-01 Thread Weiwei Li
The existence of CF_PCREL can improve performance with the guest
kernel's address space randomization.  Each guest process maps
libc.so (et al) at a different virtual address, and this allows
those translations to be shared.

Signed-off-by: Weiwei Li 
Signed-off-by: Junqiang Wang 
Reviewed-by: LIU Zhiwei 
Reviewed-by: Richard Henderson 
---
 target/riscv/cpu.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 646fa31a59..3b562d5d9f 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1193,6 +1193,8 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 
 
 #ifndef CONFIG_USER_ONLY
+cs->tcg_cflags |= CF_PCREL;
+
 if (cpu->cfg.ext_sstc) {
 riscv_timer_init(cpu);
 }
-- 
2.25.1




[PATCH v3 4/6] target/riscv: Add support for PC-relative translation

2023-04-01 Thread Weiwei Li
Add a base save_pc For PC-relative translation(CF_PCREL).
Diable the directly sync pc from tb by riscv_cpu_synchronize_from_tb.
Sync pc before it's used or updated from tb related pc:
   real_pc = (old)env->pc + target_pc(from tb) - ctx->save_pc
Use gen_get_target_pc to compute target address of auipc and successor
address of jalr.

Signed-off-by: Weiwei Li 
Signed-off-by: Junqiang Wang 
Reviewed-by: Richard Henderson 
---
 target/riscv/cpu.c  | 29 +-
 target/riscv/insn_trans/trans_rvi.c.inc | 14 +--
 target/riscv/translate.c| 53 +
 3 files changed, 75 insertions(+), 21 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 1e97473af2..646fa31a59 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -658,16 +658,18 @@ static vaddr riscv_cpu_get_pc(CPUState *cs)
 static void riscv_cpu_synchronize_from_tb(CPUState *cs,
   const TranslationBlock *tb)
 {
-RISCVCPU *cpu = RISCV_CPU(cs);
-CPURISCVState *env = &cpu->env;
-RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
+if (!(tb_cflags(tb) & CF_PCREL)) {
+RISCVCPU *cpu = RISCV_CPU(cs);
+CPURISCVState *env = &cpu->env;
+RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
 
-tcg_debug_assert(!(cs->tcg_cflags & CF_PCREL));
+tcg_debug_assert(!(cs->tcg_cflags & CF_PCREL));
 
-if (xl == MXL_RV32) {
-env->pc = (int32_t) tb->pc;
-} else {
-env->pc = tb->pc;
+if (xl == MXL_RV32) {
+env->pc = (int32_t) tb->pc;
+} else {
+env->pc = tb->pc;
+}
 }
 }
 
@@ -693,11 +695,18 @@ static void riscv_restore_state_to_opc(CPUState *cs,
 RISCVCPU *cpu = RISCV_CPU(cs);
 CPURISCVState *env = &cpu->env;
 RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
+target_ulong pc;
+
+if (tb_cflags(tb) & CF_PCREL) {
+pc = (env->pc & TARGET_PAGE_MASK) | data[0];
+} else {
+pc = data[0];
+}
 
 if (xl == MXL_RV32) {
-env->pc = (int32_t)data[0];
+env->pc = (int32_t)pc;
 } else {
-env->pc = data[0];
+env->pc = pc;
 }
 env->bins = data[1];
 }
diff --git a/target/riscv/insn_trans/trans_rvi.c.inc 
b/target/riscv/insn_trans/trans_rvi.c.inc
index 48c73cfcfe..52ef260eff 100644
--- a/target/riscv/insn_trans/trans_rvi.c.inc
+++ b/target/riscv/insn_trans/trans_rvi.c.inc
@@ -38,7 +38,9 @@ static bool trans_lui(DisasContext *ctx, arg_lui *a)
 
 static bool trans_auipc(DisasContext *ctx, arg_auipc *a)
 {
-gen_set_gpri(ctx, a->rd, a->imm + ctx->base.pc_next);
+TCGv target_pc = dest_gpr(ctx, a->rd);
+gen_get_target_pc(target_pc, ctx, a->imm + ctx->base.pc_next);
+gen_set_gpr(ctx, a->rd, target_pc);
 return true;
 }
 
@@ -52,6 +54,7 @@ static bool trans_jalr(DisasContext *ctx, arg_jalr *a)
 {
 TCGLabel *misaligned = NULL;
 TCGv target_pc = tcg_temp_new();
+TCGv succ_pc = dest_gpr(ctx, a->rd);
 
 tcg_gen_addi_tl(target_pc, get_gpr(ctx, a->rs1, EXT_NONE), a->imm);
 tcg_gen_andi_tl(target_pc, target_pc, (target_ulong)-2);
@@ -68,7 +71,9 @@ static bool trans_jalr(DisasContext *ctx, arg_jalr *a)
 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0x0, misaligned);
 }
 
-gen_set_gpri(ctx, a->rd, ctx->pc_succ_insn);
+gen_get_target_pc(succ_pc, ctx, ctx->pc_succ_insn);
+gen_set_gpr(ctx, a->rd, succ_pc);
+
 tcg_gen_mov_tl(cpu_pc, target_pc);
 lookup_and_goto_ptr(ctx);
 
@@ -159,6 +164,7 @@ static bool gen_branch(DisasContext *ctx, arg_b *a, TCGCond 
cond)
 TCGv src1 = get_gpr(ctx, a->rs1, EXT_SIGN);
 TCGv src2 = get_gpr(ctx, a->rs2, EXT_SIGN);
 target_ulong next_pc;
+target_ulong orig_pc_save = ctx->pc_save;
 
 if (get_xl(ctx) == MXL_RV128) {
 TCGv src1h = get_gprh(ctx, a->rs1);
@@ -175,6 +181,7 @@ static bool gen_branch(DisasContext *ctx, arg_b *a, TCGCond 
cond)
 
 gen_set_label(l); /* branch taken */
 
+ctx->pc_save = orig_pc_save;
 next_pc = ctx->base.pc_next + a->imm;
 if (!has_ext(ctx, RVC) && (next_pc & 0x3)) {
 /* misaligned */
@@ -182,8 +189,9 @@ static bool gen_branch(DisasContext *ctx, arg_b *a, TCGCond 
cond)
 gen_get_target_pc(target_pc, ctx, next_pc);
 gen_exception_inst_addr_mis(ctx, target_pc);
 } else {
-gen_goto_tb(ctx, 0, ctx->base.pc_next + a->imm);
+gen_goto_tb(ctx, 0, next_pc);
 }
+ctx->pc_save = -1;
 ctx->base.is_jmp = DISAS_NORETURN;
 
 return true;
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 7b5223efc2..2dd594ddae 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -59,6 +59,7 @@ typedef struct DisasContext {
 DisasContextBase base;
 /* pc_succ_insn points to the instruction following base.pc_next */
 target_ulong pc_succ_insn;
+target_ulong pc_save;
 target_ulong priv_ver;
 RISCVMXL misa_mxl_max;
 RISCVMXL xl;
@@ -2

[PATCH v3 2/6] target/riscv: Update cur_pmmask/base when xl changes

2023-04-01 Thread Weiwei Li
write_mstatus() can only change current xl when in debug mode.
And we need update cur_pmmask/base in this case.

Signed-off-by: Weiwei Li 
Signed-off-by: Junqiang Wang 
Reviewed-by: LIU Zhiwei 
---
 target/riscv/csr.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index d522efc0b6..43b9ad4500 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1277,8 +1277,15 @@ static RISCVException write_mstatus(CPURISCVState *env, 
int csrno,
 mstatus = set_field(mstatus, MSTATUS64_SXL, xl);
 }
 env->mstatus = mstatus;
-env->xl = cpu_recompute_xl(env);
 
+/*
+ * Except in debug mode, UXL/SXL can only be modified by higher
+ * privilege mode. So xl will not be changed in normal mode.
+ */
+if (env->debugger) {
+env->xl = cpu_recompute_xl(env);
+riscv_cpu_update_mask(env);
+}
 return RISCV_EXCP_NONE;
 }
 
-- 
2.25.1




[PATCH v3 6/6] target/riscv: Add pointer mask support for instruction fetch

2023-04-01 Thread Weiwei Li
Transform the fetch address in cpu_get_tb_cpu_state() when pointer
mask for instruction is enabled.

Signed-off-by: Weiwei Li 
Signed-off-by: Junqiang Wang 
Reviewed-by: Richard Henderson 
---
 target/riscv/cpu.h|  1 +
 target/riscv/cpu_helper.c | 20 +++-
 target/riscv/csr.c|  2 --
 3 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 638e47c75a..57bd9c3279 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -368,6 +368,7 @@ struct CPUArchState {
 #endif
 target_ulong cur_pmmask;
 target_ulong cur_pmbase;
+bool cur_pminsn;
 
 /* Fields from here on are preserved across CPU reset. */
 QEMUTimer *stimer; /* Internal timer for S-mode interrupt */
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index f88c503cf4..b683a770fe 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -40,6 +40,19 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
 #endif
 }
 
+static target_ulong adjust_pc_address(CPURISCVState *env, target_ulong pc)
+{
+target_ulong adjust_pc = pc;
+
+if (env->cur_pminsn) {
+adjust_pc = (adjust_pc & ~env->cur_pmmask) | env->cur_pmbase;
+} else if (env->xl == MXL_RV32) {
+adjust_pc &= UINT32_MAX;
+}
+
+return adjust_pc;
+}
+
 void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
   target_ulong *cs_base, uint32_t *pflags)
 {
@@ -48,7 +61,7 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong 
*pc,
 
 uint32_t flags = 0;
 
-*pc = env->xl == MXL_RV32 ? env->pc & UINT32_MAX : env->pc;
+*pc = adjust_pc_address(env, env->pc);
 *cs_base = 0;
 
 if (cpu->cfg.ext_zve32f) {
@@ -124,6 +137,7 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong 
*pc,
 void riscv_cpu_update_mask(CPURISCVState *env)
 {
 target_ulong mask = -1, base = 0;
+bool insn = false;
 /*
  * TODO: Current RVJ spec does not specify
  * how the extension interacts with XLEN.
@@ -135,18 +149,21 @@ void riscv_cpu_update_mask(CPURISCVState *env)
 if (env->mmte & M_PM_ENABLE) {
 mask = env->mpmmask;
 base = env->mpmbase;
+insn = env->mmte & MMTE_M_PM_INSN;
 }
 break;
 case PRV_S:
 if (env->mmte & S_PM_ENABLE) {
 mask = env->spmmask;
 base = env->spmbase;
+insn = env->mmte & MMTE_S_PM_INSN;
 }
 break;
 case PRV_U:
 if (env->mmte & U_PM_ENABLE) {
 mask = env->upmmask;
 base = env->upmbase;
+insn = env->mmte & MMTE_U_PM_INSN;
 }
 break;
 default:
@@ -161,6 +178,7 @@ void riscv_cpu_update_mask(CPURISCVState *env)
 env->cur_pmmask = mask;
 env->cur_pmbase = base;
 }
+env->cur_pminsn = insn;
 }
 
 #ifndef CONFIG_USER_ONLY
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 43b9ad4500..0902b64129 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -3518,8 +3518,6 @@ static RISCVException write_mmte(CPURISCVState *env, int 
csrno,
 /* for machine mode pm.current is hardwired to 1 */
 wpri_val |= MMTE_M_PM_CURRENT;
 
-/* hardwiring pm.instruction bit to 0, since it's not supported yet */
-wpri_val &= ~(MMTE_M_PM_INSN | MMTE_S_PM_INSN | MMTE_U_PM_INSN);
 env->mmte = wpri_val | PM_EXT_DIRTY;
 riscv_cpu_update_mask(env);
 
-- 
2.25.1




[PATCH v3 0/6] target/riscv: Fix pointer mask related support

2023-04-01 Thread Weiwei Li
This patchset tries to fix some problem in current implementation for pointer 
mask, and add support for pointer mask of instruction fetch.

The port is available here:
https://github.com/plctlab/plct-qemu/tree/plct-pm-fix-v5

v2:
* drop some error patchs
* Add patch 2 and 3 to fix the new problems
* Add patch 4 and 5 to use PC-relative translation for pointer mask for 
instruction fetch

v3:
* use target_pc temp instead of cpu_pc to store into badaddr in patch 3
* use dest_gpr instead of tcg_temp_new() for succ_pc in patch 4
* enable CF_PCREL for system mode in seperate patch 5

v4:
* Fix wrong pc_save value for conditional jump in patch 4
* Fix tcg_cflags overwrite problem to make CF_PCREL really work in new patch 5
* Fix tb mis-matched problem in new patch 6

v5:
* use gen_get_target_pc to compute target address of auipc and successor 
address of jalr in patch 4.
* separate tcg related fix patches(5, 6) from this patchset

Weiwei Li (6):
  target/riscv: Fix pointer mask transformation for vector address
  target/riscv: Update cur_pmmask/base when xl changes
  target/riscv: Fix target address to update badaddr
  target/riscv: Add support for PC-relative translation
  target/riscv: Enable PC-relative translation in system mode
  target/riscv: Add pointer mask support for instruction fetch

 target/riscv/cpu.c  | 31 +++
 target/riscv/cpu.h  |  1 +
 target/riscv/cpu_helper.c   | 20 ++-
 target/riscv/csr.c  | 11 ++--
 target/riscv/insn_trans/trans_rvi.c.inc | 37 +
 target/riscv/translate.c| 72 ++---
 target/riscv/vector_helper.c|  2 +-
 7 files changed, 131 insertions(+), 43 deletions(-)

-- 
2.25.1




[PATCH v3 1/6] target/riscv: Fix pointer mask transformation for vector address

2023-04-01 Thread Weiwei Li
actual_address = (requested_address & ~mpmmask) | mpmbase.

Signed-off-by: Weiwei Li 
Signed-off-by: Junqiang Wang 
Reviewed-by: Daniel Henrique Barboza 
Reviewed-by: LIU Zhiwei 
---
 target/riscv/vector_helper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
index 2423affe37..a58d82af8c 100644
--- a/target/riscv/vector_helper.c
+++ b/target/riscv/vector_helper.c
@@ -172,7 +172,7 @@ static inline uint32_t vext_get_total_elems(CPURISCVState 
*env, uint32_t desc,
 
 static inline target_ulong adjust_addr(CPURISCVState *env, target_ulong addr)
 {
-return (addr & env->cur_pmmask) | env->cur_pmbase;
+return (addr & ~env->cur_pmmask) | env->cur_pmbase;
 }
 
 /*
-- 
2.25.1




[PATCH v3 3/6] target/riscv: Fix target address to update badaddr

2023-04-01 Thread Weiwei Li
Compute the target address  before storing it into badaddr
when mis-aligned exception is triggered.
Use a target_pc temp to store the target address to avoid
the confusing operation that udpate target address into
cpu_pc before misalign check, then update it into badaddr
and restore cpu_pc to current pc if exception is triggered.

Signed-off-by: Weiwei Li 
Signed-off-by: Junqiang Wang 
Reviewed-by: Richard Henderson 
---
 target/riscv/insn_trans/trans_rvi.c.inc | 23 ---
 target/riscv/translate.c| 21 ++---
 2 files changed, 26 insertions(+), 18 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rvi.c.inc 
b/target/riscv/insn_trans/trans_rvi.c.inc
index 4ad54e8a49..48c73cfcfe 100644
--- a/target/riscv/insn_trans/trans_rvi.c.inc
+++ b/target/riscv/insn_trans/trans_rvi.c.inc
@@ -51,25 +51,30 @@ static bool trans_jal(DisasContext *ctx, arg_jal *a)
 static bool trans_jalr(DisasContext *ctx, arg_jalr *a)
 {
 TCGLabel *misaligned = NULL;
+TCGv target_pc = tcg_temp_new();
 
-tcg_gen_addi_tl(cpu_pc, get_gpr(ctx, a->rs1, EXT_NONE), a->imm);
-tcg_gen_andi_tl(cpu_pc, cpu_pc, (target_ulong)-2);
+tcg_gen_addi_tl(target_pc, get_gpr(ctx, a->rs1, EXT_NONE), a->imm);
+tcg_gen_andi_tl(target_pc, target_pc, (target_ulong)-2);
+
+if (get_xl(ctx) == MXL_RV32) {
+tcg_gen_ext32s_tl(target_pc, target_pc);
+}
 
-gen_set_pc(ctx, cpu_pc);
 if (!has_ext(ctx, RVC)) {
 TCGv t0 = tcg_temp_new();
 
 misaligned = gen_new_label();
-tcg_gen_andi_tl(t0, cpu_pc, 0x2);
+tcg_gen_andi_tl(t0, target_pc, 0x2);
 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0x0, misaligned);
 }
 
 gen_set_gpri(ctx, a->rd, ctx->pc_succ_insn);
+tcg_gen_mov_tl(cpu_pc, target_pc);
 lookup_and_goto_ptr(ctx);
 
 if (misaligned) {
 gen_set_label(misaligned);
-gen_exception_inst_addr_mis(ctx);
+gen_exception_inst_addr_mis(ctx, target_pc);
 }
 ctx->base.is_jmp = DISAS_NORETURN;
 
@@ -153,6 +158,7 @@ static bool gen_branch(DisasContext *ctx, arg_b *a, TCGCond 
cond)
 TCGLabel *l = gen_new_label();
 TCGv src1 = get_gpr(ctx, a->rs1, EXT_SIGN);
 TCGv src2 = get_gpr(ctx, a->rs2, EXT_SIGN);
+target_ulong next_pc;
 
 if (get_xl(ctx) == MXL_RV128) {
 TCGv src1h = get_gprh(ctx, a->rs1);
@@ -169,9 +175,12 @@ static bool gen_branch(DisasContext *ctx, arg_b *a, 
TCGCond cond)
 
 gen_set_label(l); /* branch taken */
 
-if (!has_ext(ctx, RVC) && ((ctx->base.pc_next + a->imm) & 0x3)) {
+next_pc = ctx->base.pc_next + a->imm;
+if (!has_ext(ctx, RVC) && (next_pc & 0x3)) {
 /* misaligned */
-gen_exception_inst_addr_mis(ctx);
+TCGv target_pc = tcg_temp_new();
+gen_get_target_pc(target_pc, ctx, next_pc);
+gen_exception_inst_addr_mis(ctx, target_pc);
 } else {
 gen_goto_tb(ctx, 0, ctx->base.pc_next + a->imm);
 }
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 0ee8ee147d..7b5223efc2 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -222,21 +222,18 @@ static void decode_save_opc(DisasContext *ctx)
 ctx->insn_start = NULL;
 }
 
-static void gen_set_pc_imm(DisasContext *ctx, target_ulong dest)
+static void gen_get_target_pc(TCGv target, DisasContext *ctx,
+  target_ulong dest)
 {
 if (get_xl(ctx) == MXL_RV32) {
 dest = (int32_t)dest;
 }
-tcg_gen_movi_tl(cpu_pc, dest);
+tcg_gen_movi_tl(target, dest);
 }
 
-static void gen_set_pc(DisasContext *ctx, TCGv dest)
+static void gen_set_pc_imm(DisasContext *ctx, target_ulong dest)
 {
-if (get_xl(ctx) == MXL_RV32) {
-tcg_gen_ext32s_tl(cpu_pc, dest);
-} else {
-tcg_gen_mov_tl(cpu_pc, dest);
-}
+gen_get_target_pc(cpu_pc, ctx, dest);
 }
 
 static void generate_exception(DisasContext *ctx, int excp)
@@ -257,9 +254,9 @@ static void gen_exception_illegal(DisasContext *ctx)
 }
 }
 
-static void gen_exception_inst_addr_mis(DisasContext *ctx)
+static void gen_exception_inst_addr_mis(DisasContext *ctx, TCGv target)
 {
-tcg_gen_st_tl(cpu_pc, cpu_env, offsetof(CPURISCVState, badaddr));
+tcg_gen_st_tl(target, cpu_env, offsetof(CPURISCVState, badaddr));
 generate_exception(ctx, RISCV_EXCP_INST_ADDR_MIS);
 }
 
@@ -551,7 +548,9 @@ static void gen_jal(DisasContext *ctx, int rd, target_ulong 
imm)
 next_pc = ctx->base.pc_next + imm;
 if (!has_ext(ctx, RVC)) {
 if ((next_pc & 0x3) != 0) {
-gen_exception_inst_addr_mis(ctx);
+TCGv target_pc = tcg_temp_new();
+gen_get_target_pc(target_pc, ctx, next_pc);
+gen_exception_inst_addr_mis(ctx, target_pc);
 return;
 }
 }
-- 
2.25.1




Re: [PATCH v2] hostmem-file: add offset option

2023-04-01 Thread Stefan Hajnoczi
On Sat, 1 Apr 2023 at 08:14, Alexander Graf  wrote:
> diff --git a/qapi/qom.json b/qapi/qom.json
> index a877b879b9..8f5eaa8415 100644
> --- a/qapi/qom.json
> +++ b/qapi/qom.json
> @@ -635,6 +635,10 @@
>  # specify the required alignment via this option.
>  # 0 selects a default alignment (currently the page size). (default: 
> 0)
>  #
> +# @offset: the offset into the target file that the region starts at. You can
> +#  use this option to overload multiple regions into a single fils.

s/fils/file/

Other than that:
Reviewed-by: Stefan Hajnoczi 



[PATCH v2] hostmem-file: add offset option

2023-04-01 Thread Alexander Graf
Add an option for hostmem-file to start the memory object at an offset
into the target file. This is useful if multiple memory objects reside
inside the same target file, such as a device node.

In particular, it's useful to map guest memory directly into /dev/mem
for experimentation.

Signed-off-by: Alexander Graf 

---

v1 -> v2:

  - add qom documentation
  - propagate offset into truncate, size and alignment checks
---
 backends/hostmem-file.c | 40 +++-
 include/exec/memory.h   |  2 ++
 include/exec/ram_addr.h |  3 ++-
 qapi/qom.json   |  5 +
 qemu-options.hx |  6 +-
 softmmu/memory.c|  3 ++-
 softmmu/physmem.c   | 14 ++
 7 files changed, 65 insertions(+), 8 deletions(-)

diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c
index 25141283c4..38ea65bec5 100644
--- a/backends/hostmem-file.c
+++ b/backends/hostmem-file.c
@@ -27,6 +27,7 @@ struct HostMemoryBackendFile {
 
 char *mem_path;
 uint64_t align;
+uint64_t offset;
 bool discard_data;
 bool is_pmem;
 bool readonly;
@@ -58,7 +59,8 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error 
**errp)
 ram_flags |= fb->is_pmem ? RAM_PMEM : 0;
 memory_region_init_ram_from_file(&backend->mr, OBJECT(backend), name,
  backend->size, fb->align, ram_flags,
- fb->mem_path, fb->readonly, errp);
+ fb->mem_path, fb->offset, fb->readonly,
+ errp);
 g_free(name);
 #endif
 }
@@ -125,6 +127,36 @@ static void file_memory_backend_set_align(Object *o, 
Visitor *v,
 fb->align = val;
 }
 
+static void file_memory_backend_get_offset(Object *o, Visitor *v,
+  const char *name, void *opaque,
+  Error **errp)
+{
+HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
+uint64_t val = fb->offset;
+
+visit_type_size(v, name, &val, errp);
+}
+
+static void file_memory_backend_set_offset(Object *o, Visitor *v,
+  const char *name, void *opaque,
+  Error **errp)
+{
+HostMemoryBackend *backend = MEMORY_BACKEND(o);
+HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
+uint64_t val;
+
+if (host_memory_backend_mr_inited(backend)) {
+error_setg(errp, "cannot change property '%s' of %s", name,
+   object_get_typename(o));
+return;
+}
+
+if (!visit_type_size(v, name, &val, errp)) {
+return;
+}
+fb->offset = val;
+}
+
 #ifdef CONFIG_LIBPMEM
 static bool file_memory_backend_get_pmem(Object *o, Error **errp)
 {
@@ -197,6 +229,12 @@ file_backend_class_init(ObjectClass *oc, void *data)
 file_memory_backend_get_align,
 file_memory_backend_set_align,
 NULL, NULL);
+object_class_property_add(oc, "offset", "int",
+file_memory_backend_get_offset,
+file_memory_backend_set_offset,
+NULL, NULL);
+object_class_property_set_description(oc, "offset",
+"Offset into the target file (ex: 1G)");
 #ifdef CONFIG_LIBPMEM
 object_class_property_add_bool(oc, "pmem",
 file_memory_backend_get_pmem, file_memory_backend_set_pmem);
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 15ade918ba..3b7295fbe2 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -1318,6 +1318,7 @@ void memory_region_init_resizeable_ram(MemoryRegion *mr,
  * @ram_flags: RamBlock flags. Supported flags: RAM_SHARED, RAM_PMEM,
  * RAM_NORESERVE,
  * @path: the path in which to allocate the RAM.
+ * @offset: offset within the file referenced by path
  * @readonly: true to open @path for reading, false for read/write.
  * @errp: pointer to Error*, to store an error if it happens.
  *
@@ -1331,6 +1332,7 @@ void memory_region_init_ram_from_file(MemoryRegion *mr,
   uint64_t align,
   uint32_t ram_flags,
   const char *path,
+  ram_addr_t offset,
   bool readonly,
   Error **errp);
 
diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
index f4fb6a2111..90a8269290 100644
--- a/include/exec/ram_addr.h
+++ b/include/exec/ram_addr.h
@@ -110,6 +110,7 @@ long qemu_maxrampagesize(void);
  *  @ram_flags: RamBlock flags. Supported flags: RAM_SHARED, RAM_PMEM,
  *  RAM_NORESERVE.
  *  @mem_path or @fd: specify the backing file or device
+ *  @offset: Offset into target file
  *  @readonly: true to open @path for reading, false for read/write.
  *  @errp: pointer to Error*, to store an error if it happens
  *
@@ -119,7 +120,7 @@ long qemu_maxrampagesize(void);
  */
 RAMBlock *qemu_ram_alloc_from_file

Re: xen bits broke x32 build

2023-04-01 Thread David Woodhouse



On 1 April 2023 12:57:33 BST, Michael Tokarev  wrote:
>01.04.2023 14:45, Joao Martins пишет:
>> On 01/04/2023 09:40, Michael Tokarev wrote:
>>> After bringing in xen guest support, qemu fails to build on x32:
>>> Adding the folks who added the feature too
>> 
>>> target/i386/kvm/xen-emu.c:876:5: note: in expansion of macro 
>>> ‘qemu_build_assert’
>>>    876 | qemu_build_assert(sizeof(struct vcpu_info) == 64);
>>>    | ^
>>> 
>>> This one should be easy to fix, but I wonder if there are other issues
>>> with x32 exists..
>>> 
>> Not sure.
>> 
>> struct vcpu_info is supposed to be 64bytes on both 32-bit and 64-bit builds.
>> 
>> If anything maybe arch_vcpu_info struct is different on 32-bit and 64-bit...
>> David, Paul, any ideas?
>
>Yes, it is arch_vcpu_info. I assumed it is a trivial thing, but let me explain
>if it's not the case.
>
>include/hw/xen/interface/arch-x86/xen.h :
>
>#if defined(__i386__)
>#include "xen-x86_32.h"
>#elif defined(__x86_64__)
>#include "xen-x86_64.h"
>#endif
>
>(I wonder if it ever possible to have none of the two defined).
>
>Now, xen-x86_32.h has:
>
>struct arch_vcpu_info {
>unsigned long cr2;
>unsigned long pad[5]; /* sizeof(vcpu_info_t) == 64 */
>};
>
>Assuming sizeof(long)==32bits. But actually it is 64bits on x32.
>
>While xen-x86_64.h has:
>
>struct arch_vcpu_info {
>unsigned long cr2;
>unsigned long pad; /* sizeof(vcpu_info_t) == 64 */
>};
>
>
>It looks like for x32, the test in arch-x86/xen.h should be:
>
>#if defined(__x86_64__)
>#include "xen-x86_64.h"
>#else
>#include "xen-x86_32.h"
>#endif
>
>since x32 is almost like x86_64. The only difference from x86_64
>is sizeof(pointer), which is 32bits.

Hm, doesn't x32 also align uint64_t to 64 bits (unlike i386 which only aligns 
it to 32 bits)?

>Well. Maybe xen support should be disabled entirely on x32.
>Or maybe x32 should be declared as unsupported entirely.
>I dunno.

We rely heavily on the struct layouts being precisely the same, since these are 
ABI for the Xen guests. Wherever there was some 32/64 compatibility issue — and 
often where there wasn't — that's why I littered it with those build 
assertions. 

But while there are enough in there to sanity check the i386 vs. x86_64 ABI 
differences, I wouldn't swear that I've put in enough checks for x32. So "it 
builds without hitting an assertion" does not necessarily mean it'll be 
*correct*. Let's disable it on x32.



Re: xen bits broke x32 build

2023-04-01 Thread Michael Tokarev

To clarify: I don't think this needs fixing for 8.0.

Yes, it's a regression on x32.  Xen has never worked on x32,
this just looks like forgotten case when it needs to be disabled
in qemu for x86. It's trivial to work around by adding a --disable
argument to configure.  And generally I don't know anyone actually
running qemu on x32. It's some exotic thing which apparently is
going away by its own.

Thanks,

/mjt



Re: xen bits broke x32 build

2023-04-01 Thread Michael Tokarev

01.04.2023 14:45, Joao Martins пишет:

On 01/04/2023 09:40, Michael Tokarev wrote:

After bringing in xen guest support, qemu fails to build on x32:
Adding the folks who added the feature too



target/i386/kvm/xen-emu.c:876:5: note: in expansion of macro ‘qemu_build_assert’
   876 | qemu_build_assert(sizeof(struct vcpu_info) == 64);
   | ^

This one should be easy to fix, but I wonder if there are other issues
with x32 exists..


Not sure.

struct vcpu_info is supposed to be 64bytes on both 32-bit and 64-bit builds.

If anything maybe arch_vcpu_info struct is different on 32-bit and 64-bit...
David, Paul, any ideas?


Yes, it is arch_vcpu_info. I assumed it is a trivial thing, but let me explain
if it's not the case.

include/hw/xen/interface/arch-x86/xen.h :

#if defined(__i386__)
#include "xen-x86_32.h"
#elif defined(__x86_64__)
#include "xen-x86_64.h"
#endif

(I wonder if it ever possible to have none of the two defined).

Now, xen-x86_32.h has:

struct arch_vcpu_info {
unsigned long cr2;
unsigned long pad[5]; /* sizeof(vcpu_info_t) == 64 */
};

Assuming sizeof(long)==32bits. But actually it is 64bits on x32.

While xen-x86_64.h has:

struct arch_vcpu_info {
unsigned long cr2;
unsigned long pad; /* sizeof(vcpu_info_t) == 64 */
};


It looks like for x32, the test in arch-x86/xen.h should be:

#if defined(__x86_64__)
#include "xen-x86_64.h"
#else
#include "xen-x86_32.h"
#endif

since x32 is almost like x86_64. The only difference from x86_64
is sizeof(pointer), which is 32bits.


Well. Maybe xen support should be disabled entirely on x32.
Or maybe x32 should be declared as unsupported entirely.
I dunno.

/mjt



Re: xen bits broke x32 build

2023-04-01 Thread Joao Martins
On 01/04/2023 09:40, Michael Tokarev wrote:
> After bringing in xen guest support, qemu fails to build on x32:
> Adding the folks who added the feature too

> target/i386/kvm/xen-emu.c:876:5: note: in expansion of macro 
> ‘qemu_build_assert’
>   876 | qemu_build_assert(sizeof(struct vcpu_info) == 64);
>   | ^
> 
> This one should be easy to fix, but I wonder if there are other issues
> with x32 exists..
> 
Not sure.

struct vcpu_info is supposed to be 64bytes on both 32-bit and 64-bit builds.

If anything maybe arch_vcpu_info struct is different on 32-bit and 64-bit...
David, Paul, any ideas?



Re: [PATCH 3/3] accel/tcg: Fix jump cache set in cpu_exec_loop

2023-04-01 Thread liweiwei



On 2023/4/1 12:51, Richard Henderson wrote:

Assign pc and use store_release to assign tb.

Fixes: 2dd5b7a1b91 ("accel/tcg: Move jmp-cache `CF_PCREL` checks to caller")
Reported-by: Weiwei Li 
Signed-off-by: Richard Henderson 
---
  accel/tcg/cpu-exec.c | 17 +
  1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
index c815f2dbfd..8370c92c05 100644
--- a/accel/tcg/cpu-exec.c
+++ b/accel/tcg/cpu-exec.c
@@ -257,7 +257,7 @@ static inline TranslationBlock *tb_lookup(CPUState *cpu, 
target_ulong pc,
  
  if (cflags & CF_PCREL) {

  /* Use acquire to ensure current load of pc from jc. */
-tb =  qatomic_load_acquire(&jc->array[hash].tb);
+tb = qatomic_load_acquire(&jc->array[hash].tb);
  
  if (likely(tb &&

 jc->array[hash].pc == pc &&
@@ -272,7 +272,7 @@ static inline TranslationBlock *tb_lookup(CPUState *cpu, 
target_ulong pc,
  return NULL;
  }
  jc->array[hash].pc = pc;
-/* Use store_release on tb to ensure pc is written first. */
+/* Ensure pc is written first. */
  qatomic_store_release(&jc->array[hash].tb, tb);
  } else {
  /* Use rcu_read to ensure current load of pc from *tb. */
@@ -971,18 +971,27 @@ cpu_exec_loop(CPUState *cpu, SyncClocks *sc)
  
  tb = tb_lookup(cpu, pc, cs_base, flags, cflags);

  if (tb == NULL) {
+CPUJumpCache *jc;
  uint32_t h;
  
  mmap_lock();

  tb = tb_gen_code(cpu, pc, cs_base, flags, cflags);
  mmap_unlock();
+

Blank line.

  /*
   * We add the TB in the virtual pc hash table
   * for the fast lookup
   */
  h = tb_jmp_cache_hash_func(pc);
-/* Use the pc value already stored in tb->pc. */
-qatomic_set(&cpu->tb_jmp_cache->array[h].tb, tb);
+jc = cpu->tb_jmp_cache;
+if (cflags & CF_PCREL) {
+jc->array[h].pc = pc;
+/* Ensure pc is written first. */
+qatomic_store_release(&jc->array[h].tb, tb);


Whether we should add a qatomic_load_require() before this?

Regards,

Weiwei Li


+} else {
+/* Use the pc value already stored in tb->pc. */
+qatomic_set(&jc->array[h].tb, tb);
+}
  }
  
  #ifndef CONFIG_USER_ONLY





[RFC PATCH v3 07/10] hw/arm/smmuv3: Add VMID to TLB tagging

2023-04-01 Thread Mostafa Saleh
Allow TLB to be tagged with VMID.

If stage-1 is only supported, VMID is set to -1 and ignored from STE
and CMD_TLBI_NH* cmds.

Update smmu_iotlb_insert trace event to have vmid.

Signed-off-by: Mostafa Saleh 
Reviewed-by: Eric Auger 
---
Changes in v3:
- Collected Reviewed-by tag.
Changes in v2:
-Fix TLB aliasing issue from missing check in smmu_iotlb_key_equal.
-Add vmid to traces smmu_iotlb_insert and smmu_iotlb_lookup_hit/miss.
-Add vmid to hash function.
---
 hw/arm/smmu-common.c | 36 ++--
 hw/arm/smmu-internal.h   |  2 ++
 hw/arm/smmuv3.c  | 12 +---
 hw/arm/trace-events  |  6 +++---
 include/hw/arm/smmu-common.h |  5 +++--
 5 files changed, 39 insertions(+), 22 deletions(-)

diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
index a4ebd004c5..72ed6edd48 100644
--- a/hw/arm/smmu-common.c
+++ b/hw/arm/smmu-common.c
@@ -38,7 +38,7 @@ static guint smmu_iotlb_key_hash(gconstpointer v)
 
 /* Jenkins hash */
 a = b = c = JHASH_INITVAL + sizeof(*key);
-a += key->asid + key->level + key->tg;
+a += key->asid + key->vmid + key->level + key->tg;
 b += extract64(key->iova, 0, 32);
 c += extract64(key->iova, 32, 32);
 
@@ -53,13 +53,15 @@ static gboolean smmu_iotlb_key_equal(gconstpointer v1, 
gconstpointer v2)
 SMMUIOTLBKey *k1 = (SMMUIOTLBKey *)v1, *k2 = (SMMUIOTLBKey *)v2;
 
 return (k1->asid == k2->asid) && (k1->iova == k2->iova) &&
-   (k1->level == k2->level) && (k1->tg == k2->tg);
+   (k1->level == k2->level) && (k1->tg == k2->tg) &&
+   (k1->vmid == k2->vmid);
 }
 
-SMMUIOTLBKey smmu_get_iotlb_key(uint16_t asid, uint64_t iova,
+SMMUIOTLBKey smmu_get_iotlb_key(uint16_t asid, uint16_t vmid, uint64_t iova,
 uint8_t tg, uint8_t level)
 {
-SMMUIOTLBKey key = {.asid = asid, .iova = iova, .tg = tg, .level = level};
+SMMUIOTLBKey key = {.asid = asid, .vmid = vmid, .iova = iova,
+.tg = tg, .level = level};
 
 return key;
 }
@@ -78,7 +80,8 @@ SMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg 
*cfg,
 uint64_t mask = subpage_size - 1;
 SMMUIOTLBKey key;
 
-key = smmu_get_iotlb_key(cfg->asid, iova & ~mask, tg, level);
+key = smmu_get_iotlb_key(cfg->asid, cfg->s2cfg.vmid,
+ iova & ~mask, tg, level);
 entry = g_hash_table_lookup(bs->iotlb, &key);
 if (entry) {
 break;
@@ -88,13 +91,13 @@ SMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg 
*cfg,
 
 if (entry) {
 cfg->iotlb_hits++;
-trace_smmu_iotlb_lookup_hit(cfg->asid, iova,
+trace_smmu_iotlb_lookup_hit(cfg->asid, cfg->s2cfg.vmid, iova,
 cfg->iotlb_hits, cfg->iotlb_misses,
 100 * cfg->iotlb_hits /
 (cfg->iotlb_hits + cfg->iotlb_misses));
 } else {
 cfg->iotlb_misses++;
-trace_smmu_iotlb_lookup_miss(cfg->asid, iova,
+trace_smmu_iotlb_lookup_miss(cfg->asid, cfg->s2cfg.vmid, iova,
  cfg->iotlb_hits, cfg->iotlb_misses,
  100 * cfg->iotlb_hits /
  (cfg->iotlb_hits + cfg->iotlb_misses));
@@ -111,8 +114,10 @@ void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, 
SMMUTLBEntry *new)
 smmu_iotlb_inv_all(bs);
 }
 
-*key = smmu_get_iotlb_key(cfg->asid, new->entry.iova, tg, new->level);
-trace_smmu_iotlb_insert(cfg->asid, new->entry.iova, tg, new->level);
+*key = smmu_get_iotlb_key(cfg->asid, cfg->s2cfg.vmid, new->entry.iova,
+  tg, new->level);
+trace_smmu_iotlb_insert(cfg->asid, cfg->s2cfg.vmid, new->entry.iova,
+tg, new->level);
 g_hash_table_insert(bs->iotlb, key, new);
 }
 
@@ -130,8 +135,7 @@ static gboolean smmu_hash_remove_by_asid(gpointer key, 
gpointer value,
 
 return SMMU_IOTLB_ASID(*iotlb_key) == asid;
 }
-
-static gboolean smmu_hash_remove_by_asid_iova(gpointer key, gpointer value,
+static gboolean smmu_hash_remove_by_asid_vmid_iova(gpointer key, gpointer 
value,
   gpointer user_data)
 {
 SMMUTLBEntry *iter = (SMMUTLBEntry *)value;
@@ -142,18 +146,21 @@ static gboolean smmu_hash_remove_by_asid_iova(gpointer 
key, gpointer value,
 if (info->asid >= 0 && info->asid != SMMU_IOTLB_ASID(iotlb_key)) {
 return false;
 }
+if (info->vmid >= 0 && info->vmid != SMMU_IOTLB_VMID(iotlb_key)) {
+return false;
+}
 return ((info->iova & ~entry->addr_mask) == entry->iova) ||
((entry->iova & ~info->mask) == info->iova);
 }
 
-void smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova,
+void smmu_iotlb_inv_iova(SMMUState *s, int asid, int vmid, dma_addr_t iova,
  uint8_t tg, uint64_t num_pages, ui

[RFC PATCH v3 06/10] hw/arm/smmuv3: Make TLB lookup work for stage-2

2023-04-01 Thread Mostafa Saleh
Right now, either stage-1 or stage-2 are supported, this simplifies
how we can deal with TLBs.
This patch makes TLB lookup work if stage-2 is enabled instead of
stage-1.
TLB lookup is done before a PTW, if a valid entry is found we won't
do the PTW.
To be able to do TLB lookup, we need the correct tagging info, as
granularity and input size, so we get this based on the supported
translation stage. The TLB entries are added correctly from each
stage PTW.

When nested translation is supported, this would need to change, for
example if we go with a combined TLB implementation, we would need to
use the min of the granularities in TLB.

As stage-2 shouldn't be tagged by ASID, it will be set to -1 if S1P
is not enabled.

Signed-off-by: Mostafa Saleh 
Reviewed-by: Eric Auger 
---
Changes in v3:
- Rename temp to tt_combined and move to top.
- Collected Reviewed-by tag.
Changes in v2:
- check if S1 is enabled(not supported) when reading S1 TT.
---
 hw/arm/smmuv3.c | 44 +---
 1 file changed, 33 insertions(+), 11 deletions(-)

diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
index 0f5429aed8..a1f4a4f902 100644
--- a/hw/arm/smmuv3.c
+++ b/hw/arm/smmuv3.c
@@ -727,6 +727,9 @@ static int smmuv3_decode_config(IOMMUMemoryRegion *mr, 
SMMUTransCfg *cfg,
 STE ste;
 CD cd;
 
+/* ASID defaults to -1 (if s1 is not supported). */
+cfg->asid = -1;
+
 ret = smmu_find_ste(s, sid, &ste, event);
 if (ret) {
 return ret;
@@ -824,6 +827,11 @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion 
*mr, hwaddr addr,
 .addr_mask = ~(hwaddr)0,
 .perm = IOMMU_NONE,
 };
+/*
+ * Combined attributes used for TLB lookup, as only one stage is supported,
+ * it will hold attributes based on the enabled stage.
+ */
+SMMUTransTableInfo tt_combined;
 
 qemu_mutex_lock(&s->mutex);
 
@@ -852,21 +860,35 @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion 
*mr, hwaddr addr,
 goto epilogue;
 }
 
-tt = select_tt(cfg, addr);
-if (!tt) {
-if (cfg->record_faults) {
-event.type = SMMU_EVT_F_TRANSLATION;
-event.u.f_translation.addr = addr;
-event.u.f_translation.rnw = flag & 0x1;
+if (cfg->stage == 1) {
+/* Select stage1 translation table. */
+tt = select_tt(cfg, addr);
+if (!tt) {
+if (cfg->record_faults) {
+event.type = SMMU_EVT_F_TRANSLATION;
+event.u.f_translation.addr = addr;
+event.u.f_translation.rnw = flag & 0x1;
+}
+status = SMMU_TRANS_ERROR;
+goto epilogue;
 }
-status = SMMU_TRANS_ERROR;
-goto epilogue;
-}
+tt_combined.granule_sz = tt->granule_sz;
+tt_combined.tsz = tt->tsz;
 
-page_mask = (1ULL << (tt->granule_sz)) - 1;
+} else {
+/* Stage2. */
+tt_combined.granule_sz = cfg->s2cfg.granule_sz;
+tt_combined.tsz = cfg->s2cfg.tsz;
+}
+/*
+ * TLB lookup looks for granule and input size for a translation stage,
+ * as only one stage is supported right now, choose the right values
+ * from the configuration.
+ */
+page_mask = (1ULL << tt_combined.granule_sz) - 1;
 aligned_addr = addr & ~page_mask;
 
-cached_entry = smmu_iotlb_lookup(bs, cfg, tt, aligned_addr);
+cached_entry = smmu_iotlb_lookup(bs, cfg, &tt_combined, aligned_addr);
 if (cached_entry) {
 if ((flag & IOMMU_WO) && !(cached_entry->entry.perm & IOMMU_WO)) {
 status = SMMU_TRANS_ERROR;
-- 
2.40.0.348.gf938b09366-goog




[RFC PATCH v3 03/10] hw/arm/smmuv3: Refactor stage-1 PTW

2023-04-01 Thread Mostafa Saleh
In preparation for adding stage-2 support, rename smmu_ptw_64 to
smmu_ptw_64_s1 and refactor some of the code so it can be reused in
stage-2 page table walk.

Remove AA64 check from PTW as decode_cd already ensures that AA64 is
used, otherwise it faults with C_BAD_CD.

A stage member is added to SMMUPTWEventInfo to differentiate
between stage-1 and stage-2 ptw faults.

Add stage argument to trace_smmu_ptw_level be consistent with other
trace events.

Signed-off-by: Mostafa Saleh 
Reviewed-by: Eric Auger 
---
Changes in v3:
- Collected Reviewed-by tag
- Rename translation consts and macros from SMMU_* to VMSA_*
Changes in v2:
- Refactor common functions to be use in stage-2.
- Add stage to SMMUPTWEventInfo.
- Remove AA64 check.
---
 hw/arm/smmu-common.c | 27 ++-
 hw/arm/smmuv3.c  |  2 ++
 hw/arm/trace-events  |  2 +-
 include/hw/arm/smmu-common.h | 16 +---
 4 files changed, 26 insertions(+), 21 deletions(-)

diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
index e7f1c1f219..50391a8c94 100644
--- a/hw/arm/smmu-common.c
+++ b/hw/arm/smmu-common.c
@@ -264,7 +264,7 @@ SMMUTransTableInfo *select_tt(SMMUTransCfg *cfg, dma_addr_t 
iova)
 }
 
 /**
- * smmu_ptw_64 - VMSAv8-64 Walk of the page tables for a given IOVA
+ * smmu_ptw_64_s1 - VMSAv8-64 Walk of the page tables for a given IOVA
  * @cfg: translation config
  * @iova: iova to translate
  * @perm: access type
@@ -276,9 +276,9 @@ SMMUTransTableInfo *select_tt(SMMUTransCfg *cfg, dma_addr_t 
iova)
  * Upon success, @tlbe is filled with translated_addr and entry
  * permission rights.
  */
-static int smmu_ptw_64(SMMUTransCfg *cfg,
-   dma_addr_t iova, IOMMUAccessFlags perm,
-   SMMUTLBEntry *tlbe, SMMUPTWEventInfo *info)
+static int smmu_ptw_64_s1(SMMUTransCfg *cfg,
+  dma_addr_t iova, IOMMUAccessFlags perm,
+  SMMUTLBEntry *tlbe, SMMUPTWEventInfo *info)
 {
 dma_addr_t baseaddr, indexmask;
 int stage = cfg->stage;
@@ -291,14 +291,14 @@ static int smmu_ptw_64(SMMUTransCfg *cfg,
 }
 
 granule_sz = tt->granule_sz;
-stride = granule_sz - 3;
+stride = VMSA_STRIDE(granule_sz);
 inputsize = 64 - tt->tsz;
 level = 4 - (inputsize - 4) / stride;
-indexmask = (1ULL << (inputsize - (stride * (4 - level - 1;
+indexmask = VMSA_IDXMSK(inputsize, stride, level);
 baseaddr = extract64(tt->ttb, 0, 48);
 baseaddr &= ~indexmask;
 
-while (level <= 3) {
+while (level < VMSA_LEVELS) {
 uint64_t subpage_size = 1ULL << level_shift(level, granule_sz);
 uint64_t mask = subpage_size - 1;
 uint32_t offset = iova_level_offset(iova, inputsize, level, 
granule_sz);
@@ -309,7 +309,7 @@ static int smmu_ptw_64(SMMUTransCfg *cfg,
 if (get_pte(baseaddr, offset, &pte, info)) {
 goto error;
 }
-trace_smmu_ptw_level(level, iova, subpage_size,
+trace_smmu_ptw_level(stage, level, iova, subpage_size,
  baseaddr, offset, pte);
 
 if (is_invalid_pte(pte) || is_reserved_pte(pte, level)) {
@@ -358,6 +358,7 @@ static int smmu_ptw_64(SMMUTransCfg *cfg,
 info->type = SMMU_PTW_ERR_TRANSLATION;
 
 error:
+info->stage = 1;
 tlbe->entry.perm = IOMMU_NONE;
 return -EINVAL;
 }
@@ -376,15 +377,7 @@ error:
 int smmu_ptw(SMMUTransCfg *cfg, dma_addr_t iova, IOMMUAccessFlags perm,
  SMMUTLBEntry *tlbe, SMMUPTWEventInfo *info)
 {
-if (!cfg->aa64) {
-/*
- * This code path is not entered as we check this while decoding
- * the configuration data in the derived SMMU model.
- */
-g_assert_not_reached();
-}
-
-return smmu_ptw_64(cfg, iova, perm, tlbe, info);
+return smmu_ptw_64_s1(cfg, iova, perm, tlbe, info);
 }
 
 /**
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
index 270c80b665..4e90343996 100644
--- a/hw/arm/smmuv3.c
+++ b/hw/arm/smmuv3.c
@@ -716,6 +716,8 @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion 
*mr, hwaddr addr,
 cached_entry = g_new0(SMMUTLBEntry, 1);
 
 if (smmu_ptw(cfg, aligned_addr, flag, cached_entry, &ptw_info)) {
+/* All faults from PTW has S2 field. */
+event.u.f_walk_eabt.s2 = (ptw_info.stage == 2);
 g_free(cached_entry);
 switch (ptw_info.type) {
 case SMMU_PTW_ERR_WALK_EABT:
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
index 2dee296c8f..205ac04573 100644
--- a/hw/arm/trace-events
+++ b/hw/arm/trace-events
@@ -5,7 +5,7 @@ virt_acpi_setup(void) "No fw cfg or ACPI disabled. Bailing out."
 
 # smmu-common.c
 smmu_add_mr(const char *name) "%s"
-smmu_ptw_level(int level, uint64_t iova, size_t subpage_size, uint64_t 
baseaddr, uint32_t offset, uint64_t pte) "level=%d iova=0x%"PRIx64" 
subpage_sz=0x%zx baseaddr=0x%"PRIx64" offset=%d => pte=0x%"PRIx64
+smmu_ptw_level(int stage, int level, uint64_t iova, size_t subpage_size, 
uint64_t base

[RFC PATCH v3 10/10] hw/arm/smmuv3: Add knob to choose translation stage and enable stage-2

2023-04-01 Thread Mostafa Saleh
As everything is in place, we can use a new system property to
advertise which stage is supported and remove bad_ste from STE
stage2 config.

The property added arm-smmuv3.stage can have 3 values:
- "1": Stage-1 only is advertised.
- "2": Stage-2 only is advertised.
- "all": Stage-1 + Stage-2 are supported, which is not implemented in
this patch series.

If not passed or an unsupported value is passed, it will default to
stage-1.

Advertise VMID16.

Don't try to decode CD, if stage-2 is configured.

Signed-off-by: Mostafa Saleh 
---
Changes in v2:
- Squash knob patch with stage-2 enable patch.
- Don't try to decode CD, if stage-2 is configured.
---
 hw/arm/smmuv3.c | 34 +-
 include/hw/arm/smmuv3.h |  1 +
 2 files changed, 26 insertions(+), 9 deletions(-)

diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
index 826aacf8b1..22b5613d4c 100644
--- a/hw/arm/smmuv3.c
+++ b/hw/arm/smmuv3.c
@@ -21,6 +21,7 @@
 #include "hw/irq.h"
 #include "hw/sysbus.h"
 #include "migration/vmstate.h"
+#include "hw/qdev-properties.h"
 #include "hw/qdev-core.h"
 #include "hw/pci/pci.h"
 #include "cpu.h"
@@ -248,14 +249,20 @@ void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo 
*info)
 
 static void smmuv3_init_regs(SMMUv3State *s)
 {
-/**
- * IDR0: stage1 only, AArch64 only, coherent access, 16b ASID,
- *   multi-level stream table
+/*
+ * Based on sys property, the stages supported in smmu will be advertised.
+ * At the moment "all" is not supported and default to stage-1.
  */
-s->idr[0] = FIELD_DP32(s->idr[0], IDR0, S1P, 1); /* stage 1 supported */
+if (s->stage && !strcmp("2", s->stage)) {
+s->idr[0] = FIELD_DP32(s->idr[0], IDR0, S2P, 1);
+} else {
+s->idr[0] = FIELD_DP32(s->idr[0], IDR0, S1P, 1);
+}
+
 s->idr[0] = FIELD_DP32(s->idr[0], IDR0, TTF, 2); /* AArch64 PTW only */
 s->idr[0] = FIELD_DP32(s->idr[0], IDR0, COHACC, 1); /* IO coherent */
 s->idr[0] = FIELD_DP32(s->idr[0], IDR0, ASID16, 1); /* 16-bit ASID */
+s->idr[0] = FIELD_DP32(s->idr[0], IDR0, VMID16, 1); /* 16-bit VMID */
 s->idr[0] = FIELD_DP32(s->idr[0], IDR0, TTENDIAN, 2); /* little endian */
 s->idr[0] = FIELD_DP32(s->idr[0], IDR0, STALL_MODEL, 1); /* No stall */
 /* terminated transaction will always be aborted/error returned */
@@ -458,10 +465,6 @@ static int decode_ste_s2_cfg(SMMUTransCfg *cfg, STE *ste)
 goto bad_ste;
 }
 
-/* This is still here as stage 2 has not been fully enabled yet. */
-qemu_log_mask(LOG_UNIMP, "SMMUv3 does not support stage 2 yet\n");
-goto bad_ste;
-
 return 0;
 
 bad_ste:
@@ -740,7 +743,7 @@ static int smmuv3_decode_config(IOMMUMemoryRegion *mr, 
SMMUTransCfg *cfg,
 return ret;
 }
 
-if (cfg->aborted || cfg->bypassed) {
+if (cfg->aborted || cfg->bypassed || (cfg->stage == 2)) {
 return 0;
 }
 
@@ -1809,6 +1812,18 @@ static const VMStateDescription vmstate_smmuv3 = {
 }
 };
 
+static Property smmuv3_properties[] = {
+/*
+ * Stages of translation advertised.
+ * "1": Stage 1
+ * "2": Stage 2
+ * "all": Stage 1 + Stage 2
+ * Defaults to stage 1
+ */
+DEFINE_PROP_STRING("stage", SMMUv3State, stage),
+DEFINE_PROP_END_OF_LIST()
+};
+
 static void smmuv3_instance_init(Object *obj)
 {
 /* Nothing much to do here as of now */
@@ -1825,6 +1840,7 @@ static void smmuv3_class_init(ObjectClass *klass, void 
*data)
&c->parent_phases);
 c->parent_realize = dc->realize;
 dc->realize = smmu_realize;
+device_class_set_props(dc, smmuv3_properties);
 }
 
 static int smmuv3_notify_flag_changed(IOMMUMemoryRegion *iommu,
diff --git a/include/hw/arm/smmuv3.h b/include/hw/arm/smmuv3.h
index 6031d7d325..d183a62766 100644
--- a/include/hw/arm/smmuv3.h
+++ b/include/hw/arm/smmuv3.h
@@ -62,6 +62,7 @@ struct SMMUv3State {
 
 qemu_irq irq[4];
 QemuMutex mutex;
+char *stage;
 };
 
 typedef enum {
-- 
2.40.0.348.gf938b09366-goog




[RFC PATCH v3 00/10] Add stage-2 translation for SMMUv3

2023-04-01 Thread Mostafa Saleh
This patch series adds stage-2 translation support for SMMUv3. It is
controlled by a new system property “arm-smmuv3.stage”.
- When set to “1”: Stage-1 only would be advertised and supported (default
behaviour)
- When set to “2”: Stage-2 only would be advertised and supported.
- Value “all” is reserved for nesting support. However it is not
implemented in this patch series (more about this in the end)

Features implemented in stage-2 are mostly synonymous with stage-1
- VMID16.
- Only AArch64 translation tables are supported.
- Only little endian translation table supported.
- Stall is not supported.
- HTTU is not supported, SW is expected to maintain the Access flag.

To make it easy to support nesting, a new structure(SMMUS2Cfg) is
embedded within SMMUTransCfg, to hold stage-2 configuration.

TLBs were updated to support VMID, where when stage-2 is used ASID is
set to -1 and ignored and when stage-1 is used VMID is set to -1 and
ignored.
As only one stage is supported at a time at the moment, TLB will
represent IPA=>PA translation with proper attributes(granularity and
t0sz) parsed from STEs for stage-2, and will represent VA=>PA
translation with proper attributes parsed from the CDs for stage-1.

New commands where added that are used with stage-2
- CMD_TLBI_S12_VMALL: Invalidate all translations for a VMID.
- CMD_TLBI_S2_IPA: Invalidate stage-2 by VMID and IPA
Some commands are illegal to be used from stage-2 were modified to
return CERROR_ILL.

This patch series can be used to run Linux pKVM SMMUv3 patches (currently on 
the list)
which controls stage-2 (from EL2) while providing a paravirtualized
interface the host(EL1)
https://lore.kernel.org/kvmarm/20230201125328.2186498-1-jean-phili...@linaro.org/

Looking forward, nesting is the next feature to go for, here are some
thoughts about this:

- TLB would require big changes for this, we can go either for a combined
implementation or per stage one. This would affect returns from PTW and
invalidation commands.

- Stage-1 data structures should be translated by stage-2 if enabled (as
context descriptors and ttb0/ttb1)

- Translated addresses from stage-1 should be translated by stage-2 if
enabled.

- Some existing commands(as CMD_TLBI_S2_IPA, CMD_TLBI_NH_ASID …) would be
modified and some of those would be based on the design of the TLBs.

- Currently, VMID is ignored when stage-1 is used as it can’t be used with
stage-2. However when nesting is advertised VMID shouldn’t be ignored
even if stage-2 is bypassed.

Changes in v3:
- Collected Reviewed-by tags
- Separate stage-2 record faults from stage-1
- Fix input address check in stage-2 walk
- Fix shift in STE_S2HD, STE_S2HA, STE_S2S, STE_S2R
- Add more logs for illegal configs and commands.
- Rename SMMU translation macros to VMSA as they are not part of SMMU spec
- Rename stage-2 variables and functions (iova=>ipa, ap=>s2ap, ...)
- Rename oas in SMMUS2Cfg to eff_ps
- Improve comments (mention user manuals versions, field names)

Changes in v2:
-Collected Reviewed-by tags
-Add oas to SMMUS2Cfg, and use it in PTW
-Add stage member to to SMMUPTWEventInfo to differentiate stage-1 and
 stage-2 PTW faults
-Move stage-2 knob to the last patch
-Add all STE parsing in one patch
-Pares and use S2PS and S2ENDI
-Split S2AFF patch over PTW and STE patches.
-Fix TLB aliasing issue
-Renaming and refactoring and rewording commits.
-Populate OAS based on PARANGE
-Add checks for stage-1 only commands
-Update trace events to hold translation stage, vmid when possible
-Remove feature flags for supported stages as they were redundant with IDR0


Mostafa Saleh (10):
  hw/arm/smmuv3: Add missing fields for IDR0
  hw/arm/smmuv3: Update translation config to hold stage-2
  hw/arm/smmuv3: Refactor stage-1 PTW
  hw/arm/smmuv3: Add page table walk for stage-2
  hw/arm/smmuv3: Parse STE config for stage-2
  hw/arm/smmuv3: Make TLB lookup work for stage-2
  hw/arm/smmuv3: Add VMID to TLB tagging
  hw/arm/smmuv3: Add CMDs related to stage-2
  hw/arm/smmuv3: Add stage-2 support in iova notifier
  hw/arm/smmuv3: Add knob to choose translation stage and enable stage-2

 hw/arm/smmu-common.c | 209 +---
 hw/arm/smmu-internal.h   |  37 
 hw/arm/smmuv3-internal.h |  12 +-
 hw/arm/smmuv3.c  | 364 ++-
 hw/arm/trace-events  |  14 +-
 include/hw/arm/smmu-common.h |  45 -
 include/hw/arm/smmuv3.h  |   4 +
 7 files changed, 595 insertions(+), 90 deletions(-)

-- 
2.40.0.348.gf938b09366-goog




[RFC PATCH v3 09/10] hw/arm/smmuv3: Add stage-2 support in iova notifier

2023-04-01 Thread Mostafa Saleh
In smmuv3_notify_iova, read the granule based on translation stage
and use VMID if valid value is sent.

Signed-off-by: Mostafa Saleh 
Reviewed-by: Eric Auger 
---
Changes in v3:
- Collected Reviewed-by tag.
---
 hw/arm/smmuv3.c | 39 ++-
 hw/arm/trace-events |  2 +-
 2 files changed, 27 insertions(+), 14 deletions(-)

diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
index 3b5b1fad1a..826aacf8b1 100644
--- a/hw/arm/smmuv3.c
+++ b/hw/arm/smmuv3.c
@@ -1006,18 +1006,21 @@ epilogue:
  * @mr: IOMMU mr region handle
  * @n: notifier to be called
  * @asid: address space ID or negative value if we don't care
+ * @vmid: virtual machine ID or negative value if we don't care
  * @iova: iova
  * @tg: translation granule (if communicated through range invalidation)
  * @num_pages: number of @granule sized pages (if tg != 0), otherwise 1
  */
 static void smmuv3_notify_iova(IOMMUMemoryRegion *mr,
IOMMUNotifier *n,
-   int asid, dma_addr_t iova,
-   uint8_t tg, uint64_t num_pages)
+   int asid, int vmid,
+   dma_addr_t iova, uint8_t tg,
+   uint64_t num_pages)
 {
 SMMUDevice *sdev = container_of(mr, SMMUDevice, iommu);
 IOMMUTLBEvent event;
 uint8_t granule;
+SMMUv3State *s = sdev->smmu;
 
 if (!tg) {
 SMMUEventInfo event = {.inval_ste_allowed = true};
@@ -1032,11 +1035,20 @@ static void smmuv3_notify_iova(IOMMUMemoryRegion *mr,
 return;
 }
 
-tt = select_tt(cfg, iova);
-if (!tt) {
+if (vmid >= 0 && cfg->s2cfg.vmid != vmid) {
 return;
 }
-granule = tt->granule_sz;
+
+if (STAGE1_SUPPORTED(s)) {
+tt = select_tt(cfg, iova);
+if (!tt) {
+return;
+}
+granule = tt->granule_sz;
+} else {
+granule = cfg->s2cfg.granule_sz;
+}
+
 } else {
 granule = tg * 2 + 10;
 }
@@ -1050,9 +1062,10 @@ static void smmuv3_notify_iova(IOMMUMemoryRegion *mr,
 memory_region_notify_iommu_one(n, &event);
 }
 
-/* invalidate an asid/iova range tuple in all mr's */
-static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova,
-  uint8_t tg, uint64_t num_pages)
+/* invalidate an asid/vmid/iova range tuple in all mr's */
+static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, int vmid,
+  dma_addr_t iova, uint8_t tg,
+  uint64_t num_pages)
 {
 SMMUDevice *sdev;
 
@@ -1060,11 +1073,11 @@ static void smmuv3_inv_notifiers_iova(SMMUState *s, int 
asid, dma_addr_t iova,
 IOMMUMemoryRegion *mr = &sdev->iommu;
 IOMMUNotifier *n;
 
-trace_smmuv3_inv_notifiers_iova(mr->parent_obj.name, asid, iova,
-tg, num_pages);
+trace_smmuv3_inv_notifiers_iova(mr->parent_obj.name, asid, vmid,
+iova, tg, num_pages);
 
 IOMMU_NOTIFIER_FOREACH(n, mr) {
-smmuv3_notify_iova(mr, n, asid, iova, tg, num_pages);
+smmuv3_notify_iova(mr, n, asid, vmid, iova, tg, num_pages);
 }
 }
 }
@@ -1095,7 +1108,7 @@ static void smmuv3_range_inval(SMMUState *s, Cmd *cmd)
 
 if (!tg) {
 trace_smmuv3_range_inval(vmid, asid, addr, tg, 1, ttl, leaf);
-smmuv3_inv_notifiers_iova(s, asid, addr, tg, 1);
+smmuv3_inv_notifiers_iova(s, asid, vmid, addr, tg, 1);
 smmu_iotlb_inv_iova(s, asid, vmid, addr, tg, 1, ttl);
 return;
 }
@@ -1113,7 +1126,7 @@ static void smmuv3_range_inval(SMMUState *s, Cmd *cmd)
 
 num_pages = (mask + 1) >> granule;
 trace_smmuv3_range_inval(vmid, asid, addr, tg, num_pages, ttl, leaf);
-smmuv3_inv_notifiers_iova(s, asid, addr, tg, num_pages);
+smmuv3_inv_notifiers_iova(s, asid, vmid, addr, tg, num_pages);
 smmu_iotlb_inv_iova(s, asid, vmid, addr, tg, num_pages, ttl);
 addr += mask + 1;
 }
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
index f8fdf1ca9f..cdc1ea06a8 100644
--- a/hw/arm/trace-events
+++ b/hw/arm/trace-events
@@ -53,5 +53,5 @@ smmuv3_cmdq_tlbi_s12_vmid(uint16_t vmid) "vmid=%d"
 smmuv3_config_cache_inv(uint32_t sid) "Config cache INV for sid=0x%x"
 smmuv3_notify_flag_add(const char *iommu) "ADD SMMUNotifier node for iommu 
mr=%s"
 smmuv3_notify_flag_del(const char *iommu) "DEL SMMUNotifier node for iommu 
mr=%s"
-smmuv3_inv_notifiers_iova(const char *name, uint16_t asid, uint64_t iova, 
uint8_t tg, uint64_t num_pages) "iommu mr=%s asid=%d iova=0x%"PRIx64" tg=%d 
num_pages=0x%"PRIx64
+smmuv3_inv_notifiers_iova(const char *name, uint16_t asid, uint16_t vmid, 
uint64_t iova, uint8_t tg, uint64_t num_pages) "iommu mr=%s asid=%d vmid=%d 
iova=0x%"PRIx64" tg=%d num_pag

[RFC PATCH v3 08/10] hw/arm/smmuv3: Add CMDs related to stage-2

2023-04-01 Thread Mostafa Saleh
CMD_TLBI_S2_IPA: As S1+S2 is not enabled, for now this can be the
same as CMD_TLBI_NH_VAA.

CMD_TLBI_S12_VMALL: Added new function to invalidate TLB by VMID.

For stage-1 only commands, add a check to throw CERROR_ILL if used
when stage-1 is not supported.

Signed-off-by: Mostafa Saleh 
---
Changes in v3:
- Log guest error for all illegal commands.
Changes in v2:
- Add checks for stage-1 only commands
- Rename smmuv3_s1_range_inval to smmuv3_range_inval
---
 hw/arm/smmu-common.c | 16 +++
 hw/arm/smmuv3.c  | 53 ++--
 hw/arm/trace-events  |  4 ++-
 include/hw/arm/smmu-common.h |  1 +
 4 files changed, 65 insertions(+), 9 deletions(-)

diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
index 72ed6edd48..45e9d7e752 100644
--- a/hw/arm/smmu-common.c
+++ b/hw/arm/smmu-common.c
@@ -135,6 +135,16 @@ static gboolean smmu_hash_remove_by_asid(gpointer key, 
gpointer value,
 
 return SMMU_IOTLB_ASID(*iotlb_key) == asid;
 }
+
+static gboolean smmu_hash_remove_by_vmid(gpointer key, gpointer value,
+ gpointer user_data)
+{
+uint16_t vmid = *(uint16_t *)user_data;
+SMMUIOTLBKey *iotlb_key = (SMMUIOTLBKey *)key;
+
+return SMMU_IOTLB_VMID(*iotlb_key) == vmid;
+}
+
 static gboolean smmu_hash_remove_by_asid_vmid_iova(gpointer key, gpointer 
value,
   gpointer user_data)
 {
@@ -187,6 +197,12 @@ void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid)
 g_hash_table_foreach_remove(s->iotlb, smmu_hash_remove_by_asid, &asid);
 }
 
+inline void smmu_iotlb_inv_vmid(SMMUState *s, uint16_t vmid)
+{
+trace_smmu_iotlb_inv_vmid(vmid);
+g_hash_table_foreach_remove(s->iotlb, smmu_hash_remove_by_vmid, &vmid);
+}
+
 /* VMSAv8-64 Translation */
 
 /**
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
index d7e7003da9..3b5b1fad1a 100644
--- a/hw/arm/smmuv3.c
+++ b/hw/arm/smmuv3.c
@@ -1069,7 +1069,7 @@ static void smmuv3_inv_notifiers_iova(SMMUState *s, int 
asid, dma_addr_t iova,
 }
 }
 
-static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd)
+static void smmuv3_range_inval(SMMUState *s, Cmd *cmd)
 {
 dma_addr_t end, addr = CMD_ADDR(cmd);
 uint8_t type = CMD_TYPE(cmd);
@@ -1094,7 +1094,7 @@ static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd)
 }
 
 if (!tg) {
-trace_smmuv3_s1_range_inval(vmid, asid, addr, tg, 1, ttl, leaf);
+trace_smmuv3_range_inval(vmid, asid, addr, tg, 1, ttl, leaf);
 smmuv3_inv_notifiers_iova(s, asid, addr, tg, 1);
 smmu_iotlb_inv_iova(s, asid, vmid, addr, tg, 1, ttl);
 return;
@@ -1112,7 +1112,7 @@ static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd)
 uint64_t mask = dma_aligned_pow2_mask(addr, end, 64);
 
 num_pages = (mask + 1) >> granule;
-trace_smmuv3_s1_range_inval(vmid, asid, addr, tg, num_pages, ttl, 
leaf);
+trace_smmuv3_range_inval(vmid, asid, addr, tg, num_pages, ttl, leaf);
 smmuv3_inv_notifiers_iova(s, asid, addr, tg, num_pages);
 smmu_iotlb_inv_iova(s, asid, vmid, addr, tg, num_pages, ttl);
 addr += mask + 1;
@@ -1246,12 +1246,22 @@ static int smmuv3_cmdq_consume(SMMUv3State *s)
 {
 uint16_t asid = CMD_ASID(&cmd);
 
+if (!STAGE1_SUPPORTED(s)) {
+cmd_error = SMMU_CERROR_ILL;
+break;
+}
+
 trace_smmuv3_cmdq_tlbi_nh_asid(asid);
 smmu_inv_notifiers_all(&s->smmu_state);
 smmu_iotlb_inv_asid(bs, asid);
 break;
 }
 case SMMU_CMD_TLBI_NH_ALL:
+if (!STAGE1_SUPPORTED(s)) {
+cmd_error = SMMU_CERROR_ILL;
+break;
+}
+QEMU_FALLTHROUGH;
 case SMMU_CMD_TLBI_NSNH_ALL:
 trace_smmuv3_cmdq_tlbi_nh();
 smmu_inv_notifiers_all(&s->smmu_state);
@@ -1259,7 +1269,34 @@ static int smmuv3_cmdq_consume(SMMUv3State *s)
 break;
 case SMMU_CMD_TLBI_NH_VAA:
 case SMMU_CMD_TLBI_NH_VA:
-smmuv3_s1_range_inval(bs, &cmd);
+if (!STAGE1_SUPPORTED(s)) {
+cmd_error = SMMU_CERROR_ILL;
+break;
+}
+smmuv3_range_inval(bs, &cmd);
+break;
+case SMMU_CMD_TLBI_S12_VMALL:
+uint16_t vmid = CMD_VMID(&cmd);
+
+if (!STAGE2_SUPPORTED(s)) {
+cmd_error = SMMU_CERROR_ILL;
+break;
+}
+
+trace_smmuv3_cmdq_tlbi_s12_vmid(vmid);
+smmu_inv_notifiers_all(&s->smmu_state);
+smmu_iotlb_inv_vmid(bs, vmid);
+break;
+case SMMU_CMD_TLBI_S2_IPA:
+if (!STAGE2_SUPPORTED(s)) {
+cmd_error = SMMU_CERROR_ILL;
+break;
+}
+/*
+ * As currently only either s1 or s2 are supported
+ * we can reuse same function for s2.

[RFC PATCH v3 01/10] hw/arm/smmuv3: Add missing fields for IDR0

2023-04-01 Thread Mostafa Saleh
In preparation for adding stage-2 support.
Add IDR0 fields related to stage-2.

VMID16: 16-bit VMID supported.
S2P: Stage-2 translation supported.

They are described in 6.3.1 SMMU_IDR0.

No functional change intended.

Reviewed-by: Richard Henderson 
Reviewed-by: Eric Auger 
Signed-off-by: Mostafa Saleh 

---
Changes in V2:
- Collected Reviewed-by tags.
---
 hw/arm/smmuv3-internal.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
index e8f0ebf25e..183d5ac8dc 100644
--- a/hw/arm/smmuv3-internal.h
+++ b/hw/arm/smmuv3-internal.h
@@ -34,10 +34,12 @@ typedef enum SMMUTranslationStatus {
 /* MMIO Registers */
 
 REG32(IDR0,0x0)
+FIELD(IDR0, S2P, 0 , 1)
 FIELD(IDR0, S1P, 1 , 1)
 FIELD(IDR0, TTF, 2 , 2)
 FIELD(IDR0, COHACC,  4 , 1)
 FIELD(IDR0, ASID16,  12, 1)
+FIELD(IDR0, VMID16,  18, 1)
 FIELD(IDR0, TTENDIAN,21, 2)
 FIELD(IDR0, STALL_MODEL, 24, 2)
 FIELD(IDR0, TERM_MODEL,  26, 1)
-- 
2.40.0.348.gf938b09366-goog




[RFC PATCH v3 04/10] hw/arm/smmuv3: Add page table walk for stage-2

2023-04-01 Thread Mostafa Saleh
In preparation for adding stage-2 support, add Stage-2 PTW code.
Only Aarch64 format is supported as stage-1.

Nesting stage-1 and stage-2 is not supported right now.

HTTU is not supported, SW is expected to maintain the Access flag.
This is described in the SMMUv3 manual(IHI 0070.E)
"5.2. Stream Table Entry" in "[181] S2AFFD".
This flag determines the behavior on access of a stage-2 page whose
descriptor has AF == 0:
- 0b0: An Access flag fault occurs (stall not supported).
- 0b1: An Access flag fault never occurs.
An Access fault takes priority over a Permission fault.

There are 3 address size checks for stage-2 according to "IHI 0070.E"
in "3.4. Address sizes".
- As nesting is not supported, input address is passed directly to
stage-2, and is checked against IAS.
We use cfg->oas to hold the OAS when stage-1 is not used, this is set
in the next patch.
This check is done outside of smmu_ptw_64_s2 as it is not part of
stage-2(it throws stage-1 fault), and the stage-2 function shouldn't
change it's behavior when nesting is supported.
When nesting is supported and we figure out how to combine TLB for
stage-1 and stage-2 we can move this check into the stage-1 function
as described in ARM DDI0487I.a in pseudocode
aarch64/translation/vmsa_translation/AArch64.S1Translate
aarch64/translation/vmsa_translation/AArch64.S1DisabledOutput

- Input to stage-2 is checked against s2t0sz, and throws stage-2
transaltion fault if exceeds it.

- Output of stage-2 is checked against effective PA output range.

Signed-off-by: Mostafa Saleh 
---
Changes in v3:
- Fix IPA address size check.
- s2cfg.oas renamed to s2cfg.eff_ps.
- s/iova/ipa
- s/ap/s2ap
- s/gran/granule_sz
- use level_shift instead of inline code.
- Add missing brackets in is_permission_fault_s2.
- Use new VMSA_* macros and functions instead of SMMU_*
- Rename pgd_idx to pgd_concat_idx.
- Move SMMU_MAX_S2_CONCAT to STE patch as it is not used here.
Changes in v2:
- Squash S2AFF PTW code.
- Use common functions between stage-1 and stage-2.
- Add checks for IPA and out PA.
---
 hw/arm/smmu-common.c   | 142 -
 hw/arm/smmu-internal.h |  35 ++
 2 files changed, 176 insertions(+), 1 deletion(-)

diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
index 50391a8c94..a4ebd004c5 100644
--- a/hw/arm/smmu-common.c
+++ b/hw/arm/smmu-common.c
@@ -363,6 +363,127 @@ error:
 return -EINVAL;
 }
 
+/**
+ * smmu_ptw_64_s2 - VMSAv8-64 Walk of the page tables for a given ipa
+ * for stage-2.
+ * @cfg: translation config
+ * @ipa: ipa to translate
+ * @perm: access type
+ * @tlbe: SMMUTLBEntry (out)
+ * @info: handle to an error info
+ *
+ * Return 0 on success, < 0 on error. In case of error, @info is filled
+ * and tlbe->perm is set to IOMMU_NONE.
+ * Upon success, @tlbe is filled with translated_addr and entry
+ * permission rights.
+ */
+static int smmu_ptw_64_s2(SMMUTransCfg *cfg,
+  dma_addr_t ipa, IOMMUAccessFlags perm,
+  SMMUTLBEntry *tlbe, SMMUPTWEventInfo *info)
+{
+const int stage = 2;
+int granule_sz = cfg->s2cfg.granule_sz;
+/* ARM DDI0487I.a: Table D8-7. */
+int inputsize = 64 - cfg->s2cfg.tsz;
+int level = get_start_level(cfg->s2cfg.sl0, granule_sz);
+int stride = VMSA_STRIDE(granule_sz);
+int idx = pgd_concat_idx(level, granule_sz, ipa);
+/*
+ * Get the ttb from concatenated structure.
+ * The offset is the idx * size of each ttb(number of ptes * (sizeof(pte))
+ */
+uint64_t baseaddr = extract64(cfg->s2cfg.vttb, 0, 48) + (1 << stride) *
+  idx * sizeof(uint64_t);
+dma_addr_t indexmask = VMSA_IDXMSK(inputsize, stride, level);
+
+baseaddr &= ~indexmask;
+
+/*
+ * On input, a stage 2 Translation fault occurs if the IPA is outside the
+ * range configured by the relevant S2T0SZ field of the STE.
+ */
+if (ipa >= (1ULL << inputsize)) {
+info->type = SMMU_PTW_ERR_TRANSLATION;
+goto error;
+}
+
+while (level < VMSA_LEVELS) {
+uint64_t subpage_size = 1ULL << level_shift(level, granule_sz);
+uint64_t mask = subpage_size - 1;
+uint32_t offset = iova_level_offset(ipa, inputsize, level, granule_sz);
+uint64_t pte, gpa;
+dma_addr_t pte_addr = baseaddr + offset * sizeof(pte);
+uint8_t s2ap;
+
+if (get_pte(baseaddr, offset, &pte, info)) {
+goto error;
+}
+trace_smmu_ptw_level(stage, level, ipa, subpage_size,
+ baseaddr, offset, pte);
+if (is_invalid_pte(pte) || is_reserved_pte(pte, level)) {
+trace_smmu_ptw_invalid_pte(stage, level, baseaddr,
+   pte_addr, offset, pte);
+break;
+}
+
+if (is_table_pte(pte, level)) {
+baseaddr = get_table_pte_address(pte, granule_sz);
+level++;
+continue;
+} else if (is_page_pte(

[RFC PATCH v3 02/10] hw/arm/smmuv3: Update translation config to hold stage-2

2023-04-01 Thread Mostafa Saleh
In preparation for adding stage-2 support, add a S2 config
struct(SMMUS2Cfg), composed of the following fields and embedded in
the main SMMUTransCfg:
 -tsz: Size of IPA input region (S2T0SZ)
 -sl0: Start level of translation (S2SL0)
 -affd: AF Fault Disable (S2AFFD)
 -record_faults: Record fault events (S2R)
 -granule_sz: Granule page shift (based on S2TG)
 -vmid: Virtual Machine ID (S2VMID)
 -vttb: Address of translation table base (S2TTB)
 -eff_ps: Effective PA output range (based on S2PS)

They will be used in the next patches in stage-2 address translation.

The fields in SMMUS2Cfg, are reordered to make the shared and stage-1
fields next to each other, this reordering didn't change the struct
size (104 bytes before and after).

Stage-1 only fields: aa64, asid, tt, ttb, tbi, record_faults, oas.
oas is stage-1 output address size. However, it is used to check
input address in case stage-1 is unimplemented or bypassed according
to SMMUv3 manual IHI0070.E "3.4. Address sizes"

Shared fields: stage, disabled, bypassed, aborted, iotlb_*.

No functional change intended.

Signed-off-by: Mostafa Saleh 
---
Changes in v3:
-Add record_faults for stage-2
-Reorder and document fields in SMMUTransCfg based on stage
-Rename oas in SMMUS2Cfg to eff_ps
-Improve comments in SMMUS2Cfg
Changes in v2:
-Add oas
---
 include/hw/arm/smmu-common.h | 22 +++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
index 9fcff26357..9cf3f37929 100644
--- a/include/hw/arm/smmu-common.h
+++ b/include/hw/arm/smmu-common.h
@@ -58,25 +58,41 @@ typedef struct SMMUTLBEntry {
 uint8_t granule;
 } SMMUTLBEntry;
 
+/* Stage-2 configuration. */
+typedef struct SMMUS2Cfg {
+uint8_t tsz;/* Size of IPA input region (S2T0SZ) */
+uint8_t sl0;/* Start level of translation (S2SL0) */
+bool affd;  /* AF Fault Disable (S2AFFD) */
+bool record_faults; /* Record fault events (S2R) */
+uint8_t granule_sz; /* Granule page shift (based on S2TG) */
+uint8_t eff_ps; /* Effective PA output range (based on S2PS) */
+uint16_t vmid;  /* Virtual Machine ID (S2VMID) */
+uint64_t vttb;  /* Address of translation table base (S2TTB) */
+} SMMUS2Cfg;
+
 /*
  * Generic structure populated by derived SMMU devices
  * after decoding the configuration information and used as
  * input to the page table walk
  */
 typedef struct SMMUTransCfg {
+/* Shared fields between stage-1 and stage-2. */
 int stage; /* translation stage */
-bool aa64; /* arch64 or aarch32 translation table */
 bool disabled; /* smmu is disabled */
 bool bypassed; /* translation is bypassed */
 bool aborted;  /* translation is aborted */
+uint32_t iotlb_hits;   /* counts IOTLB hits */
+uint32_t iotlb_misses; /* counts IOTLB misses*/
+/* Used by stage-1 only. */
+bool aa64; /* arch64 or aarch32 translation table */
 bool record_faults;/* record fault events */
 uint64_t ttb;  /* TT base address */
 uint8_t oas;   /* output address width */
 uint8_t tbi;   /* Top Byte Ignore */
 uint16_t asid;
 SMMUTransTableInfo tt[2];
-uint32_t iotlb_hits;   /* counts IOTLB hits for this asid */
-uint32_t iotlb_misses; /* counts IOTLB misses for this asid */
+/* Used by stage-2 only. */
+struct SMMUS2Cfg s2cfg;
 } SMMUTransCfg;
 
 typedef struct SMMUDevice {
-- 
2.40.0.348.gf938b09366-goog




[RFC PATCH v3 05/10] hw/arm/smmuv3: Parse STE config for stage-2

2023-04-01 Thread Mostafa Saleh
Parse stage-2 configuration from STE and populate it in SMMUS2Cfg.
Validity of field values are checked when possible.

Only AA64 tables are supported and Small Translation Tables (STT) are
not supported.

According to SMMUv3 UM(IHI0070E) "5.2 Stream Table Entry": All fields
with an S2 prefix (with the exception of S2VMID) are IGNORED when
stage-2 bypasses translation (Config[1] == 0).

Which means that VMID can be used(for TLB tagging) even if stage-2 is
bypassed, so we parse it unconditionally when S2P exists. Otherwise
it is set to -1.(only S1P)

As stall is not supported, if S2S is set the translation would abort.
For S2R, we reuse the same code used for stage-1 with flag
record_faults. However when nested translation is supported we would
need to separate stage-1 and stage-2 faults.

Fix wrong shift in STE_S2HD, STE_S2HA, STE_S2S.

Signed-off-by: Mostafa Saleh 
---
Changes in V3:
- Separate fault handling.
- Fix shift in STE_S2HD, STE_S2HA, STE_S2S, STE_S2R.
- Rename t0sz_valid to s2t0sz_valid.
- separate stage-2 STE parsing in decode_ste_s2_cfg.
- Add a log for invalid S2ENDI and S2TTB.
- Set default value for stage-1 OAS.
- Move and rename SMMU_MAX_S2_CONCAT to VMSA_MAX_S2_CONCAT.
Changes in V2:
- Parse S2PS and S2ENDI
- Squash with S2VMID parsing patch
- Squash with S2AFF parsing
- Squash with fault reporting patch
- Add check for S2T0SZ
- Renaming and refactoring code
---
 hw/arm/smmuv3-internal.h |  10 +-
 hw/arm/smmuv3.c  | 188 +--
 include/hw/arm/smmu-common.h |   1 +
 include/hw/arm/smmuv3.h  |   3 +
 4 files changed, 192 insertions(+), 10 deletions(-)

diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
index 183d5ac8dc..6d1c1edab7 100644
--- a/hw/arm/smmuv3-internal.h
+++ b/hw/arm/smmuv3-internal.h
@@ -526,9 +526,13 @@ typedef struct CD {
 #define STE_S2TG(x)extract32((x)->word[5], 14, 2)
 #define STE_S2PS(x)extract32((x)->word[5], 16, 3)
 #define STE_S2AA64(x)  extract32((x)->word[5], 19, 1)
-#define STE_S2HD(x)extract32((x)->word[5], 24, 1)
-#define STE_S2HA(x)extract32((x)->word[5], 25, 1)
-#define STE_S2S(x) extract32((x)->word[5], 26, 1)
+#define STE_S2ENDI(x)  extract32((x)->word[5], 20, 1)
+#define STE_S2AFFD(x)  extract32((x)->word[5], 21, 1)
+#define STE_S2HD(x)extract32((x)->word[5], 23, 1)
+#define STE_S2HA(x)extract32((x)->word[5], 24, 1)
+#define STE_S2S(x) extract32((x)->word[5], 25, 1)
+#define STE_S2R(x) extract32((x)->word[5], 26, 1)
+
 #define STE_CTXPTR(x)   \
 ({  \
 unsigned long addr; \
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
index 4e90343996..0f5429aed8 100644
--- a/hw/arm/smmuv3.c
+++ b/hw/arm/smmuv3.c
@@ -33,6 +33,16 @@
 #include "smmuv3-internal.h"
 #include "smmu-internal.h"
 
+/* If stage-1 fault enabled and ptw event targets it. */
+#define PTW_FAULT_S1(cfg, event)((cfg)->record_faults && \
+ !(event).u.f_walk_eabt.s2)
+/* If stage-2 fault enabled and ptw event targets it. */
+#define PTW_FAULT_S2(cfg, event)((cfg)->s2cfg.record_faults && \
+ (event).u.f_walk_eabt.s2)
+
+#define PTW_FAULT_ALLOWED(cfg, event)   (PTW_FAULT_S1(cfg, event) || \
+ PTW_FAULT_S2(cfg, event))
+
 /**
  * smmuv3_trigger_irq - pulse @irq if enabled and update
  * GERROR register in case of GERROR interrupt
@@ -329,11 +339,141 @@ static int smmu_get_cd(SMMUv3State *s, STE *ste, 
uint32_t ssid,
 return 0;
 }
 
+/*
+ * Max valid value is 39 when SMMU_IDR3.STT == 0.
+ * In architectures after SMMUv3.0:
+ * - If STE.S2TG selects a 4KB or 16KB granule, the minimum valid value for 
this
+ * field is MAX(16, 64-IAS)
+ * - If STE.S2TG selects a 64KB granule, the minimum valid value for this field
+ * is (64-IAS).
+ * As we only support AA64, IAS = OAS.
+ */
+static bool s2t0sz_valid(SMMUTransCfg *cfg)
+{
+if (cfg->s2cfg.tsz > 39) {
+return false;
+}
+
+if (cfg->s2cfg.granule_sz == 16) {
+return (cfg->s2cfg.tsz >= 64 - oas2bits(SMMU_IDR5_OAS));
+}
+
+return (cfg->s2cfg.tsz >= MAX(64 - oas2bits(SMMU_IDR5_OAS), 16));
+}
+
+/*
+ * Return true if s2 page table config is valid.
+ * This checks with the configured start level, ias_bits and granularity we can
+ * have a valid page table as described in ARM ARM D8.2 Translation process.
+ * The idea here is to see for the highest possible number of IPA bits, how
+ * many concatenated tables we would need, if it is more than 16, then this is
+ * not possible.
+ */
+static bool s2_pgtable_config_valid(uint8_t sl0, uint8_t t0sz, uint8_t gran)
+{
+int level = get_start_level(sl0, gran);
+uint64_t ipa_bits = 64 - t0sz;
+uint64_t max_ipa = (1ULL << ipa_bits) - 1

Re: [PATCH v2 0/4] Missing endianness conversions in user mode

2023-04-01 Thread Michael Tokarev

20.02.2023 11:58, Mathis Marion пишет:

From: Mathis Marion 

For a bit of context, I was trying to test a network border router [1]
daemon using the MIPS architecture (see [2]). I didn't have access to
real MIPS hardware so I figured I would emulate it using QEMU user mode.
I ran into a couple of problems all related to endianness conversion for
syscalls between host and target as MIPS is big endian and my x86 host
is little.

[1]: https://github.com/SiliconLabs/wisun-br-linux
[2]: https://github.com/SiliconLabs/wisun-br-linux/issues/5

v2:
- remove context from target_to_host_for_each_nlattr()

Mathis Marion (4):
   linux-user: fix timerfd read endianness conversion
   linux-user: fix sockaddr_in6 endianness
   linux-user: add target to host netlink conversions
   linux-user: handle netlink flag NLA_F_NESTED


It looks like timefd and netlink conversions are good candidates
for -stable too. I've seen reports of these not working under
qemu linux-user emulation..

Thanks,

/mjt




[PATCH trivial for-8.0] hw/virtio/virtio-qmp.c: spelling: suppoted

2023-04-01 Thread Michael Tokarev
Fixes: f3034ad71fcd0a6a58bc37830f182b307f089159
Signed-off-by: Michael Tokarev 
Reviewed-by: Stefan Weil 
---
 hw/virtio/virtio-qmp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

This patch were previously sent at 5 Nov 2022, now the
code moved to another file, and the patch is still applies
(with changed filename).

diff --git a/hw/virtio/virtio-qmp.c b/hw/virtio/virtio-qmp.c
index 808446b4c9..e76218bdd5 100644
--- a/hw/virtio/virtio-qmp.c
+++ b/hw/virtio/virtio-qmp.c
@@ -343 +343 @@ qmp_virtio_feature_map_t virtio_scsi_feature_map[] = {
-"buffers suppoted"),
+"buffers supported"),
-- 
2.30.2



Re: qemu-stable final release process

2023-04-01 Thread Michael Tokarev

Ping? :)

30.03.2023 13:18, Michael Tokarev wrote:

Hi!

Michael, there's the final step to do, after having the branch and increasing 
version number, -
this is about to make the actual release. I see scripts/make-release which 
apparently does what
it should, hopefully anyway. What's the final steps?  This tarball needs to be 
published too.

There's a branch published, 
https://gitlab.com/qemu-project/qemu/-/tree/stable-7.2 , which should
hopefully become 7.2.1. I haven't tagged it yet though.

Thanks!

/mjt







xen bits broke x32 build

2023-04-01 Thread Michael Tokarev

After bringing in xen guest support, qemu fails to build on x32:

target/i386/kvm/xen-emu.c:876:5: note: in expansion of macro ‘qemu_build_assert’
  876 | qemu_build_assert(sizeof(struct vcpu_info) == 64);
  | ^

This one should be easy to fix, but I wonder if there are other issues
with x32 exists..

Thanks,

/mjt



Re: [PATCH 04/11] qemu-options: finesse the recommendations around -blockdev

2023-04-01 Thread Michael Tokarev

30.03.2023 13:11, Alex Bennée wrote:

We are a bit premature in recommending -blockdev/-device as the best
way to configure block devices, especially in the common case.
Improve the language to hopefully make things clearer.

Suggested-by: Michael Tokarev 
Signed-off-by: Alex Bennée 
---
  qemu-options.hx | 8 ++--
  1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/qemu-options.hx b/qemu-options.hx
index 59bdf67a2c..9a69ed838e 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1143,10 +1143,14 @@ have gone through several iterations as the feature set 
and complexity
  of the block layer have grown. Many online guides to QEMU often
  reference older and deprecated options, which can lead to confusion.
  
-The recommended modern way to describe disks is to use a combination of

+The most explicit way to describe disks is to use a combination of
  ``-device`` to specify the hardware device and ``-blockdev`` to
  describe the backend. The device defines what the guest sees and the
-backend describes how QEMU handles the data.
+backend describes how QEMU handles the data. The ``-drive`` option
+combines the device and backend into a single command line options
+which is useful in the majority of cases. Older options like ``-hda``
+bake in a lot of assumptions from the days when QEMU was emulating a
+legacy PC, they are not recommended for modern configurations.


Reviewed-by: Michael Tokarev 

This is a very welcome change, in my opinion.

Thank you Alex!

/mjt