From 594fe2f680f571dfe1d69281b803bdcbac925f7a Mon Sep 17 00:00:00 2001 From: osy Date: Fri, 18 Jul 2025 13:29:23 -0700 Subject: [PATCH 1/2] tcg/tcti: implement vector immediate shifts This now seems to be required as a result of the introduction of gen_gvec_rev{16,32,64} in 38f9950c8e0315d7b26803018a3f73d5f42e6703. --- tcg/aarch64-tcti/tcg-target-has.h | 2 +- tcg/aarch64-tcti/tcg-target-opc.h.inc | 1 + tcg/aarch64-tcti/tcg-target.c.inc | 45 +++++++++++++++++-- tcg/aarch64-tcti/tcti-gadget-gen.py | 63 +++++++++++++++++++++++++-- 4 files changed, 103 insertions(+), 8 deletions(-) diff --git a/tcg/aarch64-tcti/tcg-target-has.h b/tcg/aarch64-tcti/tcg-target-has.h index 8e39891c02..67b50fcdea 100644 --- a/tcg/aarch64-tcti/tcg-target-has.h +++ b/tcg/aarch64-tcti/tcg-target-has.h @@ -84,7 +84,7 @@ #define TCG_TARGET_HAS_roti_vec 0 #define TCG_TARGET_HAS_rots_vec 0 #define TCG_TARGET_HAS_rotv_vec 0 -#define TCG_TARGET_HAS_shi_vec 0 +#define TCG_TARGET_HAS_shi_vec 1 #define TCG_TARGET_HAS_shs_vec 0 #define TCG_TARGET_HAS_shv_vec 1 #define TCG_TARGET_HAS_mul_vec 1 diff --git a/tcg/aarch64-tcti/tcg-target-opc.h.inc b/tcg/aarch64-tcti/tcg-target-opc.h.inc index 88cf2bc53d..5382315c41 100644 --- a/tcg/aarch64-tcti/tcg-target-opc.h.inc +++ b/tcg/aarch64-tcti/tcg-target-opc.h.inc @@ -12,3 +12,4 @@ */ DEF(aa64_sshl_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(aa64_sli_vec, 1, 2, 1, TCG_OPF_VECTOR) diff --git a/tcg/aarch64-tcti/tcg-target.c.inc b/tcg/aarch64-tcti/tcg-target.c.inc index 7b1186cd01..8b78abe4bb 100644 --- a/tcg/aarch64-tcti/tcg-target.c.inc +++ b/tcg/aarch64-tcti/tcg-target.c.inc @@ -217,6 +217,8 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags) return C_O1_I2(w, w, w); case INDEX_op_bitsel_vec: return C_O1_I3(w, w, w, w); + case INDEX_op_aa64_sli_vec: + return C_O1_I2(w, 0, w); default: return C_NotImplemented; @@ -490,6 +492,13 @@ static void tcg_out_ternary_gadget(TCGContext *s, const void *gadget_base[TCG_TA tcg_out_gadget(s, gadget_base[reg0][reg1][reg2]); } + +/* Write gadget pointer (three registers, last is immediate value). */ +static void tcg_out_ternary_immediate_gadget(TCGContext *s, const void *gadget_base[TCG_TARGET_GP_REGS][TCG_TARGET_GP_REGS][TCTI_GADGET_IMMEDIATE_ARRAY_LEN], unsigned reg0, unsigned reg1, unsigned reg2) +{ + tcg_out_gadget(s, gadget_base[reg0][reg1][reg2]); +} + /*************************** * TCG Scalar Operations * ***************************/ @@ -1558,13 +1567,18 @@ static void tcg_out_nop_fill(tcg_insn_unit *p, int count) tcg_out_sized_vector_gadget_no64(s, name, ternary, vece, a, b, c) -#define tcg_out_ternary_vector_gadget_with_scalar(s, name, is_scalar, vece, a, b, c) \ +#define tcg_out_sized_gadget_with_scalar(s, name, arity, is_scalar, vece, args...) \ if (is_scalar) { \ - tcg_out_ternary_gadget(s, gadget_ ## name ## _scalar, w0, w1, w2); \ + tcg_out_ ## arity ## _gadget(s, gadget_ ## name ## _scalar, args); \ } else { \ - tcg_out_ternary_vector_gadget(s, name, vece, w0, w1, w2); \ + tcg_out_sized_vector_gadget(s, name, arity, vece, args); \ } +#define tcg_out_ternary_vector_gadget_with_scalar(s, name, is_scalar, vece, a, b, c) \ + tcg_out_sized_gadget_with_scalar(s, name, ternary, is_scalar, vece, a, b, c) + +#define tcg_out_ternary_immediate_vector_gadget_with_scalar(s, name, is_scalar, vece, a, b, c) \ + tcg_out_sized_gadget_with_scalar(s, name, ternary_immediate, is_scalar, vece, a, b, c) /* Return true if v16 is a valid 16-bit shifted immediate. */ static bool is_shimm16(uint16_t v16, int *cmode, int *imm8) @@ -1765,6 +1779,20 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc, unsigned vecl, unsigned break; } + /* inhibit compiler warning because we use imm as a register */ + case INDEX_op_shli_vec: + tcg_out_ternary_immediate_vector_gadget_with_scalar(s, shl, is_scalar, vece, w0, w1, r2); + break; + case INDEX_op_shri_vec: + tcg_out_ternary_immediate_vector_gadget_with_scalar(s, ushr, is_scalar, vece, w0, w1, r2 - 1); + break; + case INDEX_op_sari_vec: + tcg_out_ternary_immediate_vector_gadget_with_scalar(s, sshr, is_scalar, vece, w0, w1, r2 - 1); + break; + case INDEX_op_aa64_sli_vec: + tcg_out_ternary_immediate_vector_gadget_with_scalar(s, sli, is_scalar, vece, w0, w2, r3); + break; + case INDEX_op_mov_vec: /* Always emitted via tcg_out_mov. */ case INDEX_op_dup_vec: /* Always emitted via tcg_out_dup_vec. */ default: @@ -1787,6 +1815,9 @@ int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece) case INDEX_op_abs_vec: case INDEX_op_not_vec: case INDEX_op_cmp_vec: + case INDEX_op_shli_vec: + case INDEX_op_shri_vec: + case INDEX_op_sari_vec: case INDEX_op_ssadd_vec: case INDEX_op_sssub_vec: case INDEX_op_usadd_vec: @@ -1827,6 +1858,14 @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece, va_end(va); switch (opc) { + case INDEX_op_rotli_vec: + t1 = tcg_temp_new_vec(type); + tcg_gen_shri_vec(vece, t1, v1, -a2 & ((8 << vece) - 1)); + vec_gen_4(INDEX_op_aa64_sli_vec, type, vece, + tcgv_vec_arg(v0), tcgv_vec_arg(t1), tcgv_vec_arg(v1), a2); + tcg_temp_free_vec(t1); + break; + case INDEX_op_shrv_vec: case INDEX_op_sarv_vec: /* Right shifts are negative left shifts for AArch64. */ diff --git a/tcg/aarch64-tcti/tcti-gadget-gen.py b/tcg/aarch64-tcti/tcti-gadget-gen.py index 275c4ba943..ebed824500 100755 --- a/tcg/aarch64-tcti/tcti-gadget-gen.py +++ b/tcg/aarch64-tcti/tcti-gadget-gen.py @@ -113,7 +113,7 @@ def simple(name, *lines, export=True): -def with_register_substitutions(name, substitutions, *lines, immediate_range=range(0)): +def with_register_substitutions(name, substitutions, *lines, immediate_range=range(0), filter=lambda p: False): """ Generates a collection of gadgtes with register substitutions. """ def _expand_op1_immediate(num): @@ -166,6 +166,10 @@ def substitutions_for_letter(letter, number, line): # For each permutation... for permutation in permutations: + # Filter any invalid combination + if filter(permutation): + continue + new_lines = lines # Replace each placeholder element with its proper value... @@ -212,9 +216,9 @@ def with_dnm(name, *lines): print("};", file=c_file) -def with_dn_immediate(name, *lines, immediate_range): +def with_dn_immediate(name, *lines, immediate_range, filter=lambda m: False): """ Generates a collection of gadgets with substitutions for Xd, Xn, and Xm, and equivalents. """ - with_register_substitutions(name, ["d", "n"], *lines, immediate_range=immediate_range) + with_register_substitutions(name, ["d", "n"], *lines, immediate_range=immediate_range, filter=lambda p: filter(p[-1])) # Fetch the files we'll be using for output. c_file, h_file = _get_output_files() @@ -236,7 +240,10 @@ def with_dn_immediate(name, *lines, immediate_range): # M array for i in immediate_range: - print(f"gadget_{name}_arg{d}_arg{n}_arg{i}", end=", ", file=c_file) + if filter(i): + print(f"(void *)0", end=", ", file=c_file) + else: + print(f"gadget_{name}_arg{d}_arg{n}_arg{i}", end=", ", file=c_file) print("},", file=c_file) print("\t},", file=c_file) @@ -625,6 +632,24 @@ def do_size_replacement(line, size): sized_lines = (scalar,) with_dnm(f"{name}_scalar", *sized_lines) +def vector_dn_immediate(name, *lines, scalar=None, immediate_range, omit_sizes=(), filter=lambda s, m: False): + """ Creates a set of gadgets for every size of a given vector op. Accepts 'S' as a size placeholder. """ + + def do_size_replacement(line, size): + return line.replace(".S", f".{size}") + + # Create a variant for each size, replacing any placeholders. + for size in VECTOR_SIZES: + if size in omit_sizes: + continue + + sized_lines = (do_size_replacement(line, size) for line in lines) + with_dn_immediate(f"{name}_{size}", *sized_lines, immediate_range=immediate_range, filter=lambda m: filter(size, m)) + + if scalar: + if isinstance(scalar, str): + sized_lines = (scalar,) + with_dn_immediate(f"{name}_scalar", *sized_lines, immediate_range=immediate_range, filter=lambda m: filter(None, m)) def vector_math_dnm(name, operation): """ Generates a collection of gadgets for vector math instructions. """ @@ -647,6 +672,9 @@ def vector_logic_dnm(name, operation): with_dnm(f"{name}_d", f"{operation} Vd.8b, Vn.8b, Vm.8b") with_dnm(f"{name}_q", f"{operation} Vd.16b, Vn.16b, Vm.16b") +def vector_math_dn_immediate(name, operation, immediate_range, filter=lambda x: False): + """ Generates a collection of gadgets for vector math instructions. """ + vector_dn_immediate(name, f"{operation} Vd.S, Vn.S, #Ii", scalar=f"{operation} Dd, Dn, #Ii", immediate_range=immediate_range, filter=filter) # # Gadget definitions. @@ -1088,6 +1116,33 @@ def vector_logic_dnm(name, operation): vector_math_dnm("shlv", "ushl") vector_math_dnm("sshl", "sshl") +def filter_shl(size, imm): + match size: + case '16b': return imm >= 8 + case '8b': return imm >= 8 + case '4h': return imm >= 16 + case '8h': return imm >= 16 + case '2s': return imm >= 32 + case '4s': return imm >= 32 + return False + +def filter_shr(size, imm): + if imm == 0: + return True + match size: + case '16b': return imm > 8 + case '8b': return imm > 8 + case '4h': return imm > 16 + case '8h': return imm > 16 + case '2s': return imm > 32 + case '4s': return imm > 32 + return False + +vector_math_dn_immediate("shl", "shl", immediate_range=range(64), filter=filter_shl) +vector_math_dn_immediate("ushr", "ushr", immediate_range=range(1,65), filter=filter_shr) +vector_math_dn_immediate("sshr", "sshr", immediate_range=range(1,65), filter=filter_shr) +vector_math_dn_immediate("sli", "sli", immediate_range=range(64), filter=filter_shl) + vector_dnm("cmeq", "cmeq Vd.S, Vn.S, Vm.S", scalar="cmeq Dd, Dn, Dm") vector_dnm("cmgt", "cmgt Vd.S, Vn.S, Vm.S", scalar="cmgt Dd, Dn, Dm") vector_dnm("cmge", "cmge Vd.S, Vn.S, Vm.S", scalar="cmge Dd, Dn, Dm") -- 2.41.0 From 35ba52817dbea01821b429737e989bc54a14d411 Mon Sep 17 00:00:00 2001 From: osy Date: Tue, 22 Jul 2025 10:13:34 -0700 Subject: [PATCH 2/2] tcg/tcti: fix goto as first instruction --- accel/tcg/tcg-accel-ops.c | 1 + 1 file changed, 1 insertion(+) diff --git a/accel/tcg/tcg-accel-ops.c b/accel/tcg/tcg-accel-ops.c index 0e8c4c1c67..e07f60357f 100644 --- a/accel/tcg/tcg-accel-ops.c +++ b/accel/tcg/tcg-accel-ops.c @@ -68,6 +68,7 @@ void tcg_cpu_init_cflags(CPUState *cpu, bool parallel) // GOTO_PTR is too complex to emit a simple gadget for. // We'll let C handle it, since the overhead is similar. cflags |= CF_NO_GOTO_PTR; + cpu->cflags_next_tb = CF_NO_GOTO_PTR; #endif tcg_cflags_set(cpu, cflags); } -- 2.41.0 From 344a5a3cbe3df0c373743969493afe7d1c4fb4d6 Mon Sep 17 00:00:00 2001 From: osy Date: Sat, 2 Aug 2025 19:22:04 -0700 Subject: [PATCH] pc-bios: add classicvirtio drivers for m68k/ppc --- pc-bios/m68k-declrom | Bin 0 -> 106496 bytes pc-bios/meson.build | 2 ++ pc-bios/ppc-ndrvloader | Bin 0 -> 191172 bytes 3 files changed, 2 insertions(+) create mode 100755 pc-bios/m68k-declrom create mode 100644 pc-bios/ppc-ndrvloader diff --git a/pc-bios/meson.build b/pc-bios/meson.build index 9fb9659c45..63e10cc6df 100644 --- a/pc-bios/meson.build +++ b/pc-bios/meson.build @@ -85,6 +85,8 @@ blobs = [ 'npcm8xx_bootrom.bin', 'vof.bin', 'vof-nvram.bin', + 'm68k-declrom', + 'ppc-ndrvloader', ] dtc = find_program('dtc', required: false) From a172998c2f8bcbd29afeb8cab9b97e43ef3a22b5 Mon Sep 17 00:00:00 2001 From: osy Date: Sun, 10 Aug 2025 21:54:34 -0700 Subject: [PATCH] pc-bios: use 2023 Microsoft UEFI certificates Restore non-secure vars variants as well. --- pc-bios/edk2-arm-secure-vars.fd.bz2 | Bin 0 -> 12654 bytes pc-bios/edk2-arm-vars.fd.bz2 | Bin 6710 -> 595 bytes pc-bios/edk2-i386-secure-vars.fd.bz2 | Bin 0 -> 12986 bytes pc-bios/edk2-i386-vars.fd.bz2 | Bin 7727 -> 612 bytes pc-bios/meson.build | 2 ++ 5 files changed, 2 insertions(+) create mode 100644 pc-bios/edk2-arm-secure-vars.fd.bz2 create mode 100644 pc-bios/edk2-i386-secure-vars.fd.bz2 diff --git a/pc-bios/meson.build b/pc-bios/meson.build index 63e10cc6df..1e1b553795 100644 --- a/pc-bios/meson.build +++ b/pc-bios/meson.build @@ -4,11 +4,13 @@ if unpack_edk2_blobs 'edk2-aarch64-code.fd', 'edk2-aarch64-secure-code.fd', 'edk2-arm-code.fd', + 'edk2-arm-secure-vars.fd', 'edk2-arm-vars.fd', 'edk2-riscv-code.fd', 'edk2-riscv-vars.fd', 'edk2-i386-code.fd', 'edk2-i386-secure-code.fd', + 'edk2-i386-secure-vars.fd', 'edk2-i386-vars.fd', 'edk2-x86_64-code.fd', 'edk2-x86_64-secure-code.fd', -- 2.41.0 From 0f1d6606c28d0ae81a1b311972c5c54e5e867bf0 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Wed, 11 Jun 2025 14:03:15 +0100 Subject: [PATCH] target/i386: fix TB exit logic in gen_movl_seg() when writing to SS Before commit e54ef98c8a ("target/i386: do not trigger IRQ shadow for LSS"), any write to SS in gen_movl_seg() would cause a TB exit. The changes introduced by this commit were intended to restrict the DISAS_EOB_INHIBIT_IRQ exit to the case where inhibit_irq is true, but missed that a DISAS_EOB_NEXT exit can still be required when writing to SS and inhibit_irq is false. Comparing the PE(s) && !VM86(s) section with the logic in x86_update_hflags(), we can see that the DISAS_EOB_NEXT exit is still required for the !CODE32 case when writing to SS in gen_movl_seg() because any change to the SS flags can affect hflags. Similarly we can see that the existing CODE32 case is still correct since a change to any of DS, ES and SS can affect hflags. Finally for the gen_op_movl_seg_real() case an explicit TB exit is not needed because the segment register selector does not affect hflags. Update the logic in gen_movl_seg() so that a write to SS with inhibit_irq set to false where PE(s) && !VM86(s) will generate a DISAS_EOB_NEXT exit along with the inline comment. This has the effect of allowing Win98SE to boot in QEMU once again. Signed-off-by: Mark Cave-Ayland Fixes: e54ef98c8a ("target/i386: do not trigger IRQ shadow for LSS") Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2987 Link: https://lore.kernel.org/r/20250611130315.383151-1-mark.cave-ayland@ilande.co.uk Reviewed-by: Peter Maydell Signed-off-by: Paolo Bonzini --- target/i386/tcg/translate.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 0fcddc2ec0..0cb87d0201 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -2033,8 +2033,11 @@ static void gen_movl_seg(DisasContext *s, X86Seg seg_reg, TCGv src, bool inhibit tcg_gen_trunc_tl_i32(sel, src); gen_helper_load_seg(tcg_env, tcg_constant_i32(seg_reg), sel); - /* For move to DS/ES/SS, the addseg or ss32 flags may change. */ - if (CODE32(s) && seg_reg < R_FS) { + /* + * For moves to SS, the SS32 flag may change. For CODE32 only, changes + * to SS, DS and ES may change the ADDSEG flags. + */ + if (seg_reg == R_SS || (CODE32(s) && seg_reg < R_FS)) { s->base.is_jmp = DISAS_EOB_NEXT; } } else { -- 2.41.0 From a3955f90f898cfa8efcdeeab285324dcbb033b31 Mon Sep 17 00:00:00 2001 From: osy Date: Mon, 11 Aug 2025 22:24:52 -0700 Subject: [PATCH] hw/i386/pc: no floppy when defaults disabled --- hw/i386/pc_piix.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 6c91e2d292..86978f4671 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -465,7 +465,7 @@ static void pc_i440fx_machine_options(MachineClass *m) m->default_machine_opts = "firmware=bios-256k.bin"; m->default_display = "std"; m->default_nic = "e1000"; - m->no_floppy = !module_object_class_by_name(TYPE_ISA_FDC); + m->no_floppy = !defaults_enabled() || !module_object_class_by_name(TYPE_ISA_FDC); m->no_parallel = !module_object_class_by_name(TYPE_ISA_PARALLEL); machine_class_allow_dynamic_sysbus_dev(m, TYPE_RAMFB_DEVICE); machine_class_allow_dynamic_sysbus_dev(m, TYPE_VMBUS_BRIDGE); @@ -811,7 +811,7 @@ static void isapc_machine_options(MachineClass *m) pcmc->has_reserved_memory = false; m->default_nic = "ne2k_isa"; m->default_cpu_type = X86_CPU_TYPE_NAME("486"); - m->no_floppy = !module_object_class_by_name(TYPE_ISA_FDC); + m->no_floppy = !defaults_enabled() || !module_object_class_by_name(TYPE_ISA_FDC); m->no_parallel = !module_object_class_by_name(TYPE_ISA_PARALLEL); } -- 2.41.0