diff --git a/crypto/meson.build b/crypto/meson.build index f065f2f277..685fb37097 100644 --- a/crypto/meson.build +++ b/crypto/meson.build @@ -42,6 +42,7 @@ if have_afalg endif crypto_ss.add(when: gnutls, if_true: files('tls-cipher-suites.c')) +util_ss.add(files('sm4.c')) util_ss.add(files('aes.c')) util_ss.add(files('init.c')) if gnutls.found() diff --git a/crypto/sm4.c b/crypto/sm4.c new file mode 100644 index 0000000000..9f0cd452c7 --- /dev/null +++ b/crypto/sm4.c @@ -0,0 +1,49 @@ +/* + * QEMU crypto sm4 support + * + * Copyright (C) 2013 - 2018 Linaro Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "crypto/sm4.h" + +uint8_t const sm4_sbox[] = { + 0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, + 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05, + 0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, + 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, + 0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, + 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62, + 0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, + 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6, + 0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, + 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8, + 0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, + 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35, + 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, + 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87, + 0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, + 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e, + 0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, + 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1, + 0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, + 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3, + 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, + 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f, + 0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, + 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51, + 0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, + 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8, + 0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, + 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0, + 0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, + 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84, + 0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, + 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48, +}; + diff --git a/disas/riscv.c b/disas/riscv.c index 03c8dc9961..7af6afc8fa 100644 --- a/disas/riscv.c +++ b/disas/riscv.c @@ -156,6 +156,8 @@ typedef enum { rv_codec_css_swsp, rv_codec_css_sdsp, rv_codec_css_sqsp, + rv_codec_k_bs, + rv_codec_k_rnum, } rv_codec; typedef enum { @@ -521,6 +523,43 @@ typedef enum { rv_op_bclr = 359, rv_op_binv = 360, rv_op_bext = 361, + rv_op_aes32esmi = 362, + rv_op_aes32esi = 363, + rv_op_aes32dsmi = 364, + rv_op_aes32dsi = 365, + rv_op_aes64ks1i = 366, + rv_op_aes64ks2 = 367, + rv_op_aes64im = 368, + rv_op_aes64esm = 369, + rv_op_aes64es = 370, + rv_op_aes64dsm = 371, + rv_op_aes64ds = 372, + rv_op_sha256sig0 = 373, + rv_op_sha256sig1 = 374, + rv_op_sha256sum0 = 375, + rv_op_sha256sum1 = 376, + rv_op_sha512sig0 = 377, + rv_op_sha512sig1 = 378, + rv_op_sha512sum0 = 379, + rv_op_sha512sum1 = 380, + rv_op_sha512sum0r = 381, + rv_op_sha512sum1r = 382, + rv_op_sha512sig0l = 383, + rv_op_sha512sig0h = 384, + rv_op_sha512sig1l = 385, + rv_op_sha512sig1h = 386, + rv_op_sm3p0 = 387, + rv_op_sm3p1 = 388, + rv_op_sm4ed = 389, + rv_op_sm4ks = 390, + rv_op_brev8 = 391, + rv_op_pack = 392, + rv_op_packh = 393, + rv_op_packw = 394, + rv_op_unzip = 395, + rv_op_zip = 396, + rv_op_xperm4 = 397, + rv_op_xperm8 = 398, } rv_op; /* structures */ @@ -540,6 +579,8 @@ typedef struct { uint8_t succ; uint8_t aq; uint8_t rl; + uint8_t bs; + uint8_t rnum; } rv_decode; typedef struct { @@ -615,6 +656,8 @@ static const char rv_freg_name_sym[32][5] = { #define rv_fmt_rd_rs2 "O\t0,2" #define rv_fmt_rs1_offset "O\t1,o" #define rv_fmt_rs2_offset "O\t2,o" +#define rv_fmt_rs1_rs2_bs "O\t1,2,b" +#define rv_fmt_rd_rs1_rnum "O\t0,1,n" /* pseudo-instruction constraints */ @@ -766,6 +809,7 @@ static const rv_comp_data rvcp_csrrw[] = { { rv_op_illegal, NULL } }; + static const rv_comp_data rvcp_csrrs[] = { { rv_op_rdcycle, rvcc_rdcycle }, { rv_op_rdtime, rvcc_rdtime }, @@ -1203,6 +1247,43 @@ const rv_opcode_data opcode_data[] = { { "bclr", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, { "binv", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, { "bext", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, + { "aes32esmi", rv_codec_k_bs, rv_fmt_rs1_rs2_bs, NULL, 0, 0, 0 }, + { "aes32esi", rv_codec_k_bs, rv_fmt_rs1_rs2_bs, NULL, 0, 0, 0 }, + { "aes32dsmi", rv_codec_k_bs, rv_fmt_rs1_rs2_bs, NULL, 0, 0, 0 }, + { "aes32dsi", rv_codec_k_bs, rv_fmt_rs1_rs2_bs, NULL, 0, 0, 0 }, + { "aes64ks1i", rv_codec_k_rnum, rv_fmt_rd_rs1_rnum, NULL, 0, 0, 0 }, + { "aes64ks2", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, + { "aes64im", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "aes64esm", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, + { "aes64es", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, + { "aes64dsm", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, + { "aes64ds", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, + { "sha256sig0", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "sha256sig1", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "sha256sum0", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "sha256sum1", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "sha512sig0", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, + { "sha512sig1", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, + { "sha512sum0", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, + { "sha512sum1", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, + { "sha512sum0r", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, + { "sha512sum1r", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, + { "sha512sig0l", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, + { "sha512sig0h", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, + { "sha512sig1l", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, + { "sha512sig1h", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, + { "sm3p0", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "sm3p1", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "sm4ed", rv_codec_k_bs, rv_fmt_rs1_rs2_bs, NULL, 0, 0, 0 }, + { "sm4ks", rv_codec_k_bs, rv_fmt_rs1_rs2_bs, NULL, 0, 0, 0 }, + { "brev8", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, + { "pack", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, + { "packh", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, + { "packw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, + { "unzip", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, + { "zip", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, + { "xperm4", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, + { "xperm8", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 } }; /* CSR names */ @@ -1216,6 +1297,7 @@ static const char *csr_name(int csrno) case 0x0003: return "fcsr"; case 0x0004: return "uie"; case 0x0005: return "utvec"; + case 0x0015: return "seed"; case 0x0040: return "uscratch"; case 0x0041: return "uepc"; case 0x0042: return "ucause"; @@ -1594,7 +1676,36 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) case 1: switch (((inst >> 27) & 0b11111)) { case 0b00000: op = rv_op_slli; break; + case 0b00001: + switch (((inst >> 20) & 0b1111111)) { + case 0b0001111: op = rv_op_zip; break; + } + break; + case 0b00010: + switch (((inst >> 20) & 0b1111111)) { + case 0b0000000: op = rv_op_sha256sum0; break; + case 0b0000001: op = rv_op_sha256sum1; break; + case 0b0000010: op = rv_op_sha256sig0; break; + case 0b0000011: op = rv_op_sha256sig1; break; + case 0b0000100: op = rv_op_sha512sum0; break; + case 0b0000101: op = rv_op_sha512sum1; break; + case 0b0000110: op = rv_op_sha512sig0; break; + case 0b0000111: op = rv_op_sha512sig1; break; + case 0b0001000: op = rv_op_sm3p0; break; + case 0b0001001: op = rv_op_sm3p1; break; + } + break; case 0b00101: op = rv_op_bseti; break; + case 0b00110: + switch (((inst >> 20) & 0b1111111)) { + case 0b0000000: op = rv_op_aes64im; break; + default: + if (((inst >> 24) & 0b0111) == 0b001) { + op = rv_op_aes64ks1i; + } + break; + } + break; case 0b01001: op = rv_op_bclri; break; case 0b01101: op = rv_op_binvi; break; case 0b01100: @@ -1615,13 +1726,20 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) case 5: switch (((inst >> 27) & 0b11111)) { case 0b00000: op = rv_op_srli; break; + case 0b00001: + switch (((inst >> 20) & 0b1111111)) { + case 0b0001111: op = rv_op_unzip; break; + } + break; case 0b00101: op = rv_op_orc_b; break; case 0b01000: op = rv_op_srai; break; case 0b01001: op = rv_op_bexti; break; case 0b01100: op = rv_op_rori; break; case 0b01101: switch ((inst >> 20) & 0b1111111) { + case 0b0011000: op = rv_op_rev8; break; case 0b0111000: op = rv_op_rev8; break; + case 0b0000111: op = rv_op_brev8; break; } break; } @@ -1742,8 +1860,11 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) case 36: switch ((inst >> 20) & 0b11111) { case 0: op = rv_op_zext_h; break; + default: op = rv_op_pack; break; } break; + case 39: op = rv_op_packh; break; + case 41: op = rv_op_clmul; break; case 42: op = rv_op_clmulr; break; case 43: op = rv_op_clmulh; break; @@ -1755,6 +1876,12 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) case 132: op = rv_op_sh2add; break; case 134: op = rv_op_sh3add; break; case 161: op = rv_op_bset; break; + case 162: op = rv_op_xperm4; break; + case 164: op = rv_op_xperm8; break; + case 200: op = rv_op_aes64es; break; + case 216: op = rv_op_aes64esm; break; + case 232: op = rv_op_aes64ds; break; + case 248: op = rv_op_aes64dsm; break; case 256: op = rv_op_sub; break; case 260: op = rv_op_xnor; break; case 261: op = rv_op_sra; break; @@ -1762,9 +1889,24 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) case 263: op = rv_op_andn; break; case 289: op = rv_op_bclr; break; case 293: op = rv_op_bext; break; + case 320: op = rv_op_sha512sum0r; break; + case 328: op = rv_op_sha512sum1r; break; + case 336: op = rv_op_sha512sig0l; break; + case 344: op = rv_op_sha512sig1l; break; + case 368: op = rv_op_sha512sig0h; break; + case 376: op = rv_op_sha512sig1h; break; case 385: op = rv_op_rol; break; - case 386: op = rv_op_ror; break; + case 389: op = rv_op_ror; break; case 417: op = rv_op_binv; break; + case 504: op = rv_op_aes64ks2; break; + } + switch ((inst >> 25) & 0b0011111) { + case 17: op = rv_op_aes32esi; break; + case 19: op = rv_op_aes32esmi; break; + case 21: op = rv_op_aes32dsi; break; + case 23: op = rv_op_aes32dsmi; break; + case 24: op = rv_op_sm4ed; break; + case 26: op = rv_op_sm4ks; break; } break; case 13: op = rv_op_lui; break; @@ -1782,6 +1924,7 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) case 36: switch ((inst >> 20) & 0b11111) { case 0: op = rv_op_zext_h; break; + default: op = rv_op_packw; break; } break; case 130: op = rv_op_sh1add_uw; break; @@ -2374,6 +2517,16 @@ static uint32_t operand_cimmq(rv_inst inst) ((inst << 57) >> 62) << 6; } +static uint32_t operand_bs(rv_inst inst) +{ + return (inst << 32) >> 62; +} + +static uint32_t operand_rnum(rv_inst inst) +{ + return (inst << 40) >> 60; +} + /* decode operands */ static void decode_inst_operands(rv_decode *dec) @@ -2653,6 +2806,16 @@ static void decode_inst_operands(rv_decode *dec) dec->rs2 = operand_crs2(inst); dec->imm = operand_cimmsqsp(inst); break; + case rv_codec_k_bs: + dec->rs1 = operand_rs1(inst); + dec->rs2 = operand_rs2(inst); + dec->bs = operand_bs(inst); + break; + case rv_codec_k_rnum: + dec->rd = operand_rd(inst); + dec->rs1 = operand_rs1(inst); + dec->rnum = operand_rnum(inst); + break; }; } @@ -2812,6 +2975,14 @@ static void format_inst(char *buf, size_t buflen, size_t tab, rv_decode *dec) case ')': append(buf, ")", buflen); break; + case 'b': + snprintf(tmp, sizeof(tmp), "%d", dec->bs); + append(buf, tmp, buflen); + break; + case 'n': + snprintf(tmp, sizeof(tmp), "%d", dec->rnum); + append(buf, tmp, buflen); + break; case '0': append(buf, rv_ireg_name_sym[dec->rd], buflen); break; diff --git a/docs/system/riscv/virt.rst b/docs/system/riscv/virt.rst index 1272b6659e..f8ecec95f3 100644 --- a/docs/system/riscv/virt.rst +++ b/docs/system/riscv/virt.rst @@ -162,3 +162,23 @@ The minimal QEMU commands to run U-Boot SPL are: To test 32-bit U-Boot images, switch to use qemu-riscv32_smode_defconfig and riscv32_spl_defconfig builds, and replace ``qemu-system-riscv64`` with ``qemu-system-riscv32`` in the command lines above to boot the 32-bit U-Boot. + +Enabling TPM +------------ + +A TPM device can be connected to the virt board by following the steps below. + +First launch the TPM emulator + + swtpm socket --tpm2 -t -d --tpmstate dir=/tmp/tpm \ + --ctrl type=unixio,path=swtpm-sock + +Then launch QEMU with: + + ... + -chardev socket,id=chrtpm,path=swtpm-sock \ + -tpmdev emulator,id=tpm0,chardev=chrtpm \ + -device tpm-tis-device,tpmdev=tpm0 + +The TPM device can be seen in the memory tree and the generated device +tree and should be accessible from the guest software. diff --git a/hw/arm/meson.build b/hw/arm/meson.build index 721a8eb8be..122e5dd992 100644 --- a/hw/arm/meson.build +++ b/hw/arm/meson.build @@ -1,6 +1,5 @@ arm_ss = ss.source_set() arm_ss.add(files('boot.c'), fdt) -arm_ss.add(when: 'CONFIG_PLATFORM_BUS', if_true: files('sysbus-fdt.c')) arm_ss.add(when: 'CONFIG_ARM_VIRT', if_true: files('virt.c')) arm_ss.add(when: 'CONFIG_ACPI', if_true: files('virt-acpi-build.c')) arm_ss.add(when: 'CONFIG_DIGIC', if_true: files('digic_boards.c')) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 5bdd98e4a1..f94278935f 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -56,7 +56,7 @@ #include "qemu/module.h" #include "hw/pci-host/gpex.h" #include "hw/virtio/virtio-pci.h" -#include "hw/arm/sysbus-fdt.h" +#include "hw/core/sysbus-fdt.h" #include "hw/platform-bus.h" #include "hw/qdev-properties.h" #include "hw/arm/fdt.h" diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c index 66a2de7e13..37fc9b919c 100644 --- a/hw/arm/xlnx-versal-virt.c +++ b/hw/arm/xlnx-versal-virt.c @@ -15,7 +15,6 @@ #include "sysemu/device_tree.h" #include "hw/boards.h" #include "hw/sysbus.h" -#include "hw/arm/sysbus-fdt.h" #include "hw/arm/fdt.h" #include "cpu.h" #include "hw/qdev-properties.h" diff --git a/hw/core/meson.build b/hw/core/meson.build index 0f884d6fd4..7a4d02b6c0 100644 --- a/hw/core/meson.build +++ b/hw/core/meson.build @@ -33,6 +33,7 @@ softmmu_ss.add(when: 'CONFIG_PTIMER', if_true: files('ptimer.c')) softmmu_ss.add(when: 'CONFIG_REGISTER', if_true: files('register.c')) softmmu_ss.add(when: 'CONFIG_SPLIT_IRQ', if_true: files('split-irq.c')) softmmu_ss.add(when: 'CONFIG_XILINX_AXI', if_true: files('stream.c')) +softmmu_ss.add(when: 'CONFIG_PLATFORM_BUS', if_true: files('sysbus-fdt.c')) softmmu_ss.add(files( 'cpu-sysemu.c', diff --git a/hw/arm/sysbus-fdt.c b/hw/core/sysbus-fdt.c similarity index 99% rename from hw/arm/sysbus-fdt.c rename to hw/core/sysbus-fdt.c index 48c5fe9bf1..19d22cbe73 100644 --- a/hw/arm/sysbus-fdt.c +++ b/hw/core/sysbus-fdt.c @@ -27,7 +27,7 @@ #ifdef CONFIG_LINUX #include #endif -#include "hw/arm/sysbus-fdt.h" +#include "hw/core/sysbus-fdt.h" #include "qemu/error-report.h" #include "sysemu/device_tree.h" #include "sysemu/tpm.h" diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index 91bb9d21c4..79ff61c464 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -34,6 +34,7 @@ config RISCV_VIRT imply PCI_DEVICES imply VIRTIO_VGA imply TEST_DEVICES + imply TPM_TIS_SYSBUS select RISCV_NUMA select GOLDFISH_RTC select MSI_NONBROKEN @@ -48,6 +49,7 @@ config RISCV_VIRT select SIFIVE_TEST select VIRTIO_MMIO select FW_CFG_DMA + select PLATFORM_BUS config SIFIVE_E bool diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c index cafd1fc9ae..10a5d0e501 100644 --- a/hw/riscv/microchip_pfsoc.c +++ b/hw/riscv/microchip_pfsoc.c @@ -571,7 +571,7 @@ static void microchip_icicle_kit_machine_init(MachineState *machine) "linux,initrd-end", end); } - if (machine->kernel_cmdline) { + if (machine->kernel_cmdline && *machine->kernel_cmdline) { qemu_fdt_setprop_string(machine->fdt, "/chosen", "bootargs", machine->kernel_cmdline); } diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index 7fbc7dea42..cc8c7637cb 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -511,7 +511,7 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry *memmap, g_free(nodename); update_bootargs: - if (cmdline) { + if (cmdline && *cmdline) { qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline); } } diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c index d059a67f9b..068ba3493e 100644 --- a/hw/riscv/spike.c +++ b/hw/riscv/spike.c @@ -174,10 +174,11 @@ static void create_fdt(SpikeState *s, const MemMapEntry *memmap, riscv_socket_fdt_write_distance_matrix(mc, fdt); - if (cmdline) { - qemu_fdt_add_subnode(fdt, "/chosen"); + qemu_fdt_add_subnode(fdt, "/chosen"); + qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", "/htif"); + + if (cmdline && *cmdline) { qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline); - qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", "/htif"); } } diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index b49c5361bd..3326f4db96 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -28,6 +28,7 @@ #include "hw/qdev-properties.h" #include "hw/char/serial.h" #include "target/riscv/cpu.h" +#include "hw/core/sysbus-fdt.h" #include "hw/riscv/riscv_hart.h" #include "hw/riscv/virt.h" #include "hw/riscv/boot.h" @@ -37,10 +38,12 @@ #include "hw/intc/riscv_imsic.h" #include "hw/intc/sifive_plic.h" #include "hw/misc/sifive_test.h" +#include "hw/platform-bus.h" #include "chardev/char.h" #include "sysemu/device_tree.h" #include "sysemu/sysemu.h" #include "sysemu/kvm.h" +#include "sysemu/tpm.h" #include "hw/pci/pci.h" #include "hw/pci-host/gpex.h" #include "hw/display/ramfb.h" @@ -68,25 +71,26 @@ #endif static const MemMapEntry virt_memmap[] = { - [VIRT_DEBUG] = { 0x0, 0x100 }, - [VIRT_MROM] = { 0x1000, 0xf000 }, - [VIRT_TEST] = { 0x100000, 0x1000 }, - [VIRT_RTC] = { 0x101000, 0x1000 }, - [VIRT_CLINT] = { 0x2000000, 0x10000 }, - [VIRT_ACLINT_SSWI] = { 0x2F00000, 0x4000 }, - [VIRT_PCIE_PIO] = { 0x3000000, 0x10000 }, - [VIRT_PLIC] = { 0xc000000, VIRT_PLIC_SIZE(VIRT_CPUS_MAX * 2) }, - [VIRT_APLIC_M] = { 0xc000000, APLIC_SIZE(VIRT_CPUS_MAX) }, - [VIRT_APLIC_S] = { 0xd000000, APLIC_SIZE(VIRT_CPUS_MAX) }, - [VIRT_UART0] = { 0x10000000, 0x100 }, - [VIRT_VIRTIO] = { 0x10001000, 0x1000 }, - [VIRT_FW_CFG] = { 0x10100000, 0x18 }, - [VIRT_FLASH] = { 0x20000000, 0x4000000 }, - [VIRT_IMSIC_M] = { 0x24000000, VIRT_IMSIC_MAX_SIZE }, - [VIRT_IMSIC_S] = { 0x28000000, VIRT_IMSIC_MAX_SIZE }, - [VIRT_PCIE_ECAM] = { 0x30000000, 0x10000000 }, - [VIRT_PCIE_MMIO] = { 0x40000000, 0x40000000 }, - [VIRT_DRAM] = { 0x80000000, 0x0 }, + [VIRT_DEBUG] = { 0x0, 0x100 }, + [VIRT_MROM] = { 0x1000, 0xf000 }, + [VIRT_TEST] = { 0x100000, 0x1000 }, + [VIRT_RTC] = { 0x101000, 0x1000 }, + [VIRT_CLINT] = { 0x2000000, 0x10000 }, + [VIRT_ACLINT_SSWI] = { 0x2F00000, 0x4000 }, + [VIRT_PCIE_PIO] = { 0x3000000, 0x10000 }, + [VIRT_PLATFORM_BUS] = { 0x4000000, 0x2000000 }, + [VIRT_PLIC] = { 0xc000000, VIRT_PLIC_SIZE(VIRT_CPUS_MAX * 2) }, + [VIRT_APLIC_M] = { 0xc000000, APLIC_SIZE(VIRT_CPUS_MAX) }, + [VIRT_APLIC_S] = { 0xd000000, APLIC_SIZE(VIRT_CPUS_MAX) }, + [VIRT_UART0] = { 0x10000000, 0x100 }, + [VIRT_VIRTIO] = { 0x10001000, 0x1000 }, + [VIRT_FW_CFG] = { 0x10100000, 0x18 }, + [VIRT_FLASH] = { 0x20000000, 0x4000000 }, + [VIRT_IMSIC_M] = { 0x24000000, VIRT_IMSIC_MAX_SIZE }, + [VIRT_IMSIC_S] = { 0x28000000, VIRT_IMSIC_MAX_SIZE }, + [VIRT_PCIE_ECAM] = { 0x30000000, 0x10000000 }, + [VIRT_PCIE_MMIO] = { 0x40000000, 0x40000000 }, + [VIRT_DRAM] = { 0x80000000, 0x0 }, }; /* PCIe high mmio is fixed for RV32 */ @@ -473,6 +477,12 @@ static void create_fdt_socket_plic(RISCVVirtState *s, riscv_socket_fdt_write_id(mc, mc->fdt, plic_name, socket); qemu_fdt_setprop_cell(mc->fdt, plic_name, "phandle", plic_phandles[socket]); + + platform_bus_add_all_fdt_nodes(mc->fdt, plic_name, + memmap[VIRT_PLATFORM_BUS].base, + memmap[VIRT_PLATFORM_BUS].size, + VIRT_PLATFORM_BUS_IRQ); + g_free(plic_name); g_free(plic_cells); @@ -550,6 +560,12 @@ static void create_fdt_imsic(RISCVVirtState *s, const MemMapEntry *memmap, IMSIC_MMIO_GROUP_MIN_SHIFT); } qemu_fdt_setprop_cell(mc->fdt, imsic_name, "phandle", *msi_m_phandle); + + platform_bus_add_all_fdt_nodes(mc->fdt, imsic_name, + memmap[VIRT_PLATFORM_BUS].base, + memmap[VIRT_PLATFORM_BUS].size, + VIRT_PLATFORM_BUS_IRQ); + g_free(imsic_name); /* S-level IMSIC node */ @@ -687,6 +703,12 @@ static void create_fdt_socket_aplic(RISCVVirtState *s, VIRT_IRQCHIP_NUM_SOURCES); riscv_socket_fdt_write_id(mc, mc->fdt, aplic_name, socket); qemu_fdt_setprop_cell(mc->fdt, aplic_name, "phandle", aplic_s_phandle); + + platform_bus_add_all_fdt_nodes(mc->fdt, aplic_name, + memmap[VIRT_PLATFORM_BUS].base, + memmap[VIRT_PLATFORM_BUS].size, + VIRT_PLATFORM_BUS_IRQ); + g_free(aplic_name); g_free(aplic_cells); @@ -1004,7 +1026,7 @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap, create_fdt_flash(s, memmap); update_bootargs: - if (cmdline) { + if (cmdline && *cmdline) { qemu_fdt_setprop_string(mc->fdt, "/chosen", "bootargs", cmdline); } } @@ -1162,6 +1184,126 @@ static DeviceState *virt_create_aia(RISCVVirtAIAType aia_type, int aia_guests, return aplic_m; } +static void create_platform_bus(RISCVVirtState *s, DeviceState *irqchip) +{ + DeviceState *dev; + SysBusDevice *sysbus; + const MemMapEntry *memmap = virt_memmap; + int i; + MemoryRegion *sysmem = get_system_memory(); + + dev = qdev_new(TYPE_PLATFORM_BUS_DEVICE); + dev->id = g_strdup(TYPE_PLATFORM_BUS_DEVICE); + qdev_prop_set_uint32(dev, "num_irqs", VIRT_PLATFORM_BUS_NUM_IRQS); + qdev_prop_set_uint32(dev, "mmio_size", memmap[VIRT_PLATFORM_BUS].size); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + s->platform_bus_dev = dev; + + sysbus = SYS_BUS_DEVICE(dev); + for (i = 0; i < VIRT_PLATFORM_BUS_NUM_IRQS; i++) { + int irq = VIRT_PLATFORM_BUS_IRQ + i; + sysbus_connect_irq(sysbus, i, qdev_get_gpio_in(irqchip, irq)); + } + + memory_region_add_subregion(sysmem, + memmap[VIRT_PLATFORM_BUS].base, + sysbus_mmio_get_region(sysbus, 0)); +} + +static void virt_machine_done(Notifier *notifier, void *data) +{ + RISCVVirtState *s = container_of(notifier, RISCVVirtState, + machine_done); + const MemMapEntry *memmap = virt_memmap; + MachineState *machine = MACHINE(s); + target_ulong start_addr = memmap[VIRT_DRAM].base; + target_ulong firmware_end_addr, kernel_start_addr; + uint32_t fdt_load_addr; + uint64_t kernel_entry; + + /* + * Only direct boot kernel is currently supported for KVM VM, + * so the "-bios" parameter is not supported when KVM is enabled. + */ + if (kvm_enabled()) { + if (machine->firmware) { + if (strcmp(machine->firmware, "none")) { + error_report("Machine mode firmware is not supported in " + "combination with KVM."); + exit(1); + } + } else { + machine->firmware = g_strdup("none"); + } + } + + if (riscv_is_32bit(&s->soc[0])) { + firmware_end_addr = riscv_find_and_load_firmware(machine, + RISCV32_BIOS_BIN, start_addr, NULL); + } else { + firmware_end_addr = riscv_find_and_load_firmware(machine, + RISCV64_BIOS_BIN, start_addr, NULL); + } + + if (machine->kernel_filename) { + kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc[0], + firmware_end_addr); + + kernel_entry = riscv_load_kernel(machine->kernel_filename, + kernel_start_addr, NULL); + + if (machine->initrd_filename) { + hwaddr start; + hwaddr end = riscv_load_initrd(machine->initrd_filename, + machine->ram_size, kernel_entry, + &start); + qemu_fdt_setprop_cell(machine->fdt, "/chosen", + "linux,initrd-start", start); + qemu_fdt_setprop_cell(machine->fdt, "/chosen", "linux,initrd-end", + end); + } + } else { + /* + * If dynamic firmware is used, it doesn't know where is the next mode + * if kernel argument is not set. + */ + kernel_entry = 0; + } + + if (drive_get(IF_PFLASH, 0, 0)) { + /* + * Pflash was supplied, let's overwrite the address we jump to after + * reset to the base of the flash. + */ + start_addr = virt_memmap[VIRT_FLASH].base; + } + + /* + * Init fw_cfg. Must be done before riscv_load_fdt, otherwise the device + * tree cannot be altered and we get FDT_ERR_NOSPACE. + */ + s->fw_cfg = create_fw_cfg(machine); + rom_set_fw(s->fw_cfg); + + /* Compute the fdt load address in dram */ + fdt_load_addr = riscv_load_fdt(memmap[VIRT_DRAM].base, + machine->ram_size, machine->fdt); + /* load the reset vector */ + riscv_setup_rom_reset_vec(machine, &s->soc[0], start_addr, + virt_memmap[VIRT_MROM].base, + virt_memmap[VIRT_MROM].size, kernel_entry, + fdt_load_addr, machine->fdt); + + /* + * Only direct boot kernel is currently supported for KVM VM, + * So here setup kernel start address and fdt address. + * TODO:Support firmware loading and integrate to TCG start + */ + if (kvm_enabled()) { + riscv_setup_direct_kernel(kernel_entry, fdt_load_addr); + } +} + static void virt_machine_init(MachineState *machine) { const MemMapEntry *memmap = virt_memmap; @@ -1169,10 +1311,6 @@ static void virt_machine_init(MachineState *machine) MemoryRegion *system_memory = get_system_memory(); MemoryRegion *mask_rom = g_new(MemoryRegion, 1); char *soc_name; - target_ulong start_addr = memmap[VIRT_DRAM].base; - target_ulong firmware_end_addr, kernel_start_addr; - uint32_t fdt_load_addr; - uint64_t kernel_entry; DeviceState *mmio_irqchip, *virtio_irqchip, *pcie_irqchip; int i, base_hartid, hart_count; @@ -1302,98 +1440,12 @@ static void virt_machine_init(MachineState *machine) memory_region_add_subregion(system_memory, memmap[VIRT_DRAM].base, machine->ram); - /* create device tree */ - create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline, - riscv_is_32bit(&s->soc[0])); - /* boot rom */ memory_region_init_rom(mask_rom, NULL, "riscv_virt_board.mrom", memmap[VIRT_MROM].size, &error_fatal); memory_region_add_subregion(system_memory, memmap[VIRT_MROM].base, mask_rom); - /* - * Only direct boot kernel is currently supported for KVM VM, - * so the "-bios" parameter is not supported when KVM is enabled. - */ - if (kvm_enabled()) { - if (machine->firmware) { - if (strcmp(machine->firmware, "none")) { - error_report("Machine mode firmware is not supported in " - "combination with KVM."); - exit(1); - } - } else { - machine->firmware = g_strdup("none"); - } - } - - if (riscv_is_32bit(&s->soc[0])) { - firmware_end_addr = riscv_find_and_load_firmware(machine, - RISCV32_BIOS_BIN, start_addr, NULL); - } else { - firmware_end_addr = riscv_find_and_load_firmware(machine, - RISCV64_BIOS_BIN, start_addr, NULL); - } - - if (machine->kernel_filename) { - kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc[0], - firmware_end_addr); - - kernel_entry = riscv_load_kernel(machine->kernel_filename, - kernel_start_addr, NULL); - - if (machine->initrd_filename) { - hwaddr start; - hwaddr end = riscv_load_initrd(machine->initrd_filename, - machine->ram_size, kernel_entry, - &start); - qemu_fdt_setprop_cell(machine->fdt, "/chosen", - "linux,initrd-start", start); - qemu_fdt_setprop_cell(machine->fdt, "/chosen", "linux,initrd-end", - end); - } - } else { - /* - * If dynamic firmware is used, it doesn't know where is the next mode - * if kernel argument is not set. - */ - kernel_entry = 0; - } - - if (drive_get(IF_PFLASH, 0, 0)) { - /* - * Pflash was supplied, let's overwrite the address we jump to after - * reset to the base of the flash. - */ - start_addr = virt_memmap[VIRT_FLASH].base; - } - - /* - * Init fw_cfg. Must be done before riscv_load_fdt, otherwise the device - * tree cannot be altered and we get FDT_ERR_NOSPACE. - */ - s->fw_cfg = create_fw_cfg(machine); - rom_set_fw(s->fw_cfg); - - /* Compute the fdt load address in dram */ - fdt_load_addr = riscv_load_fdt(memmap[VIRT_DRAM].base, - machine->ram_size, machine->fdt); - /* load the reset vector */ - riscv_setup_rom_reset_vec(machine, &s->soc[0], start_addr, - virt_memmap[VIRT_MROM].base, - virt_memmap[VIRT_MROM].size, kernel_entry, - fdt_load_addr, machine->fdt); - - /* - * Only direct boot kernel is currently supported for KVM VM, - * So here setup kernel start address and fdt address. - * TODO:Support firmware loading and integrate to TCG start - */ - if (kvm_enabled()) { - riscv_setup_direct_kernel(kernel_entry, fdt_load_addr); - } - /* SiFive Test MMIO device */ sifive_test_create(memmap[VIRT_TEST].base); @@ -1414,6 +1466,8 @@ static void virt_machine_init(MachineState *machine) memmap[VIRT_PCIE_PIO].base, DEVICE(pcie_irqchip)); + create_platform_bus(s, DEVICE(mmio_irqchip)); + serial_mm_init(system_memory, memmap[VIRT_UART0].base, 0, qdev_get_gpio_in(DEVICE(mmio_irqchip), UART0_IRQ), 399193, serial_hd(0), DEVICE_LITTLE_ENDIAN); @@ -1429,6 +1483,13 @@ static void virt_machine_init(MachineState *machine) drive_get(IF_PFLASH, 0, i)); } virt_flash_map(s, system_memory); + + /* create device tree */ + create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline, + riscv_is_32bit(&s->soc[0])); + + s->machine_done.notify = virt_machine_done; + qemu_add_machine_init_done_notifier(&s->machine_done); } static void virt_machine_instance_init(Object *obj) @@ -1509,10 +1570,37 @@ static void virt_set_aclint(Object *obj, bool value, Error **errp) s->have_aclint = value; } +static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine, + DeviceState *dev) +{ + MachineClass *mc = MACHINE_GET_CLASS(machine); + + if (device_is_dynamic_sysbus(mc, dev)) { + return HOTPLUG_HANDLER(machine); + } + return NULL; +} + +static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + RISCVVirtState *s = RISCV_VIRT_MACHINE(hotplug_dev); + + if (s->platform_bus_dev) { + MachineClass *mc = MACHINE_GET_CLASS(s); + + if (device_is_dynamic_sysbus(mc, dev)) { + platform_bus_link_device(PLATFORM_BUS_DEVICE(s->platform_bus_dev), + SYS_BUS_DEVICE(dev)); + } + } +} + static void virt_machine_class_init(ObjectClass *oc, void *data) { char str[128]; MachineClass *mc = MACHINE_CLASS(oc); + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); mc->desc = "RISC-V VirtIO board"; mc->init = virt_machine_init; @@ -1524,8 +1612,15 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) mc->get_default_cpu_node_id = riscv_numa_get_default_cpu_node_id; mc->numa_mem_supported = true; mc->default_ram_id = "riscv_virt_board.ram"; + assert(!mc->get_hotplug_handler); + mc->get_hotplug_handler = virt_machine_get_hotplug_handler; + + hc->plug = virt_machine_device_plug_cb; machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE); +#ifdef CONFIG_TPM + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS); +#endif object_class_property_add_bool(oc, "aclint", virt_get_aclint, virt_set_aclint); @@ -1554,6 +1649,10 @@ static const TypeInfo virt_machine_typeinfo = { .class_init = virt_machine_class_init, .instance_init = virt_machine_instance_init, .instance_size = sizeof(RISCVVirtState), + .interfaces = (InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, + { } + }, }; static void virt_machine_init_register_types(void) diff --git a/include/crypto/sm4.h b/include/crypto/sm4.h new file mode 100644 index 0000000000..9bd3ebc62e --- /dev/null +++ b/include/crypto/sm4.h @@ -0,0 +1,6 @@ +#ifndef QEMU_SM4_H +#define QEMU_SM4_H + +extern const uint8_t sm4_sbox[256]; + +#endif diff --git a/include/hw/arm/sysbus-fdt.h b/include/hw/core/sysbus-fdt.h similarity index 100% rename from include/hw/arm/sysbus-fdt.h rename to include/hw/core/sysbus-fdt.h diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h index 78b058ec86..984e55c77f 100644 --- a/include/hw/riscv/virt.h +++ b/include/hw/riscv/virt.h @@ -45,6 +45,8 @@ struct RISCVVirtState { MachineState parent; /*< public >*/ + Notifier machine_done; + DeviceState *platform_bus_dev; RISCVHartArrayState soc[VIRT_SOCKETS_MAX]; DeviceState *irqchip[VIRT_SOCKETS_MAX]; PFlashCFI01 *flash[2]; @@ -75,6 +77,7 @@ enum { VIRT_DRAM, VIRT_PCIE_MMIO, VIRT_PCIE_PIO, + VIRT_PLATFORM_BUS, VIRT_PCIE_ECAM }; @@ -84,9 +87,12 @@ enum { VIRTIO_IRQ = 1, /* 1 to 8 */ VIRTIO_COUNT = 8, PCIE_IRQ = 0x20, /* 32 to 35 */ - VIRTIO_NDEV = 0x35 /* Arbitrary maximum number of interrupts */ + VIRT_PLATFORM_BUS_IRQ = 64, /* 64 to 96 */ + VIRTIO_NDEV = 96 /* Arbitrary maximum number of interrupts */ }; +#define VIRT_PLATFORM_BUS_NUM_IRQS 32 + #define VIRT_IRQCHIP_IPI_MSI 1 #define VIRT_IRQCHIP_NUM_MSIS 255 #define VIRT_IRQCHIP_NUM_SOURCES VIRTIO_NDEV diff --git a/target/arm/crypto_helper.c b/target/arm/crypto_helper.c index 4c8fd34aec..d28690321f 100644 --- a/target/arm/crypto_helper.c +++ b/target/arm/crypto_helper.c @@ -15,6 +15,7 @@ #include "exec/helper-proto.h" #include "tcg/tcg-gvec-desc.h" #include "crypto/aes.h" +#include "crypto/sm4.h" #include "vec_internal.h" union CRYPTO_STATE { @@ -694,41 +695,6 @@ DO_SM3TT(crypto_sm3tt2b, 3) #undef DO_SM3TT -static uint8_t const sm4_sbox[] = { - 0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, - 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05, - 0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, - 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, - 0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, - 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62, - 0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, - 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6, - 0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, - 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8, - 0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, - 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35, - 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, - 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87, - 0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, - 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e, - 0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, - 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1, - 0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, - 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3, - 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, - 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f, - 0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, - 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51, - 0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, - 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8, - 0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, - 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0, - 0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, - 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84, - 0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, - 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48, -}; - static void do_crypto_sm4e(uint64_t *rd, uint64_t *rn, uint64_t *rm) { union CRYPTO_STATE d = { .l = { rn[0], rn[1] } }; diff --git a/target/riscv/bitmanip_helper.c b/target/riscv/bitmanip_helper.c index f1b5e5549f..b99c4a39a1 100644 --- a/target/riscv/bitmanip_helper.c +++ b/target/riscv/bitmanip_helper.c @@ -49,3 +49,83 @@ target_ulong HELPER(clmulr)(target_ulong rs1, target_ulong rs2) return result; } + +static inline target_ulong do_swap(target_ulong x, uint64_t mask, int shift) +{ + return ((x & mask) << shift) | ((x & ~mask) >> shift); +} + +target_ulong HELPER(brev8)(target_ulong rs1) +{ + target_ulong x = rs1; + + x = do_swap(x, 0x5555555555555555ull, 1); + x = do_swap(x, 0x3333333333333333ull, 2); + x = do_swap(x, 0x0f0f0f0f0f0f0f0full, 4); + return x; +} + +static const uint64_t shuf_masks[] = { + dup_const(MO_8, 0x44), + dup_const(MO_8, 0x30), + dup_const(MO_16, 0x0f00), + dup_const(MO_32, 0xff0000) +}; + +static inline target_ulong do_shuf_stage(target_ulong src, uint64_t maskL, + uint64_t maskR, int shift) +{ + target_ulong x = src & ~(maskL | maskR); + + x |= ((src << shift) & maskL) | ((src >> shift) & maskR); + return x; +} + +target_ulong HELPER(unzip)(target_ulong rs1) +{ + target_ulong x = rs1; + + x = do_shuf_stage(x, shuf_masks[0], shuf_masks[0] >> 1, 1); + x = do_shuf_stage(x, shuf_masks[1], shuf_masks[1] >> 2, 2); + x = do_shuf_stage(x, shuf_masks[2], shuf_masks[2] >> 4, 4); + x = do_shuf_stage(x, shuf_masks[3], shuf_masks[3] >> 8, 8); + return x; +} + +target_ulong HELPER(zip)(target_ulong rs1) +{ + target_ulong x = rs1; + + x = do_shuf_stage(x, shuf_masks[3], shuf_masks[3] >> 8, 8); + x = do_shuf_stage(x, shuf_masks[2], shuf_masks[2] >> 4, 4); + x = do_shuf_stage(x, shuf_masks[1], shuf_masks[1] >> 2, 2); + x = do_shuf_stage(x, shuf_masks[0], shuf_masks[0] >> 1, 1); + return x; +} + +static inline target_ulong do_xperm(target_ulong rs1, target_ulong rs2, + uint32_t sz_log2) +{ + target_ulong r = 0; + target_ulong sz = 1LL << sz_log2; + target_ulong mask = (1LL << sz) - 1; + target_ulong pos; + + for (int i = 0; i < TARGET_LONG_BITS; i += sz) { + pos = ((rs2 >> i) & mask) << sz_log2; + if (pos < sizeof(target_ulong) * 8) { + r |= ((rs1 >> pos) & mask) << i; + } + } + return r; +} + +target_ulong HELPER(xperm4)(target_ulong rs1, target_ulong rs2) +{ + return do_xperm(rs1, rs2, 2); +} + +target_ulong HELPER(xperm8)(target_ulong rs1, target_ulong rs2) +{ + return do_xperm(rs1, rs2, 3); +} diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 0c774056c5..ccacdee215 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -34,6 +34,11 @@ /* RISC-V CPU definitions */ +#define RISCV_CPU_MARCHID ((QEMU_VERSION_MAJOR << 16) | \ + (QEMU_VERSION_MINOR << 8) | \ + (QEMU_VERSION_MICRO)) +#define RISCV_CPU_MIPID RISCV_CPU_MARCHID + static const char riscv_single_letter_exts[] = "IEMAFDQCPVH"; struct isa_ext_data { @@ -607,6 +612,29 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) cpu->cfg.ext_zfinx = true; } + if (cpu->cfg.ext_zk) { + cpu->cfg.ext_zkn = true; + cpu->cfg.ext_zkr = true; + cpu->cfg.ext_zkt = true; + } + + if (cpu->cfg.ext_zkn) { + cpu->cfg.ext_zbkb = true; + cpu->cfg.ext_zbkc = true; + cpu->cfg.ext_zbkx = true; + cpu->cfg.ext_zkne = true; + cpu->cfg.ext_zknd = true; + cpu->cfg.ext_zknh = true; + } + + if (cpu->cfg.ext_zks) { + cpu->cfg.ext_zbkb = true; + cpu->cfg.ext_zbkc = true; + cpu->cfg.ext_zbkx = true; + cpu->cfg.ext_zksed = true; + cpu->cfg.ext_zksh = true; + } + /* Set the ISA extensions, checks should have happened above */ if (cpu->cfg.ext_i) { ext |= RVI; @@ -810,6 +838,10 @@ static Property riscv_cpu_properties[] = { DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128), DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64), + DEFINE_PROP_UINT32("mvendorid", RISCVCPU, cfg.mvendorid, 0), + DEFINE_PROP_UINT64("marchid", RISCVCPU, cfg.marchid, RISCV_CPU_MARCHID), + DEFINE_PROP_UINT64("mipid", RISCVCPU, cfg.mipid, RISCV_CPU_MIPID), + DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false), DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false), DEFINE_PROP_BOOL("svpbmt", RISCVCPU, cfg.ext_svpbmt, false), @@ -817,7 +849,20 @@ static Property riscv_cpu_properties[] = { DEFINE_PROP_BOOL("zba", RISCVCPU, cfg.ext_zba, true), DEFINE_PROP_BOOL("zbb", RISCVCPU, cfg.ext_zbb, true), DEFINE_PROP_BOOL("zbc", RISCVCPU, cfg.ext_zbc, true), + DEFINE_PROP_BOOL("zbkb", RISCVCPU, cfg.ext_zbkb, false), + DEFINE_PROP_BOOL("zbkc", RISCVCPU, cfg.ext_zbkc, false), + DEFINE_PROP_BOOL("zbkx", RISCVCPU, cfg.ext_zbkx, false), DEFINE_PROP_BOOL("zbs", RISCVCPU, cfg.ext_zbs, true), + DEFINE_PROP_BOOL("zk", RISCVCPU, cfg.ext_zk, false), + DEFINE_PROP_BOOL("zkn", RISCVCPU, cfg.ext_zkn, false), + DEFINE_PROP_BOOL("zknd", RISCVCPU, cfg.ext_zknd, false), + DEFINE_PROP_BOOL("zkne", RISCVCPU, cfg.ext_zkne, false), + DEFINE_PROP_BOOL("zknh", RISCVCPU, cfg.ext_zknh, false), + DEFINE_PROP_BOOL("zkr", RISCVCPU, cfg.ext_zkr, false), + DEFINE_PROP_BOOL("zks", RISCVCPU, cfg.ext_zks, false), + DEFINE_PROP_BOOL("zksed", RISCVCPU, cfg.ext_zksed, false), + DEFINE_PROP_BOOL("zksh", RISCVCPU, cfg.ext_zksh, false), + DEFINE_PROP_BOOL("zkt", RISCVCPU, cfg.ext_zkt, false), DEFINE_PROP_BOOL("zdinx", RISCVCPU, cfg.ext_zdinx, false), DEFINE_PROP_BOOL("zfinx", RISCVCPU, cfg.ext_zfinx, false), @@ -960,7 +1005,20 @@ static void riscv_isa_string_ext(RISCVCPU *cpu, char **isa_str, int max_str_len) ISA_EDATA_ENTRY(zba, ext_zba), ISA_EDATA_ENTRY(zbb, ext_zbb), ISA_EDATA_ENTRY(zbc, ext_zbc), + ISA_EDATA_ENTRY(zbkb, ext_zbkb), + ISA_EDATA_ENTRY(zbkc, ext_zbkc), + ISA_EDATA_ENTRY(zbkx, ext_zbkx), ISA_EDATA_ENTRY(zbs, ext_zbs), + ISA_EDATA_ENTRY(zk, ext_zk), + ISA_EDATA_ENTRY(zkn, ext_zkn), + ISA_EDATA_ENTRY(zknd, ext_zknd), + ISA_EDATA_ENTRY(zkne, ext_zkne), + ISA_EDATA_ENTRY(zknh, ext_zknh), + ISA_EDATA_ENTRY(zkr, ext_zkr), + ISA_EDATA_ENTRY(zks, ext_zks), + ISA_EDATA_ENTRY(zksed, ext_zksed), + ISA_EDATA_ENTRY(zksh, ext_zksh), + ISA_EDATA_ENTRY(zkt, ext_zkt), ISA_EDATA_ENTRY(zve32f, ext_zve32f), ISA_EDATA_ENTRY(zve64f, ext_zve64f), ISA_EDATA_ENTRY(svinval, ext_svinval), diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 34c22d5d3b..fe6c9a2c92 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -377,7 +377,20 @@ struct RISCVCPUConfig { bool ext_zba; bool ext_zbb; bool ext_zbc; + bool ext_zbkb; + bool ext_zbkc; + bool ext_zbkx; bool ext_zbs; + bool ext_zk; + bool ext_zkn; + bool ext_zknd; + bool ext_zkne; + bool ext_zknh; + bool ext_zkr; + bool ext_zks; + bool ext_zksed; + bool ext_zksh; + bool ext_zkt; bool ext_counters; bool ext_ifencei; bool ext_icsr; @@ -393,6 +406,10 @@ struct RISCVCPUConfig { bool ext_zve32f; bool ext_zve64f; + uint32_t mvendorid; + uint64_t marchid; + uint64_t mipid; + /* Vendor-specific custom extensions */ bool ext_XVentanaCondOps; diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 4a9e4f7d09..4d04b20d06 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -458,6 +458,9 @@ #define CSR_VSPMMASK 0x2c1 #define CSR_VSPMBASE 0x2c2 +/* Crypto Extension */ +#define CSR_SEED 0x015 + /* mstatus CSR bits */ #define MSTATUS_UIE 0x00000001 #define MSTATUS_SIE 0x00000002 @@ -800,4 +803,10 @@ typedef enum RISCVException { #define HVICTL_VALID_MASK \ (HVICTL_VTI | HVICTL_IID | HVICTL_IPRIOM | HVICTL_IPRIO) +/* seed CSR bits */ +#define SEED_OPST (0b11 << 30) +#define SEED_OPST_BIST (0b00 << 30) +#define SEED_OPST_WAIT (0b01 << 30) +#define SEED_OPST_ES16 (0b10 << 30) +#define SEED_OPST_DEAD (0b11 << 30) #endif diff --git a/target/riscv/crypto_helper.c b/target/riscv/crypto_helper.c new file mode 100644 index 0000000000..2ef30281b1 --- /dev/null +++ b/target/riscv/crypto_helper.c @@ -0,0 +1,302 @@ +/* + * RISC-V Crypto Emulation Helpers for QEMU. + * + * Copyright (c) 2021 Ruibo Lu, luruibo2000@163.com + * Copyright (c) 2021 Zewen Ye, lustrew@foxmail.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "exec/exec-all.h" +#include "exec/helper-proto.h" +#include "crypto/aes.h" +#include "crypto/sm4.h" + +#define AES_XTIME(a) \ + ((a << 1) ^ ((a & 0x80) ? 0x1b : 0)) + +#define AES_GFMUL(a, b) (( \ + (((b) & 0x1) ? (a) : 0) ^ \ + (((b) & 0x2) ? AES_XTIME(a) : 0) ^ \ + (((b) & 0x4) ? AES_XTIME(AES_XTIME(a)) : 0) ^ \ + (((b) & 0x8) ? AES_XTIME(AES_XTIME(AES_XTIME(a))) : 0)) & 0xFF) + +static inline uint32_t aes_mixcolumn_byte(uint8_t x, bool fwd) +{ + uint32_t u; + + if (fwd) { + u = (AES_GFMUL(x, 3) << 24) | (x << 16) | (x << 8) | + (AES_GFMUL(x, 2) << 0); + } else { + u = (AES_GFMUL(x, 0xb) << 24) | (AES_GFMUL(x, 0xd) << 16) | + (AES_GFMUL(x, 0x9) << 8) | (AES_GFMUL(x, 0xe) << 0); + } + return u; +} + +#define sext32_xlen(x) (target_ulong)(int32_t)(x) + +static inline target_ulong aes32_operation(target_ulong shamt, + target_ulong rs1, target_ulong rs2, + bool enc, bool mix) +{ + uint8_t si = rs2 >> shamt; + uint8_t so; + uint32_t mixed; + target_ulong res; + + if (enc) { + so = AES_sbox[si]; + if (mix) { + mixed = aes_mixcolumn_byte(so, true); + } else { + mixed = so; + } + } else { + so = AES_isbox[si]; + if (mix) { + mixed = aes_mixcolumn_byte(so, false); + } else { + mixed = so; + } + } + mixed = rol32(mixed, shamt); + res = rs1 ^ mixed; + + return sext32_xlen(res); +} + +target_ulong HELPER(aes32esmi)(target_ulong rs1, target_ulong rs2, + target_ulong shamt) +{ + return aes32_operation(shamt, rs1, rs2, true, true); +} + +target_ulong HELPER(aes32esi)(target_ulong rs1, target_ulong rs2, + target_ulong shamt) +{ + return aes32_operation(shamt, rs1, rs2, true, false); +} + +target_ulong HELPER(aes32dsmi)(target_ulong rs1, target_ulong rs2, + target_ulong shamt) +{ + return aes32_operation(shamt, rs1, rs2, false, true); +} + +target_ulong HELPER(aes32dsi)(target_ulong rs1, target_ulong rs2, + target_ulong shamt) +{ + return aes32_operation(shamt, rs1, rs2, false, false); +} + +#define BY(X, I) ((X >> (8 * I)) & 0xFF) + +#define AES_SHIFROWS_LO(RS1, RS2) ( \ + (((RS1 >> 24) & 0xFF) << 56) | (((RS2 >> 48) & 0xFF) << 48) | \ + (((RS2 >> 8) & 0xFF) << 40) | (((RS1 >> 32) & 0xFF) << 32) | \ + (((RS2 >> 56) & 0xFF) << 24) | (((RS2 >> 16) & 0xFF) << 16) | \ + (((RS1 >> 40) & 0xFF) << 8) | (((RS1 >> 0) & 0xFF) << 0)) + +#define AES_INVSHIFROWS_LO(RS1, RS2) ( \ + (((RS2 >> 24) & 0xFF) << 56) | (((RS2 >> 48) & 0xFF) << 48) | \ + (((RS1 >> 8) & 0xFF) << 40) | (((RS1 >> 32) & 0xFF) << 32) | \ + (((RS1 >> 56) & 0xFF) << 24) | (((RS2 >> 16) & 0xFF) << 16) | \ + (((RS2 >> 40) & 0xFF) << 8) | (((RS1 >> 0) & 0xFF) << 0)) + +#define AES_MIXBYTE(COL, B0, B1, B2, B3) ( \ + BY(COL, B3) ^ BY(COL, B2) ^ AES_GFMUL(BY(COL, B1), 3) ^ \ + AES_GFMUL(BY(COL, B0), 2)) + +#define AES_MIXCOLUMN(COL) ( \ + AES_MIXBYTE(COL, 3, 0, 1, 2) << 24 | \ + AES_MIXBYTE(COL, 2, 3, 0, 1) << 16 | \ + AES_MIXBYTE(COL, 1, 2, 3, 0) << 8 | AES_MIXBYTE(COL, 0, 1, 2, 3) << 0) + +#define AES_INVMIXBYTE(COL, B0, B1, B2, B3) ( \ + AES_GFMUL(BY(COL, B3), 0x9) ^ AES_GFMUL(BY(COL, B2), 0xd) ^ \ + AES_GFMUL(BY(COL, B1), 0xb) ^ AES_GFMUL(BY(COL, B0), 0xe)) + +#define AES_INVMIXCOLUMN(COL) ( \ + AES_INVMIXBYTE(COL, 3, 0, 1, 2) << 24 | \ + AES_INVMIXBYTE(COL, 2, 3, 0, 1) << 16 | \ + AES_INVMIXBYTE(COL, 1, 2, 3, 0) << 8 | \ + AES_INVMIXBYTE(COL, 0, 1, 2, 3) << 0) + +static inline target_ulong aes64_operation(target_ulong rs1, target_ulong rs2, + bool enc, bool mix) +{ + uint64_t RS1 = rs1; + uint64_t RS2 = rs2; + uint64_t result; + uint64_t temp; + uint32_t col_0; + uint32_t col_1; + + if (enc) { + temp = AES_SHIFROWS_LO(RS1, RS2); + temp = (((uint64_t)AES_sbox[(temp >> 0) & 0xFF] << 0) | + ((uint64_t)AES_sbox[(temp >> 8) & 0xFF] << 8) | + ((uint64_t)AES_sbox[(temp >> 16) & 0xFF] << 16) | + ((uint64_t)AES_sbox[(temp >> 24) & 0xFF] << 24) | + ((uint64_t)AES_sbox[(temp >> 32) & 0xFF] << 32) | + ((uint64_t)AES_sbox[(temp >> 40) & 0xFF] << 40) | + ((uint64_t)AES_sbox[(temp >> 48) & 0xFF] << 48) | + ((uint64_t)AES_sbox[(temp >> 56) & 0xFF] << 56)); + if (mix) { + col_0 = temp & 0xFFFFFFFF; + col_1 = temp >> 32; + + col_0 = AES_MIXCOLUMN(col_0); + col_1 = AES_MIXCOLUMN(col_1); + + result = ((uint64_t)col_1 << 32) | col_0; + } else { + result = temp; + } + } else { + temp = AES_INVSHIFROWS_LO(RS1, RS2); + temp = (((uint64_t)AES_isbox[(temp >> 0) & 0xFF] << 0) | + ((uint64_t)AES_isbox[(temp >> 8) & 0xFF] << 8) | + ((uint64_t)AES_isbox[(temp >> 16) & 0xFF] << 16) | + ((uint64_t)AES_isbox[(temp >> 24) & 0xFF] << 24) | + ((uint64_t)AES_isbox[(temp >> 32) & 0xFF] << 32) | + ((uint64_t)AES_isbox[(temp >> 40) & 0xFF] << 40) | + ((uint64_t)AES_isbox[(temp >> 48) & 0xFF] << 48) | + ((uint64_t)AES_isbox[(temp >> 56) & 0xFF] << 56)); + if (mix) { + col_0 = temp & 0xFFFFFFFF; + col_1 = temp >> 32; + + col_0 = AES_INVMIXCOLUMN(col_0); + col_1 = AES_INVMIXCOLUMN(col_1); + + result = ((uint64_t)col_1 << 32) | col_0; + } else { + result = temp; + } + } + + return result; +} + +target_ulong HELPER(aes64esm)(target_ulong rs1, target_ulong rs2) +{ + return aes64_operation(rs1, rs2, true, true); +} + +target_ulong HELPER(aes64es)(target_ulong rs1, target_ulong rs2) +{ + return aes64_operation(rs1, rs2, true, false); +} + +target_ulong HELPER(aes64ds)(target_ulong rs1, target_ulong rs2) +{ + return aes64_operation(rs1, rs2, false, false); +} + +target_ulong HELPER(aes64dsm)(target_ulong rs1, target_ulong rs2) +{ + return aes64_operation(rs1, rs2, false, true); +} + +target_ulong HELPER(aes64ks2)(target_ulong rs1, target_ulong rs2) +{ + uint64_t RS1 = rs1; + uint64_t RS2 = rs2; + uint32_t rs1_hi = RS1 >> 32; + uint32_t rs2_lo = RS2; + uint32_t rs2_hi = RS2 >> 32; + + uint32_t r_lo = (rs1_hi ^ rs2_lo); + uint32_t r_hi = (rs1_hi ^ rs2_lo ^ rs2_hi); + target_ulong result = ((uint64_t)r_hi << 32) | r_lo; + + return result; +} + +target_ulong HELPER(aes64ks1i)(target_ulong rs1, target_ulong rnum) +{ + uint64_t RS1 = rs1; + static const uint8_t round_consts[10] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 + }; + + uint8_t enc_rnum = rnum; + uint32_t temp = (RS1 >> 32) & 0xFFFFFFFF; + uint8_t rcon_ = 0; + target_ulong result; + + if (enc_rnum != 0xA) { + temp = ror32(temp, 8); /* Rotate right by 8 */ + rcon_ = round_consts[enc_rnum]; + } + + temp = ((uint32_t)AES_sbox[(temp >> 24) & 0xFF] << 24) | + ((uint32_t)AES_sbox[(temp >> 16) & 0xFF] << 16) | + ((uint32_t)AES_sbox[(temp >> 8) & 0xFF] << 8) | + ((uint32_t)AES_sbox[(temp >> 0) & 0xFF] << 0); + + temp ^= rcon_; + + result = ((uint64_t)temp << 32) | temp; + + return result; +} + +target_ulong HELPER(aes64im)(target_ulong rs1) +{ + uint64_t RS1 = rs1; + uint32_t col_0 = RS1 & 0xFFFFFFFF; + uint32_t col_1 = RS1 >> 32; + target_ulong result; + + col_0 = AES_INVMIXCOLUMN(col_0); + col_1 = AES_INVMIXCOLUMN(col_1); + + result = ((uint64_t)col_1 << 32) | col_0; + + return result; +} + +target_ulong HELPER(sm4ed)(target_ulong rs1, target_ulong rs2, + target_ulong shamt) +{ + uint32_t sb_in = (uint8_t)(rs2 >> shamt); + uint32_t sb_out = (uint32_t)sm4_sbox[sb_in]; + + uint32_t x = sb_out ^ (sb_out << 8) ^ (sb_out << 2) ^ (sb_out << 18) ^ + ((sb_out & 0x3f) << 26) ^ ((sb_out & 0xC0) << 10); + + uint32_t rotl = rol32(x, shamt); + + return sext32_xlen(rotl ^ (uint32_t)rs1); +} + +target_ulong HELPER(sm4ks)(target_ulong rs1, target_ulong rs2, + target_ulong shamt) +{ + uint32_t sb_in = (uint8_t)(rs2 >> shamt); + uint32_t sb_out = sm4_sbox[sb_in]; + + uint32_t x = sb_out ^ ((sb_out & 0x07) << 29) ^ ((sb_out & 0xFE) << 7) ^ + ((sb_out & 0x01) << 23) ^ ((sb_out & 0xF8) << 13); + + uint32_t rotl = rol32(x, shamt); + + return sext32_xlen(rotl ^ (uint32_t)rs1); +} +#undef sext32_xlen diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 6ba85e7b5d..3500e07f92 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -24,6 +24,8 @@ #include "qemu/main-loop.h" #include "exec/exec-all.h" #include "sysemu/cpu-timers.h" +#include "qemu/guest-random.h" +#include "qapi/error.h" /* CSR function table public API */ void riscv_get_csr_ops(int csrno, riscv_csr_operations *ops) @@ -301,6 +303,46 @@ static RISCVException debug(CPURISCVState *env, int csrno) } #endif +static RISCVException seed(CPURISCVState *env, int csrno) +{ + RISCVCPU *cpu = env_archcpu(env); + + if (!cpu->cfg.ext_zkr) { + return RISCV_EXCP_ILLEGAL_INST; + } + +#if !defined(CONFIG_USER_ONLY) + /* + * With a CSR read-write instruction: + * 1) The seed CSR is always available in machine mode as normal. + * 2) Attempted access to seed from virtual modes VS and VU always raises + * an exception(virtual instruction exception only if mseccfg.sseed=1). + * 3) Without the corresponding access control bit set to 1, any attempted + * access to seed from U, S or HS modes will raise an illegal instruction + * exception. + */ + if (env->priv == PRV_M) { + return RISCV_EXCP_NONE; + } else if (riscv_cpu_virt_enabled(env)) { + if (env->mseccfg & MSECCFG_SSEED) { + return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; + } else { + return RISCV_EXCP_ILLEGAL_INST; + } + } else { + if (env->priv == PRV_S && (env->mseccfg & MSECCFG_SSEED)) { + return RISCV_EXCP_NONE; + } else if (env->priv == PRV_U && (env->mseccfg & MSECCFG_USEED)) { + return RISCV_EXCP_NONE; + } else { + return RISCV_EXCP_ILLEGAL_INST; + } + } +#else + return RISCV_EXCP_NONE; +#endif +} + /* User Floating-Point CSRs */ static RISCVException read_fflags(CPURISCVState *env, int csrno, target_ulong *val) @@ -612,6 +654,36 @@ static RISCVException write_ignore(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } +static RISCVException read_mvendorid(CPURISCVState *env, int csrno, + target_ulong *val) +{ + CPUState *cs = env_cpu(env); + RISCVCPU *cpu = RISCV_CPU(cs); + + *val = cpu->cfg.mvendorid; + return RISCV_EXCP_NONE; +} + +static RISCVException read_marchid(CPURISCVState *env, int csrno, + target_ulong *val) +{ + CPUState *cs = env_cpu(env); + RISCVCPU *cpu = RISCV_CPU(cs); + + *val = cpu->cfg.marchid; + return RISCV_EXCP_NONE; +} + +static RISCVException read_mipid(CPURISCVState *env, int csrno, + target_ulong *val) +{ + CPUState *cs = env_cpu(env); + RISCVCPU *cpu = RISCV_CPU(cs); + + *val = cpu->cfg.mipid; + return RISCV_EXCP_NONE; +} + static RISCVException read_mhartid(CPURISCVState *env, int csrno, target_ulong *val) { @@ -3014,6 +3086,41 @@ static RISCVException write_upmbase(CPURISCVState *env, int csrno, #endif +/* Crypto Extension */ +static RISCVException rmw_seed(CPURISCVState *env, int csrno, + target_ulong *ret_value, + target_ulong new_value, + target_ulong write_mask) +{ + uint16_t random_v; + Error *random_e = NULL; + int random_r; + target_ulong rval; + + random_r = qemu_guest_getrandom(&random_v, 2, &random_e); + if (unlikely(random_r < 0)) { + /* + * Failed, for unknown reasons in the crypto subsystem. + * The best we can do is log the reason and return a + * failure indication to the guest. There is no reason + * we know to expect the failure to be transitory, so + * indicate DEAD to avoid having the guest spin on WAIT. + */ + qemu_log_mask(LOG_UNIMP, "%s: Crypto failure: %s", + __func__, error_get_pretty(random_e)); + error_free(random_e); + rval = SEED_OPST_DEAD; + } else { + rval = random_v | SEED_OPST_ES16; + } + + if (ret_value) { + *ret_value = rval; + } + + return RISCV_EXCP_NONE; +} + /* * riscv_csrrw - read and/or update control and status register * @@ -3252,6 +3359,9 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_TIME] = { "time", ctr, read_time }, [CSR_TIMEH] = { "timeh", ctr32, read_timeh }, + /* Crypto Extension */ + [CSR_SEED] = { "seed", seed, NULL, NULL, rmw_seed }, + #if !defined(CONFIG_USER_ONLY) /* Machine Timers and Counters */ [CSR_MCYCLE] = { "mcycle", any, read_instret }, @@ -3260,10 +3370,10 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_MINSTRETH] = { "minstreth", any32, read_instreth }, /* Machine Information Registers */ - [CSR_MVENDORID] = { "mvendorid", any, read_zero }, - [CSR_MARCHID] = { "marchid", any, read_zero }, - [CSR_MIMPID] = { "mimpid", any, read_zero }, - [CSR_MHARTID] = { "mhartid", any, read_mhartid }, + [CSR_MVENDORID] = { "mvendorid", any, read_mvendorid }, + [CSR_MARCHID] = { "marchid", any, read_marchid }, + [CSR_MIMPID] = { "mimpid", any, read_mipid }, + [CSR_MHARTID] = { "mhartid", any, read_mhartid }, [CSR_MCONFIGPTR] = { "mconfigptr", any, read_zero, .min_priv_ver = PRIV_VERSION_1_12_0 }, diff --git a/target/riscv/helper.h b/target/riscv/helper.h index a669d0187b..4ef3b2251d 100644 --- a/target/riscv/helper.h +++ b/target/riscv/helper.h @@ -66,6 +66,11 @@ DEF_HELPER_FLAGS_1(fclass_d, TCG_CALL_NO_RWG_SE, tl, i64) /* Bitmanip */ DEF_HELPER_FLAGS_2(clmul, TCG_CALL_NO_RWG_SE, tl, tl, tl) DEF_HELPER_FLAGS_2(clmulr, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_1(brev8, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(unzip, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(zip, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_2(xperm4, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(xperm8, TCG_CALL_NO_RWG_SE, tl, tl, tl) /* Floating Point - Half Precision */ DEF_HELPER_FLAGS_3(fadd_h, TCG_CALL_NO_RWG, i64, env, i64, i64) @@ -1107,3 +1112,20 @@ DEF_HELPER_5(divu_i128, tl, env, tl, tl, tl, tl) DEF_HELPER_5(divs_i128, tl, env, tl, tl, tl, tl) DEF_HELPER_5(remu_i128, tl, env, tl, tl, tl, tl) DEF_HELPER_5(rems_i128, tl, env, tl, tl, tl, tl) + +/* Crypto functions */ +DEF_HELPER_FLAGS_3(aes32esmi, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl) +DEF_HELPER_FLAGS_3(aes32esi, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl) +DEF_HELPER_FLAGS_3(aes32dsmi, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl) +DEF_HELPER_FLAGS_3(aes32dsi, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl) + +DEF_HELPER_FLAGS_2(aes64esm, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(aes64es, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(aes64ds, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(aes64dsm, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(aes64ks2, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(aes64ks1i, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_1(aes64im, TCG_CALL_NO_RWG_SE, tl, tl) + +DEF_HELPER_FLAGS_3(sm4ed, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl) +DEF_HELPER_FLAGS_3(sm4ks, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl) diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index 1d3ff1efe1..4033565393 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -35,6 +35,8 @@ %imm_b 31:s1 7:1 25:6 8:4 !function=ex_shift_1 %imm_j 31:s1 12:8 20:1 21:10 !function=ex_shift_1 %imm_u 12:s20 !function=ex_shift_12 +%imm_bs 30:2 !function=ex_shift_3 +%imm_rnum 20:4 # Argument sets: &empty @@ -52,6 +54,7 @@ &rmr vm rd rs2 &r2nfvm vm rd rs1 nf &rnfvm vm rd rs1 rs2 nf +&k_aes shamt rs2 rs1 rd # Formats 32: @r ....... ..... ..... ... ..... ....... &r %rs2 %rs1 %rd @@ -89,6 +92,9 @@ @sfence_vma ....... ..... ..... ... ..... ....... %rs2 %rs1 @sfence_vm ....... ..... ..... ... ..... ....... %rs1 +@k_aes .. ..... ..... ..... ... ..... ....... &k_aes shamt=%imm_bs %rs2 %rs1 %rd +@i_aes .. ..... ..... ..... ... ..... ....... &i imm=%imm_rnum %rs1 %rd + # Formats 64: @sh5 ....... ..... ..... ... ..... ....... &shift shamt=%sh5 %rs1 %rd @@ -717,8 +723,22 @@ sh2add_uw 0010000 .......... 100 ..... 0111011 @r sh3add_uw 0010000 .......... 110 ..... 0111011 @r slli_uw 00001 ............ 001 ..... 0011011 @sh -# *** RV32 Zbb Standard Extension *** +# *** RV32 Zbb/Zbkb Standard Extension *** andn 0100000 .......... 111 ..... 0110011 @r +rol 0110000 .......... 001 ..... 0110011 @r +ror 0110000 .......... 101 ..... 0110011 @r +rori 01100 ............ 101 ..... 0010011 @sh +# The encoding for rev8 differs between RV32 and RV64. +# rev8_32 denotes the RV32 variant. +rev8_32 011010 011000 ..... 101 ..... 0010011 @r2 +# The encoding for zext.h differs between RV32 and RV64. +# zext_h_32 denotes the RV32 variant. +{ + zext_h_32 0000100 00000 ..... 100 ..... 0110011 @r2 + pack 0000100 ..... ..... 100 ..... 0110011 @r +} +xnor 0100000 .......... 100 ..... 0110011 @r +# *** RV32 extra Zbb Standard Extension *** clz 011000 000000 ..... 001 ..... 0010011 @r2 cpop 011000 000010 ..... 001 ..... 0010011 @r2 ctz 011000 000001 ..... 001 ..... 0010011 @r2 @@ -728,23 +748,15 @@ min 0000101 .......... 100 ..... 0110011 @r minu 0000101 .......... 101 ..... 0110011 @r orc_b 001010 000111 ..... 101 ..... 0010011 @r2 orn 0100000 .......... 110 ..... 0110011 @r -# The encoding for rev8 differs between RV32 and RV64. -# rev8_32 denotes the RV32 variant. -rev8_32 011010 011000 ..... 101 ..... 0010011 @r2 -rol 0110000 .......... 001 ..... 0110011 @r -ror 0110000 .......... 101 ..... 0110011 @r -rori 01100 ............ 101 ..... 0010011 @sh sext_b 011000 000100 ..... 001 ..... 0010011 @r2 sext_h 011000 000101 ..... 001 ..... 0010011 @r2 -xnor 0100000 .......... 100 ..... 0110011 @r -# The encoding for zext.h differs between RV32 and RV64. -# zext_h_32 denotes the RV32 variant. -zext_h_32 0000100 00000 ..... 100 ..... 0110011 @r2 +# *** RV32 extra Zbkb Standard Extension *** +brev8 0110100 00111 ..... 101 ..... 0010011 @r2 #grevi +packh 0000100 .......... 111 ..... 0110011 @r +unzip 0000100 01111 ..... 101 ..... 0010011 @r2 #unshfl +zip 0000100 01111 ..... 001 ..... 0010011 @r2 #shfl -# *** RV64 Zbb Standard Extension (in addition to RV32 Zbb) *** -clzw 0110000 00000 ..... 001 ..... 0011011 @r2 -ctzw 0110000 00001 ..... 001 ..... 0011011 @r2 -cpopw 0110000 00010 ..... 001 ..... 0011011 @r2 +# *** RV64 Zbb/Zbkb Standard Extension (in addition to RV32 Zbb/Zbkb) *** # The encoding for rev8 differs between RV32 and RV64. # When executing on RV64, the encoding used in RV32 is an illegal # instruction, so we use different handler functions to differentiate. @@ -755,13 +767,25 @@ rorw 0110000 .......... 101 ..... 0111011 @r # The encoding for zext.h differs between RV32 and RV64. # When executing on RV64, the encoding used in RV32 is an illegal # instruction, so we use different handler functions to differentiate. -zext_h_64 0000100 00000 ..... 100 ..... 0111011 @r2 +{ + zext_h_64 0000100 00000 ..... 100 ..... 0111011 @r2 + packw 0000100 ..... ..... 100 ..... 0111011 @r +} +# *** RV64 extra Zbb Standard Extension (in addition to RV32 Zbb) *** +clzw 0110000 00000 ..... 001 ..... 0011011 @r2 +ctzw 0110000 00001 ..... 001 ..... 0011011 @r2 +cpopw 0110000 00010 ..... 001 ..... 0011011 @r2 -# *** RV32 Zbc Standard Extension *** +# *** RV32 Zbc/Zbkc Standard Extension *** clmul 0000101 .......... 001 ..... 0110011 @r clmulh 0000101 .......... 011 ..... 0110011 @r +# *** RV32 extra Zbc Standard Extension *** clmulr 0000101 .......... 010 ..... 0110011 @r +# *** RV32 Zbkx Standard Extension *** +xperm4 0010100 .......... 010 ..... 0110011 @r +xperm8 0010100 .......... 100 ..... 0110011 @r + # *** RV32 Zbs Standard Extension *** bclr 0100100 .......... 001 ..... 0110011 @r bclri 01001. ........... 001 ..... 0010011 @sh @@ -816,3 +840,42 @@ sfence_w_inval 0001100 00000 00000 000 00000 1110011 sfence_inval_ir 0001100 00001 00000 000 00000 1110011 hinval_vvma 0010011 ..... ..... 000 00000 1110011 @hfence_vvma hinval_gvma 0110011 ..... ..... 000 00000 1110011 @hfence_gvma + +# *** RV32 Zknd Standard Extension *** +aes32dsmi .. 10111 ..... ..... 000 ..... 0110011 @k_aes +aes32dsi .. 10101 ..... ..... 000 ..... 0110011 @k_aes +# *** RV64 Zknd Standard Extension *** +aes64dsm 00 11111 ..... ..... 000 ..... 0110011 @r +aes64ds 00 11101 ..... ..... 000 ..... 0110011 @r +aes64im 00 11000 00000 ..... 001 ..... 0010011 @r2 +# *** RV32 Zkne Standard Extension *** +aes32esmi .. 10011 ..... ..... 000 ..... 0110011 @k_aes +aes32esi .. 10001 ..... ..... 000 ..... 0110011 @k_aes +# *** RV64 Zkne Standard Extension *** +aes64es 00 11001 ..... ..... 000 ..... 0110011 @r +aes64esm 00 11011 ..... ..... 000 ..... 0110011 @r +# *** RV64 Zkne/zknd Standard Extension *** +aes64ks2 01 11111 ..... ..... 000 ..... 0110011 @r +aes64ks1i 00 11000 1.... ..... 001 ..... 0010011 @i_aes +# *** RV32 Zknh Standard Extension *** +sha256sig0 00 01000 00010 ..... 001 ..... 0010011 @r2 +sha256sig1 00 01000 00011 ..... 001 ..... 0010011 @r2 +sha256sum0 00 01000 00000 ..... 001 ..... 0010011 @r2 +sha256sum1 00 01000 00001 ..... 001 ..... 0010011 @r2 +sha512sum0r 01 01000 ..... ..... 000 ..... 0110011 @r +sha512sum1r 01 01001 ..... ..... 000 ..... 0110011 @r +sha512sig0l 01 01010 ..... ..... 000 ..... 0110011 @r +sha512sig0h 01 01110 ..... ..... 000 ..... 0110011 @r +sha512sig1l 01 01011 ..... ..... 000 ..... 0110011 @r +sha512sig1h 01 01111 ..... ..... 000 ..... 0110011 @r +# *** RV64 Zknh Standard Extension *** +sha512sig0 00 01000 00110 ..... 001 ..... 0010011 @r2 +sha512sig1 00 01000 00111 ..... 001 ..... 0010011 @r2 +sha512sum0 00 01000 00100 ..... 001 ..... 0010011 @r2 +sha512sum1 00 01000 00101 ..... 001 ..... 0010011 @r2 +# *** RV32 Zksh Standard Extension *** +sm3p0 00 01000 01000 ..... 001 ..... 0010011 @r2 +sm3p1 00 01000 01001 ..... 001 ..... 0010011 @r2 +# *** RV32 Zksed Standard Extension *** +sm4ed .. 11000 ..... ..... 000 ..... 0110011 @k_aes +sm4ks .. 11010 ..... ..... 000 ..... 0110011 @k_aes diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc index e8519a6d69..e2b8329f1e 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -1,5 +1,5 @@ /* - * RISC-V translation routines for the Zb[abcs] Standard Extension. + * RISC-V translation routines for the Zb[abcs] and Zbk[bcx] Standard Extension. * * Copyright (c) 2020 Kito Cheng, kito.cheng@sifive.com * Copyright (c) 2020 Frank Chang, frank.chang@sifive.com @@ -42,6 +42,18 @@ } \ } while (0) +#define REQUIRE_ZBKB(ctx) do { \ + if (!ctx->cfg_ptr->ext_zbkb) { \ + return false; \ + } \ +} while (0) + +#define REQUIRE_ZBKX(ctx) do { \ + if (!ctx->cfg_ptr->ext_zbkx) { \ + return false; \ + } \ +} while (0) + static void gen_clz(TCGv ret, TCGv arg1) { tcg_gen_clzi_tl(ret, arg1, TARGET_LONG_BITS); @@ -85,19 +97,19 @@ static bool trans_cpop(DisasContext *ctx, arg_cpop *a) static bool trans_andn(DisasContext *ctx, arg_andn *a) { - REQUIRE_ZBB(ctx); + REQUIRE_EITHER_EXT(ctx, zbb, zbkb); return gen_logic(ctx, a, tcg_gen_andc_tl); } static bool trans_orn(DisasContext *ctx, arg_orn *a) { - REQUIRE_ZBB(ctx); + REQUIRE_EITHER_EXT(ctx, zbb, zbkb); return gen_logic(ctx, a, tcg_gen_orc_tl); } static bool trans_xnor(DisasContext *ctx, arg_xnor *a) { - REQUIRE_ZBB(ctx); + REQUIRE_EITHER_EXT(ctx, zbb, zbkb); return gen_logic(ctx, a, tcg_gen_eqv_tl); } @@ -247,7 +259,7 @@ static void gen_rorw(TCGv ret, TCGv arg1, TCGv arg2) static bool trans_ror(DisasContext *ctx, arg_ror *a) { - REQUIRE_ZBB(ctx); + REQUIRE_EITHER_EXT(ctx, zbb, zbkb); return gen_shift_per_ol(ctx, a, EXT_NONE, tcg_gen_rotr_tl, gen_rorw, NULL); } @@ -264,7 +276,7 @@ static void gen_roriw(TCGv ret, TCGv arg1, target_long shamt) static bool trans_rori(DisasContext *ctx, arg_rori *a) { - REQUIRE_ZBB(ctx); + REQUIRE_EITHER_EXT(ctx, zbb, zbkb); return gen_shift_imm_fn_per_ol(ctx, a, EXT_NONE, tcg_gen_rotri_tl, gen_roriw, NULL); } @@ -289,7 +301,7 @@ static void gen_rolw(TCGv ret, TCGv arg1, TCGv arg2) static bool trans_rol(DisasContext *ctx, arg_rol *a) { - REQUIRE_ZBB(ctx); + REQUIRE_EITHER_EXT(ctx, zbb, zbkb); return gen_shift_per_ol(ctx, a, EXT_NONE, tcg_gen_rotl_tl, gen_rolw, NULL); } @@ -301,14 +313,14 @@ static void gen_rev8_32(TCGv ret, TCGv src1) static bool trans_rev8_32(DisasContext *ctx, arg_rev8_32 *a) { REQUIRE_32BIT(ctx); - REQUIRE_ZBB(ctx); + REQUIRE_EITHER_EXT(ctx, zbb, zbkb); return gen_unary(ctx, a, EXT_NONE, gen_rev8_32); } static bool trans_rev8_64(DisasContext *ctx, arg_rev8_64 *a) { REQUIRE_64BIT(ctx); - REQUIRE_ZBB(ctx); + REQUIRE_EITHER_EXT(ctx, zbb, zbkb); return gen_unary(ctx, a, EXT_NONE, tcg_gen_bswap_tl); } @@ -403,7 +415,7 @@ static bool trans_cpopw(DisasContext *ctx, arg_cpopw *a) static bool trans_rorw(DisasContext *ctx, arg_rorw *a) { REQUIRE_64BIT(ctx); - REQUIRE_ZBB(ctx); + REQUIRE_EITHER_EXT(ctx, zbb, zbkb); ctx->ol = MXL_RV32; return gen_shift(ctx, a, EXT_NONE, gen_rorw, NULL); } @@ -411,7 +423,7 @@ static bool trans_rorw(DisasContext *ctx, arg_rorw *a) static bool trans_roriw(DisasContext *ctx, arg_roriw *a) { REQUIRE_64BIT(ctx); - REQUIRE_ZBB(ctx); + REQUIRE_EITHER_EXT(ctx, zbb, zbkb); ctx->ol = MXL_RV32; return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_roriw, NULL); } @@ -419,7 +431,7 @@ static bool trans_roriw(DisasContext *ctx, arg_roriw *a) static bool trans_rolw(DisasContext *ctx, arg_rolw *a) { REQUIRE_64BIT(ctx); - REQUIRE_ZBB(ctx); + REQUIRE_EITHER_EXT(ctx, zbb, zbkb); ctx->ol = MXL_RV32; return gen_shift(ctx, a, EXT_NONE, gen_rolw, NULL); } @@ -483,7 +495,7 @@ static bool trans_slli_uw(DisasContext *ctx, arg_slli_uw *a) static bool trans_clmul(DisasContext *ctx, arg_clmul *a) { - REQUIRE_ZBC(ctx); + REQUIRE_EITHER_EXT(ctx, zbc, zbkc); return gen_arith(ctx, a, EXT_NONE, gen_helper_clmul, NULL); } @@ -495,7 +507,7 @@ static void gen_clmulh(TCGv dst, TCGv src1, TCGv src2) static bool trans_clmulh(DisasContext *ctx, arg_clmulr *a) { - REQUIRE_ZBC(ctx); + REQUIRE_EITHER_EXT(ctx, zbc, zbkc); return gen_arith(ctx, a, EXT_NONE, gen_clmulh, NULL); } @@ -504,3 +516,79 @@ static bool trans_clmulr(DisasContext *ctx, arg_clmulh *a) REQUIRE_ZBC(ctx); return gen_arith(ctx, a, EXT_NONE, gen_helper_clmulr, NULL); } + +static void gen_pack(TCGv ret, TCGv src1, TCGv src2) +{ + tcg_gen_deposit_tl(ret, src1, src2, + TARGET_LONG_BITS / 2, + TARGET_LONG_BITS / 2); +} + +static void gen_packh(TCGv ret, TCGv src1, TCGv src2) +{ + TCGv t = tcg_temp_new(); + + tcg_gen_ext8u_tl(t, src2); + tcg_gen_deposit_tl(ret, src1, t, 8, TARGET_LONG_BITS - 8); + tcg_temp_free(t); +} + +static void gen_packw(TCGv ret, TCGv src1, TCGv src2) +{ + TCGv t = tcg_temp_new(); + + tcg_gen_ext16s_tl(t, src2); + tcg_gen_deposit_tl(ret, src1, t, 16, TARGET_LONG_BITS - 16); + tcg_temp_free(t); +} + +static bool trans_brev8(DisasContext *ctx, arg_brev8 *a) +{ + REQUIRE_ZBKB(ctx); + return gen_unary(ctx, a, EXT_NONE, gen_helper_brev8); +} + +static bool trans_pack(DisasContext *ctx, arg_pack *a) +{ + REQUIRE_ZBKB(ctx); + return gen_arith(ctx, a, EXT_NONE, gen_pack, NULL); +} + +static bool trans_packh(DisasContext *ctx, arg_packh *a) +{ + REQUIRE_ZBKB(ctx); + return gen_arith(ctx, a, EXT_NONE, gen_packh, NULL); +} + +static bool trans_packw(DisasContext *ctx, arg_packw *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_ZBKB(ctx); + return gen_arith(ctx, a, EXT_NONE, gen_packw, NULL); +} + +static bool trans_unzip(DisasContext *ctx, arg_unzip *a) +{ + REQUIRE_32BIT(ctx); + REQUIRE_ZBKB(ctx); + return gen_unary(ctx, a, EXT_NONE, gen_helper_unzip); +} + +static bool trans_zip(DisasContext *ctx, arg_zip *a) +{ + REQUIRE_32BIT(ctx); + REQUIRE_ZBKB(ctx); + return gen_unary(ctx, a, EXT_NONE, gen_helper_zip); +} + +static bool trans_xperm4(DisasContext *ctx, arg_xperm4 *a) +{ + REQUIRE_ZBKX(ctx); + return gen_arith(ctx, a, EXT_NONE, gen_helper_xperm4, NULL); +} + +static bool trans_xperm8(DisasContext *ctx, arg_xperm8 *a) +{ + REQUIRE_ZBKX(ctx); + return gen_arith(ctx, a, EXT_NONE, gen_helper_xperm8, NULL); +} diff --git a/target/riscv/insn_trans/trans_rvk.c.inc b/target/riscv/insn_trans/trans_rvk.c.inc new file mode 100644 index 0000000000..90f4eeff60 --- /dev/null +++ b/target/riscv/insn_trans/trans_rvk.c.inc @@ -0,0 +1,391 @@ +/* + * RISC-V translation routines for the Zk[nd,ne,nh,sed,sh] Standard Extension. + * + * Copyright (c) 2021 Ruibo Lu, luruibo2000@163.com + * Copyright (c) 2021 Zewen Ye, lustrew@foxmail.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#define REQUIRE_ZKND(ctx) do { \ + if (!ctx->cfg_ptr->ext_zknd) { \ + return false; \ + } \ +} while (0) + +#define REQUIRE_ZKNE(ctx) do { \ + if (!ctx->cfg_ptr->ext_zkne) { \ + return false; \ + } \ +} while (0) + +#define REQUIRE_ZKNH(ctx) do { \ + if (!ctx->cfg_ptr->ext_zknh) { \ + return false; \ + } \ +} while (0) + +#define REQUIRE_ZKSED(ctx) do { \ + if (!ctx->cfg_ptr->ext_zksed) { \ + return false; \ + } \ +} while (0) + +#define REQUIRE_ZKSH(ctx) do { \ + if (!ctx->cfg_ptr->ext_zksh) { \ + return false; \ + } \ +} while (0) + +static bool gen_aes32_sm4(DisasContext *ctx, arg_k_aes *a, + void (*func)(TCGv, TCGv, TCGv, TCGv)) +{ + TCGv shamt = tcg_constant_tl(a->shamt); + TCGv dest = dest_gpr(ctx, a->rd); + TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); + TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); + + func(dest, src1, src2, shamt); + gen_set_gpr(ctx, a->rd, dest); + return true; +} + +static bool trans_aes32esmi(DisasContext *ctx, arg_aes32esmi *a) +{ + REQUIRE_32BIT(ctx); + REQUIRE_ZKNE(ctx); + return gen_aes32_sm4(ctx, a, gen_helper_aes32esmi); +} + +static bool trans_aes32esi(DisasContext *ctx, arg_aes32esi *a) +{ + REQUIRE_32BIT(ctx); + REQUIRE_ZKNE(ctx); + return gen_aes32_sm4(ctx, a, gen_helper_aes32esi); +} + +static bool trans_aes32dsmi(DisasContext *ctx, arg_aes32dsmi *a) +{ + REQUIRE_32BIT(ctx); + REQUIRE_ZKND(ctx); + return gen_aes32_sm4(ctx, a, gen_helper_aes32dsmi); +} + +static bool trans_aes32dsi(DisasContext *ctx, arg_aes32dsi *a) +{ + REQUIRE_32BIT(ctx); + REQUIRE_ZKND(ctx); + return gen_aes32_sm4(ctx, a, gen_helper_aes32dsi); +} + +static bool trans_aes64es(DisasContext *ctx, arg_aes64es *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_ZKNE(ctx); + return gen_arith(ctx, a, EXT_NONE, gen_helper_aes64es, NULL); +} + +static bool trans_aes64esm(DisasContext *ctx, arg_aes64esm *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_ZKNE(ctx); + return gen_arith(ctx, a, EXT_NONE, gen_helper_aes64esm, NULL); +} + +static bool trans_aes64ds(DisasContext *ctx, arg_aes64ds *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_ZKND(ctx); + return gen_arith(ctx, a, EXT_NONE, gen_helper_aes64ds, NULL); +} + +static bool trans_aes64dsm(DisasContext *ctx, arg_aes64dsm *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_ZKND(ctx); + return gen_arith(ctx, a, EXT_NONE, gen_helper_aes64dsm, NULL); +} + +static bool trans_aes64ks2(DisasContext *ctx, arg_aes64ks2 *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_EITHER_EXT(ctx, zknd, zkne); + return gen_arith(ctx, a, EXT_NONE, gen_helper_aes64ks2, NULL); +} + +static bool trans_aes64ks1i(DisasContext *ctx, arg_aes64ks1i *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_EITHER_EXT(ctx, zknd, zkne); + + if (a->imm > 0xA) { + return false; + } + + return gen_arith_imm_tl(ctx, a, EXT_NONE, gen_helper_aes64ks1i, NULL); +} + +static bool trans_aes64im(DisasContext *ctx, arg_aes64im *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_ZKND(ctx); + return gen_unary(ctx, a, EXT_NONE, gen_helper_aes64im); +} + +static bool gen_sha256(DisasContext *ctx, arg_r2 *a, DisasExtend ext, + void (*func)(TCGv_i32, TCGv_i32, int32_t), + int32_t num1, int32_t num2, int32_t num3) +{ + TCGv dest = dest_gpr(ctx, a->rd); + TCGv src1 = get_gpr(ctx, a->rs1, ext); + TCGv_i32 t0 = tcg_temp_new_i32(); + TCGv_i32 t1 = tcg_temp_new_i32(); + TCGv_i32 t2 = tcg_temp_new_i32(); + + tcg_gen_trunc_tl_i32(t0, src1); + tcg_gen_rotri_i32(t1, t0, num1); + tcg_gen_rotri_i32(t2, t0, num2); + tcg_gen_xor_i32(t1, t1, t2); + func(t2, t0, num3); + tcg_gen_xor_i32(t1, t1, t2); + tcg_gen_ext_i32_tl(dest, t1); + + gen_set_gpr(ctx, a->rd, dest); + tcg_temp_free_i32(t0); + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t2); + return true; +} + +static bool trans_sha256sig0(DisasContext *ctx, arg_sha256sig0 *a) +{ + REQUIRE_ZKNH(ctx); + return gen_sha256(ctx, a, EXT_NONE, tcg_gen_shri_i32, 7, 18, 3); +} + +static bool trans_sha256sig1(DisasContext *ctx, arg_sha256sig1 *a) +{ + REQUIRE_ZKNH(ctx); + return gen_sha256(ctx, a, EXT_NONE, tcg_gen_shri_i32, 17, 19, 10); +} + +static bool trans_sha256sum0(DisasContext *ctx, arg_sha256sum0 *a) +{ + REQUIRE_ZKNH(ctx); + return gen_sha256(ctx, a, EXT_NONE, tcg_gen_rotri_i32, 2, 13, 22); +} + +static bool trans_sha256sum1(DisasContext *ctx, arg_sha256sum1 *a) +{ + REQUIRE_ZKNH(ctx); + return gen_sha256(ctx, a, EXT_NONE, tcg_gen_rotri_i32, 6, 11, 25); +} + +static bool gen_sha512_rv32(DisasContext *ctx, arg_r *a, DisasExtend ext, + void (*func1)(TCGv_i64, TCGv_i64, int64_t), + void (*func2)(TCGv_i64, TCGv_i64, int64_t), + int64_t num1, int64_t num2, int64_t num3) +{ + TCGv dest = dest_gpr(ctx, a->rd); + TCGv src1 = get_gpr(ctx, a->rs1, ext); + TCGv src2 = get_gpr(ctx, a->rs2, ext); + TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 t2 = tcg_temp_new_i64(); + + tcg_gen_concat_tl_i64(t0, src1, src2); + func1(t1, t0, num1); + func2(t2, t0, num2); + tcg_gen_xor_i64(t1, t1, t2); + tcg_gen_rotri_i64(t2, t0, num3); + tcg_gen_xor_i64(t1, t1, t2); + tcg_gen_trunc_i64_tl(dest, t1); + + gen_set_gpr(ctx, a->rd, dest); + tcg_temp_free_i64(t0); + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t2); + return true; +} + +static bool trans_sha512sum0r(DisasContext *ctx, arg_sha512sum0r *a) +{ + REQUIRE_32BIT(ctx); + REQUIRE_ZKNH(ctx); + return gen_sha512_rv32(ctx, a, EXT_NONE, tcg_gen_rotli_i64, + tcg_gen_rotli_i64, 25, 30, 28); +} + +static bool trans_sha512sum1r(DisasContext *ctx, arg_sha512sum1r *a) +{ + REQUIRE_32BIT(ctx); + REQUIRE_ZKNH(ctx); + return gen_sha512_rv32(ctx, a, EXT_NONE, tcg_gen_rotli_i64, + tcg_gen_rotri_i64, 23, 14, 18); +} + +static bool trans_sha512sig0l(DisasContext *ctx, arg_sha512sig0l *a) +{ + REQUIRE_32BIT(ctx); + REQUIRE_ZKNH(ctx); + return gen_sha512_rv32(ctx, a, EXT_NONE, tcg_gen_rotri_i64, + tcg_gen_rotri_i64, 1, 7, 8); +} + +static bool trans_sha512sig1l(DisasContext *ctx, arg_sha512sig1l *a) +{ + REQUIRE_32BIT(ctx); + REQUIRE_ZKNH(ctx); + return gen_sha512_rv32(ctx, a, EXT_NONE, tcg_gen_rotli_i64, + tcg_gen_rotri_i64, 3, 6, 19); +} + +static bool gen_sha512h_rv32(DisasContext *ctx, arg_r *a, DisasExtend ext, + void (*func)(TCGv_i64, TCGv_i64, int64_t), + int64_t num1, int64_t num2, int64_t num3) +{ + TCGv dest = dest_gpr(ctx, a->rd); + TCGv src1 = get_gpr(ctx, a->rs1, ext); + TCGv src2 = get_gpr(ctx, a->rs2, ext); + TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 t2 = tcg_temp_new_i64(); + + tcg_gen_concat_tl_i64(t0, src1, src2); + func(t1, t0, num1); + tcg_gen_ext32u_i64(t2, t0); + tcg_gen_shri_i64(t2, t2, num2); + tcg_gen_xor_i64(t1, t1, t2); + tcg_gen_rotri_i64(t2, t0, num3); + tcg_gen_xor_i64(t1, t1, t2); + tcg_gen_trunc_i64_tl(dest, t1); + + gen_set_gpr(ctx, a->rd, dest); + tcg_temp_free_i64(t0); + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t2); + return true; +} + +static bool trans_sha512sig0h(DisasContext *ctx, arg_sha512sig0h *a) +{ + REQUIRE_32BIT(ctx); + REQUIRE_ZKNH(ctx); + return gen_sha512h_rv32(ctx, a, EXT_NONE, tcg_gen_rotri_i64, 1, 7, 8); +} + +static bool trans_sha512sig1h(DisasContext *ctx, arg_sha512sig1h *a) +{ + REQUIRE_32BIT(ctx); + REQUIRE_ZKNH(ctx); + return gen_sha512h_rv32(ctx, a, EXT_NONE, tcg_gen_rotli_i64, 3, 6, 19); +} + +static bool gen_sha512_rv64(DisasContext *ctx, arg_r2 *a, DisasExtend ext, + void (*func)(TCGv_i64, TCGv_i64, int64_t), + int64_t num1, int64_t num2, int64_t num3) +{ + TCGv dest = dest_gpr(ctx, a->rd); + TCGv src1 = get_gpr(ctx, a->rs1, ext); + TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 t2 = tcg_temp_new_i64(); + + tcg_gen_extu_tl_i64(t0, src1); + tcg_gen_rotri_i64(t1, t0, num1); + tcg_gen_rotri_i64(t2, t0, num2); + tcg_gen_xor_i64(t1, t1, t2); + func(t2, t0, num3); + tcg_gen_xor_i64(t1, t1, t2); + tcg_gen_trunc_i64_tl(dest, t1); + + gen_set_gpr(ctx, a->rd, dest); + tcg_temp_free_i64(t0); + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t2); + return true; +} + +static bool trans_sha512sig0(DisasContext *ctx, arg_sha512sig0 *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_ZKNH(ctx); + return gen_sha512_rv64(ctx, a, EXT_NONE, tcg_gen_shri_i64, 1, 8, 7); +} + +static bool trans_sha512sig1(DisasContext *ctx, arg_sha512sig1 *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_ZKNH(ctx); + return gen_sha512_rv64(ctx, a, EXT_NONE, tcg_gen_shri_i64, 19, 61, 6); +} + +static bool trans_sha512sum0(DisasContext *ctx, arg_sha512sum0 *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_ZKNH(ctx); + return gen_sha512_rv64(ctx, a, EXT_NONE, tcg_gen_rotri_i64, 28, 34, 39); +} + +static bool trans_sha512sum1(DisasContext *ctx, arg_sha512sum1 *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_ZKNH(ctx); + return gen_sha512_rv64(ctx, a, EXT_NONE, tcg_gen_rotri_i64, 14, 18, 41); +} + +/* SM3 */ +static bool gen_sm3(DisasContext *ctx, arg_r2 *a, int32_t b, int32_t c) +{ + TCGv dest = dest_gpr(ctx, a->rd); + TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); + TCGv_i32 t0 = tcg_temp_new_i32(); + TCGv_i32 t1 = tcg_temp_new_i32(); + + tcg_gen_trunc_tl_i32(t0, src1); + tcg_gen_rotli_i32(t1, t0, b); + tcg_gen_xor_i32(t1, t0, t1); + tcg_gen_rotli_i32(t0, t0, c); + tcg_gen_xor_i32(t1, t1, t0); + tcg_gen_ext_i32_tl(dest, t1); + gen_set_gpr(ctx, a->rd, dest); + + tcg_temp_free_i32(t0); + tcg_temp_free_i32(t1); + return true; +} + +static bool trans_sm3p0(DisasContext *ctx, arg_sm3p0 *a) +{ + REQUIRE_ZKSH(ctx); + return gen_sm3(ctx, a, 9, 17); +} + +static bool trans_sm3p1(DisasContext *ctx, arg_sm3p1 *a) +{ + REQUIRE_ZKSH(ctx); + return gen_sm3(ctx, a, 15, 23); +} + +/* SM4 */ +static bool trans_sm4ed(DisasContext *ctx, arg_sm4ed *a) +{ + REQUIRE_ZKSED(ctx); + return gen_aes32_sm4(ctx, a, gen_helper_sm4ed); +} + +static bool trans_sm4ks(DisasContext *ctx, arg_sm4ks *a) +{ + REQUIRE_ZKSED(ctx); + return gen_aes32_sm4(ctx, a, gen_helper_sm4ks); +} diff --git a/target/riscv/meson.build b/target/riscv/meson.build index 2c20f3dd8e..096249f3a3 100644 --- a/target/riscv/meson.build +++ b/target/riscv/meson.build @@ -19,7 +19,8 @@ riscv_ss.add(files( 'vector_helper.c', 'bitmanip_helper.c', 'translate.c', - 'm128_helper.c' + 'm128_helper.c', + 'crypto_helper.c' )) riscv_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'), if_false: files('kvm-stub.c')) diff --git a/target/riscv/monitor.c b/target/riscv/monitor.c index 7efb4b62c1..17e63fab00 100644 --- a/target/riscv/monitor.c +++ b/target/riscv/monitor.c @@ -84,6 +84,7 @@ static void walk_pte(Monitor *mon, hwaddr base, target_ulong start, { hwaddr pte_addr; hwaddr paddr; + target_ulong last_start = -1; target_ulong pgsize; target_ulong pte; int ptshift; @@ -111,12 +112,13 @@ static void walk_pte(Monitor *mon, hwaddr base, target_ulong start, * A leaf PTE has been found * * If current PTE's permission bits differ from the last one, - * or current PTE's ppn does not make a contiguous physical - * address block together with the last one, print out the last - * contiguous mapped block details. + * or the current PTE breaks up a contiguous virtual or + * physical mapping, address block together with the last one, + * print out the last contiguous mapped block details. */ if ((*last_attr != attr) || - (*last_paddr + *last_size != paddr)) { + (*last_paddr + *last_size != paddr) || + (last_start + *last_size != start)) { print_pte(mon, va_bits, *vbase, *pbase, *last_paddr + *last_size - *pbase, *last_attr); @@ -125,6 +127,7 @@ static void walk_pte(Monitor *mon, hwaddr base, target_ulong start, *last_attr = attr; } + last_start = start; *last_paddr = paddr; *last_size = pgsize; } else { diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index df35736883..09f1f5185d 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -39,6 +39,15 @@ void helper_raise_exception(CPURISCVState *env, uint32_t exception) target_ulong helper_csrr(CPURISCVState *env, int csr) { + /* + * The seed CSR must be accessed with a read-write instruction. A + * read-only instruction such as CSRRS/CSRRC with rs1=x0 or CSRRSI/ + * CSRRCI with uimm=0 will raise an illegal instruction exception. + */ + if (csr == CSR_SEED) { + riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); + } + target_ulong val = 0; RISCVException ret = riscv_csrrw(env, csr, &val, 0, 0); diff --git a/target/riscv/pmp.h b/target/riscv/pmp.h index fcb6b7c467..a8dd797476 100644 --- a/target/riscv/pmp.h +++ b/target/riscv/pmp.h @@ -39,9 +39,11 @@ typedef enum { } pmp_am_t; typedef enum { - MSECCFG_MML = 1 << 0, - MSECCFG_MMWP = 1 << 1, - MSECCFG_RLB = 1 << 2 + MSECCFG_MML = 1 << 0, + MSECCFG_MMWP = 1 << 1, + MSECCFG_RLB = 1 << 2, + MSECCFG_USEED = 1 << 8, + MSECCFG_SSEED = 1 << 9 } mseccfg_field_t; typedef struct { diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 6495726302..0cd1d9ee94 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -688,6 +688,13 @@ EX_SH(12) } \ } while (0) +#define REQUIRE_EITHER_EXT(ctx, A, B) do { \ + if (!ctx->cfg_ptr->ext_##A && \ + !ctx->cfg_ptr->ext_##B) { \ + return false; \ + } \ +} while (0) + static int ex_rvc_register(DisasContext *ctx, int reg) { return 8 + reg; @@ -1000,6 +1007,7 @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc) #include "insn_trans/trans_rvv.c.inc" #include "insn_trans/trans_rvb.c.inc" #include "insn_trans/trans_rvzfh.c.inc" +#include "insn_trans/trans_rvk.c.inc" #include "insn_trans/trans_privileged.c.inc" #include "insn_trans/trans_svinval.c.inc" #include "insn_trans/trans_xventanacondops.c.inc"