1 | The following changes since commit 4c5b97bfd0dd54dc27717ae8d1cd10e14eef1430: | 1 | From: Alistair Francis <alistair.francis@wdc.com> |
---|---|---|---|
2 | 2 | ||
3 | Merge remote-tracking branch 'remotes/kraxel/tags/modules-20201022-pull-request' into staging (2020-10-22 12:33:21 +0100) | 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-20201023 | 9 | git@github.com:alistair23/qemu.git tags/pull-riscv-to-apply-20211122 |
8 | 10 | ||
9 | for you to fetch changes up to 51b6c1bbc3dd1b139a9e9b021d87bcfd7d82299e: | 11 | for you to fetch changes up to 526e7443027c71fe7b04c29df529e1f9f425f9e3: |
10 | 12 | ||
11 | hw/misc/sifive_u_otp: Add backend drive support (2020-10-22 12:00:50 -0700) | 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 | A collection of RISC-V fixes for the next QEMU release. | 16 | Seventh RISC-V PR for QEMU 6.2 |
15 | 17 | ||
16 | This includes: | 18 | - Deprecate IF_NONE for SiFive OTP |
17 | - Improvements to logging output | 19 | - Don't reset SiFive OTP content |
18 | - Hypervisor instruction fixups | ||
19 | - The ability to load a noMMU kernel | ||
20 | - SiFive OTP support | ||
21 | 20 | ||
22 | ---------------------------------------------------------------- | 21 | ---------------------------------------------------------------- |
23 | Alistair Francis (5): | 22 | Philippe Mathieu-Daudé (1): |
24 | riscv: Convert interrupt logs to use qemu_log_mask() | 23 | hw/misc/sifive_u_otp: Do not reset OTP content on hardware reset |
25 | hw/riscv: sifive_u: Allow specifying the CPU | ||
26 | hw/riscv: Return the end address of the loaded firmware | ||
27 | hw/riscv: Add a riscv_is_32_bit() function | ||
28 | hw/riscv: Load the kernel after the firmware | ||
29 | 24 | ||
30 | Bin Meng (1): | 25 | Thomas Huth (1): |
31 | hw/intc: Move sifive_plic.h to the include directory | 26 | hw/misc/sifive_u_otp: Use IF_PFLASH for the OTP device instead of IF_NONE |
32 | 27 | ||
33 | Georg Kotheimer (3): | 28 | docs/about/deprecated.rst | 6 ++++++ |
34 | target/riscv: Fix update of hstatus.SPVP | 29 | hw/misc/sifive_u_otp.c | 22 +++++++++++++--------- |
35 | target/riscv: Fix update of hstatus.GVA in riscv_cpu_do_interrupt | 30 | 2 files changed, 19 insertions(+), 9 deletions(-) |
36 | target/riscv: Fix implementation of HLVX.WU instruction | ||
37 | 31 | ||
38 | Green Wan (2): | ||
39 | hw/misc/sifive_u_otp: Add write function and write-once protection | ||
40 | hw/misc/sifive_u_otp: Add backend drive support | ||
41 | |||
42 | Yifei Jiang (1): | ||
43 | target/riscv: raise exception to HS-mode at get_physical_address | ||
44 | |||
45 | {hw => include/hw}/intc/sifive_plic.h | 0 | ||
46 | include/hw/misc/sifive_u_otp.h | 5 ++ | ||
47 | include/hw/riscv/boot.h | 13 +++-- | ||
48 | include/hw/riscv/sifive_u.h | 1 + | ||
49 | target/riscv/cpu.h | 10 ++-- | ||
50 | hw/misc/sifive_u_otp.c | 95 ++++++++++++++++++++++++++++++++++- | ||
51 | hw/riscv/boot.c | 56 +++++++++++++++------ | ||
52 | hw/riscv/opentitan.c | 3 +- | ||
53 | hw/riscv/sifive_e.c | 3 +- | ||
54 | hw/riscv/sifive_u.c | 28 ++++++++--- | ||
55 | hw/riscv/spike.c | 11 ++-- | ||
56 | hw/riscv/virt.c | 11 ++-- | ||
57 | target/riscv/cpu_helper.c | 50 +++++++++++++----- | ||
58 | target/riscv/op_helper.c | 7 ++- | ||
59 | 14 files changed, 238 insertions(+), 55 deletions(-) | ||
60 | rename {hw => include/hw}/intc/sifive_plic.h (100%) | ||
61 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | Currently we log interrupts and exceptions using the trace backend in | ||
2 | riscv_cpu_do_interrupt(). We also log exceptions using the interrupt log | ||
3 | mask (-d int) in riscv_raise_exception(). | ||
4 | 1 | ||
5 | This patch converts riscv_cpu_do_interrupt() to log both interrupts and | ||
6 | exceptions with the interrupt log mask, so that both are printed when a | ||
7 | user runs QEMU with -d int. | ||
8 | |||
9 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> | ||
10 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
11 | Message-id: 29a8c766c7c4748d0f2711c3a0abb81208138c5e.1601652179.git.alistair.francis@wdc.com | ||
12 | --- | ||
13 | target/riscv/cpu_helper.c | 8 +++++++- | ||
14 | target/riscv/op_helper.c | 1 - | ||
15 | 2 files changed, 7 insertions(+), 2 deletions(-) | ||
16 | |||
17 | diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c | ||
18 | index XXXXXXX..XXXXXXX 100644 | ||
19 | --- a/target/riscv/cpu_helper.c | ||
20 | +++ b/target/riscv/cpu_helper.c | ||
21 | @@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_interrupt(CPUState *cs) | ||
22 | } | ||
23 | |||
24 | trace_riscv_trap(env->mhartid, async, cause, env->pc, tval, | ||
25 | - riscv_cpu_get_trap_name(cause, async)); | ||
26 | + riscv_cpu_get_trap_name(cause, async)); | ||
27 | + | ||
28 | + qemu_log_mask(CPU_LOG_INT, | ||
29 | + "%s: hart:"TARGET_FMT_ld", async:%d, cause:"TARGET_FMT_lx", " | ||
30 | + "epc:0x"TARGET_FMT_lx", tval:0x"TARGET_FMT_lx", desc=%s\n", | ||
31 | + __func__, env->mhartid, async, cause, env->pc, tval, | ||
32 | + riscv_cpu_get_trap_name(cause, async)); | ||
33 | |||
34 | if (env->priv <= PRV_S && | ||
35 | cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) { | ||
36 | diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c | ||
37 | index XXXXXXX..XXXXXXX 100644 | ||
38 | --- a/target/riscv/op_helper.c | ||
39 | +++ b/target/riscv/op_helper.c | ||
40 | @@ -XXX,XX +XXX,XX @@ void QEMU_NORETURN riscv_raise_exception(CPURISCVState *env, | ||
41 | uint32_t exception, uintptr_t pc) | ||
42 | { | ||
43 | CPUState *cs = env_cpu(env); | ||
44 | - qemu_log_mask(CPU_LOG_INT, "%s: %d\n", __func__, exception); | ||
45 | cs->exception_index = exception; | ||
46 | cpu_loop_exit_restore(cs, pc); | ||
47 | } | ||
48 | -- | ||
49 | 2.28.0 | ||
50 | |||
51 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Georg Kotheimer <georg.kotheimer@kernkonzept.com> | ||
2 | 1 | ||
3 | When trapping from virt into HS mode, hstatus.SPVP was set to | ||
4 | the value of sstatus.SPP, as according to the specification both | ||
5 | flags should be set to the same value. | ||
6 | However, the assignment of SPVP takes place before SPP itself is | ||
7 | updated, which results in SPVP having an outdated value. | ||
8 | |||
9 | Signed-off-by: Georg Kotheimer <georg.kotheimer@kernkonzept.com> | ||
10 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> | ||
11 | Message-id: 20201013151054.396481-1-georg.kotheimer@kernkonzept.com | ||
12 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> | ||
13 | --- | ||
14 | target/riscv/cpu_helper.c | 2 +- | ||
15 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
16 | |||
17 | diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c | ||
18 | index XXXXXXX..XXXXXXX 100644 | ||
19 | --- a/target/riscv/cpu_helper.c | ||
20 | +++ b/target/riscv/cpu_helper.c | ||
21 | @@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_interrupt(CPUState *cs) | ||
22 | /* Trap into HS mode, from virt */ | ||
23 | riscv_cpu_swap_hypervisor_regs(env); | ||
24 | env->hstatus = set_field(env->hstatus, HSTATUS_SPVP, | ||
25 | - get_field(env->mstatus, SSTATUS_SPP)); | ||
26 | + env->priv); | ||
27 | env->hstatus = set_field(env->hstatus, HSTATUS_SPV, | ||
28 | riscv_cpu_virt_enabled(env)); | ||
29 | |||
30 | -- | ||
31 | 2.28.0 | ||
32 | |||
33 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Georg Kotheimer <georg.kotheimer@kernkonzept.com> | ||
2 | 1 | ||
3 | The hstatus.GVA bit was not set if the faulting guest virtual address | ||
4 | was zero. | ||
5 | |||
6 | Signed-off-by: Georg Kotheimer <georg.kotheimer@kernkonzept.com> | ||
7 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> | ||
8 | Message-id: 20201013173054.451135-1-georg.kotheimer@kernkonzept.com | ||
9 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> | ||
10 | --- | ||
11 | target/riscv/cpu_helper.c | 4 +++- | ||
12 | 1 file changed, 3 insertions(+), 1 deletion(-) | ||
13 | |||
14 | diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c | ||
15 | index XXXXXXX..XXXXXXX 100644 | ||
16 | --- a/target/riscv/cpu_helper.c | ||
17 | +++ b/target/riscv/cpu_helper.c | ||
18 | @@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_interrupt(CPUState *cs) | ||
19 | bool async = !!(cs->exception_index & RISCV_EXCP_INT_FLAG); | ||
20 | target_ulong cause = cs->exception_index & RISCV_EXCP_INT_MASK; | ||
21 | target_ulong deleg = async ? env->mideleg : env->medeleg; | ||
22 | + bool write_tval = false; | ||
23 | target_ulong tval = 0; | ||
24 | target_ulong htval = 0; | ||
25 | target_ulong mtval2 = 0; | ||
26 | @@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_interrupt(CPUState *cs) | ||
27 | case RISCV_EXCP_INST_PAGE_FAULT: | ||
28 | case RISCV_EXCP_LOAD_PAGE_FAULT: | ||
29 | case RISCV_EXCP_STORE_PAGE_FAULT: | ||
30 | + write_tval = true; | ||
31 | tval = env->badaddr; | ||
32 | break; | ||
33 | default: | ||
34 | @@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_interrupt(CPUState *cs) | ||
35 | target_ulong hdeleg = async ? env->hideleg : env->hedeleg; | ||
36 | |||
37 | if ((riscv_cpu_virt_enabled(env) || | ||
38 | - riscv_cpu_two_stage_lookup(env)) && tval) { | ||
39 | + riscv_cpu_two_stage_lookup(env)) && write_tval) { | ||
40 | /* | ||
41 | * If we are writing a guest virtual address to stval, set | ||
42 | * this to 1. If we are trapping to VS we will set this to 0 | ||
43 | -- | ||
44 | 2.28.0 | ||
45 | |||
46 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Georg Kotheimer <georg.kotheimer@kernkonzept.com> | ||
2 | 1 | ||
3 | The HLVX.WU instruction is supposed to read a machine word, | ||
4 | but prior to this change it read a byte instead. | ||
5 | |||
6 | Fixes: 8c5362acb57 ("target/riscv: Allow generating hlv/hlvx/hsv instructions") | ||
7 | Signed-off-by: Georg Kotheimer <georg.kotheimer@kernkonzept.com> | ||
8 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
9 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> | ||
10 | Message-id: 20201013172223.443645-1-georg.kotheimer@kernkonzept.com | ||
11 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> | ||
12 | --- | ||
13 | target/riscv/op_helper.c | 6 +++--- | ||
14 | 1 file changed, 3 insertions(+), 3 deletions(-) | ||
15 | |||
16 | diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c | ||
17 | index XXXXXXX..XXXXXXX 100644 | ||
18 | --- a/target/riscv/op_helper.c | ||
19 | +++ b/target/riscv/op_helper.c | ||
20 | @@ -XXX,XX +XXX,XX @@ target_ulong helper_hyp_x_load(CPURISCVState *env, target_ulong address, | ||
21 | riscv_cpu_set_two_stage_lookup(env, true); | ||
22 | |||
23 | switch (memop) { | ||
24 | - case MO_TEUL: | ||
25 | - pte = cpu_ldub_data_ra(env, address, GETPC()); | ||
26 | - break; | ||
27 | case MO_TEUW: | ||
28 | pte = cpu_lduw_data_ra(env, address, GETPC()); | ||
29 | break; | ||
30 | + case MO_TEUL: | ||
31 | + pte = cpu_ldl_data_ra(env, address, GETPC()); | ||
32 | + break; | ||
33 | default: | ||
34 | g_assert_not_reached(); | ||
35 | } | ||
36 | -- | ||
37 | 2.28.0 | ||
38 | |||
39 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | Allow the user to specify the main application CPU for the sifive_u | ||
2 | machine. | ||
3 | 1 | ||
4 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> | ||
5 | Reviewed-by: Bin Meng <bin.meng@windriver.com> | ||
6 | Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com> | ||
7 | Tested-by: Bin Meng <bin.meng@windriver.com> | ||
8 | Message-id: b8412086c8aea0eff30fb7a17f0acf2943381b6a.1602634524.git.alistair.francis@wdc.com | ||
9 | --- | ||
10 | include/hw/riscv/sifive_u.h | 1 + | ||
11 | hw/riscv/sifive_u.c | 18 +++++++++++++----- | ||
12 | 2 files changed, 14 insertions(+), 5 deletions(-) | ||
13 | |||
14 | diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h | ||
15 | index XXXXXXX..XXXXXXX 100644 | ||
16 | --- a/include/hw/riscv/sifive_u.h | ||
17 | +++ b/include/hw/riscv/sifive_u.h | ||
18 | @@ -XXX,XX +XXX,XX @@ typedef struct SiFiveUSoCState { | ||
19 | CadenceGEMState gem; | ||
20 | |||
21 | uint32_t serial; | ||
22 | + char *cpu_type; | ||
23 | } SiFiveUSoCState; | ||
24 | |||
25 | #define TYPE_RISCV_U_MACHINE MACHINE_TYPE_NAME("sifive_u") | ||
26 | diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c | ||
27 | index XXXXXXX..XXXXXXX 100644 | ||
28 | --- a/hw/riscv/sifive_u.c | ||
29 | +++ b/hw/riscv/sifive_u.c | ||
30 | @@ -XXX,XX +XXX,XX @@ static void sifive_u_machine_init(MachineState *machine) | ||
31 | object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_RISCV_U_SOC); | ||
32 | object_property_set_uint(OBJECT(&s->soc), "serial", s->serial, | ||
33 | &error_abort); | ||
34 | + object_property_set_str(OBJECT(&s->soc), "cpu-type", machine->cpu_type, | ||
35 | + &error_abort); | ||
36 | qdev_realize(DEVICE(&s->soc), NULL, &error_abort); | ||
37 | |||
38 | /* register RAM */ | ||
39 | @@ -XXX,XX +XXX,XX @@ static void sifive_u_machine_class_init(ObjectClass *oc, void *data) | ||
40 | mc->init = sifive_u_machine_init; | ||
41 | mc->max_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + SIFIVE_U_COMPUTE_CPU_COUNT; | ||
42 | mc->min_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + 1; | ||
43 | +#if defined(TARGET_RISCV32) | ||
44 | + mc->default_cpu_type = TYPE_RISCV_CPU_SIFIVE_U34; | ||
45 | +#elif defined(TARGET_RISCV64) | ||
46 | + mc->default_cpu_type = TYPE_RISCV_CPU_SIFIVE_U54; | ||
47 | +#endif | ||
48 | mc->default_cpus = mc->min_cpus; | ||
49 | |||
50 | object_class_property_add_bool(oc, "start-in-flash", | ||
51 | @@ -XXX,XX +XXX,XX @@ type_init(sifive_u_machine_init_register_types) | ||
52 | |||
53 | static void sifive_u_soc_instance_init(Object *obj) | ||
54 | { | ||
55 | - MachineState *ms = MACHINE(qdev_get_machine()); | ||
56 | SiFiveUSoCState *s = RISCV_U_SOC(obj); | ||
57 | |||
58 | object_initialize_child(obj, "e-cluster", &s->e_cluster, TYPE_CPU_CLUSTER); | ||
59 | @@ -XXX,XX +XXX,XX @@ static void sifive_u_soc_instance_init(Object *obj) | ||
60 | |||
61 | object_initialize_child(OBJECT(&s->u_cluster), "u-cpus", &s->u_cpus, | ||
62 | TYPE_RISCV_HART_ARRAY); | ||
63 | - qdev_prop_set_uint32(DEVICE(&s->u_cpus), "num-harts", ms->smp.cpus - 1); | ||
64 | - qdev_prop_set_uint32(DEVICE(&s->u_cpus), "hartid-base", 1); | ||
65 | - qdev_prop_set_string(DEVICE(&s->u_cpus), "cpu-type", SIFIVE_U_CPU); | ||
66 | - qdev_prop_set_uint64(DEVICE(&s->u_cpus), "resetvec", 0x1004); | ||
67 | |||
68 | object_initialize_child(obj, "prci", &s->prci, TYPE_SIFIVE_U_PRCI); | ||
69 | object_initialize_child(obj, "otp", &s->otp, TYPE_SIFIVE_U_OTP); | ||
70 | @@ -XXX,XX +XXX,XX @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp) | ||
71 | int i; | ||
72 | NICInfo *nd = &nd_table[0]; | ||
73 | |||
74 | + qdev_prop_set_uint32(DEVICE(&s->u_cpus), "num-harts", ms->smp.cpus - 1); | ||
75 | + qdev_prop_set_uint32(DEVICE(&s->u_cpus), "hartid-base", 1); | ||
76 | + qdev_prop_set_string(DEVICE(&s->u_cpus), "cpu-type", s->cpu_type); | ||
77 | + qdev_prop_set_uint64(DEVICE(&s->u_cpus), "resetvec", 0x1004); | ||
78 | + | ||
79 | sysbus_realize(SYS_BUS_DEVICE(&s->e_cpus), &error_abort); | ||
80 | sysbus_realize(SYS_BUS_DEVICE(&s->u_cpus), &error_abort); | ||
81 | /* | ||
82 | @@ -XXX,XX +XXX,XX @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp) | ||
83 | |||
84 | static Property sifive_u_soc_props[] = { | ||
85 | DEFINE_PROP_UINT32("serial", SiFiveUSoCState, serial, OTP_SERIAL), | ||
86 | + DEFINE_PROP_STRING("cpu-type", SiFiveUSoCState, cpu_type), | ||
87 | DEFINE_PROP_END_OF_LIST() | ||
88 | }; | ||
89 | |||
90 | -- | ||
91 | 2.28.0 | ||
92 | |||
93 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | Instead of returning the unused entry address from riscv_load_firmware() | ||
2 | instead return the end address. Also return the end address from | ||
3 | riscv_find_and_load_firmware(). | ||
4 | 1 | ||
5 | This tells the caller if a firmware was loaded and how big it is. This | ||
6 | can be used to determine the load address of the next image (usually the | ||
7 | kernel). | ||
8 | |||
9 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> | ||
10 | Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com> | ||
11 | Reviewed-by: Bin Meng <bin.meng@windriver.com> | ||
12 | Tested-by: Bin Meng <bin.meng@windriver.com> | ||
13 | Message-id: 558cf67162342d65a23262248b040563716628b2.1602634524.git.alistair.francis@wdc.com | ||
14 | --- | ||
15 | include/hw/riscv/boot.h | 8 ++++---- | ||
16 | hw/riscv/boot.c | 28 +++++++++++++++++----------- | ||
17 | 2 files changed, 21 insertions(+), 15 deletions(-) | ||
18 | |||
19 | diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h | ||
20 | index XXXXXXX..XXXXXXX 100644 | ||
21 | --- a/include/hw/riscv/boot.h | ||
22 | +++ b/include/hw/riscv/boot.h | ||
23 | @@ -XXX,XX +XXX,XX @@ | ||
24 | #include "exec/cpu-defs.h" | ||
25 | #include "hw/loader.h" | ||
26 | |||
27 | -void riscv_find_and_load_firmware(MachineState *machine, | ||
28 | - const char *default_machine_firmware, | ||
29 | - hwaddr firmware_load_addr, | ||
30 | - symbol_fn_t sym_cb); | ||
31 | +target_ulong riscv_find_and_load_firmware(MachineState *machine, | ||
32 | + const char *default_machine_firmware, | ||
33 | + hwaddr firmware_load_addr, | ||
34 | + symbol_fn_t sym_cb); | ||
35 | char *riscv_find_firmware(const char *firmware_filename); | ||
36 | target_ulong riscv_load_firmware(const char *firmware_filename, | ||
37 | hwaddr firmware_load_addr, | ||
38 | diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c | ||
39 | index XXXXXXX..XXXXXXX 100644 | ||
40 | --- a/hw/riscv/boot.c | ||
41 | +++ b/hw/riscv/boot.c | ||
42 | @@ -XXX,XX +XXX,XX @@ | ||
43 | #define fw_dynamic_info_data(__val) cpu_to_le64(__val) | ||
44 | #endif | ||
45 | |||
46 | -void riscv_find_and_load_firmware(MachineState *machine, | ||
47 | - const char *default_machine_firmware, | ||
48 | - hwaddr firmware_load_addr, | ||
49 | - symbol_fn_t sym_cb) | ||
50 | +target_ulong riscv_find_and_load_firmware(MachineState *machine, | ||
51 | + const char *default_machine_firmware, | ||
52 | + hwaddr firmware_load_addr, | ||
53 | + symbol_fn_t sym_cb) | ||
54 | { | ||
55 | char *firmware_filename = NULL; | ||
56 | + target_ulong firmware_end_addr = firmware_load_addr; | ||
57 | |||
58 | if ((!machine->firmware) || (!strcmp(machine->firmware, "default"))) { | ||
59 | /* | ||
60 | @@ -XXX,XX +XXX,XX @@ void riscv_find_and_load_firmware(MachineState *machine, | ||
61 | |||
62 | if (firmware_filename) { | ||
63 | /* If not "none" load the firmware */ | ||
64 | - riscv_load_firmware(firmware_filename, firmware_load_addr, sym_cb); | ||
65 | + firmware_end_addr = riscv_load_firmware(firmware_filename, | ||
66 | + firmware_load_addr, sym_cb); | ||
67 | g_free(firmware_filename); | ||
68 | } | ||
69 | + | ||
70 | + return firmware_end_addr; | ||
71 | } | ||
72 | |||
73 | char *riscv_find_firmware(const char *firmware_filename) | ||
74 | @@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_firmware(const char *firmware_filename, | ||
75 | hwaddr firmware_load_addr, | ||
76 | symbol_fn_t sym_cb) | ||
77 | { | ||
78 | - uint64_t firmware_entry; | ||
79 | + uint64_t firmware_entry, firmware_size, firmware_end; | ||
80 | |||
81 | if (load_elf_ram_sym(firmware_filename, NULL, NULL, NULL, | ||
82 | - &firmware_entry, NULL, NULL, NULL, | ||
83 | + &firmware_entry, NULL, &firmware_end, NULL, | ||
84 | 0, EM_RISCV, 1, 0, NULL, true, sym_cb) > 0) { | ||
85 | - return firmware_entry; | ||
86 | + return firmware_end; | ||
87 | } | ||
88 | |||
89 | - if (load_image_targphys_as(firmware_filename, firmware_load_addr, | ||
90 | - ram_size, NULL) > 0) { | ||
91 | - return firmware_load_addr; | ||
92 | + firmware_size = load_image_targphys_as(firmware_filename, | ||
93 | + firmware_load_addr, ram_size, NULL); | ||
94 | + | ||
95 | + if (firmware_size > 0) { | ||
96 | + return firmware_load_addr + firmware_size; | ||
97 | } | ||
98 | |||
99 | error_report("could not load firmware '%s'", firmware_filename); | ||
100 | -- | ||
101 | 2.28.0 | ||
102 | |||
103 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> | ||
2 | Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com> | ||
3 | Reviewed-by: Bin Meng <bin.meng@windriver.com> | ||
4 | Tested-by: Bin Meng <bin.meng@windriver.com> | ||
5 | Message-id: 4c6a85dfb6dd470aa79356ebc1b02f479c2758e0.1602634524.git.alistair.francis@wdc.com | ||
6 | --- | ||
7 | include/hw/riscv/boot.h | 2 ++ | ||
8 | hw/riscv/boot.c | 9 +++++++++ | ||
9 | 2 files changed, 11 insertions(+) | ||
10 | 1 | ||
11 | diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h | ||
12 | index XXXXXXX..XXXXXXX 100644 | ||
13 | --- a/include/hw/riscv/boot.h | ||
14 | +++ b/include/hw/riscv/boot.h | ||
15 | @@ -XXX,XX +XXX,XX @@ | ||
16 | #include "exec/cpu-defs.h" | ||
17 | #include "hw/loader.h" | ||
18 | |||
19 | +bool riscv_is_32_bit(MachineState *machine); | ||
20 | + | ||
21 | target_ulong riscv_find_and_load_firmware(MachineState *machine, | ||
22 | const char *default_machine_firmware, | ||
23 | hwaddr firmware_load_addr, | ||
24 | diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c | ||
25 | index XXXXXXX..XXXXXXX 100644 | ||
26 | --- a/hw/riscv/boot.c | ||
27 | +++ b/hw/riscv/boot.c | ||
28 | @@ -XXX,XX +XXX,XX @@ | ||
29 | #define fw_dynamic_info_data(__val) cpu_to_le64(__val) | ||
30 | #endif | ||
31 | |||
32 | +bool riscv_is_32_bit(MachineState *machine) | ||
33 | +{ | ||
34 | + if (!strncmp(machine->cpu_type, "rv32", 4)) { | ||
35 | + return true; | ||
36 | + } else { | ||
37 | + return false; | ||
38 | + } | ||
39 | +} | ||
40 | + | ||
41 | target_ulong riscv_find_and_load_firmware(MachineState *machine, | ||
42 | const char *default_machine_firmware, | ||
43 | hwaddr firmware_load_addr, | ||
44 | -- | ||
45 | 2.28.0 | ||
46 | |||
47 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | Instead of loading the kernel at a hardcoded start address, let's load | ||
2 | the kernel at the next aligned address after the end of the firmware. | ||
3 | 1 | ||
4 | This should have no impact for current users of OpenSBI, but will | ||
5 | allow loading a noMMU kernel at the start of memory. | ||
6 | |||
7 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> | ||
8 | Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com> | ||
9 | Reviewed-by: Bin Meng <bin.meng@windriver.com> | ||
10 | Tested-by: Bin Meng <bin.meng@windriver.com> | ||
11 | Message-id: 46c00c4f15b42feb792090e3d74359e180a6d954.1602634524.git.alistair.francis@wdc.com | ||
12 | --- | ||
13 | include/hw/riscv/boot.h | 3 +++ | ||
14 | hw/riscv/boot.c | 19 ++++++++++++++----- | ||
15 | hw/riscv/opentitan.c | 3 ++- | ||
16 | hw/riscv/sifive_e.c | 3 ++- | ||
17 | hw/riscv/sifive_u.c | 10 ++++++++-- | ||
18 | hw/riscv/spike.c | 11 ++++++++--- | ||
19 | hw/riscv/virt.c | 11 ++++++++--- | ||
20 | 7 files changed, 45 insertions(+), 15 deletions(-) | ||
21 | |||
22 | diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h | ||
23 | index XXXXXXX..XXXXXXX 100644 | ||
24 | --- a/include/hw/riscv/boot.h | ||
25 | +++ b/include/hw/riscv/boot.h | ||
26 | @@ -XXX,XX +XXX,XX @@ | ||
27 | |||
28 | bool riscv_is_32_bit(MachineState *machine); | ||
29 | |||
30 | +target_ulong riscv_calc_kernel_start_addr(MachineState *machine, | ||
31 | + target_ulong firmware_end_addr); | ||
32 | target_ulong riscv_find_and_load_firmware(MachineState *machine, | ||
33 | const char *default_machine_firmware, | ||
34 | hwaddr firmware_load_addr, | ||
35 | @@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_firmware(const char *firmware_filename, | ||
36 | hwaddr firmware_load_addr, | ||
37 | symbol_fn_t sym_cb); | ||
38 | target_ulong riscv_load_kernel(const char *kernel_filename, | ||
39 | + target_ulong firmware_end_addr, | ||
40 | symbol_fn_t sym_cb); | ||
41 | hwaddr riscv_load_initrd(const char *filename, uint64_t mem_size, | ||
42 | uint64_t kernel_entry, hwaddr *start); | ||
43 | diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c | ||
44 | index XXXXXXX..XXXXXXX 100644 | ||
45 | --- a/hw/riscv/boot.c | ||
46 | +++ b/hw/riscv/boot.c | ||
47 | @@ -XXX,XX +XXX,XX @@ | ||
48 | #include <libfdt.h> | ||
49 | |||
50 | #if defined(TARGET_RISCV32) | ||
51 | -# define KERNEL_BOOT_ADDRESS 0x80400000 | ||
52 | #define fw_dynamic_info_data(__val) cpu_to_le32(__val) | ||
53 | #else | ||
54 | -# define KERNEL_BOOT_ADDRESS 0x80200000 | ||
55 | #define fw_dynamic_info_data(__val) cpu_to_le64(__val) | ||
56 | #endif | ||
57 | |||
58 | @@ -XXX,XX +XXX,XX @@ bool riscv_is_32_bit(MachineState *machine) | ||
59 | } | ||
60 | } | ||
61 | |||
62 | +target_ulong riscv_calc_kernel_start_addr(MachineState *machine, | ||
63 | + target_ulong firmware_end_addr) { | ||
64 | + if (riscv_is_32_bit(machine)) { | ||
65 | + return QEMU_ALIGN_UP(firmware_end_addr, 4 * MiB); | ||
66 | + } else { | ||
67 | + return QEMU_ALIGN_UP(firmware_end_addr, 2 * MiB); | ||
68 | + } | ||
69 | +} | ||
70 | + | ||
71 | target_ulong riscv_find_and_load_firmware(MachineState *machine, | ||
72 | const char *default_machine_firmware, | ||
73 | hwaddr firmware_load_addr, | ||
74 | @@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_firmware(const char *firmware_filename, | ||
75 | exit(1); | ||
76 | } | ||
77 | |||
78 | -target_ulong riscv_load_kernel(const char *kernel_filename, symbol_fn_t sym_cb) | ||
79 | +target_ulong riscv_load_kernel(const char *kernel_filename, | ||
80 | + target_ulong kernel_start_addr, | ||
81 | + symbol_fn_t sym_cb) | ||
82 | { | ||
83 | uint64_t kernel_entry; | ||
84 | |||
85 | @@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_kernel(const char *kernel_filename, symbol_fn_t sym_cb) | ||
86 | return kernel_entry; | ||
87 | } | ||
88 | |||
89 | - if (load_image_targphys_as(kernel_filename, KERNEL_BOOT_ADDRESS, | ||
90 | + if (load_image_targphys_as(kernel_filename, kernel_start_addr, | ||
91 | ram_size, NULL) > 0) { | ||
92 | - return KERNEL_BOOT_ADDRESS; | ||
93 | + return kernel_start_addr; | ||
94 | } | ||
95 | |||
96 | error_report("could not load kernel '%s'", kernel_filename); | ||
97 | diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c | ||
98 | index XXXXXXX..XXXXXXX 100644 | ||
99 | --- a/hw/riscv/opentitan.c | ||
100 | +++ b/hw/riscv/opentitan.c | ||
101 | @@ -XXX,XX +XXX,XX @@ static void opentitan_board_init(MachineState *machine) | ||
102 | } | ||
103 | |||
104 | if (machine->kernel_filename) { | ||
105 | - riscv_load_kernel(machine->kernel_filename, NULL); | ||
106 | + riscv_load_kernel(machine->kernel_filename, | ||
107 | + memmap[IBEX_DEV_RAM].base, NULL); | ||
108 | } | ||
109 | } | ||
110 | |||
111 | diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c | ||
112 | index XXXXXXX..XXXXXXX 100644 | ||
113 | --- a/hw/riscv/sifive_e.c | ||
114 | +++ b/hw/riscv/sifive_e.c | ||
115 | @@ -XXX,XX +XXX,XX @@ static void sifive_e_machine_init(MachineState *machine) | ||
116 | memmap[SIFIVE_E_DEV_MROM].base, &address_space_memory); | ||
117 | |||
118 | if (machine->kernel_filename) { | ||
119 | - riscv_load_kernel(machine->kernel_filename, NULL); | ||
120 | + riscv_load_kernel(machine->kernel_filename, | ||
121 | + memmap[SIFIVE_E_DEV_DTIM].base, NULL); | ||
122 | } | ||
123 | } | ||
124 | |||
125 | diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c | ||
126 | index XXXXXXX..XXXXXXX 100644 | ||
127 | --- a/hw/riscv/sifive_u.c | ||
128 | +++ b/hw/riscv/sifive_u.c | ||
129 | @@ -XXX,XX +XXX,XX @@ static void sifive_u_machine_init(MachineState *machine) | ||
130 | MemoryRegion *main_mem = g_new(MemoryRegion, 1); | ||
131 | MemoryRegion *flash0 = g_new(MemoryRegion, 1); | ||
132 | target_ulong start_addr = memmap[SIFIVE_U_DEV_DRAM].base; | ||
133 | + target_ulong firmware_end_addr, kernel_start_addr; | ||
134 | uint32_t start_addr_hi32 = 0x00000000; | ||
135 | int i; | ||
136 | uint32_t fdt_load_addr; | ||
137 | @@ -XXX,XX +XXX,XX @@ static void sifive_u_machine_init(MachineState *machine) | ||
138 | break; | ||
139 | } | ||
140 | |||
141 | - riscv_find_and_load_firmware(machine, BIOS_FILENAME, start_addr, NULL); | ||
142 | + firmware_end_addr = riscv_find_and_load_firmware(machine, BIOS_FILENAME, | ||
143 | + start_addr, NULL); | ||
144 | |||
145 | if (machine->kernel_filename) { | ||
146 | - kernel_entry = riscv_load_kernel(machine->kernel_filename, NULL); | ||
147 | + kernel_start_addr = riscv_calc_kernel_start_addr(machine, | ||
148 | + firmware_end_addr); | ||
149 | + | ||
150 | + kernel_entry = riscv_load_kernel(machine->kernel_filename, | ||
151 | + kernel_start_addr, NULL); | ||
152 | |||
153 | if (machine->initrd_filename) { | ||
154 | hwaddr start; | ||
155 | diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c | ||
156 | index XXXXXXX..XXXXXXX 100644 | ||
157 | --- a/hw/riscv/spike.c | ||
158 | +++ b/hw/riscv/spike.c | ||
159 | @@ -XXX,XX +XXX,XX @@ static void spike_board_init(MachineState *machine) | ||
160 | MemoryRegion *system_memory = get_system_memory(); | ||
161 | MemoryRegion *main_mem = g_new(MemoryRegion, 1); | ||
162 | MemoryRegion *mask_rom = g_new(MemoryRegion, 1); | ||
163 | + target_ulong firmware_end_addr, kernel_start_addr; | ||
164 | uint32_t fdt_load_addr; | ||
165 | uint64_t kernel_entry; | ||
166 | char *soc_name; | ||
167 | @@ -XXX,XX +XXX,XX @@ static void spike_board_init(MachineState *machine) | ||
168 | memory_region_add_subregion(system_memory, memmap[SPIKE_MROM].base, | ||
169 | mask_rom); | ||
170 | |||
171 | - riscv_find_and_load_firmware(machine, BIOS_FILENAME, | ||
172 | - memmap[SPIKE_DRAM].base, | ||
173 | - htif_symbol_callback); | ||
174 | + firmware_end_addr = riscv_find_and_load_firmware(machine, BIOS_FILENAME, | ||
175 | + memmap[SPIKE_DRAM].base, | ||
176 | + htif_symbol_callback); | ||
177 | |||
178 | if (machine->kernel_filename) { | ||
179 | + kernel_start_addr = riscv_calc_kernel_start_addr(machine, | ||
180 | + firmware_end_addr); | ||
181 | + | ||
182 | kernel_entry = riscv_load_kernel(machine->kernel_filename, | ||
183 | + kernel_start_addr, | ||
184 | htif_symbol_callback); | ||
185 | |||
186 | if (machine->initrd_filename) { | ||
187 | diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c | ||
188 | index XXXXXXX..XXXXXXX 100644 | ||
189 | --- a/hw/riscv/virt.c | ||
190 | +++ b/hw/riscv/virt.c | ||
191 | @@ -XXX,XX +XXX,XX @@ static void virt_machine_init(MachineState *machine) | ||
192 | char *plic_hart_config, *soc_name; | ||
193 | size_t plic_hart_config_len; | ||
194 | target_ulong start_addr = memmap[VIRT_DRAM].base; | ||
195 | + target_ulong firmware_end_addr, kernel_start_addr; | ||
196 | uint32_t fdt_load_addr; | ||
197 | uint64_t kernel_entry; | ||
198 | DeviceState *mmio_plic, *virtio_plic, *pcie_plic; | ||
199 | @@ -XXX,XX +XXX,XX @@ static void virt_machine_init(MachineState *machine) | ||
200 | memory_region_add_subregion(system_memory, memmap[VIRT_MROM].base, | ||
201 | mask_rom); | ||
202 | |||
203 | - riscv_find_and_load_firmware(machine, BIOS_FILENAME, | ||
204 | - memmap[VIRT_DRAM].base, NULL); | ||
205 | + firmware_end_addr = riscv_find_and_load_firmware(machine, BIOS_FILENAME, | ||
206 | + start_addr, NULL); | ||
207 | |||
208 | if (machine->kernel_filename) { | ||
209 | - kernel_entry = riscv_load_kernel(machine->kernel_filename, NULL); | ||
210 | + kernel_start_addr = riscv_calc_kernel_start_addr(machine, | ||
211 | + firmware_end_addr); | ||
212 | + | ||
213 | + kernel_entry = riscv_load_kernel(machine->kernel_filename, | ||
214 | + kernel_start_addr, NULL); | ||
215 | |||
216 | if (machine->initrd_filename) { | ||
217 | hwaddr start; | ||
218 | -- | ||
219 | 2.28.0 | ||
220 | |||
221 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Yifei Jiang <jiangyifei@huawei.com> | ||
2 | 1 | ||
3 | VS-stage translation at get_physical_address needs to translate pte | ||
4 | address by G-stage translation. But the G-stage translation error | ||
5 | can not be distinguished from VS-stage translation error in | ||
6 | riscv_cpu_tlb_fill. On migration, destination needs to rebuild pte, | ||
7 | and this G-stage translation error must be handled by HS-mode. So | ||
8 | introduce TRANSLATE_STAGE2_FAIL so that riscv_cpu_tlb_fill could | ||
9 | distinguish and raise it to HS-mode. | ||
10 | |||
11 | Signed-off-by: Yifei Jiang <jiangyifei@huawei.com> | ||
12 | Signed-off-by: Yipeng Yin <yinyipeng1@huawei.com> | ||
13 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> | ||
14 | Message-id: 20201014101728.848-1-jiangyifei@huawei.com | ||
15 | [ Change by AF: | ||
16 | - Clarify the fault_pte_addr shift | ||
17 | ] | ||
18 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> | ||
19 | --- | ||
20 | target/riscv/cpu.h | 10 +++++++--- | ||
21 | target/riscv/cpu_helper.c | 36 +++++++++++++++++++++++++++--------- | ||
22 | 2 files changed, 34 insertions(+), 12 deletions(-) | ||
23 | |||
24 | diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h | ||
25 | index XXXXXXX..XXXXXXX 100644 | ||
26 | --- a/target/riscv/cpu.h | ||
27 | +++ b/target/riscv/cpu.h | ||
28 | @@ -XXX,XX +XXX,XX @@ enum { | ||
29 | |||
30 | #define VEXT_VERSION_0_07_1 0x00000701 | ||
31 | |||
32 | -#define TRANSLATE_PMP_FAIL 2 | ||
33 | -#define TRANSLATE_FAIL 1 | ||
34 | -#define TRANSLATE_SUCCESS 0 | ||
35 | +enum { | ||
36 | + TRANSLATE_SUCCESS, | ||
37 | + TRANSLATE_FAIL, | ||
38 | + TRANSLATE_PMP_FAIL, | ||
39 | + TRANSLATE_G_STAGE_FAIL | ||
40 | +}; | ||
41 | + | ||
42 | #define MMU_USER_IDX 3 | ||
43 | |||
44 | #define MAX_RISCV_PMPS (16) | ||
45 | diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c | ||
46 | index XXXXXXX..XXXXXXX 100644 | ||
47 | --- a/target/riscv/cpu_helper.c | ||
48 | +++ b/target/riscv/cpu_helper.c | ||
49 | @@ -XXX,XX +XXX,XX @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv) | ||
50 | * @physical: This will be set to the calculated physical address | ||
51 | * @prot: The returned protection attributes | ||
52 | * @addr: The virtual address to be translated | ||
53 | + * @fault_pte_addr: If not NULL, this will be set to fault pte address | ||
54 | + * when a error occurs on pte address translation. | ||
55 | + * This will already be shifted to match htval. | ||
56 | * @access_type: The type of MMU access | ||
57 | * @mmu_idx: Indicates current privilege level | ||
58 | * @first_stage: Are we in first stage translation? | ||
59 | @@ -XXX,XX +XXX,XX @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv) | ||
60 | */ | ||
61 | static int get_physical_address(CPURISCVState *env, hwaddr *physical, | ||
62 | int *prot, target_ulong addr, | ||
63 | + target_ulong *fault_pte_addr, | ||
64 | int access_type, int mmu_idx, | ||
65 | bool first_stage, bool two_stage) | ||
66 | { | ||
67 | @@ -XXX,XX +XXX,XX @@ restart: | ||
68 | |||
69 | /* Do the second stage translation on the base PTE address. */ | ||
70 | int vbase_ret = get_physical_address(env, &vbase, &vbase_prot, | ||
71 | - base, MMU_DATA_LOAD, | ||
72 | + base, NULL, MMU_DATA_LOAD, | ||
73 | mmu_idx, false, true); | ||
74 | |||
75 | if (vbase_ret != TRANSLATE_SUCCESS) { | ||
76 | - return vbase_ret; | ||
77 | + if (fault_pte_addr) { | ||
78 | + *fault_pte_addr = (base + idx * ptesize) >> 2; | ||
79 | + } | ||
80 | + return TRANSLATE_G_STAGE_FAIL; | ||
81 | } | ||
82 | |||
83 | pte_addr = vbase + idx * ptesize; | ||
84 | @@ -XXX,XX +XXX,XX @@ hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) | ||
85 | int prot; | ||
86 | int mmu_idx = cpu_mmu_index(&cpu->env, false); | ||
87 | |||
88 | - if (get_physical_address(env, &phys_addr, &prot, addr, 0, mmu_idx, | ||
89 | + if (get_physical_address(env, &phys_addr, &prot, addr, NULL, 0, mmu_idx, | ||
90 | true, riscv_cpu_virt_enabled(env))) { | ||
91 | return -1; | ||
92 | } | ||
93 | |||
94 | if (riscv_cpu_virt_enabled(env)) { | ||
95 | - if (get_physical_address(env, &phys_addr, &prot, phys_addr, | ||
96 | + if (get_physical_address(env, &phys_addr, &prot, phys_addr, NULL, | ||
97 | 0, mmu_idx, false, true)) { | ||
98 | return -1; | ||
99 | } | ||
100 | @@ -XXX,XX +XXX,XX @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, | ||
101 | if (riscv_cpu_virt_enabled(env) || | ||
102 | (riscv_cpu_two_stage_lookup(env) && access_type != MMU_INST_FETCH)) { | ||
103 | /* Two stage lookup */ | ||
104 | - ret = get_physical_address(env, &pa, &prot, address, access_type, | ||
105 | + ret = get_physical_address(env, &pa, &prot, address, | ||
106 | + &env->guest_phys_fault_addr, access_type, | ||
107 | mmu_idx, true, true); | ||
108 | |||
109 | + /* | ||
110 | + * A G-stage exception may be triggered during two state lookup. | ||
111 | + * And the env->guest_phys_fault_addr has already been set in | ||
112 | + * get_physical_address(). | ||
113 | + */ | ||
114 | + if (ret == TRANSLATE_G_STAGE_FAIL) { | ||
115 | + first_stage_error = false; | ||
116 | + access_type = MMU_DATA_LOAD; | ||
117 | + } | ||
118 | + | ||
119 | qemu_log_mask(CPU_LOG_MMU, | ||
120 | "%s 1st-stage address=%" VADDR_PRIx " ret %d physical " | ||
121 | TARGET_FMT_plx " prot %d\n", | ||
122 | __func__, address, ret, pa, prot); | ||
123 | |||
124 | - if (ret != TRANSLATE_FAIL) { | ||
125 | + if (ret == TRANSLATE_SUCCESS) { | ||
126 | /* Second stage lookup */ | ||
127 | im_address = pa; | ||
128 | |||
129 | - ret = get_physical_address(env, &pa, &prot2, im_address, | ||
130 | + ret = get_physical_address(env, &pa, &prot2, im_address, NULL, | ||
131 | access_type, mmu_idx, false, true); | ||
132 | |||
133 | qemu_log_mask(CPU_LOG_MMU, | ||
134 | @@ -XXX,XX +XXX,XX @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, | ||
135 | } | ||
136 | } else { | ||
137 | /* Single stage lookup */ | ||
138 | - ret = get_physical_address(env, &pa, &prot, address, access_type, | ||
139 | - mmu_idx, true, false); | ||
140 | + ret = get_physical_address(env, &pa, &prot, address, NULL, | ||
141 | + access_type, mmu_idx, true, false); | ||
142 | |||
143 | qemu_log_mask(CPU_LOG_MMU, | ||
144 | "%s address=%" VADDR_PRIx " ret %d physical " | ||
145 | -- | ||
146 | 2.28.0 | ||
147 | |||
148 | diff view generated by jsdifflib |
1 | From: Green Wan <green.wan@sifive.com> | 1 | From: Thomas Huth <thuth@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | Add '-drive' support to OTP device. Allow users to assign a raw file | 3 | Configuring a drive with "if=none" is meant for creation of a backend |
4 | as OTP image. | 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). | ||
5 | 7 | ||
6 | test commands for 16k otp.img filled with zero: | 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. | ||
7 | 11 | ||
8 | $ dd if=/dev/zero of=./otp.img bs=1k count=16 | 12 | Signed-off-by: Thomas Huth <thuth@redhat.com> |
9 | $ ./qemu-system-riscv64 -M sifive_u -m 256M -nographic -bios none \ | 13 | Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com> |
10 | -kernel ../opensbi/build/platform/sifive/fu540/firmware/fw_payload.elf \ | 14 | Reviewed-by: Markus Armbruster <armbru@redhat.com> |
11 | -d guest_errors -drive if=none,format=raw,file=otp.img | 15 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> |
12 | 16 | Message-id: 20211119102549.217755-1-thuth@redhat.com | |
13 | Signed-off-by: Green Wan <green.wan@sifive.com> | ||
14 | Reviewed-by: Bin Meng <bin.meng@windriver.com> | ||
15 | Tested-by: Bin Meng <bin.meng@windriver.com> | ||
16 | Acked-by: Alistair Francis <alistair.francis@wdc.com> | ||
17 | Message-id: 20201020033732.12921-3-green.wan@sifive.com | ||
18 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> | 17 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> |
19 | --- | 18 | --- |
20 | include/hw/misc/sifive_u_otp.h | 2 ++ | 19 | docs/about/deprecated.rst | 6 ++++++ |
21 | hw/misc/sifive_u_otp.c | 65 ++++++++++++++++++++++++++++++++++ | 20 | hw/misc/sifive_u_otp.c | 9 ++++++++- |
22 | 2 files changed, 67 insertions(+) | 21 | 2 files changed, 14 insertions(+), 1 deletion(-) |
23 | 22 | ||
24 | diff --git a/include/hw/misc/sifive_u_otp.h b/include/hw/misc/sifive_u_otp.h | 23 | diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst |
25 | index XXXXXXX..XXXXXXX 100644 | 24 | index XXXXXXX..XXXXXXX 100644 |
26 | --- a/include/hw/misc/sifive_u_otp.h | 25 | --- a/docs/about/deprecated.rst |
27 | +++ b/include/hw/misc/sifive_u_otp.h | 26 | +++ b/docs/about/deprecated.rst |
28 | @@ -XXX,XX +XXX,XX @@ | 27 | @@ -XXX,XX +XXX,XX @@ as short-form boolean values, and passed to plugins as ``arg_name=on``. |
29 | 28 | However, short-form booleans are deprecated and full explicit ``arg_name=on`` | |
30 | #define SIFIVE_U_OTP_PA_MASK 0xfff | 29 | form is preferred. |
31 | #define SIFIVE_U_OTP_NUM_FUSES 0x1000 | 30 | |
32 | +#define SIFIVE_U_OTP_FUSE_WORD 4 | 31 | +``-drive if=none`` for the sifive_u OTP device (since 6.2) |
33 | #define SIFIVE_U_OTP_SERIAL_ADDR 0xfc | 32 | +'''''''''''''''''''''''''''''''''''''''''''''''''''''''''' |
34 | 33 | + | |
35 | #define SIFIVE_U_OTP_REG_SIZE 0x1000 | 34 | +Using ``-drive if=none`` to configure the OTP device of the sifive_u |
36 | @@ -XXX,XX +XXX,XX @@ struct SiFiveUOTPState { | 35 | +RISC-V machine is deprecated. Use ``-drive if=pflash`` instead. |
37 | uint32_t fuse_wo[SIFIVE_U_OTP_NUM_FUSES]; | 36 | + |
38 | /* config */ | 37 | |
39 | uint32_t serial; | 38 | QEMU Machine Protocol (QMP) commands |
40 | + BlockBackend *blk; | 39 | ------------------------------------ |
41 | }; | ||
42 | |||
43 | #endif /* HW_SIFIVE_U_OTP_H */ | ||
44 | diff --git a/hw/misc/sifive_u_otp.c b/hw/misc/sifive_u_otp.c | 40 | diff --git a/hw/misc/sifive_u_otp.c b/hw/misc/sifive_u_otp.c |
45 | index XXXXXXX..XXXXXXX 100644 | 41 | index XXXXXXX..XXXXXXX 100644 |
46 | --- a/hw/misc/sifive_u_otp.c | 42 | --- a/hw/misc/sifive_u_otp.c |
47 | +++ b/hw/misc/sifive_u_otp.c | 43 | +++ b/hw/misc/sifive_u_otp.c |
48 | @@ -XXX,XX +XXX,XX @@ | 44 | @@ -XXX,XX +XXX,XX @@ static void sifive_u_otp_realize(DeviceState *dev, Error **errp) |
49 | */ | ||
50 | |||
51 | #include "qemu/osdep.h" | ||
52 | +#include "qapi/error.h" | ||
53 | #include "hw/qdev-properties.h" | ||
54 | #include "hw/sysbus.h" | ||
55 | #include "qemu/log.h" | ||
56 | #include "qemu/module.h" | ||
57 | #include "hw/misc/sifive_u_otp.h" | ||
58 | +#include "sysemu/blockdev.h" | ||
59 | +#include "sysemu/block-backend.h" | ||
60 | |||
61 | #define WRITTEN_BIT_ON 0x1 | ||
62 | |||
63 | @@ -XXX,XX +XXX,XX @@ static uint64_t sifive_u_otp_read(void *opaque, hwaddr addr, unsigned int size) | ||
64 | if ((s->pce & SIFIVE_U_OTP_PCE_EN) && | ||
65 | (s->pdstb & SIFIVE_U_OTP_PDSTB_EN) && | ||
66 | (s->ptrim & SIFIVE_U_OTP_PTRIM_EN)) { | ||
67 | + | ||
68 | + /* read from backend */ | ||
69 | + if (s->blk) { | ||
70 | + int32_t buf; | ||
71 | + | ||
72 | + blk_pread(s->blk, s->pa * SIFIVE_U_OTP_FUSE_WORD, &buf, | ||
73 | + SIFIVE_U_OTP_FUSE_WORD); | ||
74 | + return buf; | ||
75 | + } | ||
76 | + | ||
77 | return s->fuse[s->pa & SIFIVE_U_OTP_PA_MASK]; | ||
78 | } else { | ||
79 | return 0xff; | ||
80 | @@ -XXX,XX +XXX,XX @@ static void sifive_u_otp_write(void *opaque, hwaddr addr, | ||
81 | /* write bit data */ | ||
82 | SET_FUSEARRAY_BIT(s->fuse, s->pa, s->paio, s->pdin); | ||
83 | |||
84 | + /* write to backend */ | ||
85 | + if (s->blk) { | ||
86 | + blk_pwrite(s->blk, s->pa * SIFIVE_U_OTP_FUSE_WORD, | ||
87 | + &s->fuse[s->pa], SIFIVE_U_OTP_FUSE_WORD, 0); | ||
88 | + } | ||
89 | + | ||
90 | /* update written bit */ | ||
91 | SET_FUSEARRAY_BIT(s->fuse_wo, s->pa, s->paio, WRITTEN_BIT_ON); | ||
92 | } | ||
93 | @@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps sifive_u_otp_ops = { | ||
94 | |||
95 | static Property sifive_u_otp_properties[] = { | ||
96 | DEFINE_PROP_UINT32("serial", SiFiveUOTPState, serial, 0), | ||
97 | + DEFINE_PROP_DRIVE("drive", SiFiveUOTPState, blk), | ||
98 | DEFINE_PROP_END_OF_LIST(), | ||
99 | }; | ||
100 | |||
101 | static void sifive_u_otp_realize(DeviceState *dev, Error **errp) | ||
102 | { | ||
103 | SiFiveUOTPState *s = SIFIVE_U_OTP(dev); | ||
104 | + DriveInfo *dinfo; | ||
105 | |||
106 | memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_u_otp_ops, s, | ||
107 | TYPE_SIFIVE_U_OTP, SIFIVE_U_OTP_REG_SIZE); | 45 | TYPE_SIFIVE_U_OTP, SIFIVE_U_OTP_REG_SIZE); |
108 | sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio); | 46 | sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio); |
109 | + | 47 | |
110 | + dinfo = drive_get_next(IF_NONE); | 48 | - dinfo = drive_get_next(IF_NONE); |
111 | + if (dinfo) { | 49 | + dinfo = drive_get_next(IF_PFLASH); |
112 | + int ret; | 50 | + if (!dinfo) { |
113 | + uint64_t perm; | 51 | + dinfo = drive_get_next(IF_NONE); |
114 | + int filesize; | 52 | + if (dinfo) { |
115 | + BlockBackend *blk; | 53 | + warn_report("using \"-drive if=none\" for the OTP is deprecated, " |
116 | + | 54 | + "use \"-drive if=pflash\" instead."); |
117 | + blk = blk_by_legacy_dinfo(dinfo); | ||
118 | + filesize = SIFIVE_U_OTP_NUM_FUSES * SIFIVE_U_OTP_FUSE_WORD; | ||
119 | + if (blk_getlength(blk) < filesize) { | ||
120 | + error_setg(errp, "OTP drive size < 16K"); | ||
121 | + return; | ||
122 | + } | ||
123 | + | ||
124 | + qdev_prop_set_drive_err(dev, "drive", blk, errp); | ||
125 | + | ||
126 | + if (s->blk) { | ||
127 | + perm = BLK_PERM_CONSISTENT_READ | | ||
128 | + (blk_is_read_only(s->blk) ? 0 : BLK_PERM_WRITE); | ||
129 | + ret = blk_set_perm(s->blk, perm, BLK_PERM_ALL, errp); | ||
130 | + if (ret < 0) { | ||
131 | + return; | ||
132 | + } | ||
133 | + | ||
134 | + if (blk_pread(s->blk, 0, s->fuse, filesize) != filesize) { | ||
135 | + error_setg(errp, "failed to read the initial flash content"); | ||
136 | + } | ||
137 | + } | 55 | + } |
138 | + } | 56 | + } |
139 | } | 57 | if (dinfo) { |
140 | 58 | int ret; | |
141 | static void sifive_u_otp_reset(DeviceState *dev) | 59 | uint64_t perm; |
142 | @@ -XXX,XX +XXX,XX @@ static void sifive_u_otp_reset(DeviceState *dev) | ||
143 | s->fuse[SIFIVE_U_OTP_SERIAL_ADDR] = s->serial; | ||
144 | s->fuse[SIFIVE_U_OTP_SERIAL_ADDR + 1] = ~(s->serial); | ||
145 | |||
146 | + if (s->blk) { | ||
147 | + /* Put serial number to backend as well*/ | ||
148 | + uint32_t serial_data; | ||
149 | + int index = SIFIVE_U_OTP_SERIAL_ADDR; | ||
150 | + | ||
151 | + serial_data = s->serial; | ||
152 | + blk_pwrite(s->blk, index * SIFIVE_U_OTP_FUSE_WORD, | ||
153 | + &serial_data, SIFIVE_U_OTP_FUSE_WORD, 0); | ||
154 | + | ||
155 | + serial_data = ~(s->serial); | ||
156 | + blk_pwrite(s->blk, (index + 1) * SIFIVE_U_OTP_FUSE_WORD, | ||
157 | + &serial_data, SIFIVE_U_OTP_FUSE_WORD, 0); | ||
158 | + } | ||
159 | + | ||
160 | /* Initialize write-once map */ | ||
161 | memset(s->fuse_wo, 0x00, sizeof(s->fuse_wo)); | ||
162 | } | ||
163 | -- | 60 | -- |
164 | 2.28.0 | 61 | 2.31.1 |
165 | 62 | ||
166 | 63 | diff view generated by jsdifflib |
1 | From: Green Wan <green.wan@sifive.com> | 1 | From: Philippe Mathieu-Daudé <f4bug@amsat.org> |
---|---|---|---|
2 | 2 | ||
3 | - Add write operation to update fuse data bit when PWE bit is on. | 3 | Once a "One Time Programmable" is programmed, it shouldn't be reset. |
4 | - Add array, fuse_wo, to store the 'written' status for all bits | ||
5 | of OTP to block the write operation. | ||
6 | 4 | ||
7 | Signed-off-by: Green Wan <green.wan@sifive.com> | 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> | ||
8 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> | 10 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> |
9 | Reviewed-by: Bin Meng <bin.meng@windriver.com> | 11 | Message-Id: <20211119104757.331579-1-f4bug@amsat.org> |
10 | Tested-by: Bin Meng <bin.meng@windriver.com> | ||
11 | Message-id: 20201020033732.12921-2-green.wan@sifive.com | ||
12 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> | 12 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> |
13 | --- | 13 | --- |
14 | include/hw/misc/sifive_u_otp.h | 3 +++ | 14 | hw/misc/sifive_u_otp.c | 13 +++++-------- |
15 | hw/misc/sifive_u_otp.c | 30 +++++++++++++++++++++++++++++- | 15 | 1 file changed, 5 insertions(+), 8 deletions(-) |
16 | 2 files changed, 32 insertions(+), 1 deletion(-) | ||
17 | 16 | ||
18 | diff --git a/include/hw/misc/sifive_u_otp.h b/include/hw/misc/sifive_u_otp.h | ||
19 | index XXXXXXX..XXXXXXX 100644 | ||
20 | --- a/include/hw/misc/sifive_u_otp.h | ||
21 | +++ b/include/hw/misc/sifive_u_otp.h | ||
22 | @@ -XXX,XX +XXX,XX @@ | ||
23 | #define SIFIVE_U_OTP_PTRIM 0x34 | ||
24 | #define SIFIVE_U_OTP_PWE 0x38 | ||
25 | |||
26 | +#define SIFIVE_U_OTP_PWE_EN (1 << 0) | ||
27 | + | ||
28 | #define SIFIVE_U_OTP_PCE_EN (1 << 0) | ||
29 | |||
30 | #define SIFIVE_U_OTP_PDSTB_EN (1 << 0) | ||
31 | @@ -XXX,XX +XXX,XX @@ struct SiFiveUOTPState { | ||
32 | uint32_t ptrim; | ||
33 | uint32_t pwe; | ||
34 | uint32_t fuse[SIFIVE_U_OTP_NUM_FUSES]; | ||
35 | + uint32_t fuse_wo[SIFIVE_U_OTP_NUM_FUSES]; | ||
36 | /* config */ | ||
37 | uint32_t serial; | ||
38 | }; | ||
39 | diff --git a/hw/misc/sifive_u_otp.c b/hw/misc/sifive_u_otp.c | 17 | diff --git a/hw/misc/sifive_u_otp.c b/hw/misc/sifive_u_otp.c |
40 | index XXXXXXX..XXXXXXX 100644 | 18 | index XXXXXXX..XXXXXXX 100644 |
41 | --- a/hw/misc/sifive_u_otp.c | 19 | --- a/hw/misc/sifive_u_otp.c |
42 | +++ b/hw/misc/sifive_u_otp.c | 20 | +++ b/hw/misc/sifive_u_otp.c |
43 | @@ -XXX,XX +XXX,XX @@ | 21 | @@ -XXX,XX +XXX,XX @@ static void sifive_u_otp_realize(DeviceState *dev, Error **errp) |
44 | #include "qemu/module.h" | 22 | |
45 | #include "hw/misc/sifive_u_otp.h" | 23 | if (blk_pread(s->blk, 0, s->fuse, filesize) != filesize) { |
46 | 24 | error_setg(errp, "failed to read the initial flash content"); | |
47 | +#define WRITTEN_BIT_ON 0x1 | 25 | + return; |
48 | + | 26 | } |
49 | +#define SET_FUSEARRAY_BIT(map, i, off, bit) \ | 27 | } |
50 | + map[i] = bit ? (map[i] | bit << off) : (map[i] & ~(0x1 << off)) | 28 | } |
51 | + | 29 | -} |
52 | +#define GET_FUSEARRAY_BIT(map, i, off) \ | 30 | - |
53 | + ((map[i] >> off) & 0x1) | 31 | -static void sifive_u_otp_reset(DeviceState *dev) |
54 | + | 32 | -{ |
55 | static uint64_t sifive_u_otp_read(void *opaque, hwaddr addr, unsigned int size) | 33 | - SiFiveUOTPState *s = SIFIVE_U_OTP(dev); |
56 | { | 34 | |
57 | SiFiveUOTPState *s = opaque; | 35 | /* Initialize all fuses' initial value to 0xFFs */ |
58 | @@ -XXX,XX +XXX,XX @@ static void sifive_u_otp_write(void *opaque, hwaddr addr, | 36 | memset(s->fuse, 0xff, sizeof(s->fuse)); |
59 | s->ptrim = val32; | ||
60 | break; | ||
61 | case SIFIVE_U_OTP_PWE: | ||
62 | - s->pwe = val32; | ||
63 | + s->pwe = val32 & SIFIVE_U_OTP_PWE_EN; | ||
64 | + | ||
65 | + /* PWE is enabled. Ignore PAS=1 (no redundancy cell) */ | ||
66 | + if (s->pwe && !s->pas) { | ||
67 | + if (GET_FUSEARRAY_BIT(s->fuse_wo, s->pa, s->paio)) { | ||
68 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
69 | + "write once error: idx<%u>, bit<%u>\n", | ||
70 | + s->pa, s->paio); | ||
71 | + break; | ||
72 | + } | ||
73 | + | ||
74 | + /* write bit data */ | ||
75 | + SET_FUSEARRAY_BIT(s->fuse, s->pa, s->paio, s->pdin); | ||
76 | + | ||
77 | + /* update written bit */ | ||
78 | + SET_FUSEARRAY_BIT(s->fuse_wo, s->pa, s->paio, WRITTEN_BIT_ON); | ||
79 | + } | ||
80 | + | ||
81 | break; | ||
82 | default: | ||
83 | qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write: addr=0x%" HWADDR_PRIx | ||
84 | @@ -XXX,XX +XXX,XX @@ static void sifive_u_otp_reset(DeviceState *dev) | 37 | @@ -XXX,XX +XXX,XX @@ static void sifive_u_otp_reset(DeviceState *dev) |
85 | /* Make a valid content of serial number */ | 38 | serial_data = s->serial; |
86 | s->fuse[SIFIVE_U_OTP_SERIAL_ADDR] = s->serial; | 39 | if (blk_pwrite(s->blk, index * SIFIVE_U_OTP_FUSE_WORD, |
87 | s->fuse[SIFIVE_U_OTP_SERIAL_ADDR + 1] = ~(s->serial); | 40 | &serial_data, SIFIVE_U_OTP_FUSE_WORD, 0) < 0) { |
88 | + | 41 | - error_report("write error index<%d>", index); |
89 | + /* Initialize write-once map */ | 42 | + error_setg(errp, "failed to write index<%d>", index); |
90 | + memset(s->fuse_wo, 0x00, sizeof(s->fuse_wo)); | 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; | ||
91 | } | 60 | } |
92 | 61 | ||
93 | static void sifive_u_otp_class_init(ObjectClass *klass, void *data) | 62 | static const TypeInfo sifive_u_otp_info = { |
94 | -- | 63 | -- |
95 | 2.28.0 | 64 | 2.31.1 |
96 | 65 | ||
97 | 66 | diff view generated by jsdifflib |