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