diff options
26 files changed, 419 insertions, 193 deletions
diff --git a/chardev/char-io.c b/chardev/char-io.c index 4451128cba..dab77b112e 100644 --- a/chardev/char-io.c +++ b/chardev/char-io.c @@ -33,6 +33,7 @@ typedef struct IOWatchPoll { IOCanReadHandler *fd_can_read; GSourceFunc fd_read; void *opaque; + GMainContext *context; } IOWatchPoll; static IOWatchPoll *io_watch_poll_from_source(GSource *source) @@ -50,28 +51,59 @@ static gboolean io_watch_poll_prepare(GSource *source, return FALSE; } + /* + * We do not register the QIOChannel watch as a child GSource. + * The 'prepare' function on the parent GSource will be + * skipped if a child GSource's 'prepare' function indicates + * readiness. We need this prepare function be guaranteed + * to run on *every* iteration of the main loop, because + * it is critical to ensure we remove the QIOChannel watch + * if 'fd_can_read' indicates the frontend cannot receive + * more data. + */ if (now_active) { iwp->src = qio_channel_create_watch( iwp->ioc, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL); g_source_set_callback(iwp->src, iwp->fd_read, iwp->opaque, NULL); - g_source_add_child_source(source, iwp->src); - g_source_unref(iwp->src); + g_source_attach(iwp->src, iwp->context); } else { - g_source_remove_child_source(source, iwp->src); + g_source_destroy(iwp->src); + g_source_unref(iwp->src); iwp->src = NULL; } return FALSE; } +static gboolean io_watch_poll_check(GSource *source) +{ + return FALSE; +} + static gboolean io_watch_poll_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { - return G_SOURCE_CONTINUE; + abort(); +} + +static void io_watch_poll_finalize(GSource *source) +{ + /* + * Due to a glib bug, removing the last reference to a source + * inside a finalize callback causes recursive locking (and a + * deadlock). This is not a problem inside other callbacks, + * including dispatch callbacks, so we call io_remove_watch_poll + * to remove this source. At this point, iwp->src must + * be NULL, or we would leak it. + */ + IOWatchPoll *iwp = io_watch_poll_from_source(source); + assert(iwp->src == NULL); } static GSourceFuncs io_watch_poll_funcs = { .prepare = io_watch_poll_prepare, + .check = io_watch_poll_check, .dispatch = io_watch_poll_dispatch, + .finalize = io_watch_poll_finalize, }; GSource *io_add_watch_poll(Chardev *chr, @@ -91,6 +123,7 @@ GSource *io_add_watch_poll(Chardev *chr, iwp->ioc = ioc; iwp->fd_read = (GSourceFunc) fd_read; iwp->src = NULL; + iwp->context = context; name = g_strdup_printf("chardev-iowatch-%s", chr->label); g_source_set_name((GSource *)iwp, name); @@ -101,10 +134,23 @@ GSource *io_add_watch_poll(Chardev *chr, return (GSource *)iwp; } +static void io_remove_watch_poll(GSource *source) +{ + IOWatchPoll *iwp; + + iwp = io_watch_poll_from_source(source); + if (iwp->src) { + g_source_destroy(iwp->src); + g_source_unref(iwp->src); + iwp->src = NULL; + } + g_source_destroy(&iwp->parent); +} + void remove_fd_in_watch(Chardev *chr) { if (chr->gsource) { - g_source_destroy(chr->gsource); + io_remove_watch_poll(chr->gsource); chr->gsource = NULL; } } diff --git a/chardev/char-socket.c b/chardev/char-socket.c index 8a0406cc1e..812d7aa38a 100644 --- a/chardev/char-socket.c +++ b/chardev/char-socket.c @@ -496,9 +496,9 @@ static gboolean tcp_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque) s->max_size <= 0) { return TRUE; } - len = tcp_chr_read_poll(opaque); - if (len > sizeof(buf)) { - len = sizeof(buf); + len = sizeof(buf); + if (len > s->max_size) { + len = s->max_size; } size = tcp_chr_recv(chr, (void *)buf, len); if (size == 0 || (size == -1 && errno != EAGAIN)) { @@ -601,6 +601,22 @@ static void update_ioc_handlers(SocketChardev *s) remove_hup_source(s); s->hup_source = qio_channel_create_watch(s->ioc, G_IO_HUP); + /* + * poll() is liable to return POLLHUP even when there is + * still incoming data available to read on the FD. If + * we have the hup_source at the same priority as the + * main io_add_watch_poll GSource, then we might end up + * processing the POLLHUP event first, closing the FD, + * and as a result silently discard data we should have + * read. + * + * By setting the hup_source to G_PRIORITY_DEFAULT + 1, + * we ensure that io_add_watch_poll GSource will always + * be dispatched first, thus guaranteeing we will be + * able to process all incoming data before closing the + * FD + */ + g_source_set_priority(s->hup_source, G_PRIORITY_DEFAULT + 1); g_source_set_callback(s->hup_source, (GSourceFunc)tcp_chr_hup, chr, NULL); g_source_attach(s->hup_source, chr->gcontext); diff --git a/contrib/plugins/howvec.c b/contrib/plugins/howvec.c index 2d10c87e0f..94bbc53820 100644 --- a/contrib/plugins/howvec.c +++ b/contrib/plugins/howvec.c @@ -167,9 +167,9 @@ static gint cmp_exec_count(gconstpointer a, gconstpointer b) static void free_record(gpointer data) { InsnExecCount *rec = (InsnExecCount *) data; + qemu_plugin_scoreboard_free(rec->count.score); g_free(rec->insn); g_free(rec); - qemu_plugin_scoreboard_free(rec->count.score); } static void plugin_exit(qemu_plugin_id_t id, void *p) diff --git a/crypto/cipher-gcrypt.c.inc b/crypto/cipher-gcrypt.c.inc index 1377cbaf14..4a8314746d 100644 --- a/crypto/cipher-gcrypt.c.inc +++ b/crypto/cipher-gcrypt.c.inc @@ -20,6 +20,56 @@ #include <gcrypt.h> +static int qcrypto_cipher_alg_to_gcry_alg(QCryptoCipherAlgorithm alg) +{ + switch (alg) { + case QCRYPTO_CIPHER_ALG_DES: + return GCRY_CIPHER_DES; + case QCRYPTO_CIPHER_ALG_3DES: + return GCRY_CIPHER_3DES; + case QCRYPTO_CIPHER_ALG_AES_128: + return GCRY_CIPHER_AES128; + case QCRYPTO_CIPHER_ALG_AES_192: + return GCRY_CIPHER_AES192; + case QCRYPTO_CIPHER_ALG_AES_256: + return GCRY_CIPHER_AES256; + case QCRYPTO_CIPHER_ALG_CAST5_128: + return GCRY_CIPHER_CAST5; + case QCRYPTO_CIPHER_ALG_SERPENT_128: + return GCRY_CIPHER_SERPENT128; + case QCRYPTO_CIPHER_ALG_SERPENT_192: + return GCRY_CIPHER_SERPENT192; + case QCRYPTO_CIPHER_ALG_SERPENT_256: + return GCRY_CIPHER_SERPENT256; + case QCRYPTO_CIPHER_ALG_TWOFISH_128: + return GCRY_CIPHER_TWOFISH128; + case QCRYPTO_CIPHER_ALG_TWOFISH_256: + return GCRY_CIPHER_TWOFISH; +#ifdef CONFIG_CRYPTO_SM4 + case QCRYPTO_CIPHER_ALG_SM4: + return GCRY_CIPHER_SM4; +#endif + default: + return GCRY_CIPHER_NONE; + } +} + +static int qcrypto_cipher_mode_to_gcry_mode(QCryptoCipherMode mode) +{ + switch (mode) { + case QCRYPTO_CIPHER_MODE_ECB: + return GCRY_CIPHER_MODE_ECB; + case QCRYPTO_CIPHER_MODE_XTS: + return GCRY_CIPHER_MODE_XTS; + case QCRYPTO_CIPHER_MODE_CBC: + return GCRY_CIPHER_MODE_CBC; + case QCRYPTO_CIPHER_MODE_CTR: + return GCRY_CIPHER_MODE_CTR; + default: + return GCRY_CIPHER_MODE_NONE; + } +} + bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg, QCryptoCipherMode mode) { @@ -43,6 +93,11 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg, return false; } + if (gcry_cipher_algo_info(qcrypto_cipher_alg_to_gcry_alg(alg), + GCRYCTL_TEST_ALGO, NULL, NULL) != 0) { + return false; + } + switch (mode) { case QCRYPTO_CIPHER_MODE_ECB: case QCRYPTO_CIPHER_MODE_CBC: @@ -188,72 +243,26 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, return NULL; } - switch (alg) { - case QCRYPTO_CIPHER_ALG_DES: - gcryalg = GCRY_CIPHER_DES; - break; - case QCRYPTO_CIPHER_ALG_3DES: - gcryalg = GCRY_CIPHER_3DES; - break; - case QCRYPTO_CIPHER_ALG_AES_128: - gcryalg = GCRY_CIPHER_AES128; - break; - case QCRYPTO_CIPHER_ALG_AES_192: - gcryalg = GCRY_CIPHER_AES192; - break; - case QCRYPTO_CIPHER_ALG_AES_256: - gcryalg = GCRY_CIPHER_AES256; - break; - case QCRYPTO_CIPHER_ALG_CAST5_128: - gcryalg = GCRY_CIPHER_CAST5; - break; - case QCRYPTO_CIPHER_ALG_SERPENT_128: - gcryalg = GCRY_CIPHER_SERPENT128; - break; - case QCRYPTO_CIPHER_ALG_SERPENT_192: - gcryalg = GCRY_CIPHER_SERPENT192; - break; - case QCRYPTO_CIPHER_ALG_SERPENT_256: - gcryalg = GCRY_CIPHER_SERPENT256; - break; - case QCRYPTO_CIPHER_ALG_TWOFISH_128: - gcryalg = GCRY_CIPHER_TWOFISH128; - break; - case QCRYPTO_CIPHER_ALG_TWOFISH_256: - gcryalg = GCRY_CIPHER_TWOFISH; - break; -#ifdef CONFIG_CRYPTO_SM4 - case QCRYPTO_CIPHER_ALG_SM4: - gcryalg = GCRY_CIPHER_SM4; - break; -#endif - default: + gcryalg = qcrypto_cipher_alg_to_gcry_alg(alg); + if (gcryalg == GCRY_CIPHER_NONE) { error_setg(errp, "Unsupported cipher algorithm %s", QCryptoCipherAlgorithm_str(alg)); return NULL; } - drv = &qcrypto_gcrypt_driver; - switch (mode) { - case QCRYPTO_CIPHER_MODE_ECB: - gcrymode = GCRY_CIPHER_MODE_ECB; - break; - case QCRYPTO_CIPHER_MODE_XTS: - gcrymode = GCRY_CIPHER_MODE_XTS; - break; - case QCRYPTO_CIPHER_MODE_CBC: - gcrymode = GCRY_CIPHER_MODE_CBC; - break; - case QCRYPTO_CIPHER_MODE_CTR: - drv = &qcrypto_gcrypt_ctr_driver; - gcrymode = GCRY_CIPHER_MODE_CTR; - break; - default: + gcrymode = qcrypto_cipher_mode_to_gcry_mode(mode); + if (gcrymode == GCRY_CIPHER_MODE_NONE) { error_setg(errp, "Unsupported cipher mode %s", QCryptoCipherMode_str(mode)); return NULL; } + if (mode == QCRYPTO_CIPHER_MODE_CTR) { + drv = &qcrypto_gcrypt_ctr_driver; + } else { + drv = &qcrypto_gcrypt_driver; + } + ctx = g_new0(QCryptoCipherGcrypt, 1); ctx->base.driver = drv; diff --git a/hw/intc/loongarch_extioi.c b/hw/intc/loongarch_extioi.c index bdfa3b481e..0b358548eb 100644 --- a/hw/intc/loongarch_extioi.c +++ b/hw/intc/loongarch_extioi.c @@ -151,7 +151,7 @@ static inline void extioi_update_sw_coremap(LoongArchExtIOI *s, int irq, continue; } - if (notify && test_bit(irq, (unsigned long *)s->isr)) { + if (notify && test_bit(irq + i, (unsigned long *)s->isr)) { /* * lower irq at old cpu and raise irq at new cpu */ diff --git a/meson.build b/meson.build index b375248a76..c9c3217ba4 100644 --- a/meson.build +++ b/meson.build @@ -3951,7 +3951,7 @@ foreach target : target_dirs c_args: c_args, dependencies: arch_deps + deps + exe['dependencies'], objects: lib.extract_all_objects(recursive: true), - link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []), + link_depends: [block_syms, qemu_syms], link_args: link_args, win_subsystem: exe['win_subsystem']) diff --git a/pc-bios/edk2-aarch64-code.fd.bz2 b/pc-bios/edk2-aarch64-code.fd.bz2 Binary files differindex 5d0a57173d..3204e2816b 100644 --- a/pc-bios/edk2-aarch64-code.fd.bz2 +++ b/pc-bios/edk2-aarch64-code.fd.bz2 diff --git a/pc-bios/edk2-arm-code.fd.bz2 b/pc-bios/edk2-arm-code.fd.bz2 Binary files differindex af49559f34..de916e9d76 100644 --- a/pc-bios/edk2-arm-code.fd.bz2 +++ b/pc-bios/edk2-arm-code.fd.bz2 diff --git a/pc-bios/edk2-i386-secure-code.fd.bz2 b/pc-bios/edk2-i386-secure-code.fd.bz2 Binary files differindex 983e1778c4..925a7d1ef0 100644 --- a/pc-bios/edk2-i386-secure-code.fd.bz2 +++ b/pc-bios/edk2-i386-secure-code.fd.bz2 diff --git a/pc-bios/edk2-riscv-code.fd.bz2 b/pc-bios/edk2-riscv-code.fd.bz2 Binary files differindex b6cd3c6f74..446117073c 100644 --- a/pc-bios/edk2-riscv-code.fd.bz2 +++ b/pc-bios/edk2-riscv-code.fd.bz2 diff --git a/roms/Makefile b/roms/Makefile index 8e5d8d26a9..edc234a0e8 100644 --- a/roms/Makefile +++ b/roms/Makefile @@ -187,6 +187,7 @@ clean: rm -rf seabios/.config seabios/out seabios/builds $(MAKE) -C ipxe/src veryclean $(MAKE) -C edk2/BaseTools clean + rm -rf edk2/Conf/{.cache,BuildEnv.sh,build_rule.txt,target.txt,tools_def.txt} $(MAKE) -C SLOF clean rm -rf u-boot/build-e500 $(MAKE) -C u-boot-sam460ex distclean diff --git a/roms/edk2-build.config b/roms/edk2-build.config index 0d367dbdb7..cc9b211542 100644 --- a/roms/edk2-build.config +++ b/roms/edk2-build.config @@ -18,6 +18,7 @@ CAVIUM_ERRATUM_27456 = TRUE [opts.ovmf.sb.smm] SECURE_BOOT_ENABLE = TRUE SMM_REQUIRE = TRUE +BUILD_SHELL = FALSE [opts.armvirt.silent] DEBUG_PRINT_ERROR_LEVEL = 0x80000000 @@ -32,9 +33,6 @@ PcdDxeNxMemoryProtectionPolicy = 0xC000000000007FD1 # shim.efi has broken MemAttr code PcdUninstallMemAttrProtocol = TRUE -[pcds.workaround.202308] -PcdFirstTimeWakeUpAPsBySipi = FALSE - #################################################################################### # i386 @@ -66,19 +64,17 @@ desc = ovmf build (64-bit) conf = OvmfPkg/OvmfPkgX64.dsc arch = X64 opts = common -pcds = workaround.202308 plat = OvmfX64 dest = ../pc-bios cpy1 = FV/OVMF_CODE.fd edk2-x86_64-code.fd [build.ovmf.x86_64.secure] desc = ovmf build (64-bit, secure boot) -conf = OvmfPkg/OvmfPkgIa32X64.dsc -arch = IA32 X64 +conf = OvmfPkg/OvmfPkgX64.dsc +arch = X64 opts = common ovmf.sb.smm -pcds = workaround.202308 -plat = Ovmf3264 +plat = OvmfX64 dest = ../pc-bios cpy1 = FV/OVMF_CODE.fd edk2-x86_64-secure-code.fd @@ -87,7 +83,6 @@ desc = ovmf build for microvm conf = OvmfPkg/Microvm/MicrovmX64.dsc arch = X64 opts = common -pcds = workaround.202308 plat = MicrovmX64 dest = ../pc-bios cpy1 = FV/MICROVM.fd edk2-x86_64-microvm.fd diff --git a/system/qemu-seccomp.c b/system/qemu-seccomp.c index 4d7439e7f7..98ffce075c 100644 --- a/system/qemu-seccomp.c +++ b/system/qemu-seccomp.c @@ -74,7 +74,7 @@ const struct scmp_arg_cmp sched_setscheduler_arg[] = { #define RULE_CLONE_FLAG(flag) \ { SCMP_SYS(clone), QEMU_SECCOMP_SET_SPAWN, \ - ARRAY_SIZE(clone_arg ## flag), clone_arg ## flag, SCMP_ACT_TRAP } + ARRAY_SIZE(clone_arg ## flag), clone_arg ## flag, SCMP_ACT_ERRNO(EPERM) } /* If no CLONE_* flags are set, except CSIGNAL, deny */ const struct scmp_arg_cmp clone_arg_none[] = { @@ -214,13 +214,13 @@ static const struct QemuSeccompSyscall denylist[] = { 0, NULL, SCMP_ACT_TRAP }, /* spawn */ { SCMP_SYS(fork), QEMU_SECCOMP_SET_SPAWN, - 0, NULL, SCMP_ACT_TRAP }, + 0, NULL, SCMP_ACT_ERRNO(EPERM) }, { SCMP_SYS(vfork), QEMU_SECCOMP_SET_SPAWN, - 0, NULL, SCMP_ACT_TRAP }, + 0, NULL, SCMP_ACT_ERRNO(EPERM) }, { SCMP_SYS(execve), QEMU_SECCOMP_SET_SPAWN, - 0, NULL, SCMP_ACT_TRAP }, + 0, NULL, SCMP_ACT_ERRNO(EPERM) }, { SCMP_SYS(clone), QEMU_SECCOMP_SET_SPAWN, - ARRAY_SIZE(clone_arg_none), clone_arg_none, SCMP_ACT_TRAP }, + ARRAY_SIZE(clone_arg_none), clone_arg_none, SCMP_ACT_ERRNO(EPERM) }, RULE_CLONE_FLAG(CLONE_VM), RULE_CLONE_FLAG(CLONE_FS), RULE_CLONE_FLAG(CLONE_FILES), diff --git a/system/vl.c b/system/vl.c index 70f4cece7f..c644222982 100644 --- a/system/vl.c +++ b/system/vl.c @@ -2653,7 +2653,7 @@ static void qemu_create_cli_devices(void) rom_reset_order_override(); } -static void qemu_machine_creation_done(void) +static bool qemu_machine_creation_done(Error **errp) { MachineState *machine = MACHINE(qdev_get_machine()); @@ -2676,15 +2676,15 @@ static void qemu_machine_creation_done(void) qdev_machine_creation_done(); - if (machine->cgs) { - /* - * Verify that Confidential Guest Support has actually been initialized - */ - assert(machine->cgs->ready); + if (machine->cgs && !machine->cgs->ready) { + error_setg(errp, "accelerator does not support confidential guest %s", + object_get_typename(OBJECT(machine->cgs))); + exit(1); } if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) { - exit(1); + error_setg(errp, "could not start gdbserver"); + return false; } if (!vga_interface_created && !default_vga && vga_interface_type != VGA_NONE) { @@ -2692,6 +2692,7 @@ static void qemu_machine_creation_done(void) "type does not use that option; " "No VGA device has been created"); } + return true; } void qmp_x_exit_preconfig(Error **errp) @@ -2703,7 +2704,9 @@ void qmp_x_exit_preconfig(Error **errp) qemu_init_board(); qemu_create_cli_devices(); - qemu_machine_creation_done(); + if (!qemu_machine_creation_done(errp)) { + return; + } if (loadvm) { RunState state = autostart ? RUN_STATE_RUNNING : runstate_get(); diff --git a/target/hppa/insns.decode b/target/hppa/insns.decode index f5a3f02fd1..f58455dfdb 100644 --- a/target/hppa/insns.decode +++ b/target/hppa/insns.decode @@ -24,16 +24,17 @@ %assemble_sr3 13:1 14:2 %assemble_sr3x 13:1 14:2 !function=expand_sr3x -%assemble_11a 0:s1 4:10 !function=expand_shl3 +%assemble_11a 4:12 0:1 !function=expand_11a %assemble_12 0:s1 2:1 3:10 !function=expand_shl2 -%assemble_12a 0:s1 3:11 !function=expand_shl2 +%assemble_12a 3:13 0:1 !function=expand_12a +%assemble_16 0:16 !function=expand_16 %assemble_17 0:s1 16:5 2:1 3:10 !function=expand_shl2 %assemble_22 0:s1 16:10 2:1 3:10 !function=expand_shl2 +%assemble_sp 14:2 !function=sp0_if_wide %assemble_21 0:s1 1:11 14:2 16:5 12:2 !function=expand_shl11 %lowsign_11 0:s1 1:10 -%lowsign_14 0:s1 1:13 %sm_imm 16:10 !function=expand_sm_imm @@ -143,9 +144,9 @@ getshadowregs 1111 1111 1111 1101 1110 1010 1101 0010 nop 000001 ----- ----- -- 11001010 0 ----- # fdc, disp nop_addrx 000001 ..... ..... -- 01001010 . ----- @addrx # fdc, index nop_addrx 000001 ..... ..... -- 01001011 . ----- @addrx # fdce -nop_addrx 000001 ..... ..... --- 0001010 . ----- @addrx # fic 0x0a -nop_addrx 000001 ..... ..... -- 01001111 . 00000 @addrx # fic 0x4f -nop_addrx 000001 ..... ..... --- 0001011 . ----- @addrx # fice +fic 000001 ..... ..... --- 0001010 . ----- @addrx # fic 0x0a +fic 000001 ..... ..... -- 01001111 . 00000 @addrx # fic 0x4f +fic 000001 ..... ..... --- 0001011 . ----- @addrx # fice nop_addrx 000001 ..... ..... -- 01001110 . 00000 @addrx # pdc probe 000001 b:5 ri:5 sp:2 imm:1 100011 write:1 0 t:5 @@ -221,7 +222,7 @@ sub_b_tsv 000010 ..... ..... .... 110100 . ..... @rrr_cf_d ldil 001000 t:5 ..................... i=%assemble_21 addil 001010 r:5 ..................... i=%assemble_21 -ldo 001101 b:5 t:5 -- .............. i=%lowsign_14 +ldo 001101 b:5 t:5 ................ i=%assemble_16 addi 101101 ..... ..... .... 0 ........... @rri_cf addi_tsv 101101 ..... ..... .... 1 ........... @rri_cf @@ -304,14 +305,18 @@ fstd 001011 ..... ..... .. . 1 -- 100 0 . ..... @fldstdi # Offset Mem #### -@ldstim11 ...... b:5 t:5 sp:2 .............. \ - &ldst disp=%assemble_11a m=%ma2_to_m x=0 scale=0 size=3 -@ldstim14 ...... b:5 t:5 sp:2 .............. \ - &ldst disp=%lowsign_14 x=0 scale=0 m=0 -@ldstim14m ...... b:5 t:5 sp:2 .............. \ - &ldst disp=%lowsign_14 x=0 scale=0 m=%neg_to_m -@ldstim12m ...... b:5 t:5 sp:2 .............. \ - &ldst disp=%assemble_12a x=0 scale=0 m=%pos_to_m +@ldstim11 ...... b:5 t:5 ................ \ + &ldst sp=%assemble_sp disp=%assemble_11a \ + m=%ma2_to_m x=0 scale=0 size=3 +@ldstim14 ...... b:5 t:5 ................ \ + &ldst sp=%assemble_sp disp=%assemble_16 \ + x=0 scale=0 m=0 +@ldstim14m ...... b:5 t:5 ................ \ + &ldst sp=%assemble_sp disp=%assemble_16 \ + x=0 scale=0 m=%neg_to_m +@ldstim12m ...... b:5 t:5 ................ \ + &ldst sp=%assemble_sp disp=%assemble_12a \ + x=0 scale=0 m=%pos_to_m # LDB, LDH, LDW, LDWM ld 010000 ..... ..... .. .............. @ldstim14 size=0 @@ -327,15 +332,19 @@ st 011010 ..... ..... .. .............. @ldstim14 size=2 st 011011 ..... ..... .. .............. @ldstim14m size=2 st 011111 ..... ..... .. ...........10. @ldstim12m size=2 -fldw 010110 b:5 ..... sp:2 .............. \ - &ldst disp=%assemble_12a t=%rm64 m=%a_to_m x=0 scale=0 size=2 -fldw 010111 b:5 ..... sp:2 ...........0.. \ - &ldst disp=%assemble_12a t=%rm64 m=0 x=0 scale=0 size=2 - -fstw 011110 b:5 ..... sp:2 .............. \ - &ldst disp=%assemble_12a t=%rm64 m=%a_to_m x=0 scale=0 size=2 -fstw 011111 b:5 ..... sp:2 ...........0.. \ - &ldst disp=%assemble_12a t=%rm64 m=0 x=0 scale=0 size=2 +fldw 010110 b:5 ..... ................ \ + &ldst disp=%assemble_12a sp=%assemble_sp \ + t=%rm64 m=%a_to_m x=0 scale=0 size=2 +fldw 010111 b:5 ..... .............0.. \ + &ldst disp=%assemble_12a sp=%assemble_sp \ + t=%rm64 m=0 x=0 scale=0 size=2 + +fstw 011110 b:5 ..... ................ \ + &ldst disp=%assemble_12a sp=%assemble_sp \ + t=%rm64 m=%a_to_m x=0 scale=0 size=2 +fstw 011111 b:5 ..... .............0.. \ + &ldst disp=%assemble_12a sp=%assemble_sp \ + t=%rm64 m=0 x=0 scale=0 size=2 ld 010100 ..... ..... .. ............0. @ldstim11 fldd 010100 ..... ..... .. ............1. @ldstim11 diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c index 80f51e753f..84785b5a5c 100644 --- a/target/hppa/mem_helper.c +++ b/target/hppa/mem_helper.c @@ -152,6 +152,49 @@ static HPPATLBEntry *hppa_alloc_tlb_ent(CPUHPPAState *env) return ent; } +#define ACCESS_ID_MASK 0xffff + +/* Return the set of protections allowed by a PID match. */ +static int match_prot_id_1(uint32_t access_id, uint32_t prot_id) +{ + if (((access_id ^ (prot_id >> 1)) & ACCESS_ID_MASK) == 0) { + return (prot_id & 1 + ? PAGE_EXEC | PAGE_READ + : PAGE_EXEC | PAGE_READ | PAGE_WRITE); + } + return 0; +} + +static int match_prot_id32(CPUHPPAState *env, uint32_t access_id) +{ + int r, i; + + for (i = CR_PID1; i <= CR_PID4; ++i) { + r = match_prot_id_1(access_id, env->cr[i]); + if (r) { + return r; + } + } + return 0; +} + +static int match_prot_id64(CPUHPPAState *env, uint32_t access_id) +{ + int r, i; + + for (i = CR_PID1; i <= CR_PID4; ++i) { + r = match_prot_id_1(access_id, env->cr[i]); + if (r) { + return r; + } + r = match_prot_id_1(access_id, env->cr[i] >> 32); + if (r) { + return r; + } + } + return 0; +} + int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx, int type, hwaddr *pphys, int *pprot, HPPATLBEntry **tlb_entry) @@ -224,29 +267,30 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx, break; } + /* + * No guest access type indicates a non-architectural access from + * within QEMU. Bypass checks for access, D, B, P and T bits. + */ + if (type == 0) { + goto egress; + } + /* access_id == 0 means public page and no check is performed */ if (ent->access_id && MMU_IDX_TO_P(mmu_idx)) { - /* If bits [31:1] match, and bit 0 is set, suppress write. */ - int match = ent->access_id * 2 + 1; - - if (match == env->cr[CR_PID1] || match == env->cr[CR_PID2] || - match == env->cr[CR_PID3] || match == env->cr[CR_PID4]) { - prot &= PAGE_READ | PAGE_EXEC; - if (type == PAGE_WRITE) { - ret = EXCP_DMPI; - goto egress; - } + int access_prot = (hppa_is_pa20(env) + ? match_prot_id64(env, ent->access_id) + : match_prot_id32(env, ent->access_id)); + if (unlikely(!(type & access_prot))) { + /* Not allowed -- Inst/Data Memory Protection Id Fault. */ + ret = type & PAGE_EXEC ? EXCP_IMP : EXCP_DMPI; + goto egress; } - } - - /* No guest access type indicates a non-architectural access from - within QEMU. Bypass checks for access, D, B and T bits. */ - if (type == 0) { - goto egress; + /* Otherwise exclude permissions not allowed (i.e WD). */ + prot &= access_prot; } if (unlikely(!(prot & type))) { - /* The access isn't allowed -- Inst/Data Memory Protection Fault. */ + /* Not allowed -- Inst/Data Memory Access Rights Fault. */ ret = (type & PAGE_EXEC) ? EXCP_IMP : EXCP_DMAR; goto egress; } diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c index 480fe80844..6cf49f33b7 100644 --- a/target/hppa/op_helper.c +++ b/target/hppa/op_helper.c @@ -281,17 +281,17 @@ static void do_stdby_e(CPUHPPAState *env, target_ulong addr, uint64_t val, case 3: /* The 3 byte store must appear atomic. */ if (parallel) { - atomic_store_mask32(env, addr - 3, val, 0xffffff00u, ra); + atomic_store_mask32(env, addr - 3, val >> 32, 0xffffff00u, ra); } else { - cpu_stw_data_ra(env, addr - 3, val >> 16, ra); - cpu_stb_data_ra(env, addr - 1, val >> 8, ra); + cpu_stw_data_ra(env, addr - 3, val >> 48, ra); + cpu_stb_data_ra(env, addr - 1, val >> 40, ra); } break; case 2: - cpu_stw_data_ra(env, addr - 2, val >> 16, ra); + cpu_stw_data_ra(env, addr - 2, val >> 48, ra); break; case 1: - cpu_stb_data_ra(env, addr - 1, val >> 24, ra); + cpu_stb_data_ra(env, addr - 1, val >> 56, ra); break; default: /* Nothing is stored, but protection is checked and the diff --git a/target/hppa/translate.c b/target/hppa/translate.c index eb2046c5ad..19594f917e 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -121,12 +121,6 @@ static int expand_shl2(DisasContext *ctx, int val) return val << 2; } -/* Used for fp memory ops. */ -static int expand_shl3(DisasContext *ctx, int val) -{ - return val << 3; -} - /* Used for assemble_21. */ static int expand_shl11(DisasContext *ctx, int val) { @@ -144,6 +138,62 @@ static int assemble_6(DisasContext *ctx, int val) return (val ^ 31) + 1; } +/* Expander for assemble_16a(s,cat(im10a,0),i). */ +static int expand_11a(DisasContext *ctx, int val) +{ + /* + * @val is bit 0 and bits [4:15]. + * Swizzle thing around depending on PSW.W. + */ + int im10a = extract32(val, 1, 10); + int s = extract32(val, 11, 2); + int i = (-(val & 1) << 13) | (im10a << 3); + + if (ctx->tb_flags & PSW_W) { + i ^= s << 13; + } + return i; +} + +/* Expander for assemble_16a(s,im11a,i). */ +static int expand_12a(DisasContext *ctx, int val) +{ + /* + * @val is bit 0 and bits [3:15]. + * Swizzle thing around depending on PSW.W. + */ + int im11a = extract32(val, 1, 11); + int s = extract32(val, 12, 2); + int i = (-(val & 1) << 13) | (im11a << 2); + + if (ctx->tb_flags & PSW_W) { + i ^= s << 13; + } + return i; +} + +/* Expander for assemble_16(s,im14). */ +static int expand_16(DisasContext *ctx, int val) +{ + /* + * @val is bits [0:15], containing both im14 and s. + * Swizzle thing around depending on PSW.W. + */ + int s = extract32(val, 14, 2); + int i = (-(val & 1) << 13) | extract32(val, 1, 13); + + if (ctx->tb_flags & PSW_W) { + i ^= s << 13; + } + return i; +} + +/* The sp field is only present with !PSW_W. */ +static int sp0_if_wide(DisasContext *ctx, int sp) +{ + return ctx->tb_flags & PSW_W ? 0 : sp; +} + /* Translate CMPI doubleword conditions to standard. */ static int cmpbid_c(DisasContext *ctx, int val) { @@ -1961,7 +2011,7 @@ static bool trans_mfia(DisasContext *ctx, arg_mfia *a) { unsigned rt = a->t; TCGv_i64 tmp = dest_gpr(ctx, rt); - tcg_gen_movi_i64(tmp, ctx->iaoq_f); + tcg_gen_movi_i64(tmp, ctx->iaoq_f & ~3ULL); save_gpr(ctx, rt, tmp); cond_free(&ctx->null_cond); @@ -2293,6 +2343,13 @@ static bool trans_nop_addrx(DisasContext *ctx, arg_ldst *a) return true; } +static bool trans_fic(DisasContext *ctx, arg_ldst *a) +{ + /* End TB for flush instruction cache, so we pick up new insns. */ + ctx->base.is_jmp = DISAS_IAQ_N_STALE; + return trans_nop_addrx(ctx, a); +} + static bool trans_probe(DisasContext *ctx, arg_probe *a) { TCGv_i64 dest, ofs; @@ -3085,7 +3142,7 @@ static bool trans_ldc(DisasContext *ctx, arg_ldst *a) dest = dest_gpr(ctx, a->t); } - form_gva(ctx, &addr, &ofs, a->b, a->x, a->scale ? a->size : 0, + form_gva(ctx, &addr, &ofs, a->b, a->x, a->scale ? 3 : 0, a->disp, a->sp, a->m, MMU_DISABLED(ctx)); /* @@ -3462,7 +3519,7 @@ static bool trans_shrp_sar(DisasContext *ctx, arg_shrp_sar *a) /* Install the new nullification. */ cond_free(&ctx->null_cond); if (a->c) { - ctx->null_cond = do_sed_cond(ctx, a->c, false, dest); + ctx->null_cond = do_sed_cond(ctx, a->c, a->d, dest); } return nullify_end(ctx); } @@ -3505,7 +3562,7 @@ static bool trans_shrp_imm(DisasContext *ctx, arg_shrp_imm *a) /* Install the new nullification. */ cond_free(&ctx->null_cond); if (a->c) { - ctx->null_cond = do_sed_cond(ctx, a->c, false, dest); + ctx->null_cond = do_sed_cond(ctx, a->c, a->d, dest); } return nullify_end(ctx); } diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 9a210d8d92..33760a2ee1 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -7735,7 +7735,7 @@ static bool x86_cpu_has_work(CPUState *cs) static int x86_cpu_mmu_index(CPUState *cs, bool ifetch) { CPUX86State *env = cpu_env(cs); - int mmu_index_32 = (env->hflags & HF_CS64_MASK) ? 1 : 0; + int mmu_index_32 = (env->hflags & HF_CS64_MASK) ? 0 : 1; int mmu_index_base = (env->hflags & HF_CPL_MASK) == 3 ? MMU_USER64_IDX : !(env->hflags & HF_SMAP_MASK) ? MMU_KNOSMAP64_IDX : diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 952174bb6f..6b05738079 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -2334,7 +2334,7 @@ static inline bool is_mmu_index_32(int mmu_index) static inline int cpu_mmu_index_kernel(CPUX86State *env) { - int mmu_index_32 = (env->hflags & HF_LMA_MASK) ? 1 : 0; + int mmu_index_32 = (env->hflags & HF_LMA_MASK) ? 0 : 1; int mmu_index_base = !(env->hflags & HF_SMAP_MASK) ? MMU_KNOSMAP64_IDX : ((env->hflags & HF_CPL_MASK) < 3 && (env->eflags & AC_MASK)) ? MMU_KNOSMAP64_IDX : MMU_KSMAP64_IDX; diff --git a/target/i386/helper.c b/target/i386/helper.c index 2070dd0dda..23ccb23a5b 100644 --- a/target/i386/helper.c +++ b/target/i386/helper.c @@ -430,7 +430,7 @@ static void do_inject_x86_mce(CPUState *cs, run_on_cpu_data data) if (need_reset) { emit_guest_memory_failure(MEMORY_FAILURE_ACTION_RESET, ar, recursive); - monitor_puts(params->mon, msg); + monitor_printf(params->mon, "%s", msg); qemu_log_mask(CPU_LOG_RESET, "%s\n", msg); qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); return; diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h index c59d7a9fcb..0834e91f30 100644 --- a/target/loongarch/cpu-csr.h +++ b/target/loongarch/cpu-csr.h @@ -67,6 +67,9 @@ FIELD(TLBENTRY, D, 1, 1) FIELD(TLBENTRY, PLV, 2, 2) FIELD(TLBENTRY, MAT, 4, 2) FIELD(TLBENTRY, G, 6, 1) +FIELD(TLBENTRY, HUGE, 6, 1) +FIELD(TLBENTRY, HGLOBAL, 12, 1) +FIELD(TLBENTRY, LEVEL, 13, 2) FIELD(TLBENTRY_32, PPN, 8, 24) FIELD(TLBENTRY_64, PPN, 12, 36) FIELD(TLBENTRY_64, NR, 61, 1) diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h index a2fc54c8a7..944153b180 100644 --- a/target/loongarch/internals.h +++ b/target/loongarch/internals.h @@ -16,11 +16,6 @@ #define TARGET_PHYS_MASK MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS) #define TARGET_VIRT_MASK MAKE_64BIT_MASK(0, TARGET_VIRT_ADDR_SPACE_BITS) -/* Global bit used for lddir/ldpte */ -#define LOONGARCH_PAGE_HUGE_SHIFT 6 -/* Global bit for huge page */ -#define LOONGARCH_HGLOBAL_SHIFT 12 - void loongarch_translate_init(void); void loongarch_cpu_dump_state(CPUState *cpu, FILE *f, int flags); diff --git a/target/loongarch/tcg/insn_trans/trans_atomic.c.inc b/target/loongarch/tcg/insn_trans/trans_atomic.c.inc index 80c2e286fd..974bc2a70f 100644 --- a/target/loongarch/tcg/insn_trans/trans_atomic.c.inc +++ b/target/loongarch/tcg/insn_trans/trans_atomic.c.inc @@ -5,14 +5,14 @@ static bool gen_ll(DisasContext *ctx, arg_rr_i *a, MemOp mop) { - TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); + TCGv t1 = tcg_temp_new(); TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); TCGv t0 = make_address_i(ctx, src1, a->imm); - tcg_gen_qemu_ld_i64(dest, t0, ctx->mem_idx, mop); + tcg_gen_qemu_ld_i64(t1, t0, ctx->mem_idx, mop); tcg_gen_st_tl(t0, tcg_env, offsetof(CPULoongArchState, lladdr)); - tcg_gen_st_tl(dest, tcg_env, offsetof(CPULoongArchState, llval)); - gen_set_gpr(a->rd, dest, EXT_NONE); + tcg_gen_st_tl(t1, tcg_env, offsetof(CPULoongArchState, llval)); + gen_set_gpr(a->rd, t1, EXT_NONE); return true; } diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c index 22be031ac7..57f5308632 100644 --- a/target/loongarch/tcg/tlb_helper.c +++ b/target/loongarch/tcg/tlb_helper.c @@ -17,6 +17,34 @@ #include "exec/log.h" #include "cpu-csr.h" +static void get_dir_base_width(CPULoongArchState *env, uint64_t *dir_base, + uint64_t *dir_width, target_ulong level) +{ + switch (level) { + case 1: + *dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_BASE); + *dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_WIDTH); + break; + case 2: + *dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR2_BASE); + *dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR2_WIDTH); + break; + case 3: + *dir_base = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_BASE); + *dir_width = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_WIDTH); + break; + case 4: + *dir_base = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR4_BASE); + *dir_width = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR4_WIDTH); + break; + default: + /* level may be zero for ldpte */ + *dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTBASE); + *dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTWIDTH); + break; + } +} + static void raise_mmu_exception(CPULoongArchState *env, target_ulong address, MMUAccessType access_type, int tlb_error) { @@ -485,7 +513,25 @@ target_ulong helper_lddir(CPULoongArchState *env, target_ulong base, target_ulong badvaddr, index, phys, ret; int shift; uint64_t dir_base, dir_width; - bool huge = (base >> LOONGARCH_PAGE_HUGE_SHIFT) & 0x1; + + if (unlikely((level == 0) || (level > 4))) { + qemu_log_mask(LOG_GUEST_ERROR, + "Attepted LDDIR with level %"PRId64"\n", level); + return base; + } + + if (FIELD_EX64(base, TLBENTRY, HUGE)) { + if (unlikely(level == 4)) { + qemu_log_mask(LOG_GUEST_ERROR, + "Attempted use of level 4 huge page\n"); + } + + if (FIELD_EX64(base, TLBENTRY, LEVEL)) { + return base; + } else { + return FIELD_DP64(base, TLBENTRY, LEVEL, level); + } + } badvaddr = env->CSR_TLBRBADV; base = base & TARGET_PHYS_MASK; @@ -494,30 +540,7 @@ target_ulong helper_lddir(CPULoongArchState *env, target_ulong base, shift = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTEWIDTH); shift = (shift + 1) * 3; - if (huge) { - return base; - } - switch (level) { - case 1: - dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_BASE); - dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_WIDTH); - break; - case 2: - dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR2_BASE); - dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR2_WIDTH); - break; - case 3: - dir_base = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_BASE); - dir_width = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_WIDTH); - break; - case 4: - dir_base = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR4_BASE); - dir_width = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR4_WIDTH); - break; - default: - do_raise_exception(env, EXCCODE_INE, GETPC()); - return 0; - } + get_dir_base_width(env, &dir_base, &dir_width, level); index = (badvaddr >> dir_base) & ((1 << dir_width) - 1); phys = base | index << shift; ret = ldq_phys(cs->as, phys) & TARGET_PHYS_MASK; @@ -530,20 +553,42 @@ void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd, CPUState *cs = env_cpu(env); target_ulong phys, tmp0, ptindex, ptoffset0, ptoffset1, ps, badv; int shift; - bool huge = (base >> LOONGARCH_PAGE_HUGE_SHIFT) & 0x1; uint64_t ptbase = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTBASE); uint64_t ptwidth = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTWIDTH); + uint64_t dir_base, dir_width; + /* + * The parameter "base" has only two types, + * one is the page table base address, + * whose bit 6 should be 0, + * and the other is the huge page entry, + * whose bit 6 should be 1. + */ base = base & TARGET_PHYS_MASK; + if (FIELD_EX64(base, TLBENTRY, HUGE)) { + /* + * Gets the huge page level and Gets huge page size. + * Clears the huge page level information in the entry. + * Clears huge page bit. + * Move HGLOBAL bit to GLOBAL bit. + */ + get_dir_base_width(env, &dir_base, &dir_width, + FIELD_EX64(base, TLBENTRY, LEVEL)); + + base = FIELD_DP64(base, TLBENTRY, LEVEL, 0); + base = FIELD_DP64(base, TLBENTRY, HUGE, 0); + if (FIELD_EX64(base, TLBENTRY, HGLOBAL)) { + base = FIELD_DP64(base, TLBENTRY, HGLOBAL, 0); + base = FIELD_DP64(base, TLBENTRY, G, 1); + } - if (huge) { - /* Huge Page. base is paddr */ - tmp0 = base ^ (1 << LOONGARCH_PAGE_HUGE_SHIFT); - /* Move Global bit */ - tmp0 = ((tmp0 & (1 << LOONGARCH_HGLOBAL_SHIFT)) >> - LOONGARCH_HGLOBAL_SHIFT) << R_TLBENTRY_G_SHIFT | - (tmp0 & (~(1 << LOONGARCH_HGLOBAL_SHIFT))); - ps = ptbase + ptwidth - 1; + ps = dir_base + dir_width - 1; + /* + * Huge pages are evenly split into parity pages + * when loaded into the tlb, + * so the tlb page size needs to be divided by 2. + */ + tmp0 = base; if (odd) { tmp0 += MAKE_64BIT_MASK(ps, 1); } diff --git a/tests/unit/test-crypto-cipher.c b/tests/unit/test-crypto-cipher.c index 11ab1a54fc..f5152e569d 100644 --- a/tests/unit/test-crypto-cipher.c +++ b/tests/unit/test-crypto-cipher.c @@ -676,9 +676,8 @@ static void test_cipher(const void *opaque) cipher = qcrypto_cipher_new( data->alg, data->mode, key, nkey, - &err); + data->plaintext ? &error_abort : &err); if (data->plaintext) { - g_assert(err == NULL); g_assert(cipher != NULL); } else { error_free_or_abort(&err); @@ -822,6 +821,10 @@ int main(int argc, char **argv) for (i = 0; i < G_N_ELEMENTS(test_data); i++) { if (qcrypto_cipher_supports(test_data[i].alg, test_data[i].mode)) { g_test_add_data_func(test_data[i].path, &test_data[i], test_cipher); + } else { + g_printerr("# skip unsupported %s:%s\n", + QCryptoCipherAlgorithm_str(test_data[i].alg), + QCryptoCipherMode_str(test_data[i].mode)); } } |