1
From: Alistair Francis <alistair.francis@wdc.com>
1
From: Alistair Francis <alistair.francis@wdc.com>
2
2
3
The following changes since commit c5fbdd60cf1fb52f01bdfe342b6fa65d5343e1b1:
3
The following changes since commit 326ff8dd09556fc2e257196c49f35009700794ac:
4
4
5
Merge tag 'qemu-sparc-20211121' of git://github.com/mcayland/qemu into staging (2021-11-21 14:12:25 +0100)
5
Merge remote-tracking branch 'remotes/jasowang/tags/net-pull-request' into staging (2021-09-20 16:17:05 +0100)
6
6
7
are available in the Git repository at:
7
are available in the Git repository at:
8
8
9
git@github.com:alistair23/qemu.git tags/pull-riscv-to-apply-20211122
9
git@github.com:alistair23/qemu.git tags/pull-riscv-to-apply-20210921
10
10
11
for you to fetch changes up to 526e7443027c71fe7b04c29df529e1f9f425f9e3:
11
for you to fetch changes up to ed481d9837250aa682f5156528bc923e1b214f76:
12
12
13
hw/misc/sifive_u_otp: Do not reset OTP content on hardware reset (2021-11-22 10:46:22 +1000)
13
hw/riscv: opentitan: Correct the USB Dev address (2021-09-21 12:10:47 +1000)
14
14
15
----------------------------------------------------------------
15
----------------------------------------------------------------
16
Seventh RISC-V PR for QEMU 6.2
16
Second RISC-V PR for QEMU 6.2
17
17
18
- Deprecate IF_NONE for SiFive OTP
18
- ePMP CSR address updates
19
- Don't reset SiFive OTP content
19
- Convert internal interrupts to use QEMU GPIO lines
20
- SiFive PWM support
21
- Support for RISC-V ACLINT
22
- SiFive PDMA fixes
23
- Update to u-boot instructions for sifive_u
24
- mstatus.SD bug fix for hypervisor extensions
25
- OpenTitan fix for USB dev address
20
26
21
----------------------------------------------------------------
27
----------------------------------------------------------------
22
Philippe Mathieu-Daudé (1):
28
Alistair Francis (9):
23
hw/misc/sifive_u_otp: Do not reset OTP content on hardware reset
29
target/riscv: Update the ePMP CSR address
30
target/riscv: Expose interrupt pending bits as GPIO lines
31
hw/intc: sifive_clint: Use RISC-V CPU GPIO lines
32
hw/intc: ibex_plic: Convert the PLIC to use RISC-V CPU GPIO lines
33
hw/intc: sifive_plic: Convert the PLIC to use RISC-V CPU GPIO lines
34
hw/intc: ibex_timer: Convert the timer to use RISC-V CPU GPIO lines
35
hw/timer: Add SiFive PWM support
36
sifive_u: Connect the SiFive PWM device
37
hw/riscv: opentitan: Correct the USB Dev address
24
38
25
Thomas Huth (1):
39
Anup Patel (4):
26
hw/misc/sifive_u_otp: Use IF_PFLASH for the OTP device instead of IF_NONE
40
hw/intc: Rename sifive_clint sources to riscv_aclint sources
41
hw/intc: Upgrade the SiFive CLINT implementation to RISC-V ACLINT
42
hw/riscv: virt: Re-factor FDT generation
43
hw/riscv: virt: Add optional ACLINT support to virt machine
27
44
28
docs/about/deprecated.rst | 6 ++++++
45
Bin Meng (2):
29
hw/misc/sifive_u_otp.c | 22 +++++++++++++---------
46
docs/system/riscv: sifive_u: Update U-Boot instructions
30
2 files changed, 19 insertions(+), 9 deletions(-)
47
target/riscv: csr: Rename HCOUNTEREN_CY and friends
31
48
49
Frank Chang (4):
50
hw/dma: sifive_pdma: reset Next* registers when Control.claim is set
51
hw/dma: sifive_pdma: claim bit must be set before DMA transactions
52
hw/dma: sifive_pdma: don't set Control.error if 0 bytes to transfer
53
target/riscv: Backup/restore mstatus.SD bit when virtual register swapped
54
55
Green Wan (1):
56
hw/dma: sifive_pdma: allow non-multiple transaction size transactions
57
58
LIU Zhiwei (1):
59
target/riscv: Fix satp write
60
61
docs/system/riscv/sifive_u.rst | 50 ++--
62
docs/system/riscv/virt.rst | 10 +
63
include/hw/intc/ibex_plic.h | 2 +
64
include/hw/intc/riscv_aclint.h | 80 +++++
65
include/hw/intc/sifive_clint.h | 60 ----
66
include/hw/intc/sifive_plic.h | 4 +
67
include/hw/riscv/sifive_u.h | 14 +-
68
include/hw/riscv/virt.h | 2 +
69
include/hw/timer/ibex_timer.h | 2 +
70
include/hw/timer/sifive_pwm.h | 62 ++++
71
target/riscv/cpu_bits.h | 12 +-
72
hw/dma/sifive_pdma.c | 54 +++-
73
hw/intc/ibex_plic.c | 17 +-
74
hw/intc/riscv_aclint.c | 460 +++++++++++++++++++++++++++++
75
hw/intc/sifive_clint.c | 287 ------------------
76
hw/intc/sifive_plic.c | 30 +-
77
hw/riscv/microchip_pfsoc.c | 13 +-
78
hw/riscv/opentitan.c | 13 +-
79
hw/riscv/shakti_c.c | 16 +-
80
hw/riscv/sifive_e.c | 15 +-
81
hw/riscv/sifive_u.c | 68 ++++-
82
hw/riscv/spike.c | 16 +-
83
hw/riscv/virt.c | 654 ++++++++++++++++++++++++++++-------------
84
hw/timer/ibex_timer.c | 17 +-
85
hw/timer/sifive_pwm.c | 468 +++++++++++++++++++++++++++++
86
target/riscv/cpu.c | 31 ++
87
target/riscv/cpu_helper.c | 3 +-
88
target/riscv/csr.c | 26 +-
89
hw/intc/Kconfig | 2 +-
90
hw/intc/meson.build | 2 +-
91
hw/riscv/Kconfig | 13 +-
92
hw/timer/Kconfig | 3 +
93
hw/timer/meson.build | 1 +
94
hw/timer/trace-events | 6 +
95
34 files changed, 1844 insertions(+), 669 deletions(-)
96
create mode 100644 include/hw/intc/riscv_aclint.h
97
delete mode 100644 include/hw/intc/sifive_clint.h
98
create mode 100644 include/hw/timer/sifive_pwm.h
99
create mode 100644 hw/intc/riscv_aclint.c
100
delete mode 100644 hw/intc/sifive_clint.c
101
create mode 100644 hw/timer/sifive_pwm.c
102
diff view generated by jsdifflib
New patch
1
From: Alistair Francis <alistair.francis@wdc.com>
1
2
3
Update the ePMP CSRs to match the 0.9.3 ePMP spec
4
https://github.com/riscv/riscv-tee/blob/61455747230a26002d741f64879dd78cc9689323/Smepmp/Smepmp.pdf
5
6
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
7
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
8
Message-id: 28c908de60b9b04fa20e63d113885c98586053f3.1630543194.git.alistair.francis@wdc.com
9
---
10
target/riscv/cpu_bits.h | 4 ++--
11
target/riscv/cpu.c | 1 +
12
2 files changed, 3 insertions(+), 2 deletions(-)
13
14
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/riscv/cpu_bits.h
17
+++ b/target/riscv/cpu_bits.h
18
@@ -XXX,XX +XXX,XX @@
19
#define CSR_MTVAL2 0x34b
20
21
/* Enhanced Physical Memory Protection (ePMP) */
22
-#define CSR_MSECCFG 0x390
23
-#define CSR_MSECCFGH 0x391
24
+#define CSR_MSECCFG 0x747
25
+#define CSR_MSECCFGH 0x757
26
/* Physical Memory Protection */
27
#define CSR_PMPCFG0 0x3a0
28
#define CSR_PMPCFG1 0x3a1
29
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/riscv/cpu.c
32
+++ b/target/riscv/cpu.c
33
@@ -XXX,XX +XXX,XX @@ static Property riscv_cpu_properties[] = {
34
DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
35
DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true),
36
DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true),
37
+ /* ePMP 0.9.3 */
38
DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false),
39
40
DEFINE_PROP_UINT64("resetvec", RISCVCPU, cfg.resetvec, DEFAULT_RSTVEC),
41
--
42
2.31.1
43
44
diff view generated by jsdifflib
New patch
1
From: LIU Zhiwei <zhiwei_liu@c-sky.com>
1
2
3
These variables should be target_ulong. If truncated to int,
4
the bool conditions they indicate will be wrong.
5
6
As satp is very important for Linux, this bug almost fails every boot.
7
8
Signed-off-by: LIU Zhiwei <zhiwei_liu@c-sky.com>
9
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
11
Message-id: 20210901124539.222868-1-zhiwei_liu@c-sky.com
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
14
target/riscv/csr.c | 2 +-
15
1 file changed, 1 insertion(+), 1 deletion(-)
16
17
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/riscv/csr.c
20
+++ b/target/riscv/csr.c
21
@@ -XXX,XX +XXX,XX @@ static RISCVException read_satp(CPURISCVState *env, int csrno,
22
static RISCVException write_satp(CPURISCVState *env, int csrno,
23
target_ulong val)
24
{
25
- int vm, mask, asid;
26
+ target_ulong vm, mask, asid;
27
28
if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
29
return RISCV_EXCP_NONE;
30
--
31
2.31.1
32
33
diff view generated by jsdifflib
New patch
1
From: Alistair Francis <alistair.francis@wdc.com>
1
2
3
Expose the 12 interrupt pending bits in MIP as GPIO lines.
4
5
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
9
Tested-by: Bin Meng <bmeng.cn@gmail.com>
10
Message-id: 069d6162f0bc2f4a4f5a44e73f6442b11c703c53.1630301632.git.alistair.francis@wdc.com
11
---
12
target/riscv/cpu.c | 30 ++++++++++++++++++++++++++++++
13
1 file changed, 30 insertions(+)
14
15
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/riscv/cpu.c
18
+++ b/target/riscv/cpu.c
19
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
20
mcc->parent_realize(dev, errp);
21
}
22
23
+#ifndef CONFIG_USER_ONLY
24
+static void riscv_cpu_set_irq(void *opaque, int irq, int level)
25
+{
26
+ RISCVCPU *cpu = RISCV_CPU(opaque);
27
+
28
+ switch (irq) {
29
+ case IRQ_U_SOFT:
30
+ case IRQ_S_SOFT:
31
+ case IRQ_VS_SOFT:
32
+ case IRQ_M_SOFT:
33
+ case IRQ_U_TIMER:
34
+ case IRQ_S_TIMER:
35
+ case IRQ_VS_TIMER:
36
+ case IRQ_M_TIMER:
37
+ case IRQ_U_EXT:
38
+ case IRQ_S_EXT:
39
+ case IRQ_VS_EXT:
40
+ case IRQ_M_EXT:
41
+ riscv_cpu_update_mip(cpu, 1 << irq, BOOL_TO_MASK(level));
42
+ break;
43
+ default:
44
+ g_assert_not_reached();
45
+ }
46
+}
47
+#endif /* CONFIG_USER_ONLY */
48
+
49
static void riscv_cpu_init(Object *obj)
50
{
51
RISCVCPU *cpu = RISCV_CPU(obj);
52
53
cpu_set_cpustate_pointers(cpu);
54
+
55
+#ifndef CONFIG_USER_ONLY
56
+ qdev_init_gpio_in(DEVICE(cpu), riscv_cpu_set_irq, 12);
57
+#endif /* CONFIG_USER_ONLY */
58
}
59
60
static Property riscv_cpu_properties[] = {
61
--
62
2.31.1
63
64
diff view generated by jsdifflib
New patch
1
From: Alistair Francis <alistair.francis@wdc.com>
1
2
3
Instead of using riscv_cpu_update_mip() let's instead use the new RISC-V
4
CPU GPIO lines to set the timer and soft MIP bits.
5
6
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
7
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
8
Tested-by: Bin Meng <bmeng.cn@gmail.com>
9
Reviewed-by: LIU Zhiwei <zhiwei_liu@c-sky.com>
10
Message-id: 946e1ef5e268b24084c7ddad84c146de62a56736.1630301632.git.alistair.francis@wdc.com
11
---
12
include/hw/intc/sifive_clint.h | 2 +
13
hw/intc/sifive_clint.c | 68 ++++++++++++++++++++++++----------
14
2 files changed, 50 insertions(+), 20 deletions(-)
15
16
diff --git a/include/hw/intc/sifive_clint.h b/include/hw/intc/sifive_clint.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/intc/sifive_clint.h
19
+++ b/include/hw/intc/sifive_clint.h
20
@@ -XXX,XX +XXX,XX @@ typedef struct SiFiveCLINTState {
21
uint32_t time_base;
22
uint32_t aperture_size;
23
uint32_t timebase_freq;
24
+ qemu_irq *timer_irqs;
25
+ qemu_irq *soft_irqs;
26
} SiFiveCLINTState;
27
28
DeviceState *sifive_clint_create(hwaddr addr, hwaddr size,
29
diff --git a/hw/intc/sifive_clint.c b/hw/intc/sifive_clint.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/intc/sifive_clint.c
32
+++ b/hw/intc/sifive_clint.c
33
@@ -XXX,XX +XXX,XX @@
34
#include "hw/qdev-properties.h"
35
#include "hw/intc/sifive_clint.h"
36
#include "qemu/timer.h"
37
+#include "hw/irq.h"
38
+
39
+typedef struct sifive_clint_callback {
40
+ SiFiveCLINTState *s;
41
+ int num;
42
+} sifive_clint_callback;
43
44
static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq)
45
{
46
@@ -XXX,XX +XXX,XX @@ static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq)
47
* Called when timecmp is written to update the QEMU timer or immediately
48
* trigger timer interrupt if mtimecmp <= current timer value.
49
*/
50
-static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value,
51
+static void sifive_clint_write_timecmp(SiFiveCLINTState *s, RISCVCPU *cpu,
52
+ int hartid,
53
+ uint64_t value,
54
uint32_t timebase_freq)
55
{
56
uint64_t next;
57
@@ -XXX,XX +XXX,XX @@ static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value,
58
if (cpu->env.timecmp <= rtc_r) {
59
/* if we're setting an MTIMECMP value in the "past",
60
immediately raise the timer interrupt */
61
- riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(1));
62
+ qemu_irq_raise(s->timer_irqs[hartid - s->hartid_base]);
63
return;
64
}
65
66
/* otherwise, set up the future timer interrupt */
67
- riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(0));
68
+ qemu_irq_lower(s->timer_irqs[hartid - s->hartid_base]);
69
diff = cpu->env.timecmp - rtc_r;
70
/* back to ns (note args switched in muldiv64) */
71
uint64_t ns_diff = muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq);
72
@@ -XXX,XX +XXX,XX @@ static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value,
73
*/
74
static void sifive_clint_timer_cb(void *opaque)
75
{
76
- RISCVCPU *cpu = opaque;
77
- riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(1));
78
+ sifive_clint_callback *state = opaque;
79
+
80
+ qemu_irq_raise(state->s->timer_irqs[state->num]);
81
}
82
83
/* CPU wants to read rtc or timecmp register */
84
@@ -XXX,XX +XXX,XX @@ static void sifive_clint_write(void *opaque, hwaddr addr, uint64_t value,
85
if (!env) {
86
error_report("clint: invalid timecmp hartid: %zu", hartid);
87
} else if ((addr & 0x3) == 0) {
88
- riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_MSIP, BOOL_TO_MASK(value));
89
+ qemu_set_irq(clint->soft_irqs[hartid - clint->hartid_base], value);
90
} else {
91
error_report("clint: invalid sip write: %08x", (uint32_t)addr);
92
}
93
@@ -XXX,XX +XXX,XX @@ static void sifive_clint_write(void *opaque, hwaddr addr, uint64_t value,
94
} else if ((addr & 0x7) == 0) {
95
/* timecmp_lo */
96
uint64_t timecmp_hi = env->timecmp >> 32;
97
- sifive_clint_write_timecmp(RISCV_CPU(cpu),
98
+ sifive_clint_write_timecmp(clint, RISCV_CPU(cpu), hartid,
99
timecmp_hi << 32 | (value & 0xFFFFFFFF), clint->timebase_freq);
100
return;
101
} else if ((addr & 0x7) == 4) {
102
/* timecmp_hi */
103
uint64_t timecmp_lo = env->timecmp;
104
- sifive_clint_write_timecmp(RISCV_CPU(cpu),
105
+ sifive_clint_write_timecmp(clint, RISCV_CPU(cpu), hartid,
106
value << 32 | (timecmp_lo & 0xFFFFFFFF), clint->timebase_freq);
107
} else {
108
error_report("clint: invalid timecmp write: %08x", (uint32_t)addr);
109
@@ -XXX,XX +XXX,XX @@ static void sifive_clint_realize(DeviceState *dev, Error **errp)
110
memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_clint_ops, s,
111
TYPE_SIFIVE_CLINT, s->aperture_size);
112
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
113
+
114
+ s->timer_irqs = g_malloc(sizeof(qemu_irq) * s->num_harts);
115
+ qdev_init_gpio_out(dev, s->timer_irqs, s->num_harts);
116
+
117
+ s->soft_irqs = g_malloc(sizeof(qemu_irq) * s->num_harts);
118
+ qdev_init_gpio_out(dev, s->soft_irqs, s->num_harts);
119
}
120
121
static void sifive_clint_class_init(ObjectClass *klass, void *data)
122
@@ -XXX,XX +XXX,XX @@ static void sifive_clint_register_types(void)
123
124
type_init(sifive_clint_register_types)
125
126
-
127
/*
128
* Create CLINT device.
129
*/
130
@@ -XXX,XX +XXX,XX @@ DeviceState *sifive_clint_create(hwaddr addr, hwaddr size,
131
bool provide_rdtime)
132
{
133
int i;
134
+
135
+ DeviceState *dev = qdev_new(TYPE_SIFIVE_CLINT);
136
+ qdev_prop_set_uint32(dev, "hartid-base", hartid_base);
137
+ qdev_prop_set_uint32(dev, "num-harts", num_harts);
138
+ qdev_prop_set_uint32(dev, "sip-base", sip_base);
139
+ qdev_prop_set_uint32(dev, "timecmp-base", timecmp_base);
140
+ qdev_prop_set_uint32(dev, "time-base", time_base);
141
+ qdev_prop_set_uint32(dev, "aperture-size", size);
142
+ qdev_prop_set_uint32(dev, "timebase-freq", timebase_freq);
143
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
144
+ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
145
+
146
for (i = 0; i < num_harts; i++) {
147
CPUState *cpu = qemu_get_cpu(hartid_base + i);
148
+ RISCVCPU *rvcpu = RISCV_CPU(cpu);
149
CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
150
+ sifive_clint_callback *cb = g_malloc0(sizeof(sifive_clint_callback));
151
+
152
if (!env) {
153
+ g_free(cb);
154
continue;
155
}
156
if (provide_rdtime) {
157
riscv_cpu_set_rdtime_fn(env, cpu_riscv_read_rtc, timebase_freq);
158
}
159
+
160
+ cb->s = SIFIVE_CLINT(dev);
161
+ cb->num = i;
162
env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
163
- &sifive_clint_timer_cb, cpu);
164
+ &sifive_clint_timer_cb, cb);
165
env->timecmp = 0;
166
+
167
+ qdev_connect_gpio_out(dev, i,
168
+ qdev_get_gpio_in(DEVICE(rvcpu), IRQ_M_TIMER));
169
+ qdev_connect_gpio_out(dev, num_harts + i,
170
+ qdev_get_gpio_in(DEVICE(rvcpu), IRQ_M_SOFT));
171
}
172
173
- DeviceState *dev = qdev_new(TYPE_SIFIVE_CLINT);
174
- qdev_prop_set_uint32(dev, "hartid-base", hartid_base);
175
- qdev_prop_set_uint32(dev, "num-harts", num_harts);
176
- qdev_prop_set_uint32(dev, "sip-base", sip_base);
177
- qdev_prop_set_uint32(dev, "timecmp-base", timecmp_base);
178
- qdev_prop_set_uint32(dev, "time-base", time_base);
179
- qdev_prop_set_uint32(dev, "aperture-size", size);
180
- qdev_prop_set_uint32(dev, "timebase-freq", timebase_freq);
181
- sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
182
- sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
183
return dev;
184
}
185
--
186
2.31.1
187
188
diff view generated by jsdifflib
New patch
1
From: Alistair Francis <alistair.francis@wdc.com>
1
2
3
Instead of using riscv_cpu_update_mip() let's instead use the new RISC-V
4
CPU GPIO lines to set the external MIP bits.
5
6
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 0a76946981852f5bd15f0c37ab35b253371027a8.1630301632.git.alistair.francis@wdc.com
10
---
11
include/hw/intc/ibex_plic.h | 2 ++
12
hw/intc/ibex_plic.c | 17 ++++++-----------
13
hw/riscv/opentitan.c | 8 ++++++++
14
3 files changed, 16 insertions(+), 11 deletions(-)
15
16
diff --git a/include/hw/intc/ibex_plic.h b/include/hw/intc/ibex_plic.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/intc/ibex_plic.h
19
+++ b/include/hw/intc/ibex_plic.h
20
@@ -XXX,XX +XXX,XX @@ struct IbexPlicState {
21
uint32_t threshold_base;
22
23
uint32_t claim_base;
24
+
25
+ qemu_irq *external_irqs;
26
};
27
28
#endif /* HW_IBEX_PLIC_H */
29
diff --git a/hw/intc/ibex_plic.c b/hw/intc/ibex_plic.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/intc/ibex_plic.c
32
+++ b/hw/intc/ibex_plic.c
33
@@ -XXX,XX +XXX,XX @@
34
#include "target/riscv/cpu_bits.h"
35
#include "target/riscv/cpu.h"
36
#include "hw/intc/ibex_plic.h"
37
+#include "hw/irq.h"
38
39
static bool addr_between(uint32_t addr, uint32_t base, uint32_t num)
40
{
41
@@ -XXX,XX +XXX,XX @@ static bool ibex_plic_irqs_pending(IbexPlicState *s, uint32_t context)
42
43
static void ibex_plic_update(IbexPlicState *s)
44
{
45
- CPUState *cpu;
46
- int level, i;
47
+ int i;
48
49
for (i = 0; i < s->num_cpus; i++) {
50
- cpu = qemu_get_cpu(i);
51
-
52
- if (!cpu) {
53
- continue;
54
- }
55
-
56
- level = ibex_plic_irqs_pending(s, 0);
57
-
58
- riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_MEIP, BOOL_TO_MASK(level));
59
+ qemu_set_irq(s->external_irqs[i], ibex_plic_irqs_pending(s, 0));
60
}
61
}
62
63
@@ -XXX,XX +XXX,XX @@ static void ibex_plic_realize(DeviceState *dev, Error **errp)
64
65
qdev_init_gpio_in(dev, ibex_plic_irq_request, s->num_sources);
66
67
+ s->external_irqs = g_malloc(sizeof(qemu_irq) * s->num_cpus);
68
+ qdev_init_gpio_out(dev, s->external_irqs, s->num_cpus);
69
+
70
/*
71
* We can't allow the supervisor to control SEIP as this would allow the
72
* supervisor to clear a pending external interrupt which will result in
73
diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/hw/riscv/opentitan.c
76
+++ b/hw/riscv/opentitan.c
77
@@ -XXX,XX +XXX,XX @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp)
78
MachineState *ms = MACHINE(qdev_get_machine());
79
LowRISCIbexSoCState *s = RISCV_IBEX_SOC(dev_soc);
80
MemoryRegion *sys_mem = get_system_memory();
81
+ int i;
82
83
object_property_set_str(OBJECT(&s->cpus), "cpu-type", ms->cpu_type,
84
&error_abort);
85
@@ -XXX,XX +XXX,XX @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp)
86
}
87
sysbus_mmio_map(SYS_BUS_DEVICE(&s->plic), 0, memmap[IBEX_DEV_PLIC].base);
88
89
+ for (i = 0; i < ms->smp.cpus; i++) {
90
+ CPUState *cpu = qemu_get_cpu(i);
91
+
92
+ qdev_connect_gpio_out(DEVICE(&s->plic), i,
93
+ qdev_get_gpio_in(DEVICE(cpu), IRQ_M_EXT));
94
+ }
95
+
96
/* UART */
97
qdev_prop_set_chr(DEVICE(&(s->uart)), "chardev", serial_hd(0));
98
if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart), errp)) {
99
--
100
2.31.1
101
102
diff view generated by jsdifflib
New patch
1
From: Alistair Francis <alistair.francis@wdc.com>
1
2
3
Instead of using riscv_cpu_update_mip() let's instead use the new RISC-V
4
CPU GPIO lines to set the external MIP bits.
5
6
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
10
Tested-by: Bin Meng <bmeng.cn@gmail.com>
11
Message-id: 0364190bfa935058a845c0fa1ecf650328840ad5.1630301632.git.alistair.francis@wdc.com
12
---
13
include/hw/intc/sifive_plic.h | 4 ++++
14
hw/intc/sifive_plic.c | 30 +++++++++++++++++++++++-------
15
hw/riscv/microchip_pfsoc.c | 2 +-
16
hw/riscv/shakti_c.c | 3 ++-
17
hw/riscv/sifive_e.c | 2 +-
18
hw/riscv/sifive_u.c | 2 +-
19
hw/riscv/virt.c | 2 +-
20
7 files changed, 33 insertions(+), 12 deletions(-)
21
22
diff --git a/include/hw/intc/sifive_plic.h b/include/hw/intc/sifive_plic.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/include/hw/intc/sifive_plic.h
25
+++ b/include/hw/intc/sifive_plic.h
26
@@ -XXX,XX +XXX,XX @@ struct SiFivePLICState {
27
uint32_t context_base;
28
uint32_t context_stride;
29
uint32_t aperture_size;
30
+
31
+ qemu_irq *m_external_irqs;
32
+ qemu_irq *s_external_irqs;
33
};
34
35
DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
36
+ uint32_t num_harts,
37
uint32_t hartid_base, uint32_t num_sources,
38
uint32_t num_priorities, uint32_t priority_base,
39
uint32_t pending_base, uint32_t enable_base,
40
diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/intc/sifive_plic.c
43
+++ b/hw/intc/sifive_plic.c
44
@@ -XXX,XX +XXX,XX @@
45
#include "hw/intc/sifive_plic.h"
46
#include "target/riscv/cpu.h"
47
#include "migration/vmstate.h"
48
+#include "hw/irq.h"
49
50
#define RISCV_DEBUG_PLIC 0
51
52
@@ -XXX,XX +XXX,XX @@ static void sifive_plic_update(SiFivePLICState *plic)
53
for (addrid = 0; addrid < plic->num_addrs; addrid++) {
54
uint32_t hartid = plic->addr_config[addrid].hartid;
55
PLICMode mode = plic->addr_config[addrid].mode;
56
- CPUState *cpu = qemu_get_cpu(hartid);
57
- CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
58
- if (!env) {
59
- continue;
60
- }
61
int level = sifive_plic_irqs_pending(plic, addrid);
62
+
63
switch (mode) {
64
case PLICMode_M:
65
- riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_MEIP, BOOL_TO_MASK(level));
66
+ qemu_set_irq(plic->m_external_irqs[hartid - plic->hartid_base], level);
67
break;
68
case PLICMode_S:
69
- riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_SEIP, BOOL_TO_MASK(level));
70
+ qemu_set_irq(plic->s_external_irqs[hartid - plic->hartid_base], level);
71
break;
72
default:
73
break;
74
@@ -XXX,XX +XXX,XX @@ static void sifive_plic_realize(DeviceState *dev, Error **errp)
75
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &plic->mmio);
76
qdev_init_gpio_in(dev, sifive_plic_irq_request, plic->num_sources);
77
78
+ plic->s_external_irqs = g_malloc(sizeof(qemu_irq) * plic->num_harts);
79
+ qdev_init_gpio_out(dev, plic->s_external_irqs, plic->num_harts);
80
+
81
+ plic->m_external_irqs = g_malloc(sizeof(qemu_irq) * plic->num_harts);
82
+ qdev_init_gpio_out(dev, plic->m_external_irqs, plic->num_harts);
83
+
84
/* We can't allow the supervisor to control SEIP as this would allow the
85
* supervisor to clear a pending external interrupt which will result in
86
* lost a interrupt in the case a PLIC is attached. The SEIP bit must be
87
@@ -XXX,XX +XXX,XX @@ type_init(sifive_plic_register_types)
88
* Create PLIC device.
89
*/
90
DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
91
+ uint32_t num_harts,
92
uint32_t hartid_base, uint32_t num_sources,
93
uint32_t num_priorities, uint32_t priority_base,
94
uint32_t pending_base, uint32_t enable_base,
95
@@ -XXX,XX +XXX,XX @@ DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
96
uint32_t context_stride, uint32_t aperture_size)
97
{
98
DeviceState *dev = qdev_new(TYPE_SIFIVE_PLIC);
99
+ int i;
100
+
101
assert(enable_stride == (enable_stride & -enable_stride));
102
assert(context_stride == (context_stride & -context_stride));
103
qdev_prop_set_string(dev, "hart-config", hart_config);
104
@@ -XXX,XX +XXX,XX @@ DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
105
qdev_prop_set_uint32(dev, "aperture-size", aperture_size);
106
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
107
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
108
+
109
+ for (i = 0; i < num_harts; i++) {
110
+ CPUState *cpu = qemu_get_cpu(hartid_base + i);
111
+
112
+ qdev_connect_gpio_out(dev, i,
113
+ qdev_get_gpio_in(DEVICE(cpu), IRQ_S_EXT));
114
+ qdev_connect_gpio_out(dev, num_harts + i,
115
+ qdev_get_gpio_in(DEVICE(cpu), IRQ_M_EXT));
116
+ }
117
+
118
return dev;
119
}
120
diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
121
index XXXXXXX..XXXXXXX 100644
122
--- a/hw/riscv/microchip_pfsoc.c
123
+++ b/hw/riscv/microchip_pfsoc.c
124
@@ -XXX,XX +XXX,XX @@ static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp)
125
126
/* PLIC */
127
s->plic = sifive_plic_create(memmap[MICROCHIP_PFSOC_PLIC].base,
128
- plic_hart_config, 0,
129
+ plic_hart_config, ms->smp.cpus, 0,
130
MICROCHIP_PFSOC_PLIC_NUM_SOURCES,
131
MICROCHIP_PFSOC_PLIC_NUM_PRIORITIES,
132
MICROCHIP_PFSOC_PLIC_PRIORITY_BASE,
133
diff --git a/hw/riscv/shakti_c.c b/hw/riscv/shakti_c.c
134
index XXXXXXX..XXXXXXX 100644
135
--- a/hw/riscv/shakti_c.c
136
+++ b/hw/riscv/shakti_c.c
137
@@ -XXX,XX +XXX,XX @@ type_init(shakti_c_machine_type_info_register)
138
139
static void shakti_c_soc_state_realize(DeviceState *dev, Error **errp)
140
{
141
+ MachineState *ms = MACHINE(qdev_get_machine());
142
ShaktiCSoCState *sss = RISCV_SHAKTI_SOC(dev);
143
MemoryRegion *system_memory = get_system_memory();
144
145
sysbus_realize(SYS_BUS_DEVICE(&sss->cpus), &error_abort);
146
147
sss->plic = sifive_plic_create(shakti_c_memmap[SHAKTI_C_PLIC].base,
148
- (char *)SHAKTI_C_PLIC_HART_CONFIG, 0,
149
+ (char *)SHAKTI_C_PLIC_HART_CONFIG, ms->smp.cpus, 0,
150
SHAKTI_C_PLIC_NUM_SOURCES,
151
SHAKTI_C_PLIC_NUM_PRIORITIES,
152
SHAKTI_C_PLIC_PRIORITY_BASE,
153
diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
154
index XXXXXXX..XXXXXXX 100644
155
--- a/hw/riscv/sifive_e.c
156
+++ b/hw/riscv/sifive_e.c
157
@@ -XXX,XX +XXX,XX @@ static void sifive_e_soc_realize(DeviceState *dev, Error **errp)
158
159
/* MMIO */
160
s->plic = sifive_plic_create(memmap[SIFIVE_E_DEV_PLIC].base,
161
- (char *)SIFIVE_E_PLIC_HART_CONFIG, 0,
162
+ (char *)SIFIVE_E_PLIC_HART_CONFIG, ms->smp.cpus, 0,
163
SIFIVE_E_PLIC_NUM_SOURCES,
164
SIFIVE_E_PLIC_NUM_PRIORITIES,
165
SIFIVE_E_PLIC_PRIORITY_BASE,
166
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
167
index XXXXXXX..XXXXXXX 100644
168
--- a/hw/riscv/sifive_u.c
169
+++ b/hw/riscv/sifive_u.c
170
@@ -XXX,XX +XXX,XX @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
171
172
/* MMIO */
173
s->plic = sifive_plic_create(memmap[SIFIVE_U_DEV_PLIC].base,
174
- plic_hart_config, 0,
175
+ plic_hart_config, ms->smp.cpus, 0,
176
SIFIVE_U_PLIC_NUM_SOURCES,
177
SIFIVE_U_PLIC_NUM_PRIORITIES,
178
SIFIVE_U_PLIC_PRIORITY_BASE,
179
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
180
index XXXXXXX..XXXXXXX 100644
181
--- a/hw/riscv/virt.c
182
+++ b/hw/riscv/virt.c
183
@@ -XXX,XX +XXX,XX @@ static void virt_machine_init(MachineState *machine)
184
/* Per-socket PLIC */
185
s->plic[i] = sifive_plic_create(
186
memmap[VIRT_PLIC].base + i * memmap[VIRT_PLIC].size,
187
- plic_hart_config, base_hartid,
188
+ plic_hart_config, hart_count, base_hartid,
189
VIRT_PLIC_NUM_SOURCES,
190
VIRT_PLIC_NUM_PRIORITIES,
191
VIRT_PLIC_PRIORITY_BASE,
192
--
193
2.31.1
194
195
diff view generated by jsdifflib
New patch
1
From: Alistair Francis <alistair.francis@wdc.com>
1
2
3
Instead of using riscv_cpu_update_mip() let's instead use the new RISC-V
4
CPU GPIO lines to set the timer MIP bits.
5
6
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 84d5b1d5783d2e79eee69a2f7ac480cc0c070db3.1630301632.git.alistair.francis@wdc.com
10
---
11
include/hw/timer/ibex_timer.h | 2 ++
12
hw/riscv/opentitan.c | 3 +++
13
hw/timer/ibex_timer.c | 17 ++++++++++++-----
14
3 files changed, 17 insertions(+), 5 deletions(-)
15
16
diff --git a/include/hw/timer/ibex_timer.h b/include/hw/timer/ibex_timer.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/timer/ibex_timer.h
19
+++ b/include/hw/timer/ibex_timer.h
20
@@ -XXX,XX +XXX,XX @@ struct IbexTimerState {
21
uint32_t timebase_freq;
22
23
qemu_irq irq;
24
+
25
+ qemu_irq m_timer_irq;
26
};
27
#endif /* HW_IBEX_TIMER_H */
28
diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/riscv/opentitan.c
31
+++ b/hw/riscv/opentitan.c
32
@@ -XXX,XX +XXX,XX @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp)
33
sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer),
34
0, qdev_get_gpio_in(DEVICE(&s->plic),
35
IBEX_TIMER_TIMEREXPIRED0_0));
36
+ qdev_connect_gpio_out(DEVICE(&s->timer), 0,
37
+ qdev_get_gpio_in(DEVICE(qemu_get_cpu(0)),
38
+ IRQ_M_TIMER));
39
40
create_unimplemented_device("riscv.lowrisc.ibex.gpio",
41
memmap[IBEX_DEV_GPIO].base, memmap[IBEX_DEV_GPIO].size);
42
diff --git a/hw/timer/ibex_timer.c b/hw/timer/ibex_timer.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/timer/ibex_timer.c
45
+++ b/hw/timer/ibex_timer.c
46
@@ -XXX,XX +XXX,XX @@ static void ibex_timer_update_irqs(IbexTimerState *s)
47
/*
48
* If the mtimecmp was in the past raise the interrupt now.
49
*/
50
- riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(1));
51
+ qemu_irq_raise(s->m_timer_irq);
52
if (s->timer_intr_enable & R_INTR_ENABLE_IE_0_MASK) {
53
s->timer_intr_state |= R_INTR_STATE_IS_0_MASK;
54
qemu_set_irq(s->irq, true);
55
@@ -XXX,XX +XXX,XX @@ static void ibex_timer_update_irqs(IbexTimerState *s)
56
}
57
58
/* Setup a timer to trigger the interrupt in the future */
59
- riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(0));
60
+ qemu_irq_lower(s->m_timer_irq);
61
qemu_set_irq(s->irq, false);
62
63
diff = cpu->env.timecmp - now;
64
@@ -XXX,XX +XXX,XX @@ static void ibex_timer_update_irqs(IbexTimerState *s)
65
static void ibex_timer_cb(void *opaque)
66
{
67
IbexTimerState *s = opaque;
68
- CPUState *cs = qemu_get_cpu(0);
69
- RISCVCPU *cpu = RISCV_CPU(cs);
70
71
- riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(1));
72
+ qemu_irq_raise(s->m_timer_irq);
73
if (s->timer_intr_enable & R_INTR_ENABLE_IE_0_MASK) {
74
s->timer_intr_state |= R_INTR_STATE_IS_0_MASK;
75
qemu_set_irq(s->irq, true);
76
@@ -XXX,XX +XXX,XX @@ static void ibex_timer_init(Object *obj)
77
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
78
}
79
80
+static void ibex_timer_realize(DeviceState *dev, Error **errp)
81
+{
82
+ IbexTimerState *s = IBEX_TIMER(dev);
83
+
84
+ qdev_init_gpio_out(dev, &s->m_timer_irq, 1);
85
+}
86
+
87
+
88
static void ibex_timer_class_init(ObjectClass *klass, void *data)
89
{
90
DeviceClass *dc = DEVICE_CLASS(klass);
91
92
dc->reset = ibex_timer_reset;
93
dc->vmsd = &vmstate_ibex_timer;
94
+ dc->realize = ibex_timer_realize;
95
device_class_set_props(dc, ibex_timer_properties);
96
}
97
98
--
99
2.31.1
100
101
diff view generated by jsdifflib
New patch
1
From: Alistair Francis <alistair.francis@wdc.com>
1
2
3
This is the initial commit of the SiFive PWM timer. This is used by
4
guest software as a timer and is included in the SiFive FU540 SoC.
5
6
Signed-off-by: Justin Restivo <jrestivo@draper.com>
7
Signed-off-by: Alexandra Clifford <aclifford@draper.com>
8
Signed-off-by: Amanda Strnad <astrnad@draper.com>
9
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
10
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
11
Message-id: 9f70a210acbfaf0e1ea6ad311ab892ac69134d8b.1631159656.git.alistair.francis@wdc.com
12
---
13
include/hw/timer/sifive_pwm.h | 62 +++++
14
hw/timer/sifive_pwm.c | 468 ++++++++++++++++++++++++++++++++++
15
hw/timer/Kconfig | 3 +
16
hw/timer/meson.build | 1 +
17
hw/timer/trace-events | 6 +
18
5 files changed, 540 insertions(+)
19
create mode 100644 include/hw/timer/sifive_pwm.h
20
create mode 100644 hw/timer/sifive_pwm.c
21
22
diff --git a/include/hw/timer/sifive_pwm.h b/include/hw/timer/sifive_pwm.h
23
new file mode 100644
24
index XXXXXXX..XXXXXXX
25
--- /dev/null
26
+++ b/include/hw/timer/sifive_pwm.h
27
@@ -XXX,XX +XXX,XX @@
28
+/*
29
+ * SiFive PWM
30
+ *
31
+ * Copyright (c) 2020 Western Digital
32
+ *
33
+ * Author: Alistair Francis <alistair.francis@wdc.com>
34
+ *
35
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
36
+ * of this software and associated documentation files (the "Software"), to deal
37
+ * in the Software without restriction, including without limitation the rights
38
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
39
+ * copies of the Software, and to permit persons to whom the Software is
40
+ * furnished to do so, subject to the following conditions:
41
+ *
42
+ * The above copyright notice and this permission notice shall be included in
43
+ * all copies or substantial portions of the Software.
44
+ *
45
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
46
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
47
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
48
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
49
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
50
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
51
+ * THE SOFTWARE.
52
+ */
53
+
54
+#ifndef HW_SIFIVE_PWM_H
55
+#define HW_SIFIVE_PWM_H
56
+
57
+#include "hw/sysbus.h"
58
+#include "qemu/timer.h"
59
+#include "qom/object.h"
60
+
61
+#define TYPE_SIFIVE_PWM "sifive-pwm"
62
+
63
+#define SIFIVE_PWM(obj) \
64
+ OBJECT_CHECK(SiFivePwmState, (obj), TYPE_SIFIVE_PWM)
65
+
66
+#define SIFIVE_PWM_CHANS 4
67
+#define SIFIVE_PWM_IRQS SIFIVE_PWM_CHANS
68
+
69
+typedef struct SiFivePwmState {
70
+ /* <private> */
71
+ SysBusDevice parent_obj;
72
+
73
+ /* <public> */
74
+ MemoryRegion mmio;
75
+ QEMUTimer timer[SIFIVE_PWM_CHANS];
76
+ /*
77
+ * if en bit(s) set, is the number of ticks when pwmcount was 0
78
+ * if en bit(s) not set, is the number of ticks in pwmcount
79
+ */
80
+ uint64_t tick_offset;
81
+ uint64_t freq_hz;
82
+
83
+ uint32_t pwmcfg;
84
+ uint32_t pwmcmp[SIFIVE_PWM_CHANS];
85
+
86
+ qemu_irq irqs[SIFIVE_PWM_IRQS];
87
+} SiFivePwmState;
88
+
89
+#endif /* HW_SIFIVE_PWM_H */
90
diff --git a/hw/timer/sifive_pwm.c b/hw/timer/sifive_pwm.c
91
new file mode 100644
92
index XXXXXXX..XXXXXXX
93
--- /dev/null
94
+++ b/hw/timer/sifive_pwm.c
95
@@ -XXX,XX +XXX,XX @@
96
+/*
97
+ * SiFive PWM
98
+ *
99
+ * Copyright (c) 2020 Western Digital
100
+ *
101
+ * Author: Alistair Francis <alistair.francis@wdc.com>
102
+ *
103
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
104
+ * of this software and associated documentation files (the "Software"), to deal
105
+ * in the Software without restriction, including without limitation the rights
106
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
107
+ * copies of the Software, and to permit persons to whom the Software is
108
+ * furnished to do so, subject to the following conditions:
109
+ *
110
+ * The above copyright notice and this permission notice shall be included in
111
+ * all copies or substantial portions of the Software.
112
+ *
113
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
114
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
115
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
116
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
117
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
118
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
119
+ * THE SOFTWARE.
120
+ */
121
+
122
+#include "qemu/osdep.h"
123
+#include "trace.h"
124
+#include "hw/irq.h"
125
+#include "hw/timer/sifive_pwm.h"
126
+#include "hw/qdev-properties.h"
127
+#include "hw/registerfields.h"
128
+#include "migration/vmstate.h"
129
+#include "qemu/log.h"
130
+#include "qemu/module.h"
131
+
132
+#define HAS_PWM_EN_BITS(cfg) ((cfg & R_CONFIG_ENONESHOT_MASK) || \
133
+ (cfg & R_CONFIG_ENALWAYS_MASK))
134
+
135
+#define PWMCMP_MASK 0xFFFF
136
+#define PWMCOUNT_MASK 0x7FFFFFFF
137
+
138
+REG32(CONFIG, 0x00)
139
+ FIELD(CONFIG, SCALE, 0, 4)
140
+ FIELD(CONFIG, STICKY, 8, 1)
141
+ FIELD(CONFIG, ZEROCMP, 9, 1)
142
+ FIELD(CONFIG, DEGLITCH, 10, 1)
143
+ FIELD(CONFIG, ENALWAYS, 12, 1)
144
+ FIELD(CONFIG, ENONESHOT, 13, 1)
145
+ FIELD(CONFIG, CMP0CENTER, 16, 1)
146
+ FIELD(CONFIG, CMP1CENTER, 17, 1)
147
+ FIELD(CONFIG, CMP2CENTER, 18, 1)
148
+ FIELD(CONFIG, CMP3CENTER, 19, 1)
149
+ FIELD(CONFIG, CMP0GANG, 24, 1)
150
+ FIELD(CONFIG, CMP1GANG, 25, 1)
151
+ FIELD(CONFIG, CMP2GANG, 26, 1)
152
+ FIELD(CONFIG, CMP3GANG, 27, 1)
153
+ FIELD(CONFIG, CMP0IP, 28, 1)
154
+ FIELD(CONFIG, CMP1IP, 29, 1)
155
+ FIELD(CONFIG, CMP2IP, 30, 1)
156
+ FIELD(CONFIG, CMP3IP, 31, 1)
157
+REG32(COUNT, 0x08)
158
+REG32(PWMS, 0x10)
159
+REG32(PWMCMP0, 0x20)
160
+REG32(PWMCMP1, 0x24)
161
+REG32(PWMCMP2, 0x28)
162
+REG32(PWMCMP3, 0x2C)
163
+
164
+static inline uint64_t sifive_pwm_ns_to_ticks(SiFivePwmState *s,
165
+ uint64_t time)
166
+{
167
+ return muldiv64(time, s->freq_hz, NANOSECONDS_PER_SECOND);
168
+}
169
+
170
+static inline uint64_t sifive_pwm_ticks_to_ns(SiFivePwmState *s,
171
+ uint64_t ticks)
172
+{
173
+ return muldiv64(ticks, NANOSECONDS_PER_SECOND, s->freq_hz);
174
+}
175
+
176
+static inline uint64_t sifive_pwm_compute_scale(SiFivePwmState *s)
177
+{
178
+ return s->pwmcfg & R_CONFIG_SCALE_MASK;
179
+}
180
+
181
+static void sifive_pwm_set_alarms(SiFivePwmState *s)
182
+{
183
+ uint64_t now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
184
+
185
+ if (HAS_PWM_EN_BITS(s->pwmcfg)) {
186
+ /*
187
+ * Subtract ticks from number of ticks when the timer was zero
188
+ * and mask to the register width.
189
+ */
190
+ uint64_t pwmcount = (sifive_pwm_ns_to_ticks(s, now_ns) -
191
+ s->tick_offset) & PWMCOUNT_MASK;
192
+ uint64_t scale = sifive_pwm_compute_scale(s);
193
+ /* PWMs only contains PWMCMP_MASK bits starting at scale */
194
+ uint64_t pwms = (pwmcount & (PWMCMP_MASK << scale)) >> scale;
195
+
196
+ for (int i = 0; i < SIFIVE_PWM_CHANS; i++) {
197
+ uint64_t pwmcmp = s->pwmcmp[i] & PWMCMP_MASK;
198
+ uint64_t pwmcmp_ticks = pwmcmp << scale;
199
+
200
+ /*
201
+ * Per circuit diagram and spec, both cases raises corresponding
202
+ * IP bit one clock cycle after time expires.
203
+ */
204
+ if (pwmcmp > pwms) {
205
+ uint64_t offset = pwmcmp_ticks - pwmcount + 1;
206
+ uint64_t when_to_fire = now_ns +
207
+ sifive_pwm_ticks_to_ns(s, offset);
208
+
209
+ trace_sifive_pwm_set_alarm(when_to_fire, now_ns);
210
+ timer_mod(&s->timer[i], when_to_fire);
211
+ } else {
212
+ /* Schedule interrupt for next cycle */
213
+ trace_sifive_pwm_set_alarm(now_ns + 1, now_ns);
214
+ timer_mod(&s->timer[i], now_ns + 1);
215
+ }
216
+
217
+ }
218
+ } else {
219
+ /*
220
+ * If timer incrementing disabled, just do pwms > pwmcmp check since
221
+ * a write may have happened to PWMs.
222
+ */
223
+ uint64_t pwmcount = (s->tick_offset) & PWMCOUNT_MASK;
224
+ uint64_t scale = sifive_pwm_compute_scale(s);
225
+ uint64_t pwms = (pwmcount & (PWMCMP_MASK << scale)) >> scale;
226
+
227
+ for (int i = 0; i < SIFIVE_PWM_CHANS; i++) {
228
+ uint64_t pwmcmp = s->pwmcmp[i] & PWMCMP_MASK;
229
+
230
+ if (pwms >= pwmcmp) {
231
+ trace_sifive_pwm_set_alarm(now_ns + 1, now_ns);
232
+ timer_mod(&s->timer[i], now_ns + 1);
233
+ } else {
234
+ /* Effectively disable timer by scheduling far in future. */
235
+ trace_sifive_pwm_set_alarm(0xFFFFFFFFFFFFFF, now_ns);
236
+ timer_mod(&s->timer[i], 0xFFFFFFFFFFFFFF);
237
+ }
238
+ }
239
+ }
240
+}
241
+
242
+static void sifive_pwm_interrupt(SiFivePwmState *s, int num)
243
+{
244
+ uint64_t now = sifive_pwm_ns_to_ticks(s,
245
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
246
+ bool was_incrementing = HAS_PWM_EN_BITS(s->pwmcfg);
247
+
248
+ trace_sifive_pwm_interrupt(num);
249
+
250
+ s->pwmcfg |= R_CONFIG_CMP0IP_MASK << num;
251
+ qemu_irq_raise(s->irqs[num]);
252
+
253
+ /*
254
+ * If the zerocmp is set and pwmcmp0 raised the interrupt
255
+ * reset the zero ticks.
256
+ */
257
+ if ((s->pwmcfg & R_CONFIG_ZEROCMP_MASK) && (num == 0)) {
258
+ /* If reset signal conditions, disable ENONESHOT. */
259
+ s->pwmcfg &= ~R_CONFIG_ENONESHOT_MASK;
260
+
261
+ if (was_incrementing) {
262
+ /* If incrementing, time in ticks is when pwmcount is zero */
263
+ s->tick_offset = now;
264
+ } else {
265
+ /* If not incrementing, pwmcount = 0 */
266
+ s->tick_offset = 0;
267
+ }
268
+ }
269
+
270
+ /*
271
+ * If carryout bit set, which we discern via looking for overflow,
272
+ * also reset ENONESHOT.
273
+ */
274
+ if (was_incrementing &&
275
+ ((now & PWMCOUNT_MASK) < (s->tick_offset & PWMCOUNT_MASK))) {
276
+ s->pwmcfg &= ~R_CONFIG_ENONESHOT_MASK;
277
+ }
278
+
279
+ /* Schedule or disable interrupts */
280
+ sifive_pwm_set_alarms(s);
281
+
282
+ /* If was enabled, and now not enabled, switch tick rep */
283
+ if (was_incrementing && !HAS_PWM_EN_BITS(s->pwmcfg)) {
284
+ s->tick_offset = (now - s->tick_offset) & PWMCOUNT_MASK;
285
+ }
286
+}
287
+
288
+static void sifive_pwm_interrupt_0(void *opaque)
289
+{
290
+ SiFivePwmState *s = opaque;
291
+
292
+ sifive_pwm_interrupt(s, 0);
293
+}
294
+
295
+static void sifive_pwm_interrupt_1(void *opaque)
296
+{
297
+ SiFivePwmState *s = opaque;
298
+
299
+ sifive_pwm_interrupt(s, 1);
300
+}
301
+
302
+static void sifive_pwm_interrupt_2(void *opaque)
303
+{
304
+ SiFivePwmState *s = opaque;
305
+
306
+ sifive_pwm_interrupt(s, 2);
307
+}
308
+
309
+static void sifive_pwm_interrupt_3(void *opaque)
310
+{
311
+ SiFivePwmState *s = opaque;
312
+
313
+ sifive_pwm_interrupt(s, 3);
314
+}
315
+
316
+static uint64_t sifive_pwm_read(void *opaque, hwaddr addr,
317
+ unsigned int size)
318
+{
319
+ SiFivePwmState *s = opaque;
320
+ uint64_t cur_time, scale;
321
+ uint64_t now = sifive_pwm_ns_to_ticks(s,
322
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
323
+
324
+ trace_sifive_pwm_read(addr);
325
+
326
+ switch (addr) {
327
+ case A_CONFIG:
328
+ return s->pwmcfg;
329
+ case A_COUNT:
330
+ cur_time = s->tick_offset;
331
+
332
+ if (HAS_PWM_EN_BITS(s->pwmcfg)) {
333
+ cur_time = now - cur_time;
334
+ }
335
+
336
+ /*
337
+ * Return the value in the counter with bit 31 always 0
338
+ * This is allowed to wrap around so we don't need to check that.
339
+ */
340
+ return cur_time & PWMCOUNT_MASK;
341
+ case A_PWMS:
342
+ cur_time = s->tick_offset;
343
+ scale = sifive_pwm_compute_scale(s);
344
+
345
+ if (HAS_PWM_EN_BITS(s->pwmcfg)) {
346
+ cur_time = now - cur_time;
347
+ }
348
+
349
+ return ((cur_time & PWMCOUNT_MASK) >> scale) & PWMCMP_MASK;
350
+ case A_PWMCMP0:
351
+ return s->pwmcmp[0] & PWMCMP_MASK;
352
+ case A_PWMCMP1:
353
+ return s->pwmcmp[1] & PWMCMP_MASK;
354
+ case A_PWMCMP2:
355
+ return s->pwmcmp[2] & PWMCMP_MASK;
356
+ case A_PWMCMP3:
357
+ return s->pwmcmp[3] & PWMCMP_MASK;
358
+ default:
359
+ qemu_log_mask(LOG_GUEST_ERROR,
360
+ "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
361
+ return 0;
362
+ }
363
+
364
+ return 0;
365
+}
366
+
367
+static void sifive_pwm_write(void *opaque, hwaddr addr,
368
+ uint64_t val64, unsigned int size)
369
+{
370
+ SiFivePwmState *s = opaque;
371
+ uint32_t value = val64;
372
+ uint64_t new_offset, scale;
373
+ uint64_t now = sifive_pwm_ns_to_ticks(s,
374
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
375
+
376
+ trace_sifive_pwm_write(value, addr);
377
+
378
+ switch (addr) {
379
+ case A_CONFIG:
380
+ if (value & (R_CONFIG_CMP0CENTER_MASK | R_CONFIG_CMP1CENTER_MASK |
381
+ R_CONFIG_CMP2CENTER_MASK | R_CONFIG_CMP3CENTER_MASK)) {
382
+ qemu_log_mask(LOG_UNIMP, "%s: CMPxCENTER is not supported\n",
383
+ __func__);
384
+ }
385
+
386
+ if (value & (R_CONFIG_CMP0GANG_MASK | R_CONFIG_CMP1GANG_MASK |
387
+ R_CONFIG_CMP2GANG_MASK | R_CONFIG_CMP3GANG_MASK)) {
388
+ qemu_log_mask(LOG_UNIMP, "%s: CMPxGANG is not supported\n",
389
+ __func__);
390
+ }
391
+
392
+ if (value & (R_CONFIG_CMP0IP_MASK | R_CONFIG_CMP1IP_MASK |
393
+ R_CONFIG_CMP2IP_MASK | R_CONFIG_CMP3IP_MASK)) {
394
+ qemu_log_mask(LOG_UNIMP, "%s: CMPxIP is not supported\n",
395
+ __func__);
396
+ }
397
+
398
+ if (!(value & R_CONFIG_CMP0IP_MASK)) {
399
+ qemu_irq_lower(s->irqs[0]);
400
+ }
401
+
402
+ if (!(value & R_CONFIG_CMP1IP_MASK)) {
403
+ qemu_irq_lower(s->irqs[1]);
404
+ }
405
+
406
+ if (!(value & R_CONFIG_CMP2IP_MASK)) {
407
+ qemu_irq_lower(s->irqs[2]);
408
+ }
409
+
410
+ if (!(value & R_CONFIG_CMP3IP_MASK)) {
411
+ qemu_irq_lower(s->irqs[3]);
412
+ }
413
+
414
+ /*
415
+ * If this write enables the timer increment
416
+ * set the time when pwmcount was zero to be cur_time - pwmcount.
417
+ * If this write disables the timer increment
418
+ * convert back from pwmcount to the time in ticks
419
+ * when pwmcount was zero.
420
+ */
421
+ if ((!HAS_PWM_EN_BITS(s->pwmcfg) && HAS_PWM_EN_BITS(value)) ||
422
+ (HAS_PWM_EN_BITS(s->pwmcfg) && !HAS_PWM_EN_BITS(value))) {
423
+ s->tick_offset = (now - s->tick_offset) & PWMCOUNT_MASK;
424
+ }
425
+
426
+ s->pwmcfg = value;
427
+ break;
428
+ case A_COUNT:
429
+ /* The guest changed the counter, updated the offset value. */
430
+ new_offset = value;
431
+
432
+ if (HAS_PWM_EN_BITS(s->pwmcfg)) {
433
+ new_offset = now - new_offset;
434
+ }
435
+
436
+ s->tick_offset = new_offset;
437
+ break;
438
+ case A_PWMS:
439
+ scale = sifive_pwm_compute_scale(s);
440
+ new_offset = (((value & PWMCMP_MASK) << scale) & PWMCOUNT_MASK);
441
+
442
+ if (HAS_PWM_EN_BITS(s->pwmcfg)) {
443
+ new_offset = now - new_offset;
444
+ }
445
+
446
+ s->tick_offset = new_offset;
447
+ break;
448
+ case A_PWMCMP0:
449
+ s->pwmcmp[0] = value & PWMCMP_MASK;
450
+ break;
451
+ case A_PWMCMP1:
452
+ s->pwmcmp[1] = value & PWMCMP_MASK;
453
+ break;
454
+ case A_PWMCMP2:
455
+ s->pwmcmp[2] = value & PWMCMP_MASK;
456
+ break;
457
+ case A_PWMCMP3:
458
+ s->pwmcmp[3] = value & PWMCMP_MASK;
459
+ break;
460
+ default:
461
+ qemu_log_mask(LOG_GUEST_ERROR,
462
+ "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
463
+ }
464
+
465
+ /* Update the alarms to reflect possible updated values */
466
+ sifive_pwm_set_alarms(s);
467
+}
468
+
469
+static void sifive_pwm_reset(DeviceState *dev)
470
+{
471
+ SiFivePwmState *s = SIFIVE_PWM(dev);
472
+ uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
473
+
474
+ s->pwmcfg = 0x00000000;
475
+ s->pwmcmp[0] = 0x00000000;
476
+ s->pwmcmp[1] = 0x00000000;
477
+ s->pwmcmp[2] = 0x00000000;
478
+ s->pwmcmp[3] = 0x00000000;
479
+
480
+ s->tick_offset = sifive_pwm_ns_to_ticks(s, now);
481
+}
482
+
483
+static const MemoryRegionOps sifive_pwm_ops = {
484
+ .read = sifive_pwm_read,
485
+ .write = sifive_pwm_write,
486
+ .endianness = DEVICE_NATIVE_ENDIAN,
487
+};
488
+
489
+static const VMStateDescription vmstate_sifive_pwm = {
490
+ .name = TYPE_SIFIVE_PWM,
491
+ .version_id = 1,
492
+ .minimum_version_id = 1,
493
+ .fields = (VMStateField[]) {
494
+ VMSTATE_TIMER_ARRAY(timer, SiFivePwmState, 4),
495
+ VMSTATE_UINT64(tick_offset, SiFivePwmState),
496
+ VMSTATE_UINT32(pwmcfg, SiFivePwmState),
497
+ VMSTATE_UINT32_ARRAY(pwmcmp, SiFivePwmState, 4),
498
+ VMSTATE_END_OF_LIST()
499
+ }
500
+};
501
+
502
+static Property sifive_pwm_properties[] = {
503
+ /* 0.5Ghz per spec after FSBL */
504
+ DEFINE_PROP_UINT64("clock-frequency", struct SiFivePwmState,
505
+ freq_hz, 500000000ULL),
506
+ DEFINE_PROP_END_OF_LIST(),
507
+};
508
+
509
+static void sifive_pwm_init(Object *obj)
510
+{
511
+ SiFivePwmState *s = SIFIVE_PWM(obj);
512
+ int i;
513
+
514
+ for (i = 0; i < SIFIVE_PWM_IRQS; i++) {
515
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irqs[i]);
516
+ }
517
+
518
+ memory_region_init_io(&s->mmio, obj, &sifive_pwm_ops, s,
519
+ TYPE_SIFIVE_PWM, 0x100);
520
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
521
+}
522
+
523
+static void sifive_pwm_realize(DeviceState *dev, Error **errp)
524
+{
525
+ SiFivePwmState *s = SIFIVE_PWM(dev);
526
+
527
+ timer_init_ns(&s->timer[0], QEMU_CLOCK_VIRTUAL,
528
+ sifive_pwm_interrupt_0, s);
529
+
530
+ timer_init_ns(&s->timer[1], QEMU_CLOCK_VIRTUAL,
531
+ sifive_pwm_interrupt_1, s);
532
+
533
+ timer_init_ns(&s->timer[2], QEMU_CLOCK_VIRTUAL,
534
+ sifive_pwm_interrupt_2, s);
535
+
536
+ timer_init_ns(&s->timer[3], QEMU_CLOCK_VIRTUAL,
537
+ sifive_pwm_interrupt_3, s);
538
+}
539
+
540
+static void sifive_pwm_class_init(ObjectClass *klass, void *data)
541
+{
542
+ DeviceClass *dc = DEVICE_CLASS(klass);
543
+
544
+ dc->reset = sifive_pwm_reset;
545
+ device_class_set_props(dc, sifive_pwm_properties);
546
+ dc->vmsd = &vmstate_sifive_pwm;
547
+ dc->realize = sifive_pwm_realize;
548
+}
549
+
550
+static const TypeInfo sifive_pwm_info = {
551
+ .name = TYPE_SIFIVE_PWM,
552
+ .parent = TYPE_SYS_BUS_DEVICE,
553
+ .instance_size = sizeof(SiFivePwmState),
554
+ .instance_init = sifive_pwm_init,
555
+ .class_init = sifive_pwm_class_init,
556
+};
557
+
558
+static void sifive_pwm_register_types(void)
559
+{
560
+ type_register_static(&sifive_pwm_info);
561
+}
562
+
563
+type_init(sifive_pwm_register_types)
564
diff --git a/hw/timer/Kconfig b/hw/timer/Kconfig
565
index XXXXXXX..XXXXXXX 100644
566
--- a/hw/timer/Kconfig
567
+++ b/hw/timer/Kconfig
568
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_A10_PIT
569
bool
570
select PTIMER
571
572
+config SIFIVE_PWM
573
+ bool
574
+
575
config STM32F2XX_TIMER
576
bool
577
578
diff --git a/hw/timer/meson.build b/hw/timer/meson.build
579
index XXXXXXX..XXXXXXX 100644
580
--- a/hw/timer/meson.build
581
+++ b/hw/timer/meson.build
582
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_STELLARIS_GPTM', if_true: files('stellaris-gptm.c')
583
softmmu_ss.add(when: 'CONFIG_STM32F2XX_TIMER', if_true: files('stm32f2xx_timer.c'))
584
softmmu_ss.add(when: 'CONFIG_XILINX', if_true: files('xilinx_timer.c'))
585
specific_ss.add(when: 'CONFIG_IBEX', if_true: files('ibex_timer.c'))
586
+softmmu_ss.add(when: 'CONFIG_SIFIVE_PWM', if_true: files('sifive_pwm.c'))
587
588
specific_ss.add(when: 'CONFIG_AVR_TIMER16', if_true: files('avr_timer16.c'))
589
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
590
index XXXXXXX..XXXXXXX 100644
591
--- a/hw/timer/trace-events
592
+++ b/hw/timer/trace-events
593
@@ -XXX,XX +XXX,XX @@ sse_counter_reset(void) "SSE system counter: reset"
594
sse_timer_read(uint64_t offset, uint64_t data, unsigned size) "SSE system timer read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
595
sse_timer_write(uint64_t offset, uint64_t data, unsigned size) "SSE system timer write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
596
sse_timer_reset(void) "SSE system timer: reset"
597
+
598
+# sifive_pwm.c
599
+sifive_pwm_set_alarm(uint64_t alarm, uint64_t now) "Setting alarm to: 0x%" PRIx64 ", now: 0x%" PRIx64
600
+sifive_pwm_interrupt(int num) "Interrupt %d"
601
+sifive_pwm_read(uint64_t offset) "Read at address: 0x%" PRIx64
602
+sifive_pwm_write(uint64_t data, uint64_t offset) "Write 0x%" PRIx64 " at address: 0x%" PRIx64
603
--
604
2.31.1
605
606
diff view generated by jsdifflib
New patch
1
From: Alistair Francis <alistair.francis@wdc.com>
1
2
3
Connect the SiFive PWM device and expose it via the device tree.
4
5
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
6
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
7
Message-id: 22f98648b4e012f78529a56f5ca60b0b27852a4d.1631159656.git.alistair.francis@wdc.com
8
---
9
docs/system/riscv/sifive_u.rst | 1 +
10
include/hw/riscv/sifive_u.h | 14 ++++++++-
11
hw/riscv/sifive_u.c | 55 +++++++++++++++++++++++++++++++++-
12
hw/riscv/Kconfig | 1 +
13
4 files changed, 69 insertions(+), 2 deletions(-)
14
15
diff --git a/docs/system/riscv/sifive_u.rst b/docs/system/riscv/sifive_u.rst
16
index XXXXXXX..XXXXXXX 100644
17
--- a/docs/system/riscv/sifive_u.rst
18
+++ b/docs/system/riscv/sifive_u.rst
19
@@ -XXX,XX +XXX,XX @@ The ``sifive_u`` machine supports the following devices:
20
* 2 QSPI controllers
21
* 1 ISSI 25WP256 flash
22
* 1 SD card in SPI mode
23
+* PWM0 and PWM1
24
25
Please note the real world HiFive Unleashed board has a fixed configuration of
26
1 E51 core and 4 U54 core combination and the RISC-V core boots in 64-bit mode.
27
diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/include/hw/riscv/sifive_u.h
30
+++ b/include/hw/riscv/sifive_u.h
31
@@ -XXX,XX +XXX,XX @@
32
#include "hw/misc/sifive_u_otp.h"
33
#include "hw/misc/sifive_u_prci.h"
34
#include "hw/ssi/sifive_spi.h"
35
+#include "hw/timer/sifive_pwm.h"
36
37
#define TYPE_RISCV_U_SOC "riscv.sifive.u.soc"
38
#define RISCV_U_SOC(obj) \
39
@@ -XXX,XX +XXX,XX @@ typedef struct SiFiveUSoCState {
40
SiFiveSPIState spi0;
41
SiFiveSPIState spi2;
42
CadenceGEMState gem;
43
+ SiFivePwmState pwm[2];
44
45
uint32_t serial;
46
char *cpu_type;
47
@@ -XXX,XX +XXX,XX @@ enum {
48
SIFIVE_U_DEV_FLASH0,
49
SIFIVE_U_DEV_DRAM,
50
SIFIVE_U_DEV_GEM,
51
- SIFIVE_U_DEV_GEM_MGMT
52
+ SIFIVE_U_DEV_GEM_MGMT,
53
+ SIFIVE_U_DEV_PWM0,
54
+ SIFIVE_U_DEV_PWM1
55
};
56
57
enum {
58
@@ -XXX,XX +XXX,XX @@ enum {
59
SIFIVE_U_PDMA_IRQ5 = 28,
60
SIFIVE_U_PDMA_IRQ6 = 29,
61
SIFIVE_U_PDMA_IRQ7 = 30,
62
+ SIFIVE_U_PWM0_IRQ0 = 42,
63
+ SIFIVE_U_PWM0_IRQ1 = 43,
64
+ SIFIVE_U_PWM0_IRQ2 = 44,
65
+ SIFIVE_U_PWM0_IRQ3 = 45,
66
+ SIFIVE_U_PWM1_IRQ0 = 46,
67
+ SIFIVE_U_PWM1_IRQ1 = 47,
68
+ SIFIVE_U_PWM1_IRQ2 = 48,
69
+ SIFIVE_U_PWM1_IRQ3 = 49,
70
SIFIVE_U_QSPI0_IRQ = 51,
71
SIFIVE_U_GEM_IRQ = 53
72
};
73
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/hw/riscv/sifive_u.c
76
+++ b/hw/riscv/sifive_u.c
77
@@ -XXX,XX +XXX,XX @@
78
* 7) DMA (Direct Memory Access Controller)
79
* 8) SPI0 connected to an SPI flash
80
* 9) SPI2 connected to an SD card
81
+ * 10) PWM0 and PWM1
82
*
83
* This board currently generates devicetree dynamically that indicates at least
84
* two harts and up to five harts.
85
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry sifive_u_memmap[] = {
86
[SIFIVE_U_DEV_PRCI] = { 0x10000000, 0x1000 },
87
[SIFIVE_U_DEV_UART0] = { 0x10010000, 0x1000 },
88
[SIFIVE_U_DEV_UART1] = { 0x10011000, 0x1000 },
89
+ [SIFIVE_U_DEV_PWM0] = { 0x10020000, 0x1000 },
90
+ [SIFIVE_U_DEV_PWM1] = { 0x10021000, 0x1000 },
91
[SIFIVE_U_DEV_QSPI0] = { 0x10040000, 0x1000 },
92
[SIFIVE_U_DEV_QSPI2] = { 0x10050000, 0x1000 },
93
[SIFIVE_U_DEV_GPIO] = { 0x10060000, 0x1000 },
94
@@ -XXX,XX +XXX,XX @@ static void create_fdt(SiFiveUState *s, const MemMapEntry *memmap,
95
qemu_fdt_setprop_cell(fdt, nodename, "reg", 0x0);
96
g_free(nodename);
97
98
+ nodename = g_strdup_printf("/soc/pwm@%lx",
99
+ (long)memmap[SIFIVE_U_DEV_PWM0].base);
100
+ qemu_fdt_add_subnode(fdt, nodename);
101
+ qemu_fdt_setprop_string(fdt, nodename, "compatible", "sifive,pwm0");
102
+ qemu_fdt_setprop_cells(fdt, nodename, "reg",
103
+ 0x0, memmap[SIFIVE_U_DEV_PWM0].base,
104
+ 0x0, memmap[SIFIVE_U_DEV_PWM0].size);
105
+ qemu_fdt_setprop_cell(fdt, nodename, "interrupt-parent", plic_phandle);
106
+ qemu_fdt_setprop_cells(fdt, nodename, "interrupts",
107
+ SIFIVE_U_PWM0_IRQ0, SIFIVE_U_PWM0_IRQ1,
108
+ SIFIVE_U_PWM0_IRQ2, SIFIVE_U_PWM0_IRQ3);
109
+ qemu_fdt_setprop_cells(fdt, nodename, "clocks",
110
+ prci_phandle, PRCI_CLK_TLCLK);
111
+ qemu_fdt_setprop_cell(fdt, nodename, "#pwm-cells", 0);
112
+ g_free(nodename);
113
+
114
+ nodename = g_strdup_printf("/soc/pwm@%lx",
115
+ (long)memmap[SIFIVE_U_DEV_PWM1].base);
116
+ qemu_fdt_add_subnode(fdt, nodename);
117
+ qemu_fdt_setprop_string(fdt, nodename, "compatible", "sifive,pwm0");
118
+ qemu_fdt_setprop_cells(fdt, nodename, "reg",
119
+ 0x0, memmap[SIFIVE_U_DEV_PWM1].base,
120
+ 0x0, memmap[SIFIVE_U_DEV_PWM1].size);
121
+ qemu_fdt_setprop_cell(fdt, nodename, "interrupt-parent", plic_phandle);
122
+ qemu_fdt_setprop_cells(fdt, nodename, "interrupts",
123
+ SIFIVE_U_PWM1_IRQ0, SIFIVE_U_PWM1_IRQ1,
124
+ SIFIVE_U_PWM1_IRQ2, SIFIVE_U_PWM1_IRQ3);
125
+ qemu_fdt_setprop_cells(fdt, nodename, "clocks",
126
+ prci_phandle, PRCI_CLK_TLCLK);
127
+ qemu_fdt_setprop_cell(fdt, nodename, "#pwm-cells", 0);
128
+ g_free(nodename);
129
+
130
nodename = g_strdup_printf("/soc/serial@%lx",
131
(long)memmap[SIFIVE_U_DEV_UART1].base);
132
qemu_fdt_add_subnode(fdt, nodename);
133
@@ -XXX,XX +XXX,XX @@ static void sifive_u_soc_instance_init(Object *obj)
134
object_initialize_child(obj, "pdma", &s->dma, TYPE_SIFIVE_PDMA);
135
object_initialize_child(obj, "spi0", &s->spi0, TYPE_SIFIVE_SPI);
136
object_initialize_child(obj, "spi2", &s->spi2, TYPE_SIFIVE_SPI);
137
+ object_initialize_child(obj, "pwm0", &s->pwm[0], TYPE_SIFIVE_PWM);
138
+ object_initialize_child(obj, "pwm1", &s->pwm[1], TYPE_SIFIVE_PWM);
139
}
140
141
static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
142
@@ -XXX,XX +XXX,XX @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
143
MemoryRegion *l2lim_mem = g_new(MemoryRegion, 1);
144
char *plic_hart_config;
145
size_t plic_hart_config_len;
146
- int i;
147
+ int i, j;
148
NICInfo *nd = &nd_table[0];
149
150
qdev_prop_set_uint32(DEVICE(&s->u_cpus), "num-harts", ms->smp.cpus - 1);
151
@@ -XXX,XX +XXX,XX @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
152
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gem), 0,
153
qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_U_GEM_IRQ));
154
155
+ /* PWM */
156
+ for (i = 0; i < 2; i++) {
157
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->pwm[i]), errp)) {
158
+ return;
159
+ }
160
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->pwm[i]), 0,
161
+ memmap[SIFIVE_U_DEV_PWM0].base + (0x1000 * i));
162
+
163
+ /* Connect PWM interrupts to the PLIC */
164
+ for (j = 0; j < SIFIVE_PWM_IRQS; j++) {
165
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->pwm[i]), j,
166
+ qdev_get_gpio_in(DEVICE(s->plic),
167
+ SIFIVE_U_PWM0_IRQ0 + (i * 4) + j));
168
+ }
169
+ }
170
+
171
create_unimplemented_device("riscv.sifive.u.gem-mgmt",
172
memmap[SIFIVE_U_DEV_GEM_MGMT].base, memmap[SIFIVE_U_DEV_GEM_MGMT].size);
173
174
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
175
index XXXXXXX..XXXXXXX 100644
176
--- a/hw/riscv/Kconfig
177
+++ b/hw/riscv/Kconfig
178
@@ -XXX,XX +XXX,XX @@ config SIFIVE_U
179
select SIFIVE_UART
180
select SIFIVE_U_OTP
181
select SIFIVE_U_PRCI
182
+ select SIFIVE_PWM
183
select SSI_M25P80
184
select SSI_SD
185
select UNIMP
186
--
187
2.31.1
188
189
diff view generated by jsdifflib
New patch
1
1
From: Anup Patel <anup.patel@wdc.com>
2
3
We will be upgrading SiFive CLINT implementation into RISC-V ACLINT
4
implementation so let's first rename the sources.
5
6
Signed-off-by: Anup Patel <anup.patel@wdc.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
9
Message-id: 20210831110603.338681-2-anup.patel@wdc.com
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
---
12
include/hw/intc/{sifive_clint.h => riscv_aclint.h} | 0
13
hw/intc/{sifive_clint.c => riscv_aclint.c} | 2 +-
14
hw/riscv/microchip_pfsoc.c | 2 +-
15
hw/riscv/shakti_c.c | 2 +-
16
hw/riscv/sifive_e.c | 2 +-
17
hw/riscv/sifive_u.c | 2 +-
18
hw/riscv/spike.c | 2 +-
19
hw/riscv/virt.c | 2 +-
20
hw/intc/Kconfig | 2 +-
21
hw/intc/meson.build | 2 +-
22
hw/riscv/Kconfig | 12 ++++++------
23
11 files changed, 15 insertions(+), 15 deletions(-)
24
rename include/hw/intc/{sifive_clint.h => riscv_aclint.h} (100%)
25
rename hw/intc/{sifive_clint.c => riscv_aclint.c} (99%)
26
27
diff --git a/include/hw/intc/sifive_clint.h b/include/hw/intc/riscv_aclint.h
28
similarity index 100%
29
rename from include/hw/intc/sifive_clint.h
30
rename to include/hw/intc/riscv_aclint.h
31
diff --git a/hw/intc/sifive_clint.c b/hw/intc/riscv_aclint.c
32
similarity index 99%
33
rename from hw/intc/sifive_clint.c
34
rename to hw/intc/riscv_aclint.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/intc/sifive_clint.c
37
+++ b/hw/intc/riscv_aclint.c
38
@@ -XXX,XX +XXX,XX @@
39
#include "hw/sysbus.h"
40
#include "target/riscv/cpu.h"
41
#include "hw/qdev-properties.h"
42
-#include "hw/intc/sifive_clint.h"
43
+#include "hw/intc/riscv_aclint.h"
44
#include "qemu/timer.h"
45
#include "hw/irq.h"
46
47
diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/riscv/microchip_pfsoc.c
50
+++ b/hw/riscv/microchip_pfsoc.c
51
@@ -XXX,XX +XXX,XX @@
52
#include "hw/riscv/boot.h"
53
#include "hw/riscv/riscv_hart.h"
54
#include "hw/riscv/microchip_pfsoc.h"
55
-#include "hw/intc/sifive_clint.h"
56
+#include "hw/intc/riscv_aclint.h"
57
#include "hw/intc/sifive_plic.h"
58
#include "sysemu/device_tree.h"
59
#include "sysemu/sysemu.h"
60
diff --git a/hw/riscv/shakti_c.c b/hw/riscv/shakti_c.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/hw/riscv/shakti_c.c
63
+++ b/hw/riscv/shakti_c.c
64
@@ -XXX,XX +XXX,XX @@
65
#include "hw/riscv/shakti_c.h"
66
#include "qapi/error.h"
67
#include "hw/intc/sifive_plic.h"
68
-#include "hw/intc/sifive_clint.h"
69
+#include "hw/intc/riscv_aclint.h"
70
#include "sysemu/sysemu.h"
71
#include "hw/qdev-properties.h"
72
#include "exec/address-spaces.h"
73
diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/hw/riscv/sifive_e.c
76
+++ b/hw/riscv/sifive_e.c
77
@@ -XXX,XX +XXX,XX @@
78
#include "hw/riscv/sifive_e.h"
79
#include "hw/riscv/boot.h"
80
#include "hw/char/sifive_uart.h"
81
-#include "hw/intc/sifive_clint.h"
82
+#include "hw/intc/riscv_aclint.h"
83
#include "hw/intc/sifive_plic.h"
84
#include "hw/misc/sifive_e_prci.h"
85
#include "chardev/char.h"
86
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/hw/riscv/sifive_u.c
89
+++ b/hw/riscv/sifive_u.c
90
@@ -XXX,XX +XXX,XX @@
91
#include "hw/riscv/sifive_u.h"
92
#include "hw/riscv/boot.h"
93
#include "hw/char/sifive_uart.h"
94
-#include "hw/intc/sifive_clint.h"
95
+#include "hw/intc/riscv_aclint.h"
96
#include "hw/intc/sifive_plic.h"
97
#include "chardev/char.h"
98
#include "net/eth.h"
99
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/hw/riscv/spike.c
102
+++ b/hw/riscv/spike.c
103
@@ -XXX,XX +XXX,XX @@
104
#include "hw/riscv/boot.h"
105
#include "hw/riscv/numa.h"
106
#include "hw/char/riscv_htif.h"
107
-#include "hw/intc/sifive_clint.h"
108
+#include "hw/intc/riscv_aclint.h"
109
#include "chardev/char.h"
110
#include "sysemu/device_tree.h"
111
#include "sysemu/sysemu.h"
112
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
113
index XXXXXXX..XXXXXXX 100644
114
--- a/hw/riscv/virt.c
115
+++ b/hw/riscv/virt.c
116
@@ -XXX,XX +XXX,XX @@
117
#include "hw/riscv/virt.h"
118
#include "hw/riscv/boot.h"
119
#include "hw/riscv/numa.h"
120
-#include "hw/intc/sifive_clint.h"
121
+#include "hw/intc/riscv_aclint.h"
122
#include "hw/intc/sifive_plic.h"
123
#include "hw/misc/sifive_test.h"
124
#include "chardev/char.h"
125
diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
126
index XXXXXXX..XXXXXXX 100644
127
--- a/hw/intc/Kconfig
128
+++ b/hw/intc/Kconfig
129
@@ -XXX,XX +XXX,XX @@ config RX_ICU
130
config LOONGSON_LIOINTC
131
bool
132
133
-config SIFIVE_CLINT
134
+config RISCV_ACLINT
135
bool
136
137
config SIFIVE_PLIC
138
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
139
index XXXXXXX..XXXXXXX 100644
140
--- a/hw/intc/meson.build
141
+++ b/hw/intc/meson.build
142
@@ -XXX,XX +XXX,XX @@ specific_ss.add(when: 'CONFIG_RX_ICU', if_true: files('rx_icu.c'))
143
specific_ss.add(when: 'CONFIG_S390_FLIC', if_true: files('s390_flic.c'))
144
specific_ss.add(when: 'CONFIG_S390_FLIC_KVM', if_true: files('s390_flic_kvm.c'))
145
specific_ss.add(when: 'CONFIG_SH_INTC', if_true: files('sh_intc.c'))
146
-specific_ss.add(when: 'CONFIG_SIFIVE_CLINT', if_true: files('sifive_clint.c'))
147
+specific_ss.add(when: 'CONFIG_RISCV_ACLINT', if_true: files('riscv_aclint.c'))
148
specific_ss.add(when: 'CONFIG_SIFIVE_PLIC', if_true: files('sifive_plic.c'))
149
specific_ss.add(when: 'CONFIG_XICS', if_true: files('xics.c'))
150
specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_XICS'],
151
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
152
index XXXXXXX..XXXXXXX 100644
153
--- a/hw/riscv/Kconfig
154
+++ b/hw/riscv/Kconfig
155
@@ -XXX,XX +XXX,XX @@ config MICROCHIP_PFSOC
156
select MCHP_PFSOC_MMUART
157
select MCHP_PFSOC_SYSREG
158
select MSI_NONBROKEN
159
- select SIFIVE_CLINT
160
+ select RISCV_ACLINT
161
select SIFIVE_PDMA
162
select SIFIVE_PLIC
163
select UNIMP
164
@@ -XXX,XX +XXX,XX @@ config SHAKTI_C
165
bool
166
select UNIMP
167
select SHAKTI_UART
168
- select SIFIVE_CLINT
169
+ select RISCV_ACLINT
170
select SIFIVE_PLIC
171
172
config RISCV_VIRT
173
@@ -XXX,XX +XXX,XX @@ config RISCV_VIRT
174
select PCI_EXPRESS_GENERIC_BRIDGE
175
select PFLASH_CFI01
176
select SERIAL
177
- select SIFIVE_CLINT
178
+ select RISCV_ACLINT
179
select SIFIVE_PLIC
180
select SIFIVE_TEST
181
select VIRTIO_MMIO
182
@@ -XXX,XX +XXX,XX @@ config RISCV_VIRT
183
config SIFIVE_E
184
bool
185
select MSI_NONBROKEN
186
- select SIFIVE_CLINT
187
+ select RISCV_ACLINT
188
select SIFIVE_GPIO
189
select SIFIVE_PLIC
190
select SIFIVE_UART
191
@@ -XXX,XX +XXX,XX @@ config SIFIVE_U
192
bool
193
select CADENCE
194
select MSI_NONBROKEN
195
- select SIFIVE_CLINT
196
+ select RISCV_ACLINT
197
select SIFIVE_GPIO
198
select SIFIVE_PDMA
199
select SIFIVE_PLIC
200
@@ -XXX,XX +XXX,XX @@ config SPIKE
201
select RISCV_NUMA
202
select HTIF
203
select MSI_NONBROKEN
204
- select SIFIVE_CLINT
205
+ select RISCV_ACLINT
206
select SIFIVE_PLIC
207
--
208
2.31.1
209
210
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: Anup Patel <anup.patel@wdc.com>
2
2
3
Configuring a drive with "if=none" is meant for creation of a backend
3
The RISC-V ACLINT is more modular and backward compatible with
4
only, it should not get automatically assigned to a device frontend.
4
original SiFive CLINT so instead of duplicating the original
5
Use "if=pflash" for the One-Time-Programmable device instead (like
5
SiFive CLINT implementation we upgrade the current SiFive CLINT
6
it is e.g. also done for the efuse device in hw/arm/xlnx-zcu102.c).
6
implementation to RISC-V ACLINT implementation.
7
7
8
Since the old way of configuring the device has already been published
8
Signed-off-by: Anup Patel <anup.patel@wdc.com>
9
with the previous QEMU versions, we cannot remove this immediately, but
10
have to deprecate it and support it for at least two more releases.
11
12
Signed-off-by: Thomas Huth <thuth@redhat.com>
13
Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
14
Reviewed-by: Markus Armbruster <armbru@redhat.com>
15
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
16
Message-id: 20211119102549.217755-1-thuth@redhat.com
10
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
11
Message-id: 20210831110603.338681-3-anup.patel@wdc.com
17
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
18
---
13
---
19
docs/about/deprecated.rst | 6 ++++++
14
include/hw/intc/riscv_aclint.h | 54 +++--
20
hw/misc/sifive_u_otp.c | 9 ++++++++-
15
hw/intc/riscv_aclint.c | 373 +++++++++++++++++++++++----------
21
2 files changed, 14 insertions(+), 1 deletion(-)
16
hw/riscv/microchip_pfsoc.c | 9 +-
17
hw/riscv/shakti_c.c | 11 +-
18
hw/riscv/sifive_e.c | 11 +-
19
hw/riscv/sifive_u.c | 9 +-
20
hw/riscv/spike.c | 14 +-
21
hw/riscv/virt.c | 14 +-
22
8 files changed, 339 insertions(+), 156 deletions(-)
22
23
23
diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
24
diff --git a/include/hw/intc/riscv_aclint.h b/include/hw/intc/riscv_aclint.h
24
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
25
--- a/docs/about/deprecated.rst
26
--- a/include/hw/intc/riscv_aclint.h
26
+++ b/docs/about/deprecated.rst
27
+++ b/include/hw/intc/riscv_aclint.h
27
@@ -XXX,XX +XXX,XX @@ as short-form boolean values, and passed to plugins as ``arg_name=on``.
28
@@ -XXX,XX +XXX,XX @@
28
However, short-form booleans are deprecated and full explicit ``arg_name=on``
29
/*
29
form is preferred.
30
- * SiFive CLINT (Core Local Interruptor) interface
30
31
+ * RISC-V ACLINT (Advanced Core Local Interruptor) interface
31
+``-drive if=none`` for the sifive_u OTP device (since 6.2)
32
*
32
+''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
33
* Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
33
+
34
* Copyright (c) 2017 SiFive, Inc.
34
+Using ``-drive if=none`` to configure the OTP device of the sifive_u
35
+ * Copyright (c) 2021 Western Digital Corporation or its affiliates.
35
+RISC-V machine is deprecated. Use ``-drive if=pflash`` instead.
36
*
36
+
37
* This program is free software; you can redistribute it and/or modify it
37
38
* under the terms and conditions of the GNU General Public License,
38
QEMU Machine Protocol (QMP) commands
39
@@ -XXX,XX +XXX,XX @@
39
------------------------------------
40
* this program. If not, see <http://www.gnu.org/licenses/>.
40
diff --git a/hw/misc/sifive_u_otp.c b/hw/misc/sifive_u_otp.c
41
*/
42
43
-#ifndef HW_SIFIVE_CLINT_H
44
-#define HW_SIFIVE_CLINT_H
45
+#ifndef HW_RISCV_ACLINT_H
46
+#define HW_RISCV_ACLINT_H
47
48
#include "hw/sysbus.h"
49
50
-#define TYPE_SIFIVE_CLINT "riscv.sifive.clint"
51
+#define TYPE_RISCV_ACLINT_MTIMER "riscv.aclint.mtimer"
52
53
-#define SIFIVE_CLINT(obj) \
54
- OBJECT_CHECK(SiFiveCLINTState, (obj), TYPE_SIFIVE_CLINT)
55
+#define RISCV_ACLINT_MTIMER(obj) \
56
+ OBJECT_CHECK(RISCVAclintMTimerState, (obj), TYPE_RISCV_ACLINT_MTIMER)
57
58
-typedef struct SiFiveCLINTState {
59
+typedef struct RISCVAclintMTimerState {
60
/*< private >*/
61
SysBusDevice parent_obj;
62
63
@@ -XXX,XX +XXX,XX @@ typedef struct SiFiveCLINTState {
64
MemoryRegion mmio;
65
uint32_t hartid_base;
66
uint32_t num_harts;
67
- uint32_t sip_base;
68
uint32_t timecmp_base;
69
uint32_t time_base;
70
uint32_t aperture_size;
71
uint32_t timebase_freq;
72
qemu_irq *timer_irqs;
73
- qemu_irq *soft_irqs;
74
-} SiFiveCLINTState;
75
+} RISCVAclintMTimerState;
76
77
-DeviceState *sifive_clint_create(hwaddr addr, hwaddr size,
78
- uint32_t hartid_base, uint32_t num_harts, uint32_t sip_base,
79
+DeviceState *riscv_aclint_mtimer_create(hwaddr addr, hwaddr size,
80
+ uint32_t hartid_base, uint32_t num_harts,
81
uint32_t timecmp_base, uint32_t time_base, uint32_t timebase_freq,
82
bool provide_rdtime);
83
84
-enum {
85
- SIFIVE_SIP_BASE = 0x0,
86
- SIFIVE_TIMECMP_BASE = 0x4000,
87
- SIFIVE_TIME_BASE = 0xBFF8
88
-};
89
+#define TYPE_RISCV_ACLINT_SWI "riscv.aclint.swi"
90
+
91
+#define RISCV_ACLINT_SWI(obj) \
92
+ OBJECT_CHECK(RISCVAclintSwiState, (obj), TYPE_RISCV_ACLINT_SWI)
93
+
94
+typedef struct RISCVAclintSwiState {
95
+ /*< private >*/
96
+ SysBusDevice parent_obj;
97
+
98
+ /*< public >*/
99
+ MemoryRegion mmio;
100
+ uint32_t hartid_base;
101
+ uint32_t num_harts;
102
+ uint32_t sswi;
103
+ qemu_irq *soft_irqs;
104
+} RISCVAclintSwiState;
105
+
106
+DeviceState *riscv_aclint_swi_create(hwaddr addr, uint32_t hartid_base,
107
+ uint32_t num_harts, bool sswi);
108
109
enum {
110
- SIFIVE_CLINT_TIMEBASE_FREQ = 10000000
111
+ RISCV_ACLINT_DEFAULT_MTIMECMP = 0x0,
112
+ RISCV_ACLINT_DEFAULT_MTIME = 0x7ff8,
113
+ RISCV_ACLINT_DEFAULT_MTIMER_SIZE = 0x8000,
114
+ RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ = 10000000,
115
+ RISCV_ACLINT_MAX_HARTS = 4095,
116
+ RISCV_ACLINT_SWI_SIZE = 0x4000
117
};
118
119
#endif
120
diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c
41
index XXXXXXX..XXXXXXX 100644
121
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/misc/sifive_u_otp.c
122
--- a/hw/intc/riscv_aclint.c
43
+++ b/hw/misc/sifive_u_otp.c
123
+++ b/hw/intc/riscv_aclint.c
44
@@ -XXX,XX +XXX,XX @@ static void sifive_u_otp_realize(DeviceState *dev, Error **errp)
124
@@ -XXX,XX +XXX,XX @@
45
TYPE_SIFIVE_U_OTP, SIFIVE_U_OTP_REG_SIZE);
125
/*
126
- * SiFive CLINT (Core Local Interruptor)
127
+ * RISC-V ACLINT (Advanced Core Local Interruptor)
128
+ * URL: https://github.com/riscv/riscv-aclint
129
*
130
* Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
131
* Copyright (c) 2017 SiFive, Inc.
132
+ * Copyright (c) 2021 Western Digital Corporation or its affiliates.
133
*
134
* This provides real-time clock, timer and interprocessor interrupts.
135
*
136
@@ -XXX,XX +XXX,XX @@
137
#include "qemu/osdep.h"
138
#include "qapi/error.h"
139
#include "qemu/error-report.h"
140
+#include "qemu/log.h"
141
#include "qemu/module.h"
142
#include "hw/sysbus.h"
143
#include "target/riscv/cpu.h"
144
@@ -XXX,XX +XXX,XX @@
145
#include "qemu/timer.h"
146
#include "hw/irq.h"
147
148
-typedef struct sifive_clint_callback {
149
- SiFiveCLINTState *s;
150
+typedef struct riscv_aclint_mtimer_callback {
151
+ RISCVAclintMTimerState *s;
152
int num;
153
-} sifive_clint_callback;
154
+} riscv_aclint_mtimer_callback;
155
156
static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq)
157
{
158
@@ -XXX,XX +XXX,XX @@ static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq)
159
* Called when timecmp is written to update the QEMU timer or immediately
160
* trigger timer interrupt if mtimecmp <= current timer value.
161
*/
162
-static void sifive_clint_write_timecmp(SiFiveCLINTState *s, RISCVCPU *cpu,
163
- int hartid,
164
- uint64_t value,
165
- uint32_t timebase_freq)
166
+static void riscv_aclint_mtimer_write_timecmp(RISCVAclintMTimerState *mtimer,
167
+ RISCVCPU *cpu,
168
+ int hartid,
169
+ uint64_t value,
170
+ uint32_t timebase_freq)
171
{
172
uint64_t next;
173
uint64_t diff;
174
@@ -XXX,XX +XXX,XX @@ static void sifive_clint_write_timecmp(SiFiveCLINTState *s, RISCVCPU *cpu,
175
176
cpu->env.timecmp = value;
177
if (cpu->env.timecmp <= rtc_r) {
178
- /* if we're setting an MTIMECMP value in the "past",
179
- immediately raise the timer interrupt */
180
- qemu_irq_raise(s->timer_irqs[hartid - s->hartid_base]);
181
+ /*
182
+ * If we're setting an MTIMECMP value in the "past",
183
+ * immediately raise the timer interrupt
184
+ */
185
+ qemu_irq_raise(mtimer->timer_irqs[hartid - mtimer->hartid_base]);
186
return;
187
}
188
189
/* otherwise, set up the future timer interrupt */
190
- qemu_irq_lower(s->timer_irqs[hartid - s->hartid_base]);
191
+ qemu_irq_lower(mtimer->timer_irqs[hartid - mtimer->hartid_base]);
192
diff = cpu->env.timecmp - rtc_r;
193
/* back to ns (note args switched in muldiv64) */
194
uint64_t ns_diff = muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq);
195
@@ -XXX,XX +XXX,XX @@ static void sifive_clint_write_timecmp(SiFiveCLINTState *s, RISCVCPU *cpu,
196
* Callback used when the timer set using timer_mod expires.
197
* Should raise the timer interrupt line
198
*/
199
-static void sifive_clint_timer_cb(void *opaque)
200
+static void riscv_aclint_mtimer_cb(void *opaque)
201
{
202
- sifive_clint_callback *state = opaque;
203
+ riscv_aclint_mtimer_callback *state = opaque;
204
205
qemu_irq_raise(state->s->timer_irqs[state->num]);
206
}
207
208
-/* CPU wants to read rtc or timecmp register */
209
-static uint64_t sifive_clint_read(void *opaque, hwaddr addr, unsigned size)
210
+/* CPU read MTIMER register */
211
+static uint64_t riscv_aclint_mtimer_read(void *opaque, hwaddr addr,
212
+ unsigned size)
213
{
214
- SiFiveCLINTState *clint = opaque;
215
- if (addr >= clint->sip_base &&
216
- addr < clint->sip_base + (clint->num_harts << 2)) {
217
- size_t hartid = clint->hartid_base + ((addr - clint->sip_base) >> 2);
218
- CPUState *cpu = qemu_get_cpu(hartid);
219
- CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
220
- if (!env) {
221
- error_report("clint: invalid timecmp hartid: %zu", hartid);
222
- } else if ((addr & 0x3) == 0) {
223
- return (env->mip & MIP_MSIP) > 0;
224
- } else {
225
- error_report("clint: invalid read: %08x", (uint32_t)addr);
226
- return 0;
227
- }
228
- } else if (addr >= clint->timecmp_base &&
229
- addr < clint->timecmp_base + (clint->num_harts << 3)) {
230
- size_t hartid = clint->hartid_base +
231
- ((addr - clint->timecmp_base) >> 3);
232
+ RISCVAclintMTimerState *mtimer = opaque;
233
+
234
+ if (addr >= mtimer->timecmp_base &&
235
+ addr < (mtimer->timecmp_base + (mtimer->num_harts << 3))) {
236
+ size_t hartid = mtimer->hartid_base +
237
+ ((addr - mtimer->timecmp_base) >> 3);
238
CPUState *cpu = qemu_get_cpu(hartid);
239
CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
240
if (!env) {
241
- error_report("clint: invalid timecmp hartid: %zu", hartid);
242
+ qemu_log_mask(LOG_GUEST_ERROR,
243
+ "aclint-mtimer: invalid hartid: %zu", hartid);
244
} else if ((addr & 0x7) == 0) {
245
/* timecmp_lo */
246
uint64_t timecmp = env->timecmp;
247
@@ -XXX,XX +XXX,XX @@ static uint64_t sifive_clint_read(void *opaque, hwaddr addr, unsigned size)
248
uint64_t timecmp = env->timecmp;
249
return (timecmp >> 32) & 0xFFFFFFFF;
250
} else {
251
- error_report("clint: invalid read: %08x", (uint32_t)addr);
252
+ qemu_log_mask(LOG_UNIMP,
253
+ "aclint-mtimer: invalid read: %08x", (uint32_t)addr);
254
return 0;
255
}
256
- } else if (addr == clint->time_base) {
257
+ } else if (addr == mtimer->time_base) {
258
/* time_lo */
259
- return cpu_riscv_read_rtc(clint->timebase_freq) & 0xFFFFFFFF;
260
- } else if (addr == clint->time_base + 4) {
261
+ return cpu_riscv_read_rtc(mtimer->timebase_freq) & 0xFFFFFFFF;
262
+ } else if (addr == mtimer->time_base + 4) {
263
/* time_hi */
264
- return (cpu_riscv_read_rtc(clint->timebase_freq) >> 32) & 0xFFFFFFFF;
265
+ return (cpu_riscv_read_rtc(mtimer->timebase_freq) >> 32) & 0xFFFFFFFF;
266
}
267
268
- error_report("clint: invalid read: %08x", (uint32_t)addr);
269
+ qemu_log_mask(LOG_UNIMP,
270
+ "aclint-mtimer: invalid read: %08x", (uint32_t)addr);
271
return 0;
272
}
273
274
-/* CPU wrote to rtc or timecmp register */
275
-static void sifive_clint_write(void *opaque, hwaddr addr, uint64_t value,
276
- unsigned size)
277
+/* CPU write MTIMER register */
278
+static void riscv_aclint_mtimer_write(void *opaque, hwaddr addr,
279
+ uint64_t value, unsigned size)
280
{
281
- SiFiveCLINTState *clint = opaque;
282
+ RISCVAclintMTimerState *mtimer = opaque;
283
284
- if (addr >= clint->sip_base &&
285
- addr < clint->sip_base + (clint->num_harts << 2)) {
286
- size_t hartid = clint->hartid_base + ((addr - clint->sip_base) >> 2);
287
- CPUState *cpu = qemu_get_cpu(hartid);
288
- CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
289
- if (!env) {
290
- error_report("clint: invalid timecmp hartid: %zu", hartid);
291
- } else if ((addr & 0x3) == 0) {
292
- qemu_set_irq(clint->soft_irqs[hartid - clint->hartid_base], value);
293
- } else {
294
- error_report("clint: invalid sip write: %08x", (uint32_t)addr);
295
- }
296
- return;
297
- } else if (addr >= clint->timecmp_base &&
298
- addr < clint->timecmp_base + (clint->num_harts << 3)) {
299
- size_t hartid = clint->hartid_base +
300
- ((addr - clint->timecmp_base) >> 3);
301
+ if (addr >= mtimer->timecmp_base &&
302
+ addr < (mtimer->timecmp_base + (mtimer->num_harts << 3))) {
303
+ size_t hartid = mtimer->hartid_base +
304
+ ((addr - mtimer->timecmp_base) >> 3);
305
CPUState *cpu = qemu_get_cpu(hartid);
306
CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
307
if (!env) {
308
- error_report("clint: invalid timecmp hartid: %zu", hartid);
309
+ qemu_log_mask(LOG_GUEST_ERROR,
310
+ "aclint-mtimer: invalid hartid: %zu", hartid);
311
} else if ((addr & 0x7) == 0) {
312
/* timecmp_lo */
313
uint64_t timecmp_hi = env->timecmp >> 32;
314
- sifive_clint_write_timecmp(clint, RISCV_CPU(cpu), hartid,
315
- timecmp_hi << 32 | (value & 0xFFFFFFFF), clint->timebase_freq);
316
+ riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hartid,
317
+ timecmp_hi << 32 | (value & 0xFFFFFFFF),
318
+ mtimer->timebase_freq);
319
return;
320
} else if ((addr & 0x7) == 4) {
321
/* timecmp_hi */
322
uint64_t timecmp_lo = env->timecmp;
323
- sifive_clint_write_timecmp(clint, RISCV_CPU(cpu), hartid,
324
- value << 32 | (timecmp_lo & 0xFFFFFFFF), clint->timebase_freq);
325
+ riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hartid,
326
+ value << 32 | (timecmp_lo & 0xFFFFFFFF),
327
+ mtimer->timebase_freq);
328
} else {
329
- error_report("clint: invalid timecmp write: %08x", (uint32_t)addr);
330
+ qemu_log_mask(LOG_UNIMP,
331
+ "aclint-mtimer: invalid timecmp write: %08x",
332
+ (uint32_t)addr);
333
}
334
return;
335
- } else if (addr == clint->time_base) {
336
+ } else if (addr == mtimer->time_base) {
337
/* time_lo */
338
- error_report("clint: time_lo write not implemented");
339
+ qemu_log_mask(LOG_UNIMP,
340
+ "aclint-mtimer: time_lo write not implemented");
341
return;
342
- } else if (addr == clint->time_base + 4) {
343
+ } else if (addr == mtimer->time_base + 4) {
344
/* time_hi */
345
- error_report("clint: time_hi write not implemented");
346
+ qemu_log_mask(LOG_UNIMP,
347
+ "aclint-mtimer: time_hi write not implemented");
348
return;
349
}
350
351
- error_report("clint: invalid write: %08x", (uint32_t)addr);
352
+ qemu_log_mask(LOG_UNIMP,
353
+ "aclint-mtimer: invalid write: %08x", (uint32_t)addr);
354
}
355
356
-static const MemoryRegionOps sifive_clint_ops = {
357
- .read = sifive_clint_read,
358
- .write = sifive_clint_write,
359
+static const MemoryRegionOps riscv_aclint_mtimer_ops = {
360
+ .read = riscv_aclint_mtimer_read,
361
+ .write = riscv_aclint_mtimer_write,
362
.endianness = DEVICE_LITTLE_ENDIAN,
363
.valid = {
364
.min_access_size = 4,
365
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps sifive_clint_ops = {
366
}
367
};
368
369
-static Property sifive_clint_properties[] = {
370
- DEFINE_PROP_UINT32("hartid-base", SiFiveCLINTState, hartid_base, 0),
371
- DEFINE_PROP_UINT32("num-harts", SiFiveCLINTState, num_harts, 0),
372
- DEFINE_PROP_UINT32("sip-base", SiFiveCLINTState, sip_base, 0),
373
- DEFINE_PROP_UINT32("timecmp-base", SiFiveCLINTState, timecmp_base, 0),
374
- DEFINE_PROP_UINT32("time-base", SiFiveCLINTState, time_base, 0),
375
- DEFINE_PROP_UINT32("aperture-size", SiFiveCLINTState, aperture_size, 0),
376
- DEFINE_PROP_UINT32("timebase-freq", SiFiveCLINTState, timebase_freq, 0),
377
+static Property riscv_aclint_mtimer_properties[] = {
378
+ DEFINE_PROP_UINT32("hartid-base", RISCVAclintMTimerState,
379
+ hartid_base, 0),
380
+ DEFINE_PROP_UINT32("num-harts", RISCVAclintMTimerState, num_harts, 1),
381
+ DEFINE_PROP_UINT32("timecmp-base", RISCVAclintMTimerState,
382
+ timecmp_base, RISCV_ACLINT_DEFAULT_MTIMECMP),
383
+ DEFINE_PROP_UINT32("time-base", RISCVAclintMTimerState,
384
+ time_base, RISCV_ACLINT_DEFAULT_MTIME),
385
+ DEFINE_PROP_UINT32("aperture-size", RISCVAclintMTimerState,
386
+ aperture_size, RISCV_ACLINT_DEFAULT_MTIMER_SIZE),
387
+ DEFINE_PROP_UINT32("timebase-freq", RISCVAclintMTimerState,
388
+ timebase_freq, 0),
389
DEFINE_PROP_END_OF_LIST(),
390
};
391
392
-static void sifive_clint_realize(DeviceState *dev, Error **errp)
393
+static void riscv_aclint_mtimer_realize(DeviceState *dev, Error **errp)
394
{
395
- SiFiveCLINTState *s = SIFIVE_CLINT(dev);
396
- memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_clint_ops, s,
397
- TYPE_SIFIVE_CLINT, s->aperture_size);
398
+ RISCVAclintMTimerState *s = RISCV_ACLINT_MTIMER(dev);
399
+ int i;
400
+
401
+ memory_region_init_io(&s->mmio, OBJECT(dev), &riscv_aclint_mtimer_ops,
402
+ s, TYPE_RISCV_ACLINT_MTIMER, s->aperture_size);
46
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
403
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
47
404
48
- dinfo = drive_get_next(IF_NONE);
405
s->timer_irqs = g_malloc(sizeof(qemu_irq) * s->num_harts);
49
+ dinfo = drive_get_next(IF_PFLASH);
406
qdev_init_gpio_out(dev, s->timer_irqs, s->num_harts);
50
+ if (!dinfo) {
407
51
+ dinfo = drive_get_next(IF_NONE);
408
- s->soft_irqs = g_malloc(sizeof(qemu_irq) * s->num_harts);
52
+ if (dinfo) {
409
- qdev_init_gpio_out(dev, s->soft_irqs, s->num_harts);
53
+ warn_report("using \"-drive if=none\" for the OTP is deprecated, "
410
+ /* Claim timer interrupt bits */
54
+ "use \"-drive if=pflash\" instead.");
411
+ for (i = 0; i < s->num_harts; i++) {
412
+ RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(s->hartid_base + i));
413
+ if (riscv_cpu_claim_interrupts(cpu, MIP_MTIP) < 0) {
414
+ error_report("MTIP already claimed");
415
+ exit(1);
55
+ }
416
+ }
56
+ }
417
+ }
57
if (dinfo) {
418
}
58
int ret;
419
59
uint64_t perm;
420
-static void sifive_clint_class_init(ObjectClass *klass, void *data)
421
+static void riscv_aclint_mtimer_class_init(ObjectClass *klass, void *data)
422
{
423
DeviceClass *dc = DEVICE_CLASS(klass);
424
- dc->realize = sifive_clint_realize;
425
- device_class_set_props(dc, sifive_clint_properties);
426
+ dc->realize = riscv_aclint_mtimer_realize;
427
+ device_class_set_props(dc, riscv_aclint_mtimer_properties);
428
}
429
430
-static const TypeInfo sifive_clint_info = {
431
- .name = TYPE_SIFIVE_CLINT,
432
+static const TypeInfo riscv_aclint_mtimer_info = {
433
+ .name = TYPE_RISCV_ACLINT_MTIMER,
434
.parent = TYPE_SYS_BUS_DEVICE,
435
- .instance_size = sizeof(SiFiveCLINTState),
436
- .class_init = sifive_clint_class_init,
437
+ .instance_size = sizeof(RISCVAclintMTimerState),
438
+ .class_init = riscv_aclint_mtimer_class_init,
439
};
440
441
-static void sifive_clint_register_types(void)
442
-{
443
- type_register_static(&sifive_clint_info);
444
-}
445
-
446
-type_init(sifive_clint_register_types)
447
-
448
/*
449
- * Create CLINT device.
450
+ * Create ACLINT MTIMER device.
451
*/
452
-DeviceState *sifive_clint_create(hwaddr addr, hwaddr size,
453
- uint32_t hartid_base, uint32_t num_harts, uint32_t sip_base,
454
+DeviceState *riscv_aclint_mtimer_create(hwaddr addr, hwaddr size,
455
+ uint32_t hartid_base, uint32_t num_harts,
456
uint32_t timecmp_base, uint32_t time_base, uint32_t timebase_freq,
457
bool provide_rdtime)
458
{
459
int i;
460
+ DeviceState *dev = qdev_new(TYPE_RISCV_ACLINT_MTIMER);
461
+
462
+ assert(num_harts <= RISCV_ACLINT_MAX_HARTS);
463
+ assert(!(addr & 0x7));
464
+ assert(!(timecmp_base & 0x7));
465
+ assert(!(time_base & 0x7));
466
467
- DeviceState *dev = qdev_new(TYPE_SIFIVE_CLINT);
468
qdev_prop_set_uint32(dev, "hartid-base", hartid_base);
469
qdev_prop_set_uint32(dev, "num-harts", num_harts);
470
- qdev_prop_set_uint32(dev, "sip-base", sip_base);
471
qdev_prop_set_uint32(dev, "timecmp-base", timecmp_base);
472
qdev_prop_set_uint32(dev, "time-base", time_base);
473
qdev_prop_set_uint32(dev, "aperture-size", size);
474
@@ -XXX,XX +XXX,XX @@ DeviceState *sifive_clint_create(hwaddr addr, hwaddr size,
475
CPUState *cpu = qemu_get_cpu(hartid_base + i);
476
RISCVCPU *rvcpu = RISCV_CPU(cpu);
477
CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
478
- sifive_clint_callback *cb = g_malloc0(sizeof(sifive_clint_callback));
479
+ riscv_aclint_mtimer_callback *cb =
480
+ g_malloc0(sizeof(riscv_aclint_mtimer_callback));
481
482
if (!env) {
483
g_free(cb);
484
@@ -XXX,XX +XXX,XX @@ DeviceState *sifive_clint_create(hwaddr addr, hwaddr size,
485
riscv_cpu_set_rdtime_fn(env, cpu_riscv_read_rtc, timebase_freq);
486
}
487
488
- cb->s = SIFIVE_CLINT(dev);
489
+ cb->s = RISCV_ACLINT_MTIMER(dev);
490
cb->num = i;
491
env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
492
- &sifive_clint_timer_cb, cb);
493
+ &riscv_aclint_mtimer_cb, cb);
494
env->timecmp = 0;
495
496
qdev_connect_gpio_out(dev, i,
497
qdev_get_gpio_in(DEVICE(rvcpu), IRQ_M_TIMER));
498
- qdev_connect_gpio_out(dev, num_harts + i,
499
- qdev_get_gpio_in(DEVICE(rvcpu), IRQ_M_SOFT));
500
}
501
502
return dev;
503
}
504
+
505
+/* CPU read [M|S]SWI register */
506
+static uint64_t riscv_aclint_swi_read(void *opaque, hwaddr addr,
507
+ unsigned size)
508
+{
509
+ RISCVAclintSwiState *swi = opaque;
510
+
511
+ if (addr < (swi->num_harts << 2)) {
512
+ size_t hartid = swi->hartid_base + (addr >> 2);
513
+ CPUState *cpu = qemu_get_cpu(hartid);
514
+ CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
515
+ if (!env) {
516
+ qemu_log_mask(LOG_GUEST_ERROR,
517
+ "aclint-swi: invalid hartid: %zu", hartid);
518
+ } else if ((addr & 0x3) == 0) {
519
+ return (swi->sswi) ? 0 : ((env->mip & MIP_MSIP) > 0);
520
+ }
521
+ }
522
+
523
+ qemu_log_mask(LOG_UNIMP,
524
+ "aclint-swi: invalid read: %08x", (uint32_t)addr);
525
+ return 0;
526
+}
527
+
528
+/* CPU write [M|S]SWI register */
529
+static void riscv_aclint_swi_write(void *opaque, hwaddr addr, uint64_t value,
530
+ unsigned size)
531
+{
532
+ RISCVAclintSwiState *swi = opaque;
533
+
534
+ if (addr < (swi->num_harts << 2)) {
535
+ size_t hartid = swi->hartid_base + (addr >> 2);
536
+ CPUState *cpu = qemu_get_cpu(hartid);
537
+ CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
538
+ if (!env) {
539
+ qemu_log_mask(LOG_GUEST_ERROR,
540
+ "aclint-swi: invalid hartid: %zu", hartid);
541
+ } else if ((addr & 0x3) == 0) {
542
+ if (value & 0x1) {
543
+ qemu_irq_raise(swi->soft_irqs[hartid - swi->hartid_base]);
544
+ } else {
545
+ if (!swi->sswi) {
546
+ qemu_irq_lower(swi->soft_irqs[hartid - swi->hartid_base]);
547
+ }
548
+ }
549
+ return;
550
+ }
551
+ }
552
+
553
+ qemu_log_mask(LOG_UNIMP,
554
+ "aclint-swi: invalid write: %08x", (uint32_t)addr);
555
+}
556
+
557
+static const MemoryRegionOps riscv_aclint_swi_ops = {
558
+ .read = riscv_aclint_swi_read,
559
+ .write = riscv_aclint_swi_write,
560
+ .endianness = DEVICE_LITTLE_ENDIAN,
561
+ .valid = {
562
+ .min_access_size = 4,
563
+ .max_access_size = 4
564
+ }
565
+};
566
+
567
+static Property riscv_aclint_swi_properties[] = {
568
+ DEFINE_PROP_UINT32("hartid-base", RISCVAclintSwiState, hartid_base, 0),
569
+ DEFINE_PROP_UINT32("num-harts", RISCVAclintSwiState, num_harts, 1),
570
+ DEFINE_PROP_UINT32("sswi", RISCVAclintSwiState, sswi, false),
571
+ DEFINE_PROP_END_OF_LIST(),
572
+};
573
+
574
+static void riscv_aclint_swi_realize(DeviceState *dev, Error **errp)
575
+{
576
+ RISCVAclintSwiState *swi = RISCV_ACLINT_SWI(dev);
577
+ int i;
578
+
579
+ memory_region_init_io(&swi->mmio, OBJECT(dev), &riscv_aclint_swi_ops, swi,
580
+ TYPE_RISCV_ACLINT_SWI, RISCV_ACLINT_SWI_SIZE);
581
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &swi->mmio);
582
+
583
+ swi->soft_irqs = g_malloc(sizeof(qemu_irq) * swi->num_harts);
584
+ qdev_init_gpio_out(dev, swi->soft_irqs, swi->num_harts);
585
+
586
+ /* Claim software interrupt bits */
587
+ for (i = 0; i < swi->num_harts; i++) {
588
+ RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(swi->hartid_base + i));
589
+ /* We don't claim mip.SSIP because it is writeable by software */
590
+ if (riscv_cpu_claim_interrupts(cpu, swi->sswi ? 0 : MIP_MSIP) < 0) {
591
+ error_report("MSIP already claimed");
592
+ exit(1);
593
+ }
594
+ }
595
+}
596
+
597
+static void riscv_aclint_swi_class_init(ObjectClass *klass, void *data)
598
+{
599
+ DeviceClass *dc = DEVICE_CLASS(klass);
600
+ dc->realize = riscv_aclint_swi_realize;
601
+ device_class_set_props(dc, riscv_aclint_swi_properties);
602
+}
603
+
604
+static const TypeInfo riscv_aclint_swi_info = {
605
+ .name = TYPE_RISCV_ACLINT_SWI,
606
+ .parent = TYPE_SYS_BUS_DEVICE,
607
+ .instance_size = sizeof(RISCVAclintSwiState),
608
+ .class_init = riscv_aclint_swi_class_init,
609
+};
610
+
611
+/*
612
+ * Create ACLINT [M|S]SWI device.
613
+ */
614
+DeviceState *riscv_aclint_swi_create(hwaddr addr, uint32_t hartid_base,
615
+ uint32_t num_harts, bool sswi)
616
+{
617
+ int i;
618
+ DeviceState *dev = qdev_new(TYPE_RISCV_ACLINT_SWI);
619
+
620
+ assert(num_harts <= RISCV_ACLINT_MAX_HARTS);
621
+ assert(!(addr & 0x3));
622
+
623
+ qdev_prop_set_uint32(dev, "hartid-base", hartid_base);
624
+ qdev_prop_set_uint32(dev, "num-harts", num_harts);
625
+ qdev_prop_set_uint32(dev, "sswi", sswi ? true : false);
626
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
627
+ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
628
+
629
+ for (i = 0; i < num_harts; i++) {
630
+ CPUState *cpu = qemu_get_cpu(hartid_base + i);
631
+ RISCVCPU *rvcpu = RISCV_CPU(cpu);
632
+
633
+ qdev_connect_gpio_out(dev, i,
634
+ qdev_get_gpio_in(DEVICE(rvcpu),
635
+ (sswi) ? IRQ_S_SOFT : IRQ_M_SOFT));
636
+ }
637
+
638
+ return dev;
639
+}
640
+
641
+static void riscv_aclint_register_types(void)
642
+{
643
+ type_register_static(&riscv_aclint_mtimer_info);
644
+ type_register_static(&riscv_aclint_swi_info);
645
+}
646
+
647
+type_init(riscv_aclint_register_types)
648
diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
649
index XXXXXXX..XXXXXXX 100644
650
--- a/hw/riscv/microchip_pfsoc.c
651
+++ b/hw/riscv/microchip_pfsoc.c
652
@@ -XXX,XX +XXX,XX @@ static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp)
653
memmap[MICROCHIP_PFSOC_BUSERR_UNIT4].size);
654
655
/* CLINT */
656
- sifive_clint_create(memmap[MICROCHIP_PFSOC_CLINT].base,
657
- memmap[MICROCHIP_PFSOC_CLINT].size, 0, ms->smp.cpus,
658
- SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
659
+ riscv_aclint_swi_create(memmap[MICROCHIP_PFSOC_CLINT].base,
660
+ 0, ms->smp.cpus, false);
661
+ riscv_aclint_mtimer_create(
662
+ memmap[MICROCHIP_PFSOC_CLINT].base + RISCV_ACLINT_SWI_SIZE,
663
+ RISCV_ACLINT_DEFAULT_MTIMER_SIZE, 0, ms->smp.cpus,
664
+ RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME,
665
CLINT_TIMEBASE_FREQ, false);
666
667
/* L2 cache controller */
668
diff --git a/hw/riscv/shakti_c.c b/hw/riscv/shakti_c.c
669
index XXXXXXX..XXXXXXX 100644
670
--- a/hw/riscv/shakti_c.c
671
+++ b/hw/riscv/shakti_c.c
672
@@ -XXX,XX +XXX,XX @@ static void shakti_c_soc_state_realize(DeviceState *dev, Error **errp)
673
SHAKTI_C_PLIC_CONTEXT_STRIDE,
674
shakti_c_memmap[SHAKTI_C_PLIC].size);
675
676
- sifive_clint_create(shakti_c_memmap[SHAKTI_C_CLINT].base,
677
- shakti_c_memmap[SHAKTI_C_CLINT].size, 0, 1,
678
- SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
679
- SIFIVE_CLINT_TIMEBASE_FREQ, false);
680
+ riscv_aclint_swi_create(shakti_c_memmap[SHAKTI_C_CLINT].base,
681
+ 0, 1, false);
682
+ riscv_aclint_mtimer_create(shakti_c_memmap[SHAKTI_C_CLINT].base +
683
+ RISCV_ACLINT_SWI_SIZE,
684
+ RISCV_ACLINT_DEFAULT_MTIMER_SIZE, 0, 1,
685
+ RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME,
686
+ RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, false);
687
688
qdev_prop_set_chr(DEVICE(&(sss->uart)), "chardev", serial_hd(0));
689
if (!sysbus_realize(SYS_BUS_DEVICE(&sss->uart), errp)) {
690
diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
691
index XXXXXXX..XXXXXXX 100644
692
--- a/hw/riscv/sifive_e.c
693
+++ b/hw/riscv/sifive_e.c
694
@@ -XXX,XX +XXX,XX @@ static void sifive_e_soc_realize(DeviceState *dev, Error **errp)
695
SIFIVE_E_PLIC_CONTEXT_BASE,
696
SIFIVE_E_PLIC_CONTEXT_STRIDE,
697
memmap[SIFIVE_E_DEV_PLIC].size);
698
- sifive_clint_create(memmap[SIFIVE_E_DEV_CLINT].base,
699
- memmap[SIFIVE_E_DEV_CLINT].size, 0, ms->smp.cpus,
700
- SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
701
- SIFIVE_CLINT_TIMEBASE_FREQ, false);
702
+ riscv_aclint_swi_create(memmap[SIFIVE_E_DEV_CLINT].base,
703
+ 0, ms->smp.cpus, false);
704
+ riscv_aclint_mtimer_create(memmap[SIFIVE_E_DEV_CLINT].base +
705
+ RISCV_ACLINT_SWI_SIZE,
706
+ RISCV_ACLINT_DEFAULT_MTIMER_SIZE, 0, ms->smp.cpus,
707
+ RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME,
708
+ RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, false);
709
create_unimplemented_device("riscv.sifive.e.aon",
710
memmap[SIFIVE_E_DEV_AON].base, memmap[SIFIVE_E_DEV_AON].size);
711
sifive_e_prci_create(memmap[SIFIVE_E_DEV_PRCI].base);
712
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
713
index XXXXXXX..XXXXXXX 100644
714
--- a/hw/riscv/sifive_u.c
715
+++ b/hw/riscv/sifive_u.c
716
@@ -XXX,XX +XXX,XX @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
717
serial_hd(0), qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_U_UART0_IRQ));
718
sifive_uart_create(system_memory, memmap[SIFIVE_U_DEV_UART1].base,
719
serial_hd(1), qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_U_UART1_IRQ));
720
- sifive_clint_create(memmap[SIFIVE_U_DEV_CLINT].base,
721
- memmap[SIFIVE_U_DEV_CLINT].size, 0, ms->smp.cpus,
722
- SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
723
+ riscv_aclint_swi_create(memmap[SIFIVE_U_DEV_CLINT].base, 0,
724
+ ms->smp.cpus, false);
725
+ riscv_aclint_mtimer_create(memmap[SIFIVE_U_DEV_CLINT].base +
726
+ RISCV_ACLINT_SWI_SIZE,
727
+ RISCV_ACLINT_DEFAULT_MTIMER_SIZE, 0, ms->smp.cpus,
728
+ RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME,
729
CLINT_TIMEBASE_FREQ, false);
730
731
if (!sysbus_realize(SYS_BUS_DEVICE(&s->prci), errp)) {
732
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
733
index XXXXXXX..XXXXXXX 100644
734
--- a/hw/riscv/spike.c
735
+++ b/hw/riscv/spike.c
736
@@ -XXX,XX +XXX,XX @@ static void create_fdt(SpikeState *s, const MemMapEntry *memmap,
737
738
qemu_fdt_add_subnode(fdt, "/cpus");
739
qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency",
740
- SIFIVE_CLINT_TIMEBASE_FREQ);
741
+ RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ);
742
qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0);
743
qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1);
744
qemu_fdt_add_subnode(fdt, "/cpus/cpu-map");
745
@@ -XXX,XX +XXX,XX @@ static void spike_board_init(MachineState *machine)
746
sysbus_realize(SYS_BUS_DEVICE(&s->soc[i]), &error_abort);
747
748
/* Core Local Interruptor (timer and IPI) for each socket */
749
- sifive_clint_create(
750
+ riscv_aclint_swi_create(
751
memmap[SPIKE_CLINT].base + i * memmap[SPIKE_CLINT].size,
752
- memmap[SPIKE_CLINT].size, base_hartid, hart_count,
753
- SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
754
- SIFIVE_CLINT_TIMEBASE_FREQ, false);
755
+ base_hartid, hart_count, false);
756
+ riscv_aclint_mtimer_create(
757
+ memmap[SPIKE_CLINT].base + i * memmap[SPIKE_CLINT].size +
758
+ RISCV_ACLINT_SWI_SIZE,
759
+ RISCV_ACLINT_DEFAULT_MTIMER_SIZE, base_hartid, hart_count,
760
+ RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME,
761
+ RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, false);
762
}
763
764
/* register system main memory (actual RAM) */
765
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
766
index XXXXXXX..XXXXXXX 100644
767
--- a/hw/riscv/virt.c
768
+++ b/hw/riscv/virt.c
769
@@ -XXX,XX +XXX,XX @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap,
770
771
qemu_fdt_add_subnode(fdt, "/cpus");
772
qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency",
773
- SIFIVE_CLINT_TIMEBASE_FREQ);
774
+ RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ);
775
qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0);
776
qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1);
777
qemu_fdt_add_subnode(fdt, "/cpus/cpu-map");
778
@@ -XXX,XX +XXX,XX @@ static void virt_machine_init(MachineState *machine)
779
sysbus_realize(SYS_BUS_DEVICE(&s->soc[i]), &error_abort);
780
781
/* Per-socket CLINT */
782
- sifive_clint_create(
783
+ riscv_aclint_swi_create(
784
memmap[VIRT_CLINT].base + i * memmap[VIRT_CLINT].size,
785
- memmap[VIRT_CLINT].size, base_hartid, hart_count,
786
- SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
787
- SIFIVE_CLINT_TIMEBASE_FREQ, true);
788
+ base_hartid, hart_count, false);
789
+ riscv_aclint_mtimer_create(
790
+ memmap[VIRT_CLINT].base + i * memmap[VIRT_CLINT].size +
791
+ RISCV_ACLINT_SWI_SIZE,
792
+ RISCV_ACLINT_DEFAULT_MTIMER_SIZE, base_hartid, hart_count,
793
+ RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME,
794
+ RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, true);
795
796
/* Per-socket PLIC hart topology configuration string */
797
plic_hart_config = plic_hart_config_string(hart_count);
60
--
798
--
61
2.31.1
799
2.31.1
62
800
63
801
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Anup Patel <anup.patel@wdc.com>
2
2
3
Once a "One Time Programmable" is programmed, it shouldn't be reset.
3
We re-factor and break the FDT generation into smaller functions
4
so that it is easier to modify FDT generation for different
5
configurations of virt machine.
4
6
5
Do not re-initialize the OTP content in the DeviceReset handler,
7
Signed-off-by: Anup Patel <anup.patel@wdc.com>
6
initialize it once in the DeviceRealize one.
7
8
Fixes: 9fb45c62ae8 ("riscv: sifive: Implement a model for SiFive FU540 OTP")
9
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
11
Message-Id: <20211119104757.331579-1-f4bug@amsat.org>
9
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
10
Message-id: 20210831110603.338681-4-anup.patel@wdc.com
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
12
---
14
hw/misc/sifive_u_otp.c | 13 +++++--------
13
hw/riscv/virt.c | 527 ++++++++++++++++++++++++++++++------------------
15
1 file changed, 5 insertions(+), 8 deletions(-)
14
1 file changed, 327 insertions(+), 200 deletions(-)
16
15
17
diff --git a/hw/misc/sifive_u_otp.c b/hw/misc/sifive_u_otp.c
16
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/misc/sifive_u_otp.c
18
--- a/hw/riscv/virt.c
20
+++ b/hw/misc/sifive_u_otp.c
19
+++ b/hw/riscv/virt.c
21
@@ -XXX,XX +XXX,XX @@ static void sifive_u_otp_realize(DeviceState *dev, Error **errp)
20
@@ -XXX,XX +XXX,XX @@ static void create_pcie_irq_map(void *fdt, char *nodename,
22
21
0x1800, 0, 0, 0x7);
23
if (blk_pread(s->blk, 0, s->fuse, filesize) != filesize) {
22
}
24
error_setg(errp, "failed to read the initial flash content");
23
25
+ return;
24
-static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap,
26
}
25
- uint64_t mem_size, const char *cmdline, bool is_32_bit)
26
+static void create_fdt_socket_cpus(RISCVVirtState *s, int socket,
27
+ char *clust_name, uint32_t *phandle,
28
+ bool is_32_bit, uint32_t *intc_phandles)
29
{
30
- void *fdt;
31
- int i, cpu, socket;
32
+ int cpu;
33
+ uint32_t cpu_phandle;
34
MachineState *mc = MACHINE(s);
35
+ char *name, *cpu_name, *core_name, *intc_name;
36
+
37
+ for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) {
38
+ cpu_phandle = (*phandle)++;
39
+
40
+ cpu_name = g_strdup_printf("/cpus/cpu@%d",
41
+ s->soc[socket].hartid_base + cpu);
42
+ qemu_fdt_add_subnode(mc->fdt, cpu_name);
43
+ qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
44
+ (is_32_bit) ? "riscv,sv32" : "riscv,sv48");
45
+ name = riscv_isa_string(&s->soc[socket].harts[cpu]);
46
+ qemu_fdt_setprop_string(mc->fdt, cpu_name, "riscv,isa", name);
47
+ g_free(name);
48
+ qemu_fdt_setprop_string(mc->fdt, cpu_name, "compatible", "riscv");
49
+ qemu_fdt_setprop_string(mc->fdt, cpu_name, "status", "okay");
50
+ qemu_fdt_setprop_cell(mc->fdt, cpu_name, "reg",
51
+ s->soc[socket].hartid_base + cpu);
52
+ qemu_fdt_setprop_string(mc->fdt, cpu_name, "device_type", "cpu");
53
+ riscv_socket_fdt_write_id(mc, mc->fdt, cpu_name, socket);
54
+ qemu_fdt_setprop_cell(mc->fdt, cpu_name, "phandle", cpu_phandle);
55
+
56
+ intc_phandles[cpu] = (*phandle)++;
57
+
58
+ intc_name = g_strdup_printf("%s/interrupt-controller", cpu_name);
59
+ qemu_fdt_add_subnode(mc->fdt, intc_name);
60
+ qemu_fdt_setprop_cell(mc->fdt, intc_name, "phandle",
61
+ intc_phandles[cpu]);
62
+ qemu_fdt_setprop_string(mc->fdt, intc_name, "compatible",
63
+ "riscv,cpu-intc");
64
+ qemu_fdt_setprop(mc->fdt, intc_name, "interrupt-controller", NULL, 0);
65
+ qemu_fdt_setprop_cell(mc->fdt, intc_name, "#interrupt-cells", 1);
66
+
67
+ core_name = g_strdup_printf("%s/core%d", clust_name, cpu);
68
+ qemu_fdt_add_subnode(mc->fdt, core_name);
69
+ qemu_fdt_setprop_cell(mc->fdt, core_name, "cpu", cpu_phandle);
70
+
71
+ g_free(core_name);
72
+ g_free(intc_name);
73
+ g_free(cpu_name);
74
+ }
75
+}
76
+
77
+static void create_fdt_socket_memory(RISCVVirtState *s,
78
+ const MemMapEntry *memmap, int socket)
79
+{
80
+ char *mem_name;
81
uint64_t addr, size;
82
- uint32_t *clint_cells, *plic_cells;
83
- unsigned long clint_addr, plic_addr;
84
- uint32_t plic_phandle[MAX_NODES];
85
- uint32_t cpu_phandle, intc_phandle, test_phandle;
86
- uint32_t phandle = 1, plic_mmio_phandle = 1;
87
- uint32_t plic_pcie_phandle = 1, plic_virtio_phandle = 1;
88
- char *mem_name, *cpu_name, *core_name, *intc_name;
89
- char *name, *clint_name, *plic_name, *clust_name;
90
- hwaddr flashsize = virt_memmap[VIRT_FLASH].size / 2;
91
- hwaddr flashbase = virt_memmap[VIRT_FLASH].base;
92
+ MachineState *mc = MACHINE(s);
93
+
94
+ addr = memmap[VIRT_DRAM].base + riscv_socket_mem_offset(mc, socket);
95
+ size = riscv_socket_mem_size(mc, socket);
96
+ mem_name = g_strdup_printf("/memory@%lx", (long)addr);
97
+ qemu_fdt_add_subnode(mc->fdt, mem_name);
98
+ qemu_fdt_setprop_cells(mc->fdt, mem_name, "reg",
99
+ addr >> 32, addr, size >> 32, size);
100
+ qemu_fdt_setprop_string(mc->fdt, mem_name, "device_type", "memory");
101
+ riscv_socket_fdt_write_id(mc, mc->fdt, mem_name, socket);
102
+ g_free(mem_name);
103
+}
104
+
105
+static void create_fdt_socket_clint(RISCVVirtState *s,
106
+ const MemMapEntry *memmap, int socket,
107
+ uint32_t *intc_phandles)
108
+{
109
+ int cpu;
110
+ char *clint_name;
111
+ uint32_t *clint_cells;
112
+ unsigned long clint_addr;
113
+ MachineState *mc = MACHINE(s);
114
static const char * const clint_compat[2] = {
115
"sifive,clint0", "riscv,clint0"
116
};
117
+
118
+ clint_cells = g_new0(uint32_t, s->soc[socket].num_harts * 4);
119
+
120
+ for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
121
+ clint_cells[cpu * 4 + 0] = cpu_to_be32(intc_phandles[cpu]);
122
+ clint_cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_SOFT);
123
+ clint_cells[cpu * 4 + 2] = cpu_to_be32(intc_phandles[cpu]);
124
+ clint_cells[cpu * 4 + 3] = cpu_to_be32(IRQ_M_TIMER);
125
+ }
126
+
127
+ clint_addr = memmap[VIRT_CLINT].base + (memmap[VIRT_CLINT].size * socket);
128
+ clint_name = g_strdup_printf("/soc/clint@%lx", clint_addr);
129
+ qemu_fdt_add_subnode(mc->fdt, clint_name);
130
+ qemu_fdt_setprop_string_array(mc->fdt, clint_name, "compatible",
131
+ (char **)&clint_compat,
132
+ ARRAY_SIZE(clint_compat));
133
+ qemu_fdt_setprop_cells(mc->fdt, clint_name, "reg",
134
+ 0x0, clint_addr, 0x0, memmap[VIRT_CLINT].size);
135
+ qemu_fdt_setprop(mc->fdt, clint_name, "interrupts-extended",
136
+ clint_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 4);
137
+ riscv_socket_fdt_write_id(mc, mc->fdt, clint_name, socket);
138
+ g_free(clint_name);
139
+
140
+ g_free(clint_cells);
141
+}
142
+
143
+static void create_fdt_socket_plic(RISCVVirtState *s,
144
+ const MemMapEntry *memmap, int socket,
145
+ uint32_t *phandle, uint32_t *intc_phandles,
146
+ uint32_t *plic_phandles)
147
+{
148
+ int cpu;
149
+ char *plic_name;
150
+ uint32_t *plic_cells;
151
+ unsigned long plic_addr;
152
+ MachineState *mc = MACHINE(s);
153
static const char * const plic_compat[2] = {
154
"sifive,plic-1.0.0", "riscv,plic0"
155
};
156
157
- if (mc->dtb) {
158
- fdt = mc->fdt = load_device_tree(mc->dtb, &s->fdt_size);
159
- if (!fdt) {
160
- error_report("load_device_tree() failed");
161
- exit(1);
162
- }
163
- goto update_bootargs;
164
- } else {
165
- fdt = mc->fdt = create_device_tree(&s->fdt_size);
166
- if (!fdt) {
167
- error_report("create_device_tree() failed");
168
- exit(1);
169
- }
170
+ plic_cells = g_new0(uint32_t, s->soc[socket].num_harts * 4);
171
+
172
+ for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
173
+ plic_cells[cpu * 4 + 0] = cpu_to_be32(intc_phandles[cpu]);
174
+ plic_cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_EXT);
175
+ plic_cells[cpu * 4 + 2] = cpu_to_be32(intc_phandles[cpu]);
176
+ plic_cells[cpu * 4 + 3] = cpu_to_be32(IRQ_S_EXT);
177
}
178
179
- qemu_fdt_setprop_string(fdt, "/", "model", "riscv-virtio,qemu");
180
- qemu_fdt_setprop_string(fdt, "/", "compatible", "riscv-virtio");
181
- qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x2);
182
- qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x2);
183
+ plic_phandles[socket] = (*phandle)++;
184
+ plic_addr = memmap[VIRT_PLIC].base + (memmap[VIRT_PLIC].size * socket);
185
+ plic_name = g_strdup_printf("/soc/plic@%lx", plic_addr);
186
+ qemu_fdt_add_subnode(mc->fdt, plic_name);
187
+ qemu_fdt_setprop_cell(mc->fdt, plic_name,
188
+ "#address-cells", FDT_PLIC_ADDR_CELLS);
189
+ qemu_fdt_setprop_cell(mc->fdt, plic_name,
190
+ "#interrupt-cells", FDT_PLIC_INT_CELLS);
191
+ qemu_fdt_setprop_string_array(mc->fdt, plic_name, "compatible",
192
+ (char **)&plic_compat,
193
+ ARRAY_SIZE(plic_compat));
194
+ qemu_fdt_setprop(mc->fdt, plic_name, "interrupt-controller", NULL, 0);
195
+ qemu_fdt_setprop(mc->fdt, plic_name, "interrupts-extended",
196
+ plic_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 4);
197
+ qemu_fdt_setprop_cells(mc->fdt, plic_name, "reg",
198
+ 0x0, plic_addr, 0x0, memmap[VIRT_PLIC].size);
199
+ qemu_fdt_setprop_cell(mc->fdt, plic_name, "riscv,ndev", VIRTIO_NDEV);
200
+ riscv_socket_fdt_write_id(mc, mc->fdt, plic_name, socket);
201
+ qemu_fdt_setprop_cell(mc->fdt, plic_name, "phandle",
202
+ plic_phandles[socket]);
203
+ g_free(plic_name);
204
+
205
+ g_free(plic_cells);
206
+}
207
208
- qemu_fdt_add_subnode(fdt, "/soc");
209
- qemu_fdt_setprop(fdt, "/soc", "ranges", NULL, 0);
210
- qemu_fdt_setprop_string(fdt, "/soc", "compatible", "simple-bus");
211
- qemu_fdt_setprop_cell(fdt, "/soc", "#size-cells", 0x2);
212
- qemu_fdt_setprop_cell(fdt, "/soc", "#address-cells", 0x2);
213
+static void create_fdt_sockets(RISCVVirtState *s, const MemMapEntry *memmap,
214
+ bool is_32_bit, uint32_t *phandle,
215
+ uint32_t *irq_mmio_phandle,
216
+ uint32_t *irq_pcie_phandle,
217
+ uint32_t *irq_virtio_phandle)
218
+{
219
+ int socket;
220
+ char *clust_name;
221
+ uint32_t *intc_phandles;
222
+ MachineState *mc = MACHINE(s);
223
+ uint32_t xplic_phandles[MAX_NODES];
224
225
- qemu_fdt_add_subnode(fdt, "/cpus");
226
- qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency",
227
+ qemu_fdt_add_subnode(mc->fdt, "/cpus");
228
+ qemu_fdt_setprop_cell(mc->fdt, "/cpus", "timebase-frequency",
229
RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ);
230
- qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0);
231
- qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1);
232
- qemu_fdt_add_subnode(fdt, "/cpus/cpu-map");
233
+ qemu_fdt_setprop_cell(mc->fdt, "/cpus", "#size-cells", 0x0);
234
+ qemu_fdt_setprop_cell(mc->fdt, "/cpus", "#address-cells", 0x1);
235
+ qemu_fdt_add_subnode(mc->fdt, "/cpus/cpu-map");
236
237
for (socket = (riscv_socket_count(mc) - 1); socket >= 0; socket--) {
238
clust_name = g_strdup_printf("/cpus/cpu-map/cluster%d", socket);
239
- qemu_fdt_add_subnode(fdt, clust_name);
240
-
241
- plic_cells = g_new0(uint32_t, s->soc[socket].num_harts * 4);
242
- clint_cells = g_new0(uint32_t, s->soc[socket].num_harts * 4);
243
-
244
- for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) {
245
- cpu_phandle = phandle++;
246
-
247
- cpu_name = g_strdup_printf("/cpus/cpu@%d",
248
- s->soc[socket].hartid_base + cpu);
249
- qemu_fdt_add_subnode(fdt, cpu_name);
250
- if (is_32_bit) {
251
- qemu_fdt_setprop_string(fdt, cpu_name, "mmu-type", "riscv,sv32");
252
- } else {
253
- qemu_fdt_setprop_string(fdt, cpu_name, "mmu-type", "riscv,sv48");
254
- }
255
- name = riscv_isa_string(&s->soc[socket].harts[cpu]);
256
- qemu_fdt_setprop_string(fdt, cpu_name, "riscv,isa", name);
257
- g_free(name);
258
- qemu_fdt_setprop_string(fdt, cpu_name, "compatible", "riscv");
259
- qemu_fdt_setprop_string(fdt, cpu_name, "status", "okay");
260
- qemu_fdt_setprop_cell(fdt, cpu_name, "reg",
261
- s->soc[socket].hartid_base + cpu);
262
- qemu_fdt_setprop_string(fdt, cpu_name, "device_type", "cpu");
263
- riscv_socket_fdt_write_id(mc, fdt, cpu_name, socket);
264
- qemu_fdt_setprop_cell(fdt, cpu_name, "phandle", cpu_phandle);
265
-
266
- intc_name = g_strdup_printf("%s/interrupt-controller", cpu_name);
267
- qemu_fdt_add_subnode(fdt, intc_name);
268
- intc_phandle = phandle++;
269
- qemu_fdt_setprop_cell(fdt, intc_name, "phandle", intc_phandle);
270
- qemu_fdt_setprop_string(fdt, intc_name, "compatible",
271
- "riscv,cpu-intc");
272
- qemu_fdt_setprop(fdt, intc_name, "interrupt-controller", NULL, 0);
273
- qemu_fdt_setprop_cell(fdt, intc_name, "#interrupt-cells", 1);
274
-
275
- clint_cells[cpu * 4 + 0] = cpu_to_be32(intc_phandle);
276
- clint_cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_SOFT);
277
- clint_cells[cpu * 4 + 2] = cpu_to_be32(intc_phandle);
278
- clint_cells[cpu * 4 + 3] = cpu_to_be32(IRQ_M_TIMER);
279
-
280
- plic_cells[cpu * 4 + 0] = cpu_to_be32(intc_phandle);
281
- plic_cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_EXT);
282
- plic_cells[cpu * 4 + 2] = cpu_to_be32(intc_phandle);
283
- plic_cells[cpu * 4 + 3] = cpu_to_be32(IRQ_S_EXT);
284
-
285
- core_name = g_strdup_printf("%s/core%d", clust_name, cpu);
286
- qemu_fdt_add_subnode(fdt, core_name);
287
- qemu_fdt_setprop_cell(fdt, core_name, "cpu", cpu_phandle);
288
-
289
- g_free(core_name);
290
- g_free(intc_name);
291
- g_free(cpu_name);
292
- }
293
+ qemu_fdt_add_subnode(mc->fdt, clust_name);
294
+
295
+ intc_phandles = g_new0(uint32_t, s->soc[socket].num_harts);
296
+
297
+ create_fdt_socket_cpus(s, socket, clust_name, phandle,
298
+ is_32_bit, intc_phandles);
299
300
- addr = memmap[VIRT_DRAM].base + riscv_socket_mem_offset(mc, socket);
301
- size = riscv_socket_mem_size(mc, socket);
302
- mem_name = g_strdup_printf("/memory@%lx", (long)addr);
303
- qemu_fdt_add_subnode(fdt, mem_name);
304
- qemu_fdt_setprop_cells(fdt, mem_name, "reg",
305
- addr >> 32, addr, size >> 32, size);
306
- qemu_fdt_setprop_string(fdt, mem_name, "device_type", "memory");
307
- riscv_socket_fdt_write_id(mc, fdt, mem_name, socket);
308
- g_free(mem_name);
309
-
310
- clint_addr = memmap[VIRT_CLINT].base +
311
- (memmap[VIRT_CLINT].size * socket);
312
- clint_name = g_strdup_printf("/soc/clint@%lx", clint_addr);
313
- qemu_fdt_add_subnode(fdt, clint_name);
314
- qemu_fdt_setprop_string_array(fdt, clint_name, "compatible",
315
- (char **)&clint_compat, ARRAY_SIZE(clint_compat));
316
- qemu_fdt_setprop_cells(fdt, clint_name, "reg",
317
- 0x0, clint_addr, 0x0, memmap[VIRT_CLINT].size);
318
- qemu_fdt_setprop(fdt, clint_name, "interrupts-extended",
319
- clint_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 4);
320
- riscv_socket_fdt_write_id(mc, fdt, clint_name, socket);
321
- g_free(clint_name);
322
-
323
- plic_phandle[socket] = phandle++;
324
- plic_addr = memmap[VIRT_PLIC].base + (memmap[VIRT_PLIC].size * socket);
325
- plic_name = g_strdup_printf("/soc/plic@%lx", plic_addr);
326
- qemu_fdt_add_subnode(fdt, plic_name);
327
- qemu_fdt_setprop_cell(fdt, plic_name,
328
- "#address-cells", FDT_PLIC_ADDR_CELLS);
329
- qemu_fdt_setprop_cell(fdt, plic_name,
330
- "#interrupt-cells", FDT_PLIC_INT_CELLS);
331
- qemu_fdt_setprop_string_array(fdt, plic_name, "compatible",
332
- (char **)&plic_compat, ARRAY_SIZE(plic_compat));
333
- qemu_fdt_setprop(fdt, plic_name, "interrupt-controller", NULL, 0);
334
- qemu_fdt_setprop(fdt, plic_name, "interrupts-extended",
335
- plic_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 4);
336
- qemu_fdt_setprop_cells(fdt, plic_name, "reg",
337
- 0x0, plic_addr, 0x0, memmap[VIRT_PLIC].size);
338
- qemu_fdt_setprop_cell(fdt, plic_name, "riscv,ndev", VIRTIO_NDEV);
339
- riscv_socket_fdt_write_id(mc, fdt, plic_name, socket);
340
- qemu_fdt_setprop_cell(fdt, plic_name, "phandle", plic_phandle[socket]);
341
- g_free(plic_name);
342
-
343
- g_free(clint_cells);
344
- g_free(plic_cells);
345
+ create_fdt_socket_memory(s, memmap, socket);
346
+
347
+ create_fdt_socket_clint(s, memmap, socket, intc_phandles);
348
+
349
+ create_fdt_socket_plic(s, memmap, socket, phandle,
350
+ intc_phandles, xplic_phandles);
351
+
352
+ g_free(intc_phandles);
353
g_free(clust_name);
354
}
355
356
for (socket = 0; socket < riscv_socket_count(mc); socket++) {
357
if (socket == 0) {
358
- plic_mmio_phandle = plic_phandle[socket];
359
- plic_virtio_phandle = plic_phandle[socket];
360
- plic_pcie_phandle = plic_phandle[socket];
361
+ *irq_mmio_phandle = xplic_phandles[socket];
362
+ *irq_virtio_phandle = xplic_phandles[socket];
363
+ *irq_pcie_phandle = xplic_phandles[socket];
364
}
365
if (socket == 1) {
366
- plic_virtio_phandle = plic_phandle[socket];
367
- plic_pcie_phandle = plic_phandle[socket];
368
+ *irq_virtio_phandle = xplic_phandles[socket];
369
+ *irq_pcie_phandle = xplic_phandles[socket];
370
}
371
if (socket == 2) {
372
- plic_pcie_phandle = plic_phandle[socket];
373
+ *irq_pcie_phandle = xplic_phandles[socket];
27
}
374
}
28
}
375
}
29
-}
376
30
-
377
- riscv_socket_fdt_write_distance_matrix(mc, fdt);
31
-static void sifive_u_otp_reset(DeviceState *dev)
378
+ riscv_socket_fdt_write_distance_matrix(mc, mc->fdt);
32
-{
379
+}
33
- SiFiveUOTPState *s = SIFIVE_U_OTP(dev);
380
+
34
381
+static void create_fdt_virtio(RISCVVirtState *s, const MemMapEntry *memmap,
35
/* Initialize all fuses' initial value to 0xFFs */
382
+ uint32_t irq_virtio_phandle)
36
memset(s->fuse, 0xff, sizeof(s->fuse));
383
+{
37
@@ -XXX,XX +XXX,XX @@ static void sifive_u_otp_reset(DeviceState *dev)
384
+ int i;
38
serial_data = s->serial;
385
+ char *name;
39
if (blk_pwrite(s->blk, index * SIFIVE_U_OTP_FUSE_WORD,
386
+ MachineState *mc = MACHINE(s);
40
&serial_data, SIFIVE_U_OTP_FUSE_WORD, 0) < 0) {
387
41
- error_report("write error index<%d>", index);
388
for (i = 0; i < VIRTIO_COUNT; i++) {
42
+ error_setg(errp, "failed to write index<%d>", index);
389
name = g_strdup_printf("/soc/virtio_mmio@%lx",
43
+ return;
390
(long)(memmap[VIRT_VIRTIO].base + i * memmap[VIRT_VIRTIO].size));
44
}
391
- qemu_fdt_add_subnode(fdt, name);
45
392
- qemu_fdt_setprop_string(fdt, name, "compatible", "virtio,mmio");
46
serial_data = ~(s->serial);
393
- qemu_fdt_setprop_cells(fdt, name, "reg",
47
if (blk_pwrite(s->blk, (index + 1) * SIFIVE_U_OTP_FUSE_WORD,
394
+ qemu_fdt_add_subnode(mc->fdt, name);
48
&serial_data, SIFIVE_U_OTP_FUSE_WORD, 0) < 0) {
395
+ qemu_fdt_setprop_string(mc->fdt, name, "compatible", "virtio,mmio");
49
- error_report("write error index<%d>", index + 1);
396
+ qemu_fdt_setprop_cells(mc->fdt, name, "reg",
50
+ error_setg(errp, "failed to write index<%d>", index + 1);
397
0x0, memmap[VIRT_VIRTIO].base + i * memmap[VIRT_VIRTIO].size,
51
+ return;
398
0x0, memmap[VIRT_VIRTIO].size);
52
}
399
- qemu_fdt_setprop_cell(fdt, name, "interrupt-parent",
400
- plic_virtio_phandle);
401
- qemu_fdt_setprop_cell(fdt, name, "interrupts", VIRTIO_IRQ + i);
402
+ qemu_fdt_setprop_cell(mc->fdt, name, "interrupt-parent",
403
+ irq_virtio_phandle);
404
+ qemu_fdt_setprop_cell(mc->fdt, name, "interrupts", VIRTIO_IRQ + i);
405
g_free(name);
53
}
406
}
54
407
+}
55
@@ -XXX,XX +XXX,XX @@ static void sifive_u_otp_class_init(ObjectClass *klass, void *data)
408
+
56
409
+static void create_fdt_pcie(RISCVVirtState *s, const MemMapEntry *memmap,
57
device_class_set_props(dc, sifive_u_otp_properties);
410
+ uint32_t irq_pcie_phandle)
58
dc->realize = sifive_u_otp_realize;
411
+{
59
- dc->reset = sifive_u_otp_reset;
412
+ char *name;
413
+ MachineState *mc = MACHINE(s);
414
415
name = g_strdup_printf("/soc/pci@%lx",
416
(long) memmap[VIRT_PCIE_ECAM].base);
417
- qemu_fdt_add_subnode(fdt, name);
418
- qemu_fdt_setprop_cell(fdt, name, "#address-cells", FDT_PCI_ADDR_CELLS);
419
- qemu_fdt_setprop_cell(fdt, name, "#interrupt-cells", FDT_PCI_INT_CELLS);
420
- qemu_fdt_setprop_cell(fdt, name, "#size-cells", 0x2);
421
- qemu_fdt_setprop_string(fdt, name, "compatible", "pci-host-ecam-generic");
422
- qemu_fdt_setprop_string(fdt, name, "device_type", "pci");
423
- qemu_fdt_setprop_cell(fdt, name, "linux,pci-domain", 0);
424
- qemu_fdt_setprop_cells(fdt, name, "bus-range", 0,
425
+ qemu_fdt_add_subnode(mc->fdt, name);
426
+ qemu_fdt_setprop_cell(mc->fdt, name, "#address-cells",
427
+ FDT_PCI_ADDR_CELLS);
428
+ qemu_fdt_setprop_cell(mc->fdt, name, "#interrupt-cells",
429
+ FDT_PCI_INT_CELLS);
430
+ qemu_fdt_setprop_cell(mc->fdt, name, "#size-cells", 0x2);
431
+ qemu_fdt_setprop_string(mc->fdt, name, "compatible",
432
+ "pci-host-ecam-generic");
433
+ qemu_fdt_setprop_string(mc->fdt, name, "device_type", "pci");
434
+ qemu_fdt_setprop_cell(mc->fdt, name, "linux,pci-domain", 0);
435
+ qemu_fdt_setprop_cells(mc->fdt, name, "bus-range", 0,
436
memmap[VIRT_PCIE_ECAM].size / PCIE_MMCFG_SIZE_MIN - 1);
437
- qemu_fdt_setprop(fdt, name, "dma-coherent", NULL, 0);
438
- qemu_fdt_setprop_cells(fdt, name, "reg", 0,
439
+ qemu_fdt_setprop(mc->fdt, name, "dma-coherent", NULL, 0);
440
+ qemu_fdt_setprop_cells(mc->fdt, name, "reg", 0,
441
memmap[VIRT_PCIE_ECAM].base, 0, memmap[VIRT_PCIE_ECAM].size);
442
- qemu_fdt_setprop_sized_cells(fdt, name, "ranges",
443
+ qemu_fdt_setprop_sized_cells(mc->fdt, name, "ranges",
444
1, FDT_PCI_RANGE_IOPORT, 2, 0,
445
2, memmap[VIRT_PCIE_PIO].base, 2, memmap[VIRT_PCIE_PIO].size,
446
1, FDT_PCI_RANGE_MMIO,
447
@@ -XXX,XX +XXX,XX @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap,
448
2, virt_high_pcie_memmap.base,
449
2, virt_high_pcie_memmap.base, 2, virt_high_pcie_memmap.size);
450
451
- create_pcie_irq_map(fdt, name, plic_pcie_phandle);
452
+ create_pcie_irq_map(mc->fdt, name, irq_pcie_phandle);
453
g_free(name);
454
+}
455
456
- test_phandle = phandle++;
457
+static void create_fdt_reset(RISCVVirtState *s, const MemMapEntry *memmap,
458
+ uint32_t *phandle)
459
+{
460
+ char *name;
461
+ uint32_t test_phandle;
462
+ MachineState *mc = MACHINE(s);
463
+
464
+ test_phandle = (*phandle)++;
465
name = g_strdup_printf("/soc/test@%lx",
466
(long)memmap[VIRT_TEST].base);
467
- qemu_fdt_add_subnode(fdt, name);
468
+ qemu_fdt_add_subnode(mc->fdt, name);
469
{
470
static const char * const compat[3] = {
471
"sifive,test1", "sifive,test0", "syscon"
472
};
473
- qemu_fdt_setprop_string_array(fdt, name, "compatible", (char **)&compat,
474
- ARRAY_SIZE(compat));
475
+ qemu_fdt_setprop_string_array(mc->fdt, name, "compatible",
476
+ (char **)&compat, ARRAY_SIZE(compat));
477
}
478
- qemu_fdt_setprop_cells(fdt, name, "reg",
479
- 0x0, memmap[VIRT_TEST].base,
480
- 0x0, memmap[VIRT_TEST].size);
481
- qemu_fdt_setprop_cell(fdt, name, "phandle", test_phandle);
482
- test_phandle = qemu_fdt_get_phandle(fdt, name);
483
+ qemu_fdt_setprop_cells(mc->fdt, name, "reg",
484
+ 0x0, memmap[VIRT_TEST].base, 0x0, memmap[VIRT_TEST].size);
485
+ qemu_fdt_setprop_cell(mc->fdt, name, "phandle", test_phandle);
486
+ test_phandle = qemu_fdt_get_phandle(mc->fdt, name);
487
g_free(name);
488
489
name = g_strdup_printf("/soc/reboot");
490
- qemu_fdt_add_subnode(fdt, name);
491
- qemu_fdt_setprop_string(fdt, name, "compatible", "syscon-reboot");
492
- qemu_fdt_setprop_cell(fdt, name, "regmap", test_phandle);
493
- qemu_fdt_setprop_cell(fdt, name, "offset", 0x0);
494
- qemu_fdt_setprop_cell(fdt, name, "value", FINISHER_RESET);
495
+ qemu_fdt_add_subnode(mc->fdt, name);
496
+ qemu_fdt_setprop_string(mc->fdt, name, "compatible", "syscon-reboot");
497
+ qemu_fdt_setprop_cell(mc->fdt, name, "regmap", test_phandle);
498
+ qemu_fdt_setprop_cell(mc->fdt, name, "offset", 0x0);
499
+ qemu_fdt_setprop_cell(mc->fdt, name, "value", FINISHER_RESET);
500
g_free(name);
501
502
name = g_strdup_printf("/soc/poweroff");
503
- qemu_fdt_add_subnode(fdt, name);
504
- qemu_fdt_setprop_string(fdt, name, "compatible", "syscon-poweroff");
505
- qemu_fdt_setprop_cell(fdt, name, "regmap", test_phandle);
506
- qemu_fdt_setprop_cell(fdt, name, "offset", 0x0);
507
- qemu_fdt_setprop_cell(fdt, name, "value", FINISHER_PASS);
508
+ qemu_fdt_add_subnode(mc->fdt, name);
509
+ qemu_fdt_setprop_string(mc->fdt, name, "compatible", "syscon-poweroff");
510
+ qemu_fdt_setprop_cell(mc->fdt, name, "regmap", test_phandle);
511
+ qemu_fdt_setprop_cell(mc->fdt, name, "offset", 0x0);
512
+ qemu_fdt_setprop_cell(mc->fdt, name, "value", FINISHER_PASS);
513
g_free(name);
514
+}
515
+
516
+static void create_fdt_uart(RISCVVirtState *s, const MemMapEntry *memmap,
517
+ uint32_t irq_mmio_phandle)
518
+{
519
+ char *name;
520
+ MachineState *mc = MACHINE(s);
521
522
name = g_strdup_printf("/soc/uart@%lx", (long)memmap[VIRT_UART0].base);
523
- qemu_fdt_add_subnode(fdt, name);
524
- qemu_fdt_setprop_string(fdt, name, "compatible", "ns16550a");
525
- qemu_fdt_setprop_cells(fdt, name, "reg",
526
+ qemu_fdt_add_subnode(mc->fdt, name);
527
+ qemu_fdt_setprop_string(mc->fdt, name, "compatible", "ns16550a");
528
+ qemu_fdt_setprop_cells(mc->fdt, name, "reg",
529
0x0, memmap[VIRT_UART0].base,
530
0x0, memmap[VIRT_UART0].size);
531
- qemu_fdt_setprop_cell(fdt, name, "clock-frequency", 3686400);
532
- qemu_fdt_setprop_cell(fdt, name, "interrupt-parent", plic_mmio_phandle);
533
- qemu_fdt_setprop_cell(fdt, name, "interrupts", UART0_IRQ);
534
+ qemu_fdt_setprop_cell(mc->fdt, name, "clock-frequency", 3686400);
535
+ qemu_fdt_setprop_cell(mc->fdt, name, "interrupt-parent", irq_mmio_phandle);
536
+ qemu_fdt_setprop_cell(mc->fdt, name, "interrupts", UART0_IRQ);
537
538
- qemu_fdt_add_subnode(fdt, "/chosen");
539
- qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", name);
540
+ qemu_fdt_add_subnode(mc->fdt, "/chosen");
541
+ qemu_fdt_setprop_string(mc->fdt, "/chosen", "stdout-path", name);
542
g_free(name);
543
+}
544
+
545
+static void create_fdt_rtc(RISCVVirtState *s, const MemMapEntry *memmap,
546
+ uint32_t irq_mmio_phandle)
547
+{
548
+ char *name;
549
+ MachineState *mc = MACHINE(s);
550
551
name = g_strdup_printf("/soc/rtc@%lx", (long)memmap[VIRT_RTC].base);
552
- qemu_fdt_add_subnode(fdt, name);
553
- qemu_fdt_setprop_string(fdt, name, "compatible", "google,goldfish-rtc");
554
- qemu_fdt_setprop_cells(fdt, name, "reg",
555
- 0x0, memmap[VIRT_RTC].base,
556
- 0x0, memmap[VIRT_RTC].size);
557
- qemu_fdt_setprop_cell(fdt, name, "interrupt-parent", plic_mmio_phandle);
558
- qemu_fdt_setprop_cell(fdt, name, "interrupts", RTC_IRQ);
559
+ qemu_fdt_add_subnode(mc->fdt, name);
560
+ qemu_fdt_setprop_string(mc->fdt, name, "compatible",
561
+ "google,goldfish-rtc");
562
+ qemu_fdt_setprop_cells(mc->fdt, name, "reg",
563
+ 0x0, memmap[VIRT_RTC].base, 0x0, memmap[VIRT_RTC].size);
564
+ qemu_fdt_setprop_cell(mc->fdt, name, "interrupt-parent",
565
+ irq_mmio_phandle);
566
+ qemu_fdt_setprop_cell(mc->fdt, name, "interrupts", RTC_IRQ);
567
g_free(name);
568
+}
569
+
570
+static void create_fdt_flash(RISCVVirtState *s, const MemMapEntry *memmap)
571
+{
572
+ char *name;
573
+ MachineState *mc = MACHINE(s);
574
+ hwaddr flashsize = virt_memmap[VIRT_FLASH].size / 2;
575
+ hwaddr flashbase = virt_memmap[VIRT_FLASH].base;
576
577
name = g_strdup_printf("/flash@%" PRIx64, flashbase);
578
qemu_fdt_add_subnode(mc->fdt, name);
579
@@ -XXX,XX +XXX,XX @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap,
580
2, flashbase + flashsize, 2, flashsize);
581
qemu_fdt_setprop_cell(mc->fdt, name, "bank-width", 4);
582
g_free(name);
583
+}
584
+
585
+static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap,
586
+ uint64_t mem_size, const char *cmdline, bool is_32_bit)
587
+{
588
+ MachineState *mc = MACHINE(s);
589
+ uint32_t phandle = 1, irq_mmio_phandle = 1;
590
+ uint32_t irq_pcie_phandle = 1, irq_virtio_phandle = 1;
591
+
592
+ if (mc->dtb) {
593
+ mc->fdt = load_device_tree(mc->dtb, &s->fdt_size);
594
+ if (!mc->fdt) {
595
+ error_report("load_device_tree() failed");
596
+ exit(1);
597
+ }
598
+ goto update_bootargs;
599
+ } else {
600
+ mc->fdt = create_device_tree(&s->fdt_size);
601
+ if (!mc->fdt) {
602
+ error_report("create_device_tree() failed");
603
+ exit(1);
604
+ }
605
+ }
606
+
607
+ qemu_fdt_setprop_string(mc->fdt, "/", "model", "riscv-virtio,qemu");
608
+ qemu_fdt_setprop_string(mc->fdt, "/", "compatible", "riscv-virtio");
609
+ qemu_fdt_setprop_cell(mc->fdt, "/", "#size-cells", 0x2);
610
+ qemu_fdt_setprop_cell(mc->fdt, "/", "#address-cells", 0x2);
611
+
612
+ qemu_fdt_add_subnode(mc->fdt, "/soc");
613
+ qemu_fdt_setprop(mc->fdt, "/soc", "ranges", NULL, 0);
614
+ qemu_fdt_setprop_string(mc->fdt, "/soc", "compatible", "simple-bus");
615
+ qemu_fdt_setprop_cell(mc->fdt, "/soc", "#size-cells", 0x2);
616
+ qemu_fdt_setprop_cell(mc->fdt, "/soc", "#address-cells", 0x2);
617
+
618
+ create_fdt_sockets(s, memmap, is_32_bit, &phandle,
619
+ &irq_mmio_phandle, &irq_pcie_phandle, &irq_virtio_phandle);
620
+
621
+ create_fdt_virtio(s, memmap, irq_virtio_phandle);
622
+
623
+ create_fdt_pcie(s, memmap, irq_pcie_phandle);
624
+
625
+ create_fdt_reset(s, memmap, &phandle);
626
+
627
+ create_fdt_uart(s, memmap, irq_mmio_phandle);
628
+
629
+ create_fdt_rtc(s, memmap, irq_mmio_phandle);
630
+
631
+ create_fdt_flash(s, memmap);
632
633
update_bootargs:
634
if (cmdline) {
635
- qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline);
636
+ qemu_fdt_setprop_string(mc->fdt, "/chosen", "bootargs", cmdline);
637
}
60
}
638
}
61
639
62
static const TypeInfo sifive_u_otp_info = {
63
--
640
--
64
2.31.1
641
2.31.1
65
642
66
643
diff view generated by jsdifflib
New patch
1
1
From: Anup Patel <anup.patel@wdc.com>
2
3
We extend virt machine to emulate ACLINT devices only when "aclint=on"
4
parameter is passed along with machine name in QEMU command-line.
5
6
Signed-off-by: Anup Patel <anup.patel@wdc.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
9
Message-id: 20210831110603.338681-5-anup.patel@wdc.com
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
---
12
docs/system/riscv/virt.rst | 10 ++++
13
include/hw/riscv/virt.h | 2 +
14
hw/riscv/virt.c | 113 ++++++++++++++++++++++++++++++++++++-
15
3 files changed, 124 insertions(+), 1 deletion(-)
16
17
diff --git a/docs/system/riscv/virt.rst b/docs/system/riscv/virt.rst
18
index XXXXXXX..XXXXXXX 100644
19
--- a/docs/system/riscv/virt.rst
20
+++ b/docs/system/riscv/virt.rst
21
@@ -XXX,XX +XXX,XX @@ with the default OpenSBI firmware image as the -bios. It also supports
22
the recommended RISC-V bootflow: U-Boot SPL (M-mode) loads OpenSBI fw_dynamic
23
firmware and U-Boot proper (S-mode), using the standard -bios functionality.
24
25
+Machine-specific options
26
+------------------------
27
+
28
+The following machine-specific options are supported:
29
+
30
+- aclint=[on|off]
31
+
32
+ When this option is "on", ACLINT devices will be emulated instead of
33
+ SiFive CLINT. When not specified, this option is assumed to be "off".
34
+
35
Running Linux kernel
36
--------------------
37
38
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
39
index XXXXXXX..XXXXXXX 100644
40
--- a/include/hw/riscv/virt.h
41
+++ b/include/hw/riscv/virt.h
42
@@ -XXX,XX +XXX,XX @@ struct RISCVVirtState {
43
FWCfgState *fw_cfg;
44
45
int fdt_size;
46
+ bool have_aclint;
47
};
48
49
enum {
50
@@ -XXX,XX +XXX,XX @@ enum {
51
VIRT_TEST,
52
VIRT_RTC,
53
VIRT_CLINT,
54
+ VIRT_ACLINT_SSWI,
55
VIRT_PLIC,
56
VIRT_UART0,
57
VIRT_VIRTIO,
58
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/hw/riscv/virt.c
61
+++ b/hw/riscv/virt.c
62
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry virt_memmap[] = {
63
[VIRT_TEST] = { 0x100000, 0x1000 },
64
[VIRT_RTC] = { 0x101000, 0x1000 },
65
[VIRT_CLINT] = { 0x2000000, 0x10000 },
66
+ [VIRT_ACLINT_SSWI] = { 0x2F00000, 0x4000 },
67
[VIRT_PCIE_PIO] = { 0x3000000, 0x10000 },
68
[VIRT_PLIC] = { 0xc000000, VIRT_PLIC_SIZE(VIRT_CPUS_MAX * 2) },
69
[VIRT_UART0] = { 0x10000000, 0x100 },
70
@@ -XXX,XX +XXX,XX @@ static void create_fdt_socket_clint(RISCVVirtState *s,
71
g_free(clint_cells);
72
}
73
74
+static void create_fdt_socket_aclint(RISCVVirtState *s,
75
+ const MemMapEntry *memmap, int socket,
76
+ uint32_t *intc_phandles)
77
+{
78
+ int cpu;
79
+ char *name;
80
+ unsigned long addr;
81
+ uint32_t aclint_cells_size;
82
+ uint32_t *aclint_mswi_cells;
83
+ uint32_t *aclint_sswi_cells;
84
+ uint32_t *aclint_mtimer_cells;
85
+ MachineState *mc = MACHINE(s);
86
+
87
+ aclint_mswi_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
88
+ aclint_mtimer_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
89
+ aclint_sswi_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
90
+
91
+ for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
92
+ aclint_mswi_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
93
+ aclint_mswi_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_SOFT);
94
+ aclint_mtimer_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
95
+ aclint_mtimer_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_TIMER);
96
+ aclint_sswi_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
97
+ aclint_sswi_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_S_SOFT);
98
+ }
99
+ aclint_cells_size = s->soc[socket].num_harts * sizeof(uint32_t) * 2;
100
+
101
+ addr = memmap[VIRT_CLINT].base + (memmap[VIRT_CLINT].size * socket);
102
+ name = g_strdup_printf("/soc/mswi@%lx", addr);
103
+ qemu_fdt_add_subnode(mc->fdt, name);
104
+ qemu_fdt_setprop_string(mc->fdt, name, "compatible", "riscv,aclint-mswi");
105
+ qemu_fdt_setprop_cells(mc->fdt, name, "reg",
106
+ 0x0, addr, 0x0, RISCV_ACLINT_SWI_SIZE);
107
+ qemu_fdt_setprop(mc->fdt, name, "interrupts-extended",
108
+ aclint_mswi_cells, aclint_cells_size);
109
+ qemu_fdt_setprop(mc->fdt, name, "interrupt-controller", NULL, 0);
110
+ qemu_fdt_setprop_cell(mc->fdt, name, "#interrupt-cells", 0);
111
+ riscv_socket_fdt_write_id(mc, mc->fdt, name, socket);
112
+ g_free(name);
113
+
114
+ addr = memmap[VIRT_CLINT].base + RISCV_ACLINT_SWI_SIZE +
115
+ (memmap[VIRT_CLINT].size * socket);
116
+ name = g_strdup_printf("/soc/mtimer@%lx", addr);
117
+ qemu_fdt_add_subnode(mc->fdt, name);
118
+ qemu_fdt_setprop_string(mc->fdt, name, "compatible",
119
+ "riscv,aclint-mtimer");
120
+ qemu_fdt_setprop_cells(mc->fdt, name, "reg",
121
+ 0x0, addr + RISCV_ACLINT_DEFAULT_MTIME,
122
+ 0x0, memmap[VIRT_CLINT].size - RISCV_ACLINT_SWI_SIZE -
123
+ RISCV_ACLINT_DEFAULT_MTIME,
124
+ 0x0, addr + RISCV_ACLINT_DEFAULT_MTIMECMP,
125
+ 0x0, RISCV_ACLINT_DEFAULT_MTIME);
126
+ qemu_fdt_setprop(mc->fdt, name, "interrupts-extended",
127
+ aclint_mtimer_cells, aclint_cells_size);
128
+ riscv_socket_fdt_write_id(mc, mc->fdt, name, socket);
129
+ g_free(name);
130
+
131
+ addr = memmap[VIRT_ACLINT_SSWI].base +
132
+ (memmap[VIRT_ACLINT_SSWI].size * socket);
133
+ name = g_strdup_printf("/soc/sswi@%lx", addr);
134
+ qemu_fdt_add_subnode(mc->fdt, name);
135
+ qemu_fdt_setprop_string(mc->fdt, name, "compatible", "riscv,aclint-sswi");
136
+ qemu_fdt_setprop_cells(mc->fdt, name, "reg",
137
+ 0x0, addr, 0x0, memmap[VIRT_ACLINT_SSWI].size);
138
+ qemu_fdt_setprop(mc->fdt, name, "interrupts-extended",
139
+ aclint_sswi_cells, aclint_cells_size);
140
+ qemu_fdt_setprop(mc->fdt, name, "interrupt-controller", NULL, 0);
141
+ qemu_fdt_setprop_cell(mc->fdt, name, "#interrupt-cells", 0);
142
+ riscv_socket_fdt_write_id(mc, mc->fdt, name, socket);
143
+ g_free(name);
144
+
145
+ g_free(aclint_mswi_cells);
146
+ g_free(aclint_mtimer_cells);
147
+ g_free(aclint_sswi_cells);
148
+}
149
+
150
static void create_fdt_socket_plic(RISCVVirtState *s,
151
const MemMapEntry *memmap, int socket,
152
uint32_t *phandle, uint32_t *intc_phandles,
153
@@ -XXX,XX +XXX,XX @@ static void create_fdt_sockets(RISCVVirtState *s, const MemMapEntry *memmap,
154
155
create_fdt_socket_memory(s, memmap, socket);
156
157
- create_fdt_socket_clint(s, memmap, socket, intc_phandles);
158
+ if (s->have_aclint) {
159
+ create_fdt_socket_aclint(s, memmap, socket, intc_phandles);
160
+ } else {
161
+ create_fdt_socket_clint(s, memmap, socket, intc_phandles);
162
+ }
163
164
create_fdt_socket_plic(s, memmap, socket, phandle,
165
intc_phandles, xplic_phandles);
166
@@ -XXX,XX +XXX,XX @@ static void virt_machine_init(MachineState *machine)
167
RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME,
168
RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, true);
169
170
+ /* Per-socket ACLINT SSWI */
171
+ if (s->have_aclint) {
172
+ riscv_aclint_swi_create(
173
+ memmap[VIRT_ACLINT_SSWI].base +
174
+ i * memmap[VIRT_ACLINT_SSWI].size,
175
+ base_hartid, hart_count, true);
176
+ }
177
+
178
/* Per-socket PLIC hart topology configuration string */
179
plic_hart_config = plic_hart_config_string(hart_count);
180
181
@@ -XXX,XX +XXX,XX @@ static void virt_machine_instance_init(Object *obj)
182
{
183
}
184
185
+static bool virt_get_aclint(Object *obj, Error **errp)
186
+{
187
+ MachineState *ms = MACHINE(obj);
188
+ RISCVVirtState *s = RISCV_VIRT_MACHINE(ms);
189
+
190
+ return s->have_aclint;
191
+}
192
+
193
+static void virt_set_aclint(Object *obj, bool value, Error **errp)
194
+{
195
+ MachineState *ms = MACHINE(obj);
196
+ RISCVVirtState *s = RISCV_VIRT_MACHINE(ms);
197
+
198
+ s->have_aclint = value;
199
+}
200
+
201
static void virt_machine_class_init(ObjectClass *oc, void *data)
202
{
203
MachineClass *mc = MACHINE_CLASS(oc);
204
@@ -XXX,XX +XXX,XX @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
205
mc->numa_mem_supported = true;
206
207
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
208
+
209
+ object_class_property_add_bool(oc, "aclint", virt_get_aclint,
210
+ virt_set_aclint);
211
+ object_class_property_set_description(oc, "aclint",
212
+ "Set on/off to enable/disable "
213
+ "emulating ACLINT devices");
214
}
215
216
static const TypeInfo virt_machine_typeinfo = {
217
--
218
2.31.1
219
220
diff view generated by jsdifflib
New patch
1
From: Frank Chang <frank.chang@sifive.com>
1
2
3
Setting Control.claim clears all of the chanel's Next registers.
4
This is effective only when Control.claim is set from 0 to 1.
5
6
Signed-off-by: Frank Chang <frank.chang@sifive.com>
7
Tested-by: Max Hsu <max.hsu@sifive.com>
8
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
9
Tested-by: Bin Meng <bmeng.cn@gmail.com>
10
Message-id: 20210912130553.179501-2-frank.chang@sifive.com
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
13
hw/dma/sifive_pdma.c | 19 +++++++++++++++++++
14
1 file changed, 19 insertions(+)
15
16
diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/dma/sifive_pdma.c
19
+++ b/hw/dma/sifive_pdma.c
20
@@ -XXX,XX +XXX,XX @@
21
#define DMA_EXEC_DST 0x110
22
#define DMA_EXEC_SRC 0x118
23
24
+/*
25
+ * FU540/FU740 docs are incorrect with NextConfig.wsize/rsize reset values.
26
+ * The reset values tested on Unleashed/Unmatched boards are 6 instead of 0.
27
+ */
28
+#define CONFIG_WRSZ_DEFAULT 6
29
+#define CONFIG_RDSZ_DEFAULT 6
30
+
31
enum dma_chan_state {
32
DMA_CHAN_STATE_IDLE,
33
DMA_CHAN_STATE_STARTED,
34
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_write(void *opaque, hwaddr offset,
35
{
36
SiFivePDMAState *s = opaque;
37
int ch = SIFIVE_PDMA_CHAN_NO(offset);
38
+ bool claimed;
39
40
if (ch >= SIFIVE_PDMA_CHANS) {
41
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid channel no %d\n",
42
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_write(void *opaque, hwaddr offset,
43
offset &= 0xfff;
44
switch (offset) {
45
case DMA_CONTROL:
46
+ claimed = !!s->chan[ch].control & CONTROL_CLAIM;
47
+
48
+ if (!claimed && (value & CONTROL_CLAIM)) {
49
+ /* reset Next* registers */
50
+ s->chan[ch].next_config = (CONFIG_RDSZ_DEFAULT << CONFIG_RDSZ_SHIFT) |
51
+ (CONFIG_WRSZ_DEFAULT << CONFIG_WRSZ_SHIFT);
52
+ s->chan[ch].next_bytes = 0;
53
+ s->chan[ch].next_dst = 0;
54
+ s->chan[ch].next_src = 0;
55
+ }
56
+
57
s->chan[ch].control = value;
58
59
if (value & CONTROL_RUN) {
60
--
61
2.31.1
62
63
diff view generated by jsdifflib
New patch
1
From: Frank Chang <frank.chang@sifive.com>
1
2
3
Real PDMA must have Control.claim bit to be set before
4
Control.run bit is set to start any DMA transactions.
5
Otherwise nothing will be transferred.
6
7
The following result is PDMA tested in U-Boot on Unmatched board:
8
9
=> mw.l 0x3000000 0x0 <= Disclaim channel 0
10
(Channel 0 is not claimed)
11
=> mw.l 0x3000004 0x55000000 <= wsize = rsize = 5 (2^5 = 32 bytes)
12
=> mw.q 0x3000008 0x2 <= NextBytes = 2
13
=> mw.q 0x3000010 0x84000000 <= NextDestination = 0x84000000
14
=> mw.q 0x3000018 0x84001000 <= NextSource = 0x84001000
15
=> mw.l 0x84000000 0x87654321 <= Fill test data to dst
16
=> mw.l 0x84001000 0x12345678 <= Fill test data to src
17
=> md.l 0x84000000 1; md.l 0x84001000 1 <= Dump src/dst memory contents
18
84000000: 87654321 !Ce.
19
84001000: 12345678 xV4.
20
=> md.l 0x3000000 8 <= Dump PDMA status
21
03000000: 00000000 55000000 00000002 00000000 .......U........
22
03000010: 84000000 00000000 84001000 00000000 ................
23
=> mw.l 0x3000000 0x3 <= Set channel 0 run and claim bits
24
=> md.l 0x3000000 8 <= Dump PDMA status
25
03000000: 00000001 66000000 00000000 00000000 .......f........
26
03000010: 00000000 00000000 00000000 00000000 ................
27
=> md.l 0x84000000 1; md.l 0x84001000 1 <= Dump src/dst memory contents
28
84000000: 87654321 !Ce.
29
84001000: 12345678 xV4.
30
31
Signed-off-by: Frank Chang <frank.chang@sifive.com>
32
Tested-by: Max Hsu <max.hsu@sifive.com>
33
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
34
Tested-by: Bin Meng <bmeng.cn@gmail.com>
35
Message-id: 20210912130553.179501-3-frank.chang@sifive.com
36
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
37
---
38
hw/dma/sifive_pdma.c | 9 +++++++++
39
1 file changed, 9 insertions(+)
40
41
diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/dma/sifive_pdma.c
44
+++ b/hw/dma/sifive_pdma.c
45
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_write(void *opaque, hwaddr offset,
46
47
s->chan[ch].control = value;
48
49
+ /*
50
+ * If channel was not claimed before run bit is set,
51
+ * DMA won't run.
52
+ */
53
+ if (!claimed) {
54
+ s->chan[ch].control &= ~CONTROL_RUN;
55
+ return;
56
+ }
57
+
58
if (value & CONTROL_RUN) {
59
sifive_pdma_run(s, ch);
60
}
61
--
62
2.31.1
63
64
diff view generated by jsdifflib
New patch
1
From: Green Wan <green.wan@sifive.com>
1
2
3
Real PDMA is able to deal with non-multiple transaction size transactions.
4
5
The following result is PDMA tested in U-Boot on Unmatched board:
6
7
=> mw.l 0x3000000 0x0 <= Disclaim channel 0
8
=> mw.l 0x3000000 0x1 <= Claim channel 0
9
=> mw.l 0x3000004 0x11000000 <= wsize = rsize = 1 (2^1 = 2 bytes)
10
=> mw.q 0x3000008 0x3 <= NextBytes = 3
11
=> mw.q 0x3000010 0x84000000 <= NextDestination = 0x84000000
12
=> mw.q 0x3000018 0x84001000 <= NextSource = 0x84001000
13
=> mw.l 0x84000000 0x87654321 <= Fill test data to dst
14
=> mw.l 0x84001000 0x12345678 <= Fill test data to src
15
=> md.l 0x84000000 1; md.l 0x84001000 1 <= Dump src/dst memory contents
16
84000000: 87654321 !Ce.
17
84001000: 12345678 xV4.
18
=> md.l 0x3000000 8 <= Dump PDMA status
19
03000000: 00000001 11000000 00000003 00000000 ................
20
03000010: 84000000 00000000 84001000 00000000 ................
21
=> mw.l 0x3000000 0x3 <= Set channel 0 run and claim bits
22
=> md.l 0x3000000 8 <= Dump PDMA status
23
03000000: 40000001 11000000 00000003 00000000 ...@............
24
03000010: 84000000 00000000 84001000 00000000 ................
25
=> md.l 0x84000000 1; md.l 0x84001000 1 <= Dump src/dst memory contents
26
84000000: 87345678 xV4.
27
84001000: 12345678 xV4.
28
29
Signed-off-by: Green Wan <green.wan@sifive.com>
30
Reviewed-by: Frank Chang <frank.chang@sifive.com>
31
Tested-by: Max Hsu <max.hsu@sifive.com>
32
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
33
Tested-by: Bin Meng <bmeng.cn@gmail.com>
34
Signed-off-by: Frank Chang <frank.chang@sifive.com>
35
Message-id: 20210912130553.179501-4-frank.chang@sifive.com
36
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
37
---
38
hw/dma/sifive_pdma.c | 16 ++++++++++------
39
1 file changed, 10 insertions(+), 6 deletions(-)
40
41
diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/dma/sifive_pdma.c
44
+++ b/hw/dma/sifive_pdma.c
45
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch)
46
uint64_t dst = s->chan[ch].next_dst;
47
uint64_t src = s->chan[ch].next_src;
48
uint32_t config = s->chan[ch].next_config;
49
- int wsize, rsize, size;
50
+ int wsize, rsize, size, remainder;
51
uint8_t buf[64];
52
int n;
53
54
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch)
55
size = 6;
56
}
57
size = 1 << size;
58
-
59
- /* the bytes to transfer should be multiple of transaction size */
60
- if (bytes % size) {
61
- goto error;
62
- }
63
+ remainder = bytes % size;
64
65
/* indicate a DMA transfer is started */
66
s->chan[ch].state = DMA_CHAN_STATE_STARTED;
67
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch)
68
s->chan[ch].exec_bytes -= size;
69
}
70
71
+ if (remainder) {
72
+ cpu_physical_memory_read(s->chan[ch].exec_src, buf, remainder);
73
+ cpu_physical_memory_write(s->chan[ch].exec_dst, buf, remainder);
74
+ s->chan[ch].exec_src += remainder;
75
+ s->chan[ch].exec_dst += remainder;
76
+ s->chan[ch].exec_bytes -= remainder;
77
+ }
78
+
79
/* indicate a DMA transfer is done */
80
s->chan[ch].state = DMA_CHAN_STATE_DONE;
81
s->chan[ch].control &= ~CONTROL_RUN;
82
--
83
2.31.1
84
85
diff view generated by jsdifflib
New patch
1
From: Frank Chang <frank.chang@sifive.com>
1
2
3
Real PDMA doesn't set Control.error if there are 0 bytes to be
4
transferred. The DMA transfer is still success.
5
6
The following result is PDMA tested in U-Boot on Unmatched board:
7
8
=> mw.l 0x3000000 0x0 <= Disclaim channel 0
9
=> mw.l 0x3000000 0x1 <= Claim channel 0
10
=> mw.l 0x3000004 0x55000000 <= wsize = rsize = 5 (2^5 = 32 bytes)
11
=> mw.q 0x3000008 0x0 <= NextBytes = 0
12
=> mw.q 0x3000010 0x84000000 <= NextDestination = 0x84000000
13
=> mw.q 0x3000018 0x84001000 <= NextSource = 0x84001000
14
=> mw.l 0x84000000 0x87654321 <= Fill test data to dst
15
=> mw.l 0x84001000 0x12345678 <= Fill test data to src
16
=> md.l 0x84000000 1; md.l 0x84001000 1 <= Dump src/dst memory contents
17
84000000: 87654321 !Ce.
18
84001000: 12345678 xV4.
19
=> md.l 0x3000000 8 <= Dump PDMA status
20
03000000: 00000001 55000000 00000000 00000000 .......U........
21
03000010: 84000000 00000000 84001000 00000000 ................
22
=> mw.l 0x3000000 0x3 <= Set channel 0 run and claim bits
23
=> md.l 0x3000000 8 <= Dump PDMA status
24
03000000: 40000001 55000000 00000000 00000000 ...@...U........
25
03000010: 84000000 00000000 84001000 00000000 ................
26
=> md.l 0x84000000 1; md.l 0x84001000 1 <= Dump src/dst memory contents
27
84000000: 87654321 !Ce.
28
84001000: 12345678 xV4.
29
30
Signed-off-by: Frank Chang <frank.chang@sifive.com>
31
Tested-by: Max Hsu <max.hsu@sifive.com>
32
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
33
Tested-by: Bin Meng <bmeng.cn@gmail.com>
34
Message-id: 20210912130553.179501-5-frank.chang@sifive.com
35
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
36
---
37
hw/dma/sifive_pdma.c | 12 ++++++------
38
1 file changed, 6 insertions(+), 6 deletions(-)
39
40
diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/dma/sifive_pdma.c
43
+++ b/hw/dma/sifive_pdma.c
44
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch)
45
46
/* do nothing if bytes to transfer is zero */
47
if (!bytes) {
48
- goto error;
49
+ goto done;
50
}
51
52
/*
53
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch)
54
s->chan[ch].exec_bytes -= remainder;
55
}
56
57
- /* indicate a DMA transfer is done */
58
- s->chan[ch].state = DMA_CHAN_STATE_DONE;
59
- s->chan[ch].control &= ~CONTROL_RUN;
60
- s->chan[ch].control |= CONTROL_DONE;
61
-
62
/* reload exec_ registers if repeat is required */
63
if (s->chan[ch].next_config & CONFIG_REPEAT) {
64
s->chan[ch].exec_bytes = bytes;
65
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch)
66
s->chan[ch].exec_src = src;
67
}
68
69
+done:
70
+ /* indicate a DMA transfer is done */
71
+ s->chan[ch].state = DMA_CHAN_STATE_DONE;
72
+ s->chan[ch].control &= ~CONTROL_RUN;
73
+ s->chan[ch].control |= CONTROL_DONE;
74
return;
75
76
error:
77
--
78
2.31.1
79
80
diff view generated by jsdifflib
New patch
1
From: Bin Meng <bmeng.cn@gmail.com>
1
2
3
In U-Boot v2021.07 release, there were 2 major changes for the
4
SiFive Unleashed board support:
5
6
- Board config name was changed from sifive_fu540_defconfig to
7
sifive_unleashed_defconfig
8
- The generic binman tool was used to generate the FIT image
9
(combination of U-Boot proper, DTB and OpenSBI firmware)
10
11
which make the existing U-Boot instructions out of date.
12
13
Update the doc with latest instructions.
14
15
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
16
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
17
Message-id: 20210911153431.10362-1-bmeng.cn@gmail.com
18
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
19
---
20
docs/system/riscv/sifive_u.rst | 49 ++++++++++++++++++----------------
21
1 file changed, 26 insertions(+), 23 deletions(-)
22
23
diff --git a/docs/system/riscv/sifive_u.rst b/docs/system/riscv/sifive_u.rst
24
index XXXXXXX..XXXXXXX 100644
25
--- a/docs/system/riscv/sifive_u.rst
26
+++ b/docs/system/riscv/sifive_u.rst
27
@@ -XXX,XX +XXX,XX @@ command line options with ``qemu-system-riscv32``.
28
Running U-Boot
29
--------------
30
31
-U-Boot mainline v2021.01 release is tested at the time of writing. To build a
32
+U-Boot mainline v2021.07 release is tested at the time of writing. To build a
33
U-Boot mainline bootloader that can be booted by the ``sifive_u`` machine, use
34
-the sifive_fu540_defconfig with similar commands as described above for Linux:
35
+the sifive_unleashed_defconfig with similar commands as described above for
36
+Linux:
37
38
.. code-block:: bash
39
40
$ export CROSS_COMPILE=riscv64-linux-
41
$ export OPENSBI=/path/to/opensbi-riscv64-generic-fw_dynamic.bin
42
- $ make sifive_fu540_defconfig
43
+ $ make sifive_unleashed_defconfig
44
45
You will get spl/u-boot-spl.bin and u-boot.itb file in the build tree.
46
47
@@ -XXX,XX +XXX,XX @@ board on QEMU ``sifive_u`` machine out of the box. This allows users to
48
develop and test the recommended RISC-V boot flow with a real world use
49
case: ZSBL (in QEMU) loads U-Boot SPL from SD card or SPI flash to L2LIM,
50
then U-Boot SPL loads the combined payload image of OpenSBI fw_dynamic
51
-firmware and U-Boot proper. However sometimes we want to have a quick test
52
-of booting U-Boot on QEMU without the needs of preparing the SPI flash or
53
-SD card images, an alternate way can be used, which is to create a U-Boot
54
-S-mode image by modifying the configuration of U-Boot:
55
+firmware and U-Boot proper.
56
+
57
+However sometimes we want to have a quick test of booting U-Boot on QEMU
58
+without the needs of preparing the SPI flash or SD card images, an alternate
59
+way can be used, which is to create a U-Boot S-mode image by modifying the
60
+configuration of U-Boot:
61
62
.. code-block:: bash
63
64
+ $ export CROSS_COMPILE=riscv64-linux-
65
+ $ make sifive_unleashed_defconfig
66
$ make menuconfig
67
68
-then manually select the following configuration in U-Boot:
69
-
70
- Device Tree Control > Provider of DTB for DT Control > Prior Stage bootloader DTB
71
+then manually select the following configuration:
72
73
-This lets U-Boot to use the QEMU generated device tree blob. During the build,
74
-a build error will be seen below:
75
+ * Device Tree Control ---> Provider of DTB for DT Control ---> Prior Stage bootloader DTB
76
77
-.. code-block:: none
78
+and unselect the following configuration:
79
80
- MKIMAGE u-boot.img
81
- ./tools/mkimage: Can't open arch/riscv/dts/hifive-unleashed-a00.dtb: No such file or directory
82
- ./tools/mkimage: failed to build FIT
83
- make: *** [Makefile:1440: u-boot.img] Error 1
84
+ * Library routines ---> Allow access to binman information in the device tree
85
86
-The above errors can be safely ignored as we don't run U-Boot SPL under QEMU
87
-in this alternate configuration.
88
+This changes U-Boot to use the QEMU generated device tree blob, and bypass
89
+running the U-Boot SPL stage.
90
91
Boot the 64-bit U-Boot S-mode image directly:
92
93
@@ -XXX,XX +XXX,XX @@ It's possible to create a 32-bit U-Boot S-mode image as well.
94
.. code-block:: bash
95
96
$ export CROSS_COMPILE=riscv64-linux-
97
- $ make sifive_fu540_defconfig
98
+ $ make sifive_unleashed_defconfig
99
$ make menuconfig
100
101
then manually update the following configuration in U-Boot:
102
103
- Device Tree Control > Provider of DTB for DT Control > Prior Stage bootloader DTB
104
- RISC-V architecture > Base ISA > RV32I
105
- Boot images > Text Base > 0x80400000
106
+ * Device Tree Control ---> Provider of DTB for DT Control ---> Prior Stage bootloader DTB
107
+ * RISC-V architecture ---> Base ISA ---> RV32I
108
+ * Boot options ---> Boot images ---> Text Base ---> 0x80400000
109
+
110
+and unselect the following configuration:
111
+
112
+ * Library routines ---> Allow access to binman information in the device tree
113
114
Use the same command line options to boot the 32-bit U-Boot S-mode image:
115
116
--
117
2.31.1
118
119
diff view generated by jsdifflib
New patch
1
From: Frank Chang <frank.chang@sifive.com>
1
2
3
When virtual registers are swapped, mstatus.SD bit should also be
4
backed up/restored. Otherwise, mstatus.SD bit will be incorrectly kept
5
across the world switches.
6
7
Signed-off-by: Frank Chang <frank.chang@sifive.com>
8
Reviewed-by: Vincent Chen <vincent.chen@sifive.com>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Message-id: 20210914013717.881430-1-frank.chang@sifive.com
11
[ Changes by AF:
12
- Convert variable to a uint64_t to fix clang error
13
]
14
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
15
---
16
target/riscv/cpu_helper.c | 3 ++-
17
1 file changed, 2 insertions(+), 1 deletion(-)
18
19
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/riscv/cpu_helper.c
22
+++ b/target/riscv/cpu_helper.c
23
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_fp_enabled(CPURISCVState *env)
24
25
void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env)
26
{
27
+ uint64_t sd = riscv_cpu_is_32bit(env) ? MSTATUS32_SD : MSTATUS64_SD;
28
uint64_t mstatus_mask = MSTATUS_MXR | MSTATUS_SUM | MSTATUS_FS |
29
MSTATUS_SPP | MSTATUS_SPIE | MSTATUS_SIE |
30
- MSTATUS64_UXL;
31
+ MSTATUS64_UXL | sd;
32
bool current_virt = riscv_cpu_virt_enabled(env);
33
34
g_assert(riscv_has_ext(env, RVH));
35
--
36
2.31.1
37
38
diff view generated by jsdifflib
New patch
1
From: Bin Meng <bmeng.cn@gmail.com>
1
2
3
The macro name HCOUNTEREN_CY suggests it is for CSR HCOUNTEREN, but
4
in fact it applies to M-mode and S-mode CSR too. Rename these macros
5
to have the COUNTEREN_ prefix.
6
7
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Message-id: 20210915084601.24304-1-bmeng.cn@gmail.com
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
---
12
target/riscv/cpu_bits.h | 8 ++++----
13
target/riscv/csr.c | 24 ++++++++++++------------
14
2 files changed, 16 insertions(+), 16 deletions(-)
15
16
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/riscv/cpu_bits.h
19
+++ b/target/riscv/cpu_bits.h
20
@@ -XXX,XX +XXX,XX @@
21
#define HSTATUS32_WPRI 0xFF8FF87E
22
#define HSTATUS64_WPRI 0xFFFFFFFFFF8FF87EULL
23
24
-#define HCOUNTEREN_CY (1 << 0)
25
-#define HCOUNTEREN_TM (1 << 1)
26
-#define HCOUNTEREN_IR (1 << 2)
27
-#define HCOUNTEREN_HPM3 (1 << 3)
28
+#define COUNTEREN_CY (1 << 0)
29
+#define COUNTEREN_TM (1 << 1)
30
+#define COUNTEREN_IR (1 << 2)
31
+#define COUNTEREN_HPM3 (1 << 3)
32
33
/* Privilege modes */
34
#define PRV_U 0
35
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/riscv/csr.c
38
+++ b/target/riscv/csr.c
39
@@ -XXX,XX +XXX,XX @@ static RISCVException ctr(CPURISCVState *env, int csrno)
40
if (riscv_cpu_virt_enabled(env)) {
41
switch (csrno) {
42
case CSR_CYCLE:
43
- if (!get_field(env->hcounteren, HCOUNTEREN_CY) &&
44
- get_field(env->mcounteren, HCOUNTEREN_CY)) {
45
+ if (!get_field(env->hcounteren, COUNTEREN_CY) &&
46
+ get_field(env->mcounteren, COUNTEREN_CY)) {
47
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
48
}
49
break;
50
case CSR_TIME:
51
- if (!get_field(env->hcounteren, HCOUNTEREN_TM) &&
52
- get_field(env->mcounteren, HCOUNTEREN_TM)) {
53
+ if (!get_field(env->hcounteren, COUNTEREN_TM) &&
54
+ get_field(env->mcounteren, COUNTEREN_TM)) {
55
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
56
}
57
break;
58
case CSR_INSTRET:
59
- if (!get_field(env->hcounteren, HCOUNTEREN_IR) &&
60
- get_field(env->mcounteren, HCOUNTEREN_IR)) {
61
+ if (!get_field(env->hcounteren, COUNTEREN_IR) &&
62
+ get_field(env->mcounteren, COUNTEREN_IR)) {
63
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
64
}
65
break;
66
@@ -XXX,XX +XXX,XX @@ static RISCVException ctr(CPURISCVState *env, int csrno)
67
if (riscv_cpu_is_32bit(env)) {
68
switch (csrno) {
69
case CSR_CYCLEH:
70
- if (!get_field(env->hcounteren, HCOUNTEREN_CY) &&
71
- get_field(env->mcounteren, HCOUNTEREN_CY)) {
72
+ if (!get_field(env->hcounteren, COUNTEREN_CY) &&
73
+ get_field(env->mcounteren, COUNTEREN_CY)) {
74
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
75
}
76
break;
77
case CSR_TIMEH:
78
- if (!get_field(env->hcounteren, HCOUNTEREN_TM) &&
79
- get_field(env->mcounteren, HCOUNTEREN_TM)) {
80
+ if (!get_field(env->hcounteren, COUNTEREN_TM) &&
81
+ get_field(env->mcounteren, COUNTEREN_TM)) {
82
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
83
}
84
break;
85
case CSR_INSTRETH:
86
- if (!get_field(env->hcounteren, HCOUNTEREN_IR) &&
87
- get_field(env->mcounteren, HCOUNTEREN_IR)) {
88
+ if (!get_field(env->hcounteren, COUNTEREN_IR) &&
89
+ get_field(env->mcounteren, COUNTEREN_IR)) {
90
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
91
}
92
break;
93
--
94
2.31.1
95
96
diff view generated by jsdifflib
New patch
1
From: Alistair Francis <alistair.francis@wdc.com>
1
2
3
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
4
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
5
Message-id: d6cb4dfe75a2f536f217d7075b750ece3acb1535.1631767043.git.alistair.francis@wdc.com
6
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
7
---
8
hw/riscv/opentitan.c | 2 +-
9
1 file changed, 1 insertion(+), 1 deletion(-)
10
11
diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/riscv/opentitan.c
14
+++ b/hw/riscv/opentitan.c
15
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry ibex_memmap[] = {
16
[IBEX_DEV_TIMER] = { 0x40100000, 0x1000 },
17
[IBEX_DEV_SENSOR_CTRL] = { 0x40110000, 0x1000 },
18
[IBEX_DEV_OTP_CTRL] = { 0x40130000, 0x4000 },
19
+ [IBEX_DEV_USBDEV] = { 0x40150000, 0x1000 },
20
[IBEX_DEV_PWRMGR] = { 0x40400000, 0x1000 },
21
[IBEX_DEV_RSTMGR] = { 0x40410000, 0x1000 },
22
[IBEX_DEV_CLKMGR] = { 0x40420000, 0x1000 },
23
[IBEX_DEV_PINMUX] = { 0x40460000, 0x1000 },
24
[IBEX_DEV_PADCTRL] = { 0x40470000, 0x1000 },
25
- [IBEX_DEV_USBDEV] = { 0x40500000, 0x1000 },
26
[IBEX_DEV_FLASH_CTRL] = { 0x41000000, 0x1000 },
27
[IBEX_DEV_PLIC] = { 0x41010000, 0x1000 },
28
[IBEX_DEV_AES] = { 0x41100000, 0x1000 },
29
--
30
2.31.1
31
32
diff view generated by jsdifflib