Second RISC-V PR for QEMU 7.1
* Improve device tree generation * Support configuarable marchid, mvendorid, mipid CSR values * Add support for the Zbkb, Zbkc, Zbkx, Zknd/Zkne, Zknh, Zksed/Zksh and Zkr extensions * Fix incorrect PTE merge in walk_pte * Add TPM support to the virt board -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEE9sSsRtSTSGjTuM6PIeENKd+XcFQFAmJraeUACgkQIeENKd+X cFRLjgf9GFmxPhOC8cb7wN6xsiJIiVmmcTGHKfUgFTAIR2KLOEm2fo28YNrgewok Hi7FBHLhYKEivz70GFVg7q6oJlqhYx8fL4AB0sodTetIcJGQPQgz8zN7ZD8utnzA d6n7ZruyW5IuUqCBUcsHNqBHxoYanR88rr6YpxU+nSz0WALYRgQliXm5zqK1rwNc v8HpLHyN7JUmAQmJ1U6Uc6IFi/cFn9e/Hs/uRMevKov2nCTxeeAq5G2r8JGKpx35 VRid91dcWbGiRY1xHWqnl/0WZxl8Jp4av1e5NDbXfwYPvwiI2fza5KFasp2S38yR VvnUcI+p73qclCF7LkfL9c//xQT1iA== =Xkoz -----END PGP SIGNATURE----- Merge tag 'pull-riscv-to-apply-20220429' of github.com:alistair23/qemu into staging Second RISC-V PR for QEMU 7.1 * Improve device tree generation * Support configuarable marchid, mvendorid, mipid CSR values * Add support for the Zbkb, Zbkc, Zbkx, Zknd/Zkne, Zknh, Zksed/Zksh and Zkr extensions * Fix incorrect PTE merge in walk_pte * Add TPM support to the virt board # -----BEGIN PGP SIGNATURE----- # # iQEzBAABCAAdFiEE9sSsRtSTSGjTuM6PIeENKd+XcFQFAmJraeUACgkQIeENKd+X # cFRLjgf9GFmxPhOC8cb7wN6xsiJIiVmmcTGHKfUgFTAIR2KLOEm2fo28YNrgewok # Hi7FBHLhYKEivz70GFVg7q6oJlqhYx8fL4AB0sodTetIcJGQPQgz8zN7ZD8utnzA # d6n7ZruyW5IuUqCBUcsHNqBHxoYanR88rr6YpxU+nSz0WALYRgQliXm5zqK1rwNc # v8HpLHyN7JUmAQmJ1U6Uc6IFi/cFn9e/Hs/uRMevKov2nCTxeeAq5G2r8JGKpx35 # VRid91dcWbGiRY1xHWqnl/0WZxl8Jp4av1e5NDbXfwYPvwiI2fza5KFasp2S38yR # VvnUcI+p73qclCF7LkfL9c//xQT1iA== # =Xkoz # -----END PGP SIGNATURE----- # gpg: Signature made Thu 28 Apr 2022 09:30:29 PM PDT # gpg: using RSA key F6C4AC46D4934868D3B8CE8F21E10D29DF977054 # gpg: Good signature from "Alistair Francis <alistair@alistair23.me>" [undefined] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: F6C4 AC46 D493 4868 D3B8 CE8F 21E1 0D29 DF97 7054 * tag 'pull-riscv-to-apply-20220429' of github.com:alistair23/qemu: (25 commits) hw/riscv: Enable TPM backends hw/riscv: virt: Add device plug support hw/riscv: virt: Add support for generating platform FDT entries hw/riscv: virt: Create a platform bus hw/core: Move the ARM sysbus-fdt to core hw/riscv: virt: Add a machine done notifier target/riscv: add scalar crypto related extenstion strings to isa_string target/riscv: Fix incorrect PTE merge in walk_pte target/riscv: rvk: expose zbk* and zk* properties disas/riscv.c: rvk: add disas support for Zbk* and Zk* instructions target/riscv: rvk: add CSR support for Zkr target/riscv: rvk: add support for zksed/zksh extension target/riscv: rvk: add support for sha512 related instructions for RV64 in zknh extension target/riscv: rvk: add support for sha512 related instructions for RV32 in zknh extension target/riscv: rvk: add support for sha256 related instructions in zknh extension target/riscv: rvk: add support for zkne/zknd extension in RV64 target/riscv: rvk: add support for zknd/zkne extension in RV32 crypto: move sm4_sbox from target/arm target/riscv: rvk: add support for zbkx extension target/riscv: rvk: add support for zbkc extension ... Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
731340813f
@ -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()
|
||||
|
49
crypto/sm4.c
Normal file
49
crypto/sm4.c
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* QEMU crypto sm4 support
|
||||
*
|
||||
* Copyright (C) 2013 - 2018 Linaro Ltd <ard.biesheuvel@linaro.org>
|
||||
*
|
||||
* 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,
|
||||
};
|
||||
|
173
disas/riscv.c
173
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;
|
||||
|
@ -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.
|
||||
|
@ -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'))
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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',
|
||||
|
@ -27,7 +27,7 @@
|
||||
#ifdef CONFIG_LINUX
|
||||
#include <linux/vfio.h>
|
||||
#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"
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
319
hw/riscv/virt.c
319
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)
|
||||
|
6
include/crypto/sm4.h
Normal file
6
include/crypto/sm4.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef QEMU_SM4_H
|
||||
#define QEMU_SM4_H
|
||||
|
||||
extern const uint8_t sm4_sbox[256];
|
||||
|
||||
#endif
|
@ -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
|
||||
|
@ -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] } };
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
302
target/riscv/crypto_helper.c
Normal file
302
target/riscv/crypto_helper.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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
|
@ -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 },
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
391
target/riscv/insn_trans/trans_rvk.c.inc
Normal file
391
target/riscv/insn_trans/trans_rvk.c.inc
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
@ -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'))
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user