1 | The following changes since commit 3c8c36c9087da957f580a9bb5ebf7814a753d1c6: | 1 | From: Alistair Francis <alistair.francis@wdc.com> |
---|---|---|---|
2 | 2 | ||
3 | Merge remote-tracking branch 'remotes/kraxel/tags/ui-20201104-pull-request' into staging (2020-11-04 16:52:17 +0000) | 3 | The following changes since commit c5fbdd60cf1fb52f01bdfe342b6fa65d5343e1b1: |
4 | |||
5 | Merge tag 'qemu-sparc-20211121' of git://github.com/mcayland/qemu into staging (2021-11-21 14:12:25 +0100) | ||
4 | 6 | ||
5 | are available in the Git repository at: | 7 | are available in the Git repository at: |
6 | 8 | ||
7 | git@github.com:alistair23/qemu.git tags/pull-riscv-to-apply-20201109 | 9 | git@github.com:alistair23/qemu.git tags/pull-riscv-to-apply-20211122 |
8 | 10 | ||
9 | for you to fetch changes up to 96338fefc19a143abdc91f6c44f37683274b08d4: | 11 | for you to fetch changes up to 526e7443027c71fe7b04c29df529e1f9f425f9e3: |
10 | 12 | ||
11 | hw/intc/ibex_plic: Clear the claim register when read (2020-11-09 15:09:53 -0800) | 13 | hw/misc/sifive_u_otp: Do not reset OTP content on hardware reset (2021-11-22 10:46:22 +1000) |
12 | 14 | ||
13 | ---------------------------------------------------------------- | 15 | ---------------------------------------------------------------- |
14 | This fixes two bugs in the RISC-V port. One is a bug in the | 16 | Seventh RISC-V PR for QEMU 6.2 |
15 | Ibex PLIC, the other fixes the Hypvervisor access functions. | 17 | |
18 | - Deprecate IF_NONE for SiFive OTP | ||
19 | - Don't reset SiFive OTP content | ||
16 | 20 | ||
17 | ---------------------------------------------------------------- | 21 | ---------------------------------------------------------------- |
18 | Alistair Francis (6): | 22 | Philippe Mathieu-Daudé (1): |
19 | target/riscv: Add a virtualised MMU Mode | 23 | hw/misc/sifive_u_otp: Do not reset OTP content on hardware reset |
20 | target/riscv: Set the virtualised MMU mode when doing hyp accesses | ||
21 | target/riscv: Remove the HS_TWO_STAGE flag | ||
22 | target/riscv: Remove the hyp load and store functions | ||
23 | target/riscv: Split the Hypervisor execute load helpers | ||
24 | hw/intc/ibex_plic: Clear the claim register when read | ||
25 | 24 | ||
26 | target/riscv/cpu-param.h | 11 ++- | 25 | Thomas Huth (1): |
27 | target/riscv/cpu.h | 19 ++++- | 26 | hw/misc/sifive_u_otp: Use IF_PFLASH for the OTP device instead of IF_NONE |
28 | target/riscv/cpu_bits.h | 1 - | ||
29 | target/riscv/helper.h | 5 +- | ||
30 | hw/intc/ibex_plic.c | 3 + | ||
31 | target/riscv/cpu_helper.c | 62 ++++++-------- | ||
32 | target/riscv/op_helper.c | 124 ++------------------------- | ||
33 | target/riscv/translate.c | 2 + | ||
34 | target/riscv/insn_trans/trans_rvh.c.inc | 143 ++++++++++++-------------------- | ||
35 | 9 files changed, 115 insertions(+), 255 deletions(-) | ||
36 | 27 | ||
28 | docs/about/deprecated.rst | 6 ++++++ | ||
29 | hw/misc/sifive_u_otp.c | 22 +++++++++++++--------- | ||
30 | 2 files changed, 19 insertions(+), 9 deletions(-) | ||
31 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | Add a new MMU mode that includes the current virt mode. | ||
2 | 1 | ||
3 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> | ||
4 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
5 | Message-id: 4b301bc0ea36da962fc1605371b65019ac3073df.1604464950.git.alistair.francis@wdc.com | ||
6 | --- | ||
7 | target/riscv/cpu-param.h | 11 ++++++++++- | ||
8 | target/riscv/cpu.h | 4 +++- | ||
9 | target/riscv/cpu_helper.c | 2 +- | ||
10 | 3 files changed, 14 insertions(+), 3 deletions(-) | ||
11 | |||
12 | diff --git a/target/riscv/cpu-param.h b/target/riscv/cpu-param.h | ||
13 | index XXXXXXX..XXXXXXX 100644 | ||
14 | --- a/target/riscv/cpu-param.h | ||
15 | +++ b/target/riscv/cpu-param.h | ||
16 | @@ -XXX,XX +XXX,XX @@ | ||
17 | # define TARGET_VIRT_ADDR_SPACE_BITS 32 /* sv32 */ | ||
18 | #endif | ||
19 | #define TARGET_PAGE_BITS 12 /* 4 KiB Pages */ | ||
20 | -#define NB_MMU_MODES 4 | ||
21 | +/* | ||
22 | + * The current MMU Modes are: | ||
23 | + * - U mode 0b000 | ||
24 | + * - S mode 0b001 | ||
25 | + * - M mode 0b011 | ||
26 | + * - U mode HLV/HLVX/HSV 0b100 | ||
27 | + * - S mode HLV/HLVX/HSV 0b101 | ||
28 | + * - M mode HLV/HLVX/HSV 0b111 | ||
29 | + */ | ||
30 | +#define NB_MMU_MODES 8 | ||
31 | |||
32 | #endif | ||
33 | diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h | ||
34 | index XXXXXXX..XXXXXXX 100644 | ||
35 | --- a/target/riscv/cpu.h | ||
36 | +++ b/target/riscv/cpu.h | ||
37 | @@ -XXX,XX +XXX,XX @@ void QEMU_NORETURN riscv_raise_exception(CPURISCVState *env, | ||
38 | target_ulong riscv_cpu_get_fflags(CPURISCVState *env); | ||
39 | void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong); | ||
40 | |||
41 | -#define TB_FLAGS_MMU_MASK 3 | ||
42 | +#define TB_FLAGS_MMU_MASK 7 | ||
43 | +#define TB_FLAGS_PRIV_MMU_MASK 3 | ||
44 | +#define TB_FLAGS_PRIV_HYP_ACCESS_MASK (1 << 2) | ||
45 | #define TB_FLAGS_MSTATUS_FS MSTATUS_FS | ||
46 | |||
47 | typedef CPURISCVState CPUArchState; | ||
48 | diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c | ||
49 | index XXXXXXX..XXXXXXX 100644 | ||
50 | --- a/target/riscv/cpu_helper.c | ||
51 | +++ b/target/riscv/cpu_helper.c | ||
52 | @@ -XXX,XX +XXX,XX @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical, | ||
53 | * (riscv_cpu_do_interrupt) is correct */ | ||
54 | MemTxResult res; | ||
55 | MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; | ||
56 | - int mode = mmu_idx; | ||
57 | + int mode = mmu_idx & TB_FLAGS_PRIV_MMU_MASK; | ||
58 | bool use_background = false; | ||
59 | |||
60 | /* | ||
61 | -- | ||
62 | 2.29.2 | ||
63 | |||
64 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | When performing the hypervisor load/store operations set the MMU mode to | ||
2 | indicate that we are virtualised. | ||
3 | 1 | ||
4 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> | ||
5 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
6 | Message-id: e411c61a1452cad16853f13cac2fb86dc91ebee8.1604464950.git.alistair.francis@wdc.com | ||
7 | --- | ||
8 | target/riscv/op_helper.c | 30 +++++++++++++++++------------- | ||
9 | 1 file changed, 17 insertions(+), 13 deletions(-) | ||
10 | |||
11 | diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c | ||
12 | index XXXXXXX..XXXXXXX 100644 | ||
13 | --- a/target/riscv/op_helper.c | ||
14 | +++ b/target/riscv/op_helper.c | ||
15 | @@ -XXX,XX +XXX,XX @@ target_ulong helper_hyp_load(CPURISCVState *env, target_ulong address, | ||
16 | (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) && | ||
17 | get_field(env->hstatus, HSTATUS_HU))) { | ||
18 | target_ulong pte; | ||
19 | + int mmu_idx = cpu_mmu_index(env, false) | TB_FLAGS_PRIV_HYP_ACCESS_MASK; | ||
20 | |||
21 | riscv_cpu_set_two_stage_lookup(env, true); | ||
22 | |||
23 | switch (memop) { | ||
24 | case MO_SB: | ||
25 | - pte = cpu_ldsb_data_ra(env, address, GETPC()); | ||
26 | + pte = cpu_ldsb_mmuidx_ra(env, address, mmu_idx, GETPC()); | ||
27 | break; | ||
28 | case MO_UB: | ||
29 | - pte = cpu_ldub_data_ra(env, address, GETPC()); | ||
30 | + pte = cpu_ldub_mmuidx_ra(env, address, mmu_idx, GETPC()); | ||
31 | break; | ||
32 | case MO_TESW: | ||
33 | - pte = cpu_ldsw_data_ra(env, address, GETPC()); | ||
34 | + pte = cpu_ldsw_mmuidx_ra(env, address, mmu_idx, GETPC()); | ||
35 | break; | ||
36 | case MO_TEUW: | ||
37 | - pte = cpu_lduw_data_ra(env, address, GETPC()); | ||
38 | + pte = cpu_lduw_mmuidx_ra(env, address, mmu_idx, GETPC()); | ||
39 | break; | ||
40 | case MO_TESL: | ||
41 | - pte = cpu_ldl_data_ra(env, address, GETPC()); | ||
42 | + pte = cpu_ldl_mmuidx_ra(env, address, mmu_idx, GETPC()); | ||
43 | break; | ||
44 | case MO_TEUL: | ||
45 | - pte = cpu_ldl_data_ra(env, address, GETPC()); | ||
46 | + pte = cpu_ldl_mmuidx_ra(env, address, mmu_idx, GETPC()); | ||
47 | break; | ||
48 | case MO_TEQ: | ||
49 | - pte = cpu_ldq_data_ra(env, address, GETPC()); | ||
50 | + pte = cpu_ldq_mmuidx_ra(env, address, mmu_idx, GETPC()); | ||
51 | break; | ||
52 | default: | ||
53 | g_assert_not_reached(); | ||
54 | @@ -XXX,XX +XXX,XX @@ void helper_hyp_store(CPURISCVState *env, target_ulong address, | ||
55 | (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) || | ||
56 | (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) && | ||
57 | get_field(env->hstatus, HSTATUS_HU))) { | ||
58 | + int mmu_idx = cpu_mmu_index(env, false) | TB_FLAGS_PRIV_HYP_ACCESS_MASK; | ||
59 | + | ||
60 | riscv_cpu_set_two_stage_lookup(env, true); | ||
61 | |||
62 | switch (memop) { | ||
63 | case MO_SB: | ||
64 | case MO_UB: | ||
65 | - cpu_stb_data_ra(env, address, val, GETPC()); | ||
66 | + cpu_stb_mmuidx_ra(env, address, val, mmu_idx, GETPC()); | ||
67 | break; | ||
68 | case MO_TESW: | ||
69 | case MO_TEUW: | ||
70 | - cpu_stw_data_ra(env, address, val, GETPC()); | ||
71 | + cpu_stw_mmuidx_ra(env, address, val, mmu_idx, GETPC()); | ||
72 | break; | ||
73 | case MO_TESL: | ||
74 | case MO_TEUL: | ||
75 | - cpu_stl_data_ra(env, address, val, GETPC()); | ||
76 | + cpu_stl_mmuidx_ra(env, address, val, mmu_idx, GETPC()); | ||
77 | break; | ||
78 | case MO_TEQ: | ||
79 | - cpu_stq_data_ra(env, address, val, GETPC()); | ||
80 | + cpu_stq_mmuidx_ra(env, address, val, mmu_idx, GETPC()); | ||
81 | break; | ||
82 | default: | ||
83 | g_assert_not_reached(); | ||
84 | @@ -XXX,XX +XXX,XX @@ target_ulong helper_hyp_x_load(CPURISCVState *env, target_ulong address, | ||
85 | (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) && | ||
86 | get_field(env->hstatus, HSTATUS_HU))) { | ||
87 | target_ulong pte; | ||
88 | + int mmu_idx = cpu_mmu_index(env, false) | TB_FLAGS_PRIV_HYP_ACCESS_MASK; | ||
89 | |||
90 | riscv_cpu_set_two_stage_lookup(env, true); | ||
91 | |||
92 | switch (memop) { | ||
93 | case MO_TEUW: | ||
94 | - pte = cpu_lduw_data_ra(env, address, GETPC()); | ||
95 | + pte = cpu_lduw_mmuidx_ra(env, address, mmu_idx, GETPC()); | ||
96 | break; | ||
97 | case MO_TEUL: | ||
98 | - pte = cpu_ldl_data_ra(env, address, GETPC()); | ||
99 | + pte = cpu_ldl_mmuidx_ra(env, address, mmu_idx, GETPC()); | ||
100 | break; | ||
101 | default: | ||
102 | g_assert_not_reached(); | ||
103 | -- | ||
104 | 2.29.2 | ||
105 | |||
106 | diff view generated by jsdifflib |
1 | Remove the special Virtulisation load and store functions and just use | 1 | From: Thomas Huth <thuth@redhat.com> |
---|---|---|---|
2 | the standard tcg tcg_gen_qemu_ld_tl() and tcg_gen_qemu_st_tl() functions | ||
3 | instead. | ||
4 | 2 | ||
5 | As part of this change we ensure we still run an access check to make | 3 | Configuring a drive with "if=none" is meant for creation of a backend |
6 | sure we can perform the operations. | 4 | only, it should not get automatically assigned to a device frontend. |
5 | Use "if=pflash" for the One-Time-Programmable device instead (like | ||
6 | it is e.g. also done for the efuse device in hw/arm/xlnx-zcu102.c). | ||
7 | 7 | ||
8 | Since the old way of configuring the device has already been published | ||
9 | with the previous QEMU versions, we cannot remove this immediately, but | ||
10 | have to deprecate it and support it for at least two more releases. | ||
11 | |||
12 | Signed-off-by: Thomas Huth <thuth@redhat.com> | ||
13 | Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
14 | Reviewed-by: Markus Armbruster <armbru@redhat.com> | ||
15 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> | ||
16 | Message-id: 20211119102549.217755-1-thuth@redhat.com | ||
8 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> | 17 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> |
9 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
10 | Message-id: 189ac3e53ef2854824d18aad7074c6649f17de2c.1604464950.git.alistair.francis@wdc.com | ||
11 | --- | 18 | --- |
12 | target/riscv/cpu.h | 12 +++ | 19 | docs/about/deprecated.rst | 6 ++++++ |
13 | target/riscv/helper.h | 2 - | 20 | hw/misc/sifive_u_otp.c | 9 ++++++++- |
14 | target/riscv/op_helper.c | 86 ----------------- | 21 | 2 files changed, 14 insertions(+), 1 deletion(-) |
15 | target/riscv/translate.c | 2 + | ||
16 | target/riscv/insn_trans/trans_rvh.c.inc | 123 +++++++++--------------- | ||
17 | 5 files changed, 59 insertions(+), 166 deletions(-) | ||
18 | 22 | ||
19 | diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h | 23 | diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst |
20 | index XXXXXXX..XXXXXXX 100644 | 24 | index XXXXXXX..XXXXXXX 100644 |
21 | --- a/target/riscv/cpu.h | 25 | --- a/docs/about/deprecated.rst |
22 | +++ b/target/riscv/cpu.h | 26 | +++ b/docs/about/deprecated.rst |
23 | @@ -XXX,XX +XXX,XX @@ FIELD(TB_FLAGS, VL_EQ_VLMAX, 2, 1) | 27 | @@ -XXX,XX +XXX,XX @@ as short-form boolean values, and passed to plugins as ``arg_name=on``. |
24 | FIELD(TB_FLAGS, LMUL, 3, 2) | 28 | However, short-form booleans are deprecated and full explicit ``arg_name=on`` |
25 | FIELD(TB_FLAGS, SEW, 5, 3) | 29 | form is preferred. |
26 | FIELD(TB_FLAGS, VILL, 8, 1) | 30 | |
27 | +/* Is a Hypervisor instruction load/store allowed? */ | 31 | +``-drive if=none`` for the sifive_u OTP device (since 6.2) |
28 | +FIELD(TB_FLAGS, HLSX, 9, 1) | 32 | +'''''''''''''''''''''''''''''''''''''''''''''''''''''''''' |
29 | |||
30 | /* | ||
31 | * A simplification for VLMAX | ||
32 | @@ -XXX,XX +XXX,XX @@ static inline void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc, | ||
33 | if (riscv_cpu_fp_enabled(env)) { | ||
34 | flags |= env->mstatus & MSTATUS_FS; | ||
35 | } | ||
36 | + | 33 | + |
37 | + if (riscv_has_ext(env, RVH)) { | 34 | +Using ``-drive if=none`` to configure the OTP device of the sifive_u |
38 | + if (env->priv == PRV_M || | 35 | +RISC-V machine is deprecated. Use ``-drive if=pflash`` instead. |
39 | + (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) || | 36 | + |
40 | + (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) && | 37 | |
41 | + get_field(env->hstatus, HSTATUS_HU))) { | 38 | QEMU Machine Protocol (QMP) commands |
42 | + flags = FIELD_DP32(flags, TB_FLAGS, HLSX, 1); | 39 | ------------------------------------ |
40 | diff --git a/hw/misc/sifive_u_otp.c b/hw/misc/sifive_u_otp.c | ||
41 | index XXXXXXX..XXXXXXX 100644 | ||
42 | --- a/hw/misc/sifive_u_otp.c | ||
43 | +++ b/hw/misc/sifive_u_otp.c | ||
44 | @@ -XXX,XX +XXX,XX @@ static void sifive_u_otp_realize(DeviceState *dev, Error **errp) | ||
45 | TYPE_SIFIVE_U_OTP, SIFIVE_U_OTP_REG_SIZE); | ||
46 | sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio); | ||
47 | |||
48 | - dinfo = drive_get_next(IF_NONE); | ||
49 | + dinfo = drive_get_next(IF_PFLASH); | ||
50 | + if (!dinfo) { | ||
51 | + dinfo = drive_get_next(IF_NONE); | ||
52 | + if (dinfo) { | ||
53 | + warn_report("using \"-drive if=none\" for the OTP is deprecated, " | ||
54 | + "use \"-drive if=pflash\" instead."); | ||
43 | + } | 55 | + } |
44 | + } | 56 | + } |
45 | #endif | 57 | if (dinfo) { |
46 | + | 58 | int ret; |
47 | *pflags = flags; | 59 | uint64_t perm; |
48 | } | ||
49 | |||
50 | diff --git a/target/riscv/helper.h b/target/riscv/helper.h | ||
51 | index XXXXXXX..XXXXXXX 100644 | ||
52 | --- a/target/riscv/helper.h | ||
53 | +++ b/target/riscv/helper.h | ||
54 | @@ -XXX,XX +XXX,XX @@ DEF_HELPER_1(tlb_flush, void, env) | ||
55 | #ifndef CONFIG_USER_ONLY | ||
56 | DEF_HELPER_1(hyp_tlb_flush, void, env) | ||
57 | DEF_HELPER_1(hyp_gvma_tlb_flush, void, env) | ||
58 | -DEF_HELPER_4(hyp_load, tl, env, tl, tl, tl) | ||
59 | -DEF_HELPER_5(hyp_store, void, env, tl, tl, tl, tl) | ||
60 | DEF_HELPER_4(hyp_x_load, tl, env, tl, tl, tl) | ||
61 | #endif | ||
62 | |||
63 | diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c | ||
64 | index XXXXXXX..XXXXXXX 100644 | ||
65 | --- a/target/riscv/op_helper.c | ||
66 | +++ b/target/riscv/op_helper.c | ||
67 | @@ -XXX,XX +XXX,XX @@ void helper_hyp_gvma_tlb_flush(CPURISCVState *env) | ||
68 | helper_hyp_tlb_flush(env); | ||
69 | } | ||
70 | |||
71 | -target_ulong helper_hyp_load(CPURISCVState *env, target_ulong address, | ||
72 | - target_ulong attrs, target_ulong memop) | ||
73 | -{ | ||
74 | - if (env->priv == PRV_M || | ||
75 | - (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) || | ||
76 | - (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) && | ||
77 | - get_field(env->hstatus, HSTATUS_HU))) { | ||
78 | - target_ulong pte; | ||
79 | - int mmu_idx = cpu_mmu_index(env, false) | TB_FLAGS_PRIV_HYP_ACCESS_MASK; | ||
80 | - | ||
81 | - switch (memop) { | ||
82 | - case MO_SB: | ||
83 | - pte = cpu_ldsb_mmuidx_ra(env, address, mmu_idx, GETPC()); | ||
84 | - break; | ||
85 | - case MO_UB: | ||
86 | - pte = cpu_ldub_mmuidx_ra(env, address, mmu_idx, GETPC()); | ||
87 | - break; | ||
88 | - case MO_TESW: | ||
89 | - pte = cpu_ldsw_mmuidx_ra(env, address, mmu_idx, GETPC()); | ||
90 | - break; | ||
91 | - case MO_TEUW: | ||
92 | - pte = cpu_lduw_mmuidx_ra(env, address, mmu_idx, GETPC()); | ||
93 | - break; | ||
94 | - case MO_TESL: | ||
95 | - pte = cpu_ldl_mmuidx_ra(env, address, mmu_idx, GETPC()); | ||
96 | - break; | ||
97 | - case MO_TEUL: | ||
98 | - pte = cpu_ldl_mmuidx_ra(env, address, mmu_idx, GETPC()); | ||
99 | - break; | ||
100 | - case MO_TEQ: | ||
101 | - pte = cpu_ldq_mmuidx_ra(env, address, mmu_idx, GETPC()); | ||
102 | - break; | ||
103 | - default: | ||
104 | - g_assert_not_reached(); | ||
105 | - } | ||
106 | - | ||
107 | - return pte; | ||
108 | - } | ||
109 | - | ||
110 | - if (riscv_cpu_virt_enabled(env)) { | ||
111 | - riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC()); | ||
112 | - } else { | ||
113 | - riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); | ||
114 | - } | ||
115 | - return 0; | ||
116 | -} | ||
117 | - | ||
118 | -void helper_hyp_store(CPURISCVState *env, target_ulong address, | ||
119 | - target_ulong val, target_ulong attrs, target_ulong memop) | ||
120 | -{ | ||
121 | - if (env->priv == PRV_M || | ||
122 | - (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) || | ||
123 | - (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) && | ||
124 | - get_field(env->hstatus, HSTATUS_HU))) { | ||
125 | - int mmu_idx = cpu_mmu_index(env, false) | TB_FLAGS_PRIV_HYP_ACCESS_MASK; | ||
126 | - | ||
127 | - switch (memop) { | ||
128 | - case MO_SB: | ||
129 | - case MO_UB: | ||
130 | - cpu_stb_mmuidx_ra(env, address, val, mmu_idx, GETPC()); | ||
131 | - break; | ||
132 | - case MO_TESW: | ||
133 | - case MO_TEUW: | ||
134 | - cpu_stw_mmuidx_ra(env, address, val, mmu_idx, GETPC()); | ||
135 | - break; | ||
136 | - case MO_TESL: | ||
137 | - case MO_TEUL: | ||
138 | - cpu_stl_mmuidx_ra(env, address, val, mmu_idx, GETPC()); | ||
139 | - break; | ||
140 | - case MO_TEQ: | ||
141 | - cpu_stq_mmuidx_ra(env, address, val, mmu_idx, GETPC()); | ||
142 | - break; | ||
143 | - default: | ||
144 | - g_assert_not_reached(); | ||
145 | - } | ||
146 | - | ||
147 | - return; | ||
148 | - } | ||
149 | - | ||
150 | - if (riscv_cpu_virt_enabled(env)) { | ||
151 | - riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC()); | ||
152 | - } else { | ||
153 | - riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); | ||
154 | - } | ||
155 | -} | ||
156 | - | ||
157 | target_ulong helper_hyp_x_load(CPURISCVState *env, target_ulong address, | ||
158 | target_ulong attrs, target_ulong memop) | ||
159 | { | ||
160 | diff --git a/target/riscv/translate.c b/target/riscv/translate.c | ||
161 | index XXXXXXX..XXXXXXX 100644 | ||
162 | --- a/target/riscv/translate.c | ||
163 | +++ b/target/riscv/translate.c | ||
164 | @@ -XXX,XX +XXX,XX @@ typedef struct DisasContext { | ||
165 | to reset this known value. */ | ||
166 | int frm; | ||
167 | bool ext_ifencei; | ||
168 | + bool hlsx; | ||
169 | /* vector extension */ | ||
170 | bool vill; | ||
171 | uint8_t lmul; | ||
172 | @@ -XXX,XX +XXX,XX @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) | ||
173 | ctx->frm = -1; /* unknown rounding mode */ | ||
174 | ctx->ext_ifencei = cpu->cfg.ext_ifencei; | ||
175 | ctx->vlen = cpu->cfg.vlen; | ||
176 | + ctx->hlsx = FIELD_EX32(tb_flags, TB_FLAGS, HLSX); | ||
177 | ctx->vill = FIELD_EX32(tb_flags, TB_FLAGS, VILL); | ||
178 | ctx->sew = FIELD_EX32(tb_flags, TB_FLAGS, SEW); | ||
179 | ctx->lmul = FIELD_EX32(tb_flags, TB_FLAGS, LMUL); | ||
180 | diff --git a/target/riscv/insn_trans/trans_rvh.c.inc b/target/riscv/insn_trans/trans_rvh.c.inc | ||
181 | index XXXXXXX..XXXXXXX 100644 | ||
182 | --- a/target/riscv/insn_trans/trans_rvh.c.inc | ||
183 | +++ b/target/riscv/insn_trans/trans_rvh.c.inc | ||
184 | @@ -XXX,XX +XXX,XX @@ | ||
185 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
186 | */ | ||
187 | |||
188 | +#ifndef CONFIG_USER_ONLY | ||
189 | +static void check_access(DisasContext *ctx) { | ||
190 | + if (!ctx->hlsx) { | ||
191 | + if (ctx->virt_enabled) { | ||
192 | + generate_exception(ctx, RISCV_EXCP_VIRT_INSTRUCTION_FAULT); | ||
193 | + } else { | ||
194 | + generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST); | ||
195 | + } | ||
196 | + } | ||
197 | +} | ||
198 | +#endif | ||
199 | + | ||
200 | static bool trans_hlv_b(DisasContext *ctx, arg_hlv_b *a) | ||
201 | { | ||
202 | REQUIRE_EXT(ctx, RVH); | ||
203 | #ifndef CONFIG_USER_ONLY | ||
204 | TCGv t0 = tcg_temp_new(); | ||
205 | TCGv t1 = tcg_temp_new(); | ||
206 | - TCGv mem_idx = tcg_temp_new(); | ||
207 | - TCGv memop = tcg_temp_new(); | ||
208 | + | ||
209 | + check_access(ctx); | ||
210 | |||
211 | gen_get_gpr(t0, a->rs1); | ||
212 | - tcg_gen_movi_tl(mem_idx, ctx->mem_idx); | ||
213 | - tcg_gen_movi_tl(memop, MO_SB); | ||
214 | |||
215 | - gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop); | ||
216 | + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_SB); | ||
217 | gen_set_gpr(a->rd, t1); | ||
218 | |||
219 | tcg_temp_free(t0); | ||
220 | tcg_temp_free(t1); | ||
221 | - tcg_temp_free(mem_idx); | ||
222 | - tcg_temp_free(memop); | ||
223 | return true; | ||
224 | #else | ||
225 | return false; | ||
226 | @@ -XXX,XX +XXX,XX @@ static bool trans_hlv_h(DisasContext *ctx, arg_hlv_h *a) | ||
227 | #ifndef CONFIG_USER_ONLY | ||
228 | TCGv t0 = tcg_temp_new(); | ||
229 | TCGv t1 = tcg_temp_new(); | ||
230 | - TCGv mem_idx = tcg_temp_new(); | ||
231 | - TCGv memop = tcg_temp_new(); | ||
232 | + | ||
233 | + check_access(ctx); | ||
234 | |||
235 | gen_get_gpr(t0, a->rs1); | ||
236 | - tcg_gen_movi_tl(mem_idx, ctx->mem_idx); | ||
237 | - tcg_gen_movi_tl(memop, MO_TESW); | ||
238 | |||
239 | - gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop); | ||
240 | + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TESW); | ||
241 | gen_set_gpr(a->rd, t1); | ||
242 | |||
243 | tcg_temp_free(t0); | ||
244 | tcg_temp_free(t1); | ||
245 | - tcg_temp_free(mem_idx); | ||
246 | - tcg_temp_free(memop); | ||
247 | return true; | ||
248 | #else | ||
249 | return false; | ||
250 | @@ -XXX,XX +XXX,XX @@ static bool trans_hlv_w(DisasContext *ctx, arg_hlv_w *a) | ||
251 | #ifndef CONFIG_USER_ONLY | ||
252 | TCGv t0 = tcg_temp_new(); | ||
253 | TCGv t1 = tcg_temp_new(); | ||
254 | - TCGv mem_idx = tcg_temp_new(); | ||
255 | - TCGv memop = tcg_temp_new(); | ||
256 | + | ||
257 | + check_access(ctx); | ||
258 | |||
259 | gen_get_gpr(t0, a->rs1); | ||
260 | - tcg_gen_movi_tl(mem_idx, ctx->mem_idx); | ||
261 | - tcg_gen_movi_tl(memop, MO_TESL); | ||
262 | |||
263 | - gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop); | ||
264 | + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TESL); | ||
265 | gen_set_gpr(a->rd, t1); | ||
266 | |||
267 | tcg_temp_free(t0); | ||
268 | tcg_temp_free(t1); | ||
269 | - tcg_temp_free(mem_idx); | ||
270 | - tcg_temp_free(memop); | ||
271 | return true; | ||
272 | #else | ||
273 | return false; | ||
274 | @@ -XXX,XX +XXX,XX @@ static bool trans_hlv_bu(DisasContext *ctx, arg_hlv_bu *a) | ||
275 | #ifndef CONFIG_USER_ONLY | ||
276 | TCGv t0 = tcg_temp_new(); | ||
277 | TCGv t1 = tcg_temp_new(); | ||
278 | - TCGv mem_idx = tcg_temp_new(); | ||
279 | - TCGv memop = tcg_temp_new(); | ||
280 | + | ||
281 | + check_access(ctx); | ||
282 | |||
283 | gen_get_gpr(t0, a->rs1); | ||
284 | - tcg_gen_movi_tl(mem_idx, ctx->mem_idx); | ||
285 | - tcg_gen_movi_tl(memop, MO_UB); | ||
286 | |||
287 | - gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop); | ||
288 | + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_UB); | ||
289 | gen_set_gpr(a->rd, t1); | ||
290 | |||
291 | tcg_temp_free(t0); | ||
292 | tcg_temp_free(t1); | ||
293 | - tcg_temp_free(mem_idx); | ||
294 | - tcg_temp_free(memop); | ||
295 | return true; | ||
296 | #else | ||
297 | return false; | ||
298 | @@ -XXX,XX +XXX,XX @@ static bool trans_hlv_hu(DisasContext *ctx, arg_hlv_hu *a) | ||
299 | #ifndef CONFIG_USER_ONLY | ||
300 | TCGv t0 = tcg_temp_new(); | ||
301 | TCGv t1 = tcg_temp_new(); | ||
302 | - TCGv mem_idx = tcg_temp_new(); | ||
303 | - TCGv memop = tcg_temp_new(); | ||
304 | |||
305 | - gen_get_gpr(t0, a->rs1); | ||
306 | - tcg_gen_movi_tl(mem_idx, ctx->mem_idx); | ||
307 | - tcg_gen_movi_tl(memop, MO_TEUW); | ||
308 | + check_access(ctx); | ||
309 | |||
310 | - gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop); | ||
311 | + gen_get_gpr(t0, a->rs1); | ||
312 | + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TEUW); | ||
313 | gen_set_gpr(a->rd, t1); | ||
314 | |||
315 | tcg_temp_free(t0); | ||
316 | tcg_temp_free(t1); | ||
317 | - tcg_temp_free(mem_idx); | ||
318 | - tcg_temp_free(memop); | ||
319 | return true; | ||
320 | #else | ||
321 | return false; | ||
322 | @@ -XXX,XX +XXX,XX @@ static bool trans_hsv_b(DisasContext *ctx, arg_hsv_b *a) | ||
323 | #ifndef CONFIG_USER_ONLY | ||
324 | TCGv t0 = tcg_temp_new(); | ||
325 | TCGv dat = tcg_temp_new(); | ||
326 | - TCGv mem_idx = tcg_temp_new(); | ||
327 | - TCGv memop = tcg_temp_new(); | ||
328 | + | ||
329 | + check_access(ctx); | ||
330 | |||
331 | gen_get_gpr(t0, a->rs1); | ||
332 | gen_get_gpr(dat, a->rs2); | ||
333 | - tcg_gen_movi_tl(mem_idx, ctx->mem_idx); | ||
334 | - tcg_gen_movi_tl(memop, MO_SB); | ||
335 | |||
336 | - gen_helper_hyp_store(cpu_env, t0, dat, mem_idx, memop); | ||
337 | + tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_SB); | ||
338 | |||
339 | tcg_temp_free(t0); | ||
340 | tcg_temp_free(dat); | ||
341 | - tcg_temp_free(mem_idx); | ||
342 | - tcg_temp_free(memop); | ||
343 | return true; | ||
344 | #else | ||
345 | return false; | ||
346 | @@ -XXX,XX +XXX,XX @@ static bool trans_hsv_h(DisasContext *ctx, arg_hsv_h *a) | ||
347 | #ifndef CONFIG_USER_ONLY | ||
348 | TCGv t0 = tcg_temp_new(); | ||
349 | TCGv dat = tcg_temp_new(); | ||
350 | - TCGv mem_idx = tcg_temp_new(); | ||
351 | - TCGv memop = tcg_temp_new(); | ||
352 | + | ||
353 | + check_access(ctx); | ||
354 | |||
355 | gen_get_gpr(t0, a->rs1); | ||
356 | gen_get_gpr(dat, a->rs2); | ||
357 | - tcg_gen_movi_tl(mem_idx, ctx->mem_idx); | ||
358 | - tcg_gen_movi_tl(memop, MO_TESW); | ||
359 | |||
360 | - gen_helper_hyp_store(cpu_env, t0, dat, mem_idx, memop); | ||
361 | + tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TESW); | ||
362 | |||
363 | tcg_temp_free(t0); | ||
364 | tcg_temp_free(dat); | ||
365 | - tcg_temp_free(mem_idx); | ||
366 | - tcg_temp_free(memop); | ||
367 | return true; | ||
368 | #else | ||
369 | return false; | ||
370 | @@ -XXX,XX +XXX,XX @@ static bool trans_hsv_w(DisasContext *ctx, arg_hsv_w *a) | ||
371 | #ifndef CONFIG_USER_ONLY | ||
372 | TCGv t0 = tcg_temp_new(); | ||
373 | TCGv dat = tcg_temp_new(); | ||
374 | - TCGv mem_idx = tcg_temp_new(); | ||
375 | - TCGv memop = tcg_temp_new(); | ||
376 | + | ||
377 | + check_access(ctx); | ||
378 | |||
379 | gen_get_gpr(t0, a->rs1); | ||
380 | gen_get_gpr(dat, a->rs2); | ||
381 | - tcg_gen_movi_tl(mem_idx, ctx->mem_idx); | ||
382 | - tcg_gen_movi_tl(memop, MO_TESL); | ||
383 | |||
384 | - gen_helper_hyp_store(cpu_env, t0, dat, mem_idx, memop); | ||
385 | + tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TESL); | ||
386 | |||
387 | tcg_temp_free(t0); | ||
388 | tcg_temp_free(dat); | ||
389 | - tcg_temp_free(mem_idx); | ||
390 | - tcg_temp_free(memop); | ||
391 | return true; | ||
392 | #else | ||
393 | return false; | ||
394 | @@ -XXX,XX +XXX,XX @@ static bool trans_hlv_wu(DisasContext *ctx, arg_hlv_wu *a) | ||
395 | #ifndef CONFIG_USER_ONLY | ||
396 | TCGv t0 = tcg_temp_new(); | ||
397 | TCGv t1 = tcg_temp_new(); | ||
398 | - TCGv mem_idx = tcg_temp_new(); | ||
399 | - TCGv memop = tcg_temp_new(); | ||
400 | + | ||
401 | + check_access(ctx); | ||
402 | |||
403 | gen_get_gpr(t0, a->rs1); | ||
404 | - tcg_gen_movi_tl(mem_idx, ctx->mem_idx); | ||
405 | - tcg_gen_movi_tl(memop, MO_TEUL); | ||
406 | |||
407 | - gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop); | ||
408 | + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TEUL); | ||
409 | gen_set_gpr(a->rd, t1); | ||
410 | |||
411 | tcg_temp_free(t0); | ||
412 | tcg_temp_free(t1); | ||
413 | - tcg_temp_free(mem_idx); | ||
414 | - tcg_temp_free(memop); | ||
415 | return true; | ||
416 | #else | ||
417 | return false; | ||
418 | @@ -XXX,XX +XXX,XX @@ static bool trans_hlv_d(DisasContext *ctx, arg_hlv_d *a) | ||
419 | #ifndef CONFIG_USER_ONLY | ||
420 | TCGv t0 = tcg_temp_new(); | ||
421 | TCGv t1 = tcg_temp_new(); | ||
422 | - TCGv mem_idx = tcg_temp_new(); | ||
423 | - TCGv memop = tcg_temp_new(); | ||
424 | + | ||
425 | + check_access(ctx); | ||
426 | |||
427 | gen_get_gpr(t0, a->rs1); | ||
428 | - tcg_gen_movi_tl(mem_idx, ctx->mem_idx); | ||
429 | - tcg_gen_movi_tl(memop, MO_TEQ); | ||
430 | |||
431 | - gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop); | ||
432 | + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TEQ); | ||
433 | gen_set_gpr(a->rd, t1); | ||
434 | |||
435 | tcg_temp_free(t0); | ||
436 | tcg_temp_free(t1); | ||
437 | - tcg_temp_free(mem_idx); | ||
438 | - tcg_temp_free(memop); | ||
439 | return true; | ||
440 | #else | ||
441 | return false; | ||
442 | @@ -XXX,XX +XXX,XX @@ static bool trans_hsv_d(DisasContext *ctx, arg_hsv_d *a) | ||
443 | #ifndef CONFIG_USER_ONLY | ||
444 | TCGv t0 = tcg_temp_new(); | ||
445 | TCGv dat = tcg_temp_new(); | ||
446 | - TCGv mem_idx = tcg_temp_new(); | ||
447 | - TCGv memop = tcg_temp_new(); | ||
448 | + | ||
449 | + check_access(ctx); | ||
450 | |||
451 | gen_get_gpr(t0, a->rs1); | ||
452 | gen_get_gpr(dat, a->rs2); | ||
453 | - tcg_gen_movi_tl(mem_idx, ctx->mem_idx); | ||
454 | - tcg_gen_movi_tl(memop, MO_TEQ); | ||
455 | |||
456 | - gen_helper_hyp_store(cpu_env, t0, dat, mem_idx, memop); | ||
457 | + tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TEQ); | ||
458 | |||
459 | tcg_temp_free(t0); | ||
460 | tcg_temp_free(dat); | ||
461 | - tcg_temp_free(mem_idx); | ||
462 | - tcg_temp_free(memop); | ||
463 | return true; | ||
464 | #else | ||
465 | return false; | ||
466 | -- | 60 | -- |
467 | 2.29.2 | 61 | 2.31.1 |
468 | 62 | ||
469 | 63 | diff view generated by jsdifflib |
1 | The HS_TWO_STAGE flag is no longer required as the MMU index contains | 1 | From: Philippe Mathieu-Daudé <f4bug@amsat.org> |
---|---|---|---|
2 | the information if we are performing a two stage access. | ||
3 | 2 | ||
3 | Once a "One Time Programmable" is programmed, it shouldn't be reset. | ||
4 | |||
5 | Do not re-initialize the OTP content in the DeviceReset handler, | ||
6 | initialize it once in the DeviceRealize one. | ||
7 | |||
8 | Fixes: 9fb45c62ae8 ("riscv: sifive: Implement a model for SiFive FU540 OTP") | ||
9 | Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
10 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> | ||
11 | Message-Id: <20211119104757.331579-1-f4bug@amsat.org> | ||
4 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> | 12 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> |
5 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
6 | Message-id: f514b128b1ff0fb41c85f914cee18f905007a922.1604464950.git.alistair.francis@wdc.com | ||
7 | --- | 13 | --- |
8 | target/riscv/cpu.h | 3 +- | 14 | hw/misc/sifive_u_otp.c | 13 +++++-------- |
9 | target/riscv/cpu_bits.h | 1 - | 15 | 1 file changed, 5 insertions(+), 8 deletions(-) |
10 | target/riscv/cpu_helper.c | 60 ++++++++++++++++----------------------- | ||
11 | target/riscv/op_helper.c | 12 -------- | ||
12 | 4 files changed, 25 insertions(+), 51 deletions(-) | ||
13 | 16 | ||
14 | diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h | 17 | diff --git a/hw/misc/sifive_u_otp.c b/hw/misc/sifive_u_otp.c |
15 | index XXXXXXX..XXXXXXX 100644 | 18 | index XXXXXXX..XXXXXXX 100644 |
16 | --- a/target/riscv/cpu.h | 19 | --- a/hw/misc/sifive_u_otp.c |
17 | +++ b/target/riscv/cpu.h | 20 | +++ b/hw/misc/sifive_u_otp.c |
18 | @@ -XXX,XX +XXX,XX @@ bool riscv_cpu_virt_enabled(CPURISCVState *env); | 21 | @@ -XXX,XX +XXX,XX @@ static void sifive_u_otp_realize(DeviceState *dev, Error **errp) |
19 | void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable); | 22 | |
20 | bool riscv_cpu_force_hs_excep_enabled(CPURISCVState *env); | 23 | if (blk_pread(s->blk, 0, s->fuse, filesize) != filesize) { |
21 | void riscv_cpu_set_force_hs_excep(CPURISCVState *env, bool enable); | 24 | error_setg(errp, "failed to read the initial flash content"); |
22 | -bool riscv_cpu_two_stage_lookup(CPURISCVState *env); | 25 | + return; |
23 | -void riscv_cpu_set_two_stage_lookup(CPURISCVState *env, bool enable); | 26 | } |
24 | +bool riscv_cpu_two_stage_lookup(int mmu_idx); | 27 | } |
25 | int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch); | 28 | } |
26 | hwaddr riscv_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); | ||
27 | void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr, | ||
28 | diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h | ||
29 | index XXXXXXX..XXXXXXX 100644 | ||
30 | --- a/target/riscv/cpu_bits.h | ||
31 | +++ b/target/riscv/cpu_bits.h | ||
32 | @@ -XXX,XX +XXX,XX @@ | ||
33 | * page table fault. | ||
34 | */ | ||
35 | #define FORCE_HS_EXCEP 2 | ||
36 | -#define HS_TWO_STAGE 4 | ||
37 | |||
38 | /* RV32 satp CSR field masks */ | ||
39 | #define SATP32_MODE 0x80000000 | ||
40 | diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c | ||
41 | index XXXXXXX..XXXXXXX 100644 | ||
42 | --- a/target/riscv/cpu_helper.c | ||
43 | +++ b/target/riscv/cpu_helper.c | ||
44 | @@ -XXX,XX +XXX,XX @@ void riscv_cpu_set_force_hs_excep(CPURISCVState *env, bool enable) | ||
45 | env->virt = set_field(env->virt, FORCE_HS_EXCEP, enable); | ||
46 | } | ||
47 | |||
48 | -bool riscv_cpu_two_stage_lookup(CPURISCVState *env) | ||
49 | +bool riscv_cpu_two_stage_lookup(int mmu_idx) | ||
50 | { | ||
51 | - if (!riscv_has_ext(env, RVH)) { | ||
52 | - return false; | ||
53 | - } | ||
54 | - | ||
55 | - return get_field(env->virt, HS_TWO_STAGE); | ||
56 | -} | 29 | -} |
57 | - | 30 | - |
58 | -void riscv_cpu_set_two_stage_lookup(CPURISCVState *env, bool enable) | 31 | -static void sifive_u_otp_reset(DeviceState *dev) |
59 | -{ | 32 | -{ |
60 | - if (!riscv_has_ext(env, RVH)) { | 33 | - SiFiveUOTPState *s = SIFIVE_U_OTP(dev); |
61 | - return; | 34 | |
62 | - } | 35 | /* Initialize all fuses' initial value to 0xFFs */ |
63 | - | 36 | memset(s->fuse, 0xff, sizeof(s->fuse)); |
64 | - env->virt = set_field(env->virt, HS_TWO_STAGE, enable); | 37 | @@ -XXX,XX +XXX,XX @@ static void sifive_u_otp_reset(DeviceState *dev) |
65 | + return mmu_idx & TB_FLAGS_PRIV_HYP_ACCESS_MASK; | 38 | serial_data = s->serial; |
39 | if (blk_pwrite(s->blk, index * SIFIVE_U_OTP_FUSE_WORD, | ||
40 | &serial_data, SIFIVE_U_OTP_FUSE_WORD, 0) < 0) { | ||
41 | - error_report("write error index<%d>", index); | ||
42 | + error_setg(errp, "failed to write index<%d>", index); | ||
43 | + return; | ||
44 | } | ||
45 | |||
46 | serial_data = ~(s->serial); | ||
47 | if (blk_pwrite(s->blk, (index + 1) * SIFIVE_U_OTP_FUSE_WORD, | ||
48 | &serial_data, SIFIVE_U_OTP_FUSE_WORD, 0) < 0) { | ||
49 | - error_report("write error index<%d>", index + 1); | ||
50 | + error_setg(errp, "failed to write index<%d>", index + 1); | ||
51 | + return; | ||
52 | } | ||
53 | } | ||
54 | |||
55 | @@ -XXX,XX +XXX,XX @@ static void sifive_u_otp_class_init(ObjectClass *klass, void *data) | ||
56 | |||
57 | device_class_set_props(dc, sifive_u_otp_properties); | ||
58 | dc->realize = sifive_u_otp_realize; | ||
59 | - dc->reset = sifive_u_otp_reset; | ||
66 | } | 60 | } |
67 | 61 | ||
68 | int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts) | 62 | static const TypeInfo sifive_u_otp_info = { |
69 | @@ -XXX,XX +XXX,XX @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical, | ||
70 | * was called. Background registers will be used if the guest has | ||
71 | * forced a two stage translation to be on (in HS or M mode). | ||
72 | */ | ||
73 | - if (riscv_cpu_two_stage_lookup(env) && access_type != MMU_INST_FETCH) { | ||
74 | + if (!riscv_cpu_virt_enabled(env) && riscv_cpu_two_stage_lookup(mmu_idx)) { | ||
75 | use_background = true; | ||
76 | } | ||
77 | |||
78 | @@ -XXX,XX +XXX,XX @@ restart: | ||
79 | |||
80 | static void raise_mmu_exception(CPURISCVState *env, target_ulong address, | ||
81 | MMUAccessType access_type, bool pmp_violation, | ||
82 | - bool first_stage) | ||
83 | + bool first_stage, bool two_stage) | ||
84 | { | ||
85 | CPUState *cs = env_cpu(env); | ||
86 | int page_fault_exceptions; | ||
87 | @@ -XXX,XX +XXX,XX @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address, | ||
88 | } | ||
89 | break; | ||
90 | case MMU_DATA_LOAD: | ||
91 | - if ((riscv_cpu_virt_enabled(env) || riscv_cpu_two_stage_lookup(env)) && | ||
92 | - !first_stage) { | ||
93 | + if (two_stage && !first_stage) { | ||
94 | cs->exception_index = RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT; | ||
95 | } else { | ||
96 | cs->exception_index = page_fault_exceptions ? | ||
97 | @@ -XXX,XX +XXX,XX @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address, | ||
98 | } | ||
99 | break; | ||
100 | case MMU_DATA_STORE: | ||
101 | - if ((riscv_cpu_virt_enabled(env) || riscv_cpu_two_stage_lookup(env)) && | ||
102 | - !first_stage) { | ||
103 | + if (two_stage && !first_stage) { | ||
104 | cs->exception_index = RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT; | ||
105 | } else { | ||
106 | cs->exception_index = page_fault_exceptions ? | ||
107 | @@ -XXX,XX +XXX,XX @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, | ||
108 | int prot, prot2; | ||
109 | bool pmp_violation = false; | ||
110 | bool first_stage_error = true; | ||
111 | + bool two_stage_lookup = false; | ||
112 | int ret = TRANSLATE_FAIL; | ||
113 | int mode = mmu_idx; | ||
114 | target_ulong tlb_size = 0; | ||
115 | @@ -XXX,XX +XXX,XX @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, | ||
116 | access_type != MMU_INST_FETCH && | ||
117 | get_field(env->mstatus, MSTATUS_MPRV) && | ||
118 | get_field(env->mstatus, MSTATUS_MPV)) { | ||
119 | - riscv_cpu_set_two_stage_lookup(env, true); | ||
120 | + two_stage_lookup = true; | ||
121 | } | ||
122 | |||
123 | if (riscv_cpu_virt_enabled(env) || | ||
124 | - (riscv_cpu_two_stage_lookup(env) && access_type != MMU_INST_FETCH)) { | ||
125 | + ((riscv_cpu_two_stage_lookup(mmu_idx) || two_stage_lookup) && | ||
126 | + access_type != MMU_INST_FETCH)) { | ||
127 | /* Two stage lookup */ | ||
128 | ret = get_physical_address(env, &pa, &prot, address, | ||
129 | &env->guest_phys_fault_addr, access_type, | ||
130 | @@ -XXX,XX +XXX,XX @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, | ||
131 | __func__, address, ret, pa, prot); | ||
132 | } | ||
133 | |||
134 | - /* We did the two stage lookup based on MPRV, unset the lookup */ | ||
135 | - if (riscv_has_ext(env, RVH) && env->priv == PRV_M && | ||
136 | - access_type != MMU_INST_FETCH && | ||
137 | - get_field(env->mstatus, MSTATUS_MPRV) && | ||
138 | - get_field(env->mstatus, MSTATUS_MPV)) { | ||
139 | - riscv_cpu_set_two_stage_lookup(env, false); | ||
140 | - } | ||
141 | - | ||
142 | if (riscv_feature(env, RISCV_FEATURE_PMP) && | ||
143 | (ret == TRANSLATE_SUCCESS) && | ||
144 | !pmp_hart_has_privs(env, pa, size, 1 << access_type, mode)) { | ||
145 | @@ -XXX,XX +XXX,XX @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, | ||
146 | } else if (probe) { | ||
147 | return false; | ||
148 | } else { | ||
149 | - raise_mmu_exception(env, address, access_type, pmp_violation, first_stage_error); | ||
150 | + raise_mmu_exception(env, address, access_type, pmp_violation, | ||
151 | + first_stage_error, | ||
152 | + riscv_cpu_virt_enabled(env) || | ||
153 | + riscv_cpu_two_stage_lookup(mmu_idx)); | ||
154 | riscv_raise_exception(env, cs->exception_index, retaddr); | ||
155 | } | ||
156 | |||
157 | @@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_interrupt(CPUState *cs) | ||
158 | /* handle the trap in S-mode */ | ||
159 | if (riscv_has_ext(env, RVH)) { | ||
160 | target_ulong hdeleg = async ? env->hideleg : env->hedeleg; | ||
161 | + bool two_stage_lookup = false; | ||
162 | + | ||
163 | + if (env->priv == PRV_M || | ||
164 | + (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) || | ||
165 | + (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) && | ||
166 | + get_field(env->hstatus, HSTATUS_HU))) { | ||
167 | + two_stage_lookup = true; | ||
168 | + } | ||
169 | |||
170 | - if ((riscv_cpu_virt_enabled(env) || | ||
171 | - riscv_cpu_two_stage_lookup(env)) && write_tval) { | ||
172 | + if ((riscv_cpu_virt_enabled(env) || two_stage_lookup) && write_tval) { | ||
173 | /* | ||
174 | * If we are writing a guest virtual address to stval, set | ||
175 | * this to 1. If we are trapping to VS we will set this to 0 | ||
176 | @@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_interrupt(CPUState *cs) | ||
177 | riscv_cpu_set_force_hs_excep(env, 0); | ||
178 | } else { | ||
179 | /* Trap into HS mode */ | ||
180 | - if (!riscv_cpu_two_stage_lookup(env)) { | ||
181 | + if (!two_stage_lookup) { | ||
182 | env->hstatus = set_field(env->hstatus, HSTATUS_SPV, | ||
183 | riscv_cpu_virt_enabled(env)); | ||
184 | } | ||
185 | - riscv_cpu_set_two_stage_lookup(env, false); | ||
186 | htval = env->guest_phys_fault_addr; | ||
187 | } | ||
188 | } | ||
189 | diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c | ||
190 | index XXXXXXX..XXXXXXX 100644 | ||
191 | --- a/target/riscv/op_helper.c | ||
192 | +++ b/target/riscv/op_helper.c | ||
193 | @@ -XXX,XX +XXX,XX @@ target_ulong helper_hyp_load(CPURISCVState *env, target_ulong address, | ||
194 | target_ulong pte; | ||
195 | int mmu_idx = cpu_mmu_index(env, false) | TB_FLAGS_PRIV_HYP_ACCESS_MASK; | ||
196 | |||
197 | - riscv_cpu_set_two_stage_lookup(env, true); | ||
198 | - | ||
199 | switch (memop) { | ||
200 | case MO_SB: | ||
201 | pte = cpu_ldsb_mmuidx_ra(env, address, mmu_idx, GETPC()); | ||
202 | @@ -XXX,XX +XXX,XX @@ target_ulong helper_hyp_load(CPURISCVState *env, target_ulong address, | ||
203 | g_assert_not_reached(); | ||
204 | } | ||
205 | |||
206 | - riscv_cpu_set_two_stage_lookup(env, false); | ||
207 | - | ||
208 | return pte; | ||
209 | } | ||
210 | |||
211 | @@ -XXX,XX +XXX,XX @@ void helper_hyp_store(CPURISCVState *env, target_ulong address, | ||
212 | get_field(env->hstatus, HSTATUS_HU))) { | ||
213 | int mmu_idx = cpu_mmu_index(env, false) | TB_FLAGS_PRIV_HYP_ACCESS_MASK; | ||
214 | |||
215 | - riscv_cpu_set_two_stage_lookup(env, true); | ||
216 | - | ||
217 | switch (memop) { | ||
218 | case MO_SB: | ||
219 | case MO_UB: | ||
220 | @@ -XXX,XX +XXX,XX @@ void helper_hyp_store(CPURISCVState *env, target_ulong address, | ||
221 | g_assert_not_reached(); | ||
222 | } | ||
223 | |||
224 | - riscv_cpu_set_two_stage_lookup(env, false); | ||
225 | - | ||
226 | return; | ||
227 | } | ||
228 | |||
229 | @@ -XXX,XX +XXX,XX @@ target_ulong helper_hyp_x_load(CPURISCVState *env, target_ulong address, | ||
230 | target_ulong pte; | ||
231 | int mmu_idx = cpu_mmu_index(env, false) | TB_FLAGS_PRIV_HYP_ACCESS_MASK; | ||
232 | |||
233 | - riscv_cpu_set_two_stage_lookup(env, true); | ||
234 | - | ||
235 | switch (memop) { | ||
236 | case MO_TEUW: | ||
237 | pte = cpu_lduw_mmuidx_ra(env, address, mmu_idx, GETPC()); | ||
238 | @@ -XXX,XX +XXX,XX @@ target_ulong helper_hyp_x_load(CPURISCVState *env, target_ulong address, | ||
239 | g_assert_not_reached(); | ||
240 | } | ||
241 | |||
242 | - riscv_cpu_set_two_stage_lookup(env, false); | ||
243 | - | ||
244 | return pte; | ||
245 | } | ||
246 | |||
247 | -- | 63 | -- |
248 | 2.29.2 | 64 | 2.31.1 |
249 | 65 | ||
250 | 66 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | Split the hypervisor execute load functions into two seperate functions. | ||
2 | This avoids us having to pass the memop to the C helper functions. | ||
3 | 1 | ||
4 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> | ||
5 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
6 | Message-id: 5b1550f0faa3c435cc77f3c1ae811dea98ab9e36.1604464950.git.alistair.francis@wdc.com | ||
7 | --- | ||
8 | target/riscv/helper.h | 3 ++- | ||
9 | target/riscv/op_helper.c | 36 +++++++------------------ | ||
10 | target/riscv/insn_trans/trans_rvh.c.inc | 20 +++++--------- | ||
11 | 3 files changed, 17 insertions(+), 42 deletions(-) | ||
12 | |||
13 | diff --git a/target/riscv/helper.h b/target/riscv/helper.h | ||
14 | index XXXXXXX..XXXXXXX 100644 | ||
15 | --- a/target/riscv/helper.h | ||
16 | +++ b/target/riscv/helper.h | ||
17 | @@ -XXX,XX +XXX,XX @@ DEF_HELPER_1(tlb_flush, void, env) | ||
18 | #ifndef CONFIG_USER_ONLY | ||
19 | DEF_HELPER_1(hyp_tlb_flush, void, env) | ||
20 | DEF_HELPER_1(hyp_gvma_tlb_flush, void, env) | ||
21 | -DEF_HELPER_4(hyp_x_load, tl, env, tl, tl, tl) | ||
22 | +DEF_HELPER_2(hyp_hlvx_hu, tl, env, tl) | ||
23 | +DEF_HELPER_2(hyp_hlvx_wu, tl, env, tl) | ||
24 | #endif | ||
25 | |||
26 | /* Vector functions */ | ||
27 | diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c | ||
28 | index XXXXXXX..XXXXXXX 100644 | ||
29 | --- a/target/riscv/op_helper.c | ||
30 | +++ b/target/riscv/op_helper.c | ||
31 | @@ -XXX,XX +XXX,XX @@ void helper_hyp_gvma_tlb_flush(CPURISCVState *env) | ||
32 | helper_hyp_tlb_flush(env); | ||
33 | } | ||
34 | |||
35 | -target_ulong helper_hyp_x_load(CPURISCVState *env, target_ulong address, | ||
36 | - target_ulong attrs, target_ulong memop) | ||
37 | +target_ulong helper_hyp_hlvx_hu(CPURISCVState *env, target_ulong address) | ||
38 | { | ||
39 | - if (env->priv == PRV_M || | ||
40 | - (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) || | ||
41 | - (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) && | ||
42 | - get_field(env->hstatus, HSTATUS_HU))) { | ||
43 | - target_ulong pte; | ||
44 | - int mmu_idx = cpu_mmu_index(env, false) | TB_FLAGS_PRIV_HYP_ACCESS_MASK; | ||
45 | - | ||
46 | - switch (memop) { | ||
47 | - case MO_TEUW: | ||
48 | - pte = cpu_lduw_mmuidx_ra(env, address, mmu_idx, GETPC()); | ||
49 | - break; | ||
50 | - case MO_TEUL: | ||
51 | - pte = cpu_ldl_mmuidx_ra(env, address, mmu_idx, GETPC()); | ||
52 | - break; | ||
53 | - default: | ||
54 | - g_assert_not_reached(); | ||
55 | - } | ||
56 | + int mmu_idx = cpu_mmu_index(env, true) | TB_FLAGS_PRIV_HYP_ACCESS_MASK; | ||
57 | |||
58 | - return pte; | ||
59 | - } | ||
60 | + return cpu_lduw_mmuidx_ra(env, address, mmu_idx, GETPC()); | ||
61 | +} | ||
62 | |||
63 | - if (riscv_cpu_virt_enabled(env)) { | ||
64 | - riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC()); | ||
65 | - } else { | ||
66 | - riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); | ||
67 | - } | ||
68 | - return 0; | ||
69 | +target_ulong helper_hyp_hlvx_wu(CPURISCVState *env, target_ulong address) | ||
70 | +{ | ||
71 | + int mmu_idx = cpu_mmu_index(env, true) | TB_FLAGS_PRIV_HYP_ACCESS_MASK; | ||
72 | + | ||
73 | + return cpu_ldl_mmuidx_ra(env, address, mmu_idx, GETPC()); | ||
74 | } | ||
75 | |||
76 | #endif /* !CONFIG_USER_ONLY */ | ||
77 | diff --git a/target/riscv/insn_trans/trans_rvh.c.inc b/target/riscv/insn_trans/trans_rvh.c.inc | ||
78 | index XXXXXXX..XXXXXXX 100644 | ||
79 | --- a/target/riscv/insn_trans/trans_rvh.c.inc | ||
80 | +++ b/target/riscv/insn_trans/trans_rvh.c.inc | ||
81 | @@ -XXX,XX +XXX,XX @@ static bool trans_hlvx_hu(DisasContext *ctx, arg_hlvx_hu *a) | ||
82 | #ifndef CONFIG_USER_ONLY | ||
83 | TCGv t0 = tcg_temp_new(); | ||
84 | TCGv t1 = tcg_temp_new(); | ||
85 | - TCGv mem_idx = tcg_temp_new(); | ||
86 | - TCGv memop = tcg_temp_new(); | ||
87 | + | ||
88 | + check_access(ctx); | ||
89 | |||
90 | gen_get_gpr(t0, a->rs1); | ||
91 | - tcg_gen_movi_tl(mem_idx, ctx->mem_idx); | ||
92 | - tcg_gen_movi_tl(memop, MO_TEUW); | ||
93 | |||
94 | - gen_helper_hyp_x_load(t1, cpu_env, t0, mem_idx, memop); | ||
95 | + gen_helper_hyp_hlvx_hu(t1, cpu_env, t0); | ||
96 | gen_set_gpr(a->rd, t1); | ||
97 | |||
98 | tcg_temp_free(t0); | ||
99 | tcg_temp_free(t1); | ||
100 | - tcg_temp_free(mem_idx); | ||
101 | - tcg_temp_free(memop); | ||
102 | return true; | ||
103 | #else | ||
104 | return false; | ||
105 | @@ -XXX,XX +XXX,XX @@ static bool trans_hlvx_wu(DisasContext *ctx, arg_hlvx_wu *a) | ||
106 | #ifndef CONFIG_USER_ONLY | ||
107 | TCGv t0 = tcg_temp_new(); | ||
108 | TCGv t1 = tcg_temp_new(); | ||
109 | - TCGv mem_idx = tcg_temp_new(); | ||
110 | - TCGv memop = tcg_temp_new(); | ||
111 | + | ||
112 | + check_access(ctx); | ||
113 | |||
114 | gen_get_gpr(t0, a->rs1); | ||
115 | - tcg_gen_movi_tl(mem_idx, ctx->mem_idx); | ||
116 | - tcg_gen_movi_tl(memop, MO_TEUL); | ||
117 | |||
118 | - gen_helper_hyp_x_load(t1, cpu_env, t0, mem_idx, memop); | ||
119 | + gen_helper_hyp_hlvx_wu(t1, cpu_env, t0); | ||
120 | gen_set_gpr(a->rd, t1); | ||
121 | |||
122 | tcg_temp_free(t0); | ||
123 | tcg_temp_free(t1); | ||
124 | - tcg_temp_free(mem_idx); | ||
125 | - tcg_temp_free(memop); | ||
126 | return true; | ||
127 | #else | ||
128 | return false; | ||
129 | -- | ||
130 | 2.29.2 | ||
131 | |||
132 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | After claiming the interrupt by reading the claim register we want to | ||
2 | clear the register to make sure the interrupt doesn't appear at the next | ||
3 | read. | ||
4 | 1 | ||
5 | This matches the documentation for the claim register as when an interrupt | ||
6 | is claimed by a target the relevant bit of IP is cleared (which we already | ||
7 | do): https://docs.opentitan.org/hw/ip/rv_plic/doc/index.html | ||
8 | |||
9 | This also matches the current hardware. | ||
10 | |||
11 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> | ||
12 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
13 | Message-id: 68d4575deef2559b7a747f3bda193fcf43af4558.1604629928.git.alistair.francis@wdc.com | ||
14 | --- | ||
15 | hw/intc/ibex_plic.c | 3 +++ | ||
16 | 1 file changed, 3 insertions(+) | ||
17 | |||
18 | diff --git a/hw/intc/ibex_plic.c b/hw/intc/ibex_plic.c | ||
19 | index XXXXXXX..XXXXXXX 100644 | ||
20 | --- a/hw/intc/ibex_plic.c | ||
21 | +++ b/hw/intc/ibex_plic.c | ||
22 | @@ -XXX,XX +XXX,XX @@ static uint64_t ibex_plic_read(void *opaque, hwaddr addr, | ||
23 | /* Return the current claimed interrupt */ | ||
24 | ret = s->claim; | ||
25 | |||
26 | + /* Clear the claimed interrupt */ | ||
27 | + s->claim = 0x00000000; | ||
28 | + | ||
29 | /* Update the interrupt status after the claim */ | ||
30 | ibex_plic_update(s); | ||
31 | } | ||
32 | -- | ||
33 | 2.29.2 | ||
34 | |||
35 | diff view generated by jsdifflib |