1
The following changes since commit c95bd5ff1660883d15ad6e0005e4c8571604f51a:
1
From: Alistair Francis <alistair.francis@wdc.com>
2
2
3
Merge remote-tracking branch 'remotes/philmd/tags/mips-fixes-20210322' into staging (2021-03-22 14:26:13 +0000)
3
The following changes since commit 326ff8dd09556fc2e257196c49f35009700794ac:
4
5
Merge remote-tracking branch 'remotes/jasowang/tags/net-pull-request' into staging (2021-09-20 16:17:05 +0100)
4
6
5
are available in the Git repository at:
7
are available in the Git repository at:
6
8
7
git@github.com:alistair23/qemu.git tags/pull-riscv-to-apply-20210322-2
9
git@github.com:alistair23/qemu.git tags/pull-riscv-to-apply-20210921
8
10
9
for you to fetch changes up to 9a27f69bd668d9d71674407badc412ce1231c7d5:
11
for you to fetch changes up to ed481d9837250aa682f5156528bc923e1b214f76:
10
12
11
target/riscv: Prevent lost illegal instruction exceptions (2021-03-22 21:54:40 -0400)
13
hw/riscv: opentitan: Correct the USB Dev address (2021-09-21 12:10:47 +1000)
12
14
13
----------------------------------------------------------------
15
----------------------------------------------------------------
14
RISC-V PR for 6.0
16
Second RISC-V PR for QEMU 6.2
15
17
16
This PR includes:
18
- ePMP CSR address updates
17
- Fix for vector CSR access
19
- Convert internal interrupts to use QEMU GPIO lines
18
- Improvements to the Ibex UART device
20
- SiFive PWM support
19
- PMP improvements and bug fixes
21
- Support for RISC-V ACLINT
20
- Hypervisor extension bug fixes
22
- SiFive PDMA fixes
21
- ramfb support for the virt machine
23
- Update to u-boot instructions for sifive_u
22
- Fast read support for SST flash
24
- mstatus.SD bug fix for hypervisor extensions
23
- Improvements to the microchip_pfsoc machine
25
- OpenTitan fix for USB dev address
24
26
25
----------------------------------------------------------------
27
----------------------------------------------------------------
26
Alexander Wagner (1):
28
Alistair Francis (9):
27
hw/char: disable ibex uart receive if the buffer is full
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
28
38
29
Asherah Connor (2):
39
Anup Patel (4):
30
hw/riscv: Add fw_cfg support to virt
40
hw/intc: Rename sifive_clint sources to riscv_aclint sources
31
hw/riscv: allow ramfb on virt
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
32
44
33
Bin Meng (3):
45
Bin Meng (2):
34
hw/block: m25p80: Support fast read for SST flashes
46
docs/system/riscv: sifive_u: Update U-Boot instructions
35
hw/riscv: microchip_pfsoc: Map EMMC/SD mux register
47
target/riscv: csr: Rename HCOUNTEREN_CY and friends
36
docs/system: riscv: Add documentation for 'microchip-icicle-kit' machine
37
48
38
Frank Chang (1):
49
Frank Chang (4):
39
target/riscv: fix vs() to return proper error code
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
40
54
41
Georg Kotheimer (6):
55
Green Wan (1):
42
target/riscv: Adjust privilege level for HLV(X)/HSV instructions
56
hw/dma: sifive_pdma: allow non-multiple transaction size transactions
43
target/riscv: Make VSTIP and VSEIP read-only in hip
44
target/riscv: Use background registers also for MSTATUS_MPV
45
target/riscv: Fix read and write accesses to vsip and vsie
46
target/riscv: Add proper two-stage lookup exception detection
47
target/riscv: Prevent lost illegal instruction exceptions
48
57
49
Jim Shu (3):
58
LIU Zhiwei (1):
50
target/riscv: propagate PMP permission to TLB page
59
target/riscv: Fix satp write
51
target/riscv: add log of PMP permission checking
52
target/riscv: flush TLB pages if PMP permission has been changed
53
60
54
docs/system/riscv/microchip-icicle-kit.rst | 89 ++++++++++++++
61
docs/system/riscv/sifive_u.rst | 50 ++--
55
docs/system/target-riscv.rst | 1 +
62
docs/system/riscv/virt.rst | 10 +
56
include/hw/char/ibex_uart.h | 4 +
63
include/hw/intc/ibex_plic.h | 2 +
57
include/hw/riscv/microchip_pfsoc.h | 1 +
64
include/hw/intc/riscv_aclint.h | 80 +++++
58
include/hw/riscv/virt.h | 2 +
65
include/hw/intc/sifive_clint.h | 60 ----
59
target/riscv/cpu.h | 4 +
66
include/hw/intc/sifive_plic.h | 4 +
60
target/riscv/pmp.h | 4 +-
67
include/hw/riscv/sifive_u.h | 14 +-
61
hw/block/m25p80.c | 3 +
68
include/hw/riscv/virt.h | 2 +
62
hw/char/ibex_uart.c | 23 +++-
69
include/hw/timer/ibex_timer.h | 2 +
63
hw/riscv/microchip_pfsoc.c | 6 +
70
include/hw/timer/sifive_pwm.h | 62 ++++
64
hw/riscv/virt.c | 33 ++++++
71
target/riscv/cpu_bits.h | 12 +-
65
target/riscv/cpu.c | 1 +
72
hw/dma/sifive_pdma.c | 54 +++-
66
target/riscv/cpu_helper.c | 144 +++++++++++++++--------
73
hw/intc/ibex_plic.c | 17 +-
67
target/riscv/csr.c | 77 +++++++------
74
hw/intc/riscv_aclint.c | 460 +++++++++++++++++++++++++++++
68
target/riscv/pmp.c | 84 ++++++++++----
75
hw/intc/sifive_clint.c | 287 ------------------
69
target/riscv/translate.c | 179 +----------------------------
76
hw/intc/sifive_plic.c | 30 +-
70
hw/riscv/Kconfig | 1 +
77
hw/riscv/microchip_pfsoc.c | 13 +-
71
17 files changed, 367 insertions(+), 289 deletions(-)
78
hw/riscv/opentitan.c | 13 +-
72
create mode 100644 docs/system/riscv/microchip-icicle-kit.rst
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
73
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
1
From: Frank Chang <frank.chang@sifive.com>
1
From: LIU Zhiwei <zhiwei_liu@c-sky.com>
2
2
3
vs() should return -RISCV_EXCP_ILLEGAL_INST instead of -1 if rvv feature
3
These variables should be target_ulong. If truncated to int,
4
is not enabled.
4
the bool conditions they indicate will be wrong.
5
5
6
If -1 is returned, exception will be raised and cs->exception_index will
6
As satp is very important for Linux, this bug almost fails every boot.
7
be set to the negative return value. The exception will then be treated
8
as an instruction access fault instead of illegal instruction fault.
9
7
10
Signed-off-by: Frank Chang <frank.chang@sifive.com>
8
Signed-off-by: LIU Zhiwei <zhiwei_liu@c-sky.com>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
12
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
13
Message-id: 20210223065935.20208-1-frank.chang@sifive.com
11
Message-id: 20210901124539.222868-1-zhiwei_liu@c-sky.com
14
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
15
---
13
---
16
target/riscv/csr.c | 2 +-
14
target/riscv/csr.c | 2 +-
17
1 file changed, 1 insertion(+), 1 deletion(-)
15
1 file changed, 1 insertion(+), 1 deletion(-)
18
16
19
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
17
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
20
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
21
--- a/target/riscv/csr.c
19
--- a/target/riscv/csr.c
22
+++ b/target/riscv/csr.c
20
+++ b/target/riscv/csr.c
23
@@ -XXX,XX +XXX,XX @@ static int vs(CPURISCVState *env, int csrno)
21
@@ -XXX,XX +XXX,XX @@ static RISCVException read_satp(CPURISCVState *env, int csrno,
24
if (env->misa & RVV) {
22
static RISCVException write_satp(CPURISCVState *env, int csrno,
25
return 0;
23
target_ulong val)
26
}
24
{
27
- return -1;
25
- int vm, mask, asid;
28
+ return -RISCV_EXCP_ILLEGAL_INST;
26
+ target_ulong vm, mask, asid;
29
}
27
30
28
if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
31
static int ctr(CPURISCVState *env, int csrno)
29
return RISCV_EXCP_NONE;
32
--
30
--
33
2.30.1
31
2.31.1
34
32
35
33
diff view generated by jsdifflib
1
From: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
1
From: Alistair Francis <alistair.francis@wdc.com>
2
2
3
The current two-stage lookup detection in riscv_cpu_do_interrupt falls
3
Expose the 12 interrupt pending bits in MIP as GPIO lines.
4
short of its purpose, as all it checks is whether two-stage address
5
translation either via the hypervisor-load store instructions or the
6
MPRV feature would be allowed.
7
4
8
What we really need instead is whether two-stage address translation was
5
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
9
active when the exception was raised. However, in riscv_cpu_do_interrupt
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
we do not have the information to reliably detect this. Therefore, when
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
we raise a memory fault exception we have to record whether two-stage
8
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
12
address translation is active.
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(+)
13
14
14
Signed-off-by: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
15
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
16
Message-id: 20210319141459.1196741-1-georg.kotheimer@kernkonzept.com
17
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
18
---
19
target/riscv/cpu.h | 4 ++++
20
target/riscv/cpu.c | 1 +
21
target/riscv/cpu_helper.c | 21 ++++++++-------------
22
3 files changed, 13 insertions(+), 13 deletions(-)
23
24
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/target/riscv/cpu.h
27
+++ b/target/riscv/cpu.h
28
@@ -XXX,XX +XXX,XX @@ struct CPURISCVState {
29
target_ulong satp_hs;
30
uint64_t mstatus_hs;
31
32
+ /* Signals whether the current exception occurred with two-stage address
33
+ translation active. */
34
+ bool two_stage_lookup;
35
+
36
target_ulong scounteren;
37
target_ulong mcounteren;
38
39
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
15
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
40
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
41
--- a/target/riscv/cpu.c
17
--- a/target/riscv/cpu.c
42
+++ b/target/riscv/cpu.c
18
+++ b/target/riscv/cpu.c
43
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_reset(DeviceState *dev)
19
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
44
env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
20
mcc->parent_realize(dev, errp);
45
env->mcause = 0;
46
env->pc = env->resetvec;
47
+ env->two_stage_lookup = false;
48
#endif
49
cs->exception_index = EXCP_NONE;
50
env->load_res = -1;
51
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/riscv/cpu_helper.c
54
+++ b/target/riscv/cpu_helper.c
55
@@ -XXX,XX +XXX,XX @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
56
g_assert_not_reached();
57
}
58
env->badaddr = address;
59
+ env->two_stage_lookup = two_stage;
60
}
21
}
61
22
62
hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
23
+#ifndef CONFIG_USER_ONLY
63
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
24
+static void riscv_cpu_set_irq(void *opaque, int irq, int level)
64
}
25
+{
65
26
+ RISCVCPU *cpu = RISCV_CPU(opaque);
66
env->badaddr = addr;
27
+
67
+ env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
28
+ switch (irq) {
68
+ riscv_cpu_two_stage_lookup(mmu_idx);
29
+ case IRQ_U_SOFT:
69
riscv_raise_exception(&cpu->env, cs->exception_index, retaddr);
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 */
70
}
58
}
71
59
72
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
60
static Property riscv_cpu_properties[] = {
73
g_assert_not_reached();
74
}
75
env->badaddr = addr;
76
+ env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
77
+ riscv_cpu_two_stage_lookup(mmu_idx);
78
riscv_raise_exception(env, cs->exception_index, retaddr);
79
}
80
#endif /* !CONFIG_USER_ONLY */
81
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_interrupt(CPUState *cs)
82
/* handle the trap in S-mode */
83
if (riscv_has_ext(env, RVH)) {
84
target_ulong hdeleg = async ? env->hideleg : env->hedeleg;
85
- bool two_stage_lookup = false;
86
87
- if (env->priv == PRV_M ||
88
- (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) ||
89
- (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) &&
90
- get_field(env->hstatus, HSTATUS_HU))) {
91
- two_stage_lookup = true;
92
- }
93
-
94
- if ((riscv_cpu_virt_enabled(env) || two_stage_lookup) && write_tval) {
95
+ if (env->two_stage_lookup && write_tval) {
96
/*
97
* If we are writing a guest virtual address to stval, set
98
* this to 1. If we are trapping to VS we will set this to 0
99
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_interrupt(CPUState *cs)
100
riscv_cpu_set_force_hs_excep(env, 0);
101
} else {
102
/* Trap into HS mode */
103
- if (!two_stage_lookup) {
104
- env->hstatus = set_field(env->hstatus, HSTATUS_SPV,
105
- riscv_cpu_virt_enabled(env));
106
- }
107
+ env->hstatus = set_field(env->hstatus, HSTATUS_SPV, false);
108
htval = env->guest_phys_fault_addr;
109
}
110
}
111
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_interrupt(CPUState *cs)
112
* RISC-V ISA Specification.
113
*/
114
115
+ env->two_stage_lookup = false;
116
#endif
117
cs->exception_index = EXCP_NONE; /* mark handled to qemu */
118
}
119
--
61
--
120
2.30.1
62
2.31.1
121
63
122
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
1
From: Bin Meng <bin.meng@windriver.com>
1
From: Alistair Francis <alistair.francis@wdc.com>
2
2
3
Since HSS commit c20a89f8dcac, the Icicle Kit reference design has
3
Instead of using riscv_cpu_update_mip() let's instead use the new RISC-V
4
been updated to use a register mapped at 0x4f000000 instead of a
4
CPU GPIO lines to set the external MIP bits.
5
GPIO to control whether eMMC or SD card is to be used. With this
6
support the same HSS image can be used for both eMMC and SD card
7
boot flow, while previously two different board configurations were
8
used. This is undocumented but one can take a look at the HSS code
9
HSS_MMCInit() in services/mmc/mmc_api.c.
10
5
11
With this commit, HSS image built from 2020.12 release boots again.
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(-)
12
21
13
Signed-off-by: Bin Meng <bin.meng@windriver.com>
22
diff --git a/include/hw/intc/sifive_plic.h b/include/hw/intc/sifive_plic.h
14
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
15
Message-id: 20210322075248.136255-1-bmeng.cn@gmail.com
16
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
17
---
18
include/hw/riscv/microchip_pfsoc.h | 1 +
19
hw/riscv/microchip_pfsoc.c | 6 ++++++
20
2 files changed, 7 insertions(+)
21
22
diff --git a/include/hw/riscv/microchip_pfsoc.h b/include/hw/riscv/microchip_pfsoc.h
23
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
24
--- a/include/hw/riscv/microchip_pfsoc.h
24
--- a/include/hw/intc/sifive_plic.h
25
+++ b/include/hw/riscv/microchip_pfsoc.h
25
+++ b/include/hw/intc/sifive_plic.h
26
@@ -XXX,XX +XXX,XX @@ enum {
26
@@ -XXX,XX +XXX,XX @@ struct SiFivePLICState {
27
MICROCHIP_PFSOC_ENVM_DATA,
27
uint32_t context_base;
28
MICROCHIP_PFSOC_QSPI_XIP,
28
uint32_t context_stride;
29
MICROCHIP_PFSOC_IOSCB,
29
uint32_t aperture_size;
30
+ MICROCHIP_PFSOC_EMMC_SD_MUX,
30
+
31
MICROCHIP_PFSOC_DRAM_LO,
31
+ qemu_irq *m_external_irqs;
32
MICROCHIP_PFSOC_DRAM_LO_ALIAS,
32
+ qemu_irq *s_external_irqs;
33
MICROCHIP_PFSOC_DRAM_HI,
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
}
34
diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
120
diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
35
index XXXXXXX..XXXXXXX 100644
121
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/riscv/microchip_pfsoc.c
122
--- a/hw/riscv/microchip_pfsoc.c
37
+++ b/hw/riscv/microchip_pfsoc.c
123
+++ b/hw/riscv/microchip_pfsoc.c
38
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry microchip_pfsoc_memmap[] = {
39
[MICROCHIP_PFSOC_ENVM_DATA] = { 0x20220000, 0x20000 },
40
[MICROCHIP_PFSOC_QSPI_XIP] = { 0x21000000, 0x1000000 },
41
[MICROCHIP_PFSOC_IOSCB] = { 0x30000000, 0x10000000 },
42
+ [MICROCHIP_PFSOC_EMMC_SD_MUX] = { 0x4f000000, 0x4 },
43
[MICROCHIP_PFSOC_DRAM_LO] = { 0x80000000, 0x40000000 },
44
[MICROCHIP_PFSOC_DRAM_LO_ALIAS] = { 0xc0000000, 0x40000000 },
45
[MICROCHIP_PFSOC_DRAM_HI] = { 0x1000000000, 0x0 },
46
@@ -XXX,XX +XXX,XX @@ static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp)
124
@@ -XXX,XX +XXX,XX @@ static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp)
47
sysbus_mmio_map(SYS_BUS_DEVICE(&s->ioscb), 0,
125
48
memmap[MICROCHIP_PFSOC_IOSCB].base);
126
/* PLIC */
49
127
s->plic = sifive_plic_create(memmap[MICROCHIP_PFSOC_PLIC].base,
50
+ /* eMMC/SD mux */
128
- plic_hart_config, 0,
51
+ create_unimplemented_device("microchip.pfsoc.emmc_sd_mux",
129
+ plic_hart_config, ms->smp.cpus, 0,
52
+ memmap[MICROCHIP_PFSOC_EMMC_SD_MUX].base,
130
MICROCHIP_PFSOC_PLIC_NUM_SOURCES,
53
+ memmap[MICROCHIP_PFSOC_EMMC_SD_MUX].size);
131
MICROCHIP_PFSOC_PLIC_NUM_PRIORITIES,
54
+
132
MICROCHIP_PFSOC_PLIC_PRIORITY_BASE,
55
/* QSPI Flash */
133
diff --git a/hw/riscv/shakti_c.c b/hw/riscv/shakti_c.c
56
memory_region_init_rom(qspi_xip_mem, OBJECT(dev),
134
index XXXXXXX..XXXXXXX 100644
57
"microchip.pfsoc.qspi_xip",
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,
58
--
192
--
59
2.30.1
193
2.31.1
60
194
61
195
diff view generated by jsdifflib
1
From: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
1
From: Alistair Francis <alistair.francis@wdc.com>
2
2
3
The previous implementation was broken in many ways:
3
Instead of using riscv_cpu_update_mip() let's instead use the new RISC-V
4
- Used mideleg instead of hideleg to mask accesses
4
CPU GPIO lines to set the timer MIP bits.
5
- Used MIP_VSSIP instead of VS_MODE_INTERRUPTS to mask writes to vsie
6
- Did not shift between S bits and VS bits (VSEIP <-> SEIP, ...)
7
5
8
Signed-off-by: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Message-id: 20210311094738.1376795-1-georg.kotheimer@kernkonzept.com
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
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
12
---
10
---
13
target/riscv/csr.c | 68 +++++++++++++++++++++++-----------------------
11
include/hw/timer/ibex_timer.h | 2 ++
14
1 file changed, 34 insertions(+), 34 deletions(-)
12
hw/riscv/opentitan.c | 3 +++
13
hw/timer/ibex_timer.c | 17 ++++++++++++-----
14
3 files changed, 17 insertions(+), 5 deletions(-)
15
15
16
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
16
diff --git a/include/hw/timer/ibex_timer.h b/include/hw/timer/ibex_timer.h
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/riscv/csr.c
18
--- a/include/hw/timer/ibex_timer.h
19
+++ b/target/riscv/csr.c
19
+++ b/include/hw/timer/ibex_timer.h
20
@@ -XXX,XX +XXX,XX @@ static int write_sstatus(CPURISCVState *env, int csrno, target_ulong val)
20
@@ -XXX,XX +XXX,XX @@ struct IbexTimerState {
21
return write_mstatus(env, CSR_MSTATUS, newval);
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);
22
}
78
}
23
79
24
+static int read_vsie(CPURISCVState *env, int csrno, target_ulong *val)
80
+static void ibex_timer_realize(DeviceState *dev, Error **errp)
25
+{
81
+{
26
+ /* Shift the VS bits to their S bit location in vsie */
82
+ IbexTimerState *s = IBEX_TIMER(dev);
27
+ *val = (env->mie & env->hideleg & VS_MODE_INTERRUPTS) >> 1;
83
+
28
+ return 0;
84
+ qdev_init_gpio_out(dev, &s->m_timer_irq, 1);
29
+}
85
+}
30
+
86
+
31
static int read_sie(CPURISCVState *env, int csrno, target_ulong *val)
87
+
88
static void ibex_timer_class_init(ObjectClass *klass, void *data)
32
{
89
{
33
if (riscv_cpu_virt_enabled(env)) {
90
DeviceClass *dc = DEVICE_CLASS(klass);
34
- /* Tell the guest the VS bits, shifted to the S bit locations */
91
35
- *val = (env->mie & env->mideleg & VS_MODE_INTERRUPTS) >> 1;
92
dc->reset = ibex_timer_reset;
36
+ read_vsie(env, CSR_VSIE, val);
93
dc->vmsd = &vmstate_ibex_timer;
37
} else {
94
+ dc->realize = ibex_timer_realize;
38
*val = env->mie & env->mideleg;
95
device_class_set_props(dc, ibex_timer_properties);
39
}
40
return 0;
41
}
96
}
42
97
43
-static int write_sie(CPURISCVState *env, int csrno, target_ulong val)
44
+static int write_vsie(CPURISCVState *env, int csrno, target_ulong val)
45
{
46
- target_ulong newval;
47
+ /* Shift the S bits to their VS bit location in mie */
48
+ target_ulong newval = (env->mie & ~VS_MODE_INTERRUPTS) |
49
+ ((val << 1) & env->hideleg & VS_MODE_INTERRUPTS);
50
+ return write_mie(env, CSR_MIE, newval);
51
+}
52
53
+static int write_sie(CPURISCVState *env, int csrno, target_ulong val)
54
+{
55
if (riscv_cpu_virt_enabled(env)) {
56
- /* Shift the guests S bits to VS */
57
- newval = (env->mie & ~VS_MODE_INTERRUPTS) |
58
- ((val << 1) & VS_MODE_INTERRUPTS);
59
+ write_vsie(env, CSR_VSIE, val);
60
} else {
61
- newval = (env->mie & ~S_MODE_INTERRUPTS) | (val & S_MODE_INTERRUPTS);
62
+ target_ulong newval = (env->mie & ~S_MODE_INTERRUPTS) |
63
+ (val & S_MODE_INTERRUPTS);
64
+ write_mie(env, CSR_MIE, newval);
65
}
66
67
- return write_mie(env, CSR_MIE, newval);
68
+ return 0;
69
}
70
71
static int read_stvec(CPURISCVState *env, int csrno, target_ulong *val)
72
@@ -XXX,XX +XXX,XX @@ static int write_sbadaddr(CPURISCVState *env, int csrno, target_ulong val)
73
return 0;
74
}
75
76
+static int rmw_vsip(CPURISCVState *env, int csrno, target_ulong *ret_value,
77
+ target_ulong new_value, target_ulong write_mask)
78
+{
79
+ /* Shift the S bits to their VS bit location in mip */
80
+ int ret = rmw_mip(env, 0, ret_value, new_value << 1,
81
+ (write_mask << 1) & vsip_writable_mask & env->hideleg);
82
+ *ret_value &= VS_MODE_INTERRUPTS;
83
+ /* Shift the VS bits to their S bit location in vsip */
84
+ *ret_value >>= 1;
85
+ return ret;
86
+}
87
+
88
static int rmw_sip(CPURISCVState *env, int csrno, target_ulong *ret_value,
89
target_ulong new_value, target_ulong write_mask)
90
{
91
int ret;
92
93
if (riscv_cpu_virt_enabled(env)) {
94
- /* Shift the new values to line up with the VS bits */
95
- ret = rmw_mip(env, CSR_MSTATUS, ret_value, new_value << 1,
96
- (write_mask & sip_writable_mask) << 1 & env->mideleg);
97
- ret &= vsip_writable_mask;
98
- ret >>= 1;
99
+ ret = rmw_vsip(env, CSR_VSIP, ret_value, new_value, write_mask);
100
} else {
101
ret = rmw_mip(env, CSR_MSTATUS, ret_value, new_value,
102
write_mask & env->mideleg & sip_writable_mask);
103
@@ -XXX,XX +XXX,XX @@ static int write_vsstatus(CPURISCVState *env, int csrno, target_ulong val)
104
return 0;
105
}
106
107
-static int rmw_vsip(CPURISCVState *env, int csrno, target_ulong *ret_value,
108
- target_ulong new_value, target_ulong write_mask)
109
-{
110
- int ret = rmw_mip(env, 0, ret_value, new_value,
111
- write_mask & env->mideleg & vsip_writable_mask);
112
- return ret;
113
-}
114
-
115
-static int read_vsie(CPURISCVState *env, int csrno, target_ulong *val)
116
-{
117
- *val = env->mie & env->mideleg & VS_MODE_INTERRUPTS;
118
- return 0;
119
-}
120
-
121
-static int write_vsie(CPURISCVState *env, int csrno, target_ulong val)
122
-{
123
- target_ulong newval = (env->mie & ~env->mideleg) | (val & env->mideleg & MIP_VSSIP);
124
- return write_mie(env, CSR_MIE, newval);
125
-}
126
-
127
static int read_vstvec(CPURISCVState *env, int csrno, target_ulong *val)
128
{
129
*val = env->vstvec;
130
--
98
--
131
2.30.1
99
2.31.1
132
100
133
101
diff view generated by jsdifflib
1
From: Bin Meng <bin.meng@windriver.com>
1
From: Alistair Francis <alistair.francis@wdc.com>
2
2
3
This adds the documentation to describe what is supported for the
3
This is the initial commit of the SiFive PWM timer. This is used by
4
'microchip-icicle-kit' machine, and how to boot the machine in QEMU.
4
guest software as a timer and is included in the SiFive FU540 SoC.
5
5
6
Signed-off-by: Bin Meng <bin.meng@windriver.com>
6
Signed-off-by: Justin Restivo <jrestivo@draper.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
Signed-off-by: Alexandra Clifford <aclifford@draper.com>
8
Message-id: 20210322075248.136255-2-bmeng.cn@gmail.com
8
Signed-off-by: Amanda Strnad <astrnad@draper.com>
9
Signed-off-by: Alistair Francis <alistair.francis@wdc.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
10
---
12
---
11
docs/system/riscv/microchip-icicle-kit.rst | 89 ++++++++++++++++++++++
13
include/hw/timer/sifive_pwm.h | 62 +++++
12
docs/system/target-riscv.rst | 1 +
14
hw/timer/sifive_pwm.c | 468 ++++++++++++++++++++++++++++++++++
13
2 files changed, 90 insertions(+)
15
hw/timer/Kconfig | 3 +
14
create mode 100644 docs/system/riscv/microchip-icicle-kit.rst
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
15
21
16
diff --git a/docs/system/riscv/microchip-icicle-kit.rst b/docs/system/riscv/microchip-icicle-kit.rst
22
diff --git a/include/hw/timer/sifive_pwm.h b/include/hw/timer/sifive_pwm.h
17
new file mode 100644
23
new file mode 100644
18
index XXXXXXX..XXXXXXX
24
index XXXXXXX..XXXXXXX
19
--- /dev/null
25
--- /dev/null
20
+++ b/docs/system/riscv/microchip-icicle-kit.rst
26
+++ b/include/hw/timer/sifive_pwm.h
21
@@ -XXX,XX +XXX,XX @@
27
@@ -XXX,XX +XXX,XX @@
22
+Microchip PolarFire SoC Icicle Kit (``microchip-icicle-kit``)
28
+/*
23
+=============================================================
29
+ * SiFive PWM
24
+
30
+ *
25
+Microchip PolarFire SoC Icicle Kit integrates a PolarFire SoC, with one
31
+ * Copyright (c) 2020 Western Digital
26
+SiFive's E51 plus four U54 cores and many on-chip peripherals and an FPGA.
32
+ *
27
+
33
+ * Author: Alistair Francis <alistair.francis@wdc.com>
28
+For more details about Microchip PolarFire SoC, please see:
34
+ *
29
+https://www.microsemi.com/product-directory/soc-fpgas/5498-polarfire-soc-fpga
35
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
30
+
36
+ * of this software and associated documentation files (the "Software"), to deal
31
+The Icicle Kit board information can be found here:
37
+ * in the Software without restriction, including without limitation the rights
32
+https://www.microsemi.com/existing-parts/parts/152514
38
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
33
+
39
+ * copies of the Software, and to permit persons to whom the Software is
34
+Supported devices
40
+ * furnished to do so, subject to the following conditions:
35
+-----------------
41
+ *
36
+
42
+ * The above copyright notice and this permission notice shall be included in
37
+The ``microchip-icicle-kit`` machine supports the following devices:
43
+ * all copies or substantial portions of the Software.
38
+
44
+ *
39
+ * 1 E51 core
45
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
40
+ * 4 U54 cores
46
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
41
+ * Core Level Interruptor (CLINT)
47
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
42
+ * Platform-Level Interrupt Controller (PLIC)
48
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
43
+ * L2 Loosely Integrated Memory (L2-LIM)
49
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
44
+ * DDR memory controller
50
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
45
+ * 5 MMUARTs
51
+ * THE SOFTWARE.
46
+ * 1 DMA controller
52
+ */
47
+ * 2 GEM Ethernet controllers
53
+
48
+ * 1 SDHC storage controller
54
+#ifndef HW_SIFIVE_PWM_H
49
+
55
+#define HW_SIFIVE_PWM_H
50
+Boot options
56
+
51
+------------
57
+#include "hw/sysbus.h"
52
+
58
+#include "qemu/timer.h"
53
+The ``microchip-icicle-kit`` machine can start using the standard -bios
59
+#include "qom/object.h"
54
+functionality for loading its BIOS image, aka Hart Software Services (HSS_).
60
+
55
+HSS loads the second stage bootloader U-Boot from an SD card. It does not
61
+#define TYPE_SIFIVE_PWM "sifive-pwm"
56
+support direct kernel loading via the -kernel option. One has to load kernel
62
+
57
+from U-Boot.
63
+#define SIFIVE_PWM(obj) \
58
+
64
+ OBJECT_CHECK(SiFivePwmState, (obj), TYPE_SIFIVE_PWM)
59
+The memory is set to 1537 MiB by default which is the minimum required high
65
+
60
+memory size by HSS. A sanity check on ram size is performed in the machine
66
+#define SIFIVE_PWM_CHANS 4
61
+init routine to prompt user to increase the RAM size to > 1537 MiB when less
67
+#define SIFIVE_PWM_IRQS SIFIVE_PWM_CHANS
62
+than 1537 MiB ram is detected.
68
+
63
+
69
+typedef struct SiFivePwmState {
64
+Boot the machine
70
+ /* <private> */
65
+----------------
71
+ SysBusDevice parent_obj;
66
+
72
+
67
+HSS 2020.12 release is tested at the time of writing. To build an HSS image
73
+ /* <public> */
68
+that can be booted by the ``microchip-icicle-kit`` machine, type the following
74
+ MemoryRegion mmio;
69
+in the HSS source tree:
75
+ QEMUTimer timer[SIFIVE_PWM_CHANS];
70
+
76
+ /*
71
+.. code-block:: bash
77
+ * if en bit(s) set, is the number of ticks when pwmcount was 0
72
+
78
+ * if en bit(s) not set, is the number of ticks in pwmcount
73
+ $ export CROSS_COMPILE=riscv64-linux-
79
+ */
74
+ $ cp boards/mpfs-icicle-kit-es/def_config .config
80
+ uint64_t tick_offset;
75
+ $ make BOARD=mpfs-icicle-kit-es
81
+ uint64_t freq_hz;
76
+
82
+
77
+Download the official SD card image released by Microchip and prepare it for
83
+ uint32_t pwmcfg;
78
+QEMU usage:
84
+ uint32_t pwmcmp[SIFIVE_PWM_CHANS];
79
+
85
+
80
+.. code-block:: bash
86
+ qemu_irq irqs[SIFIVE_PWM_IRQS];
81
+
87
+} SiFivePwmState;
82
+ $ wget ftp://ftpsoc.microsemi.com/outgoing/core-image-minimal-dev-icicle-kit-es-sd-20201009141623.rootfs.wic.gz
88
+
83
+ $ gunzip core-image-minimal-dev-icicle-kit-es-sd-20201009141623.rootfs.wic.gz
89
+#endif /* HW_SIFIVE_PWM_H */
84
+ $ qemu-img resize core-image-minimal-dev-icicle-kit-es-sd-20201009141623.rootfs.wic 4G
90
diff --git a/hw/timer/sifive_pwm.c b/hw/timer/sifive_pwm.c
85
+
91
new file mode 100644
86
+Then we can boot the machine by:
92
index XXXXXXX..XXXXXXX
87
+
93
--- /dev/null
88
+.. code-block:: bash
94
+++ b/hw/timer/sifive_pwm.c
89
+
95
@@ -XXX,XX +XXX,XX @@
90
+ $ qemu-system-riscv64 -M microchip-icicle-kit -smp 5 \
96
+/*
91
+ -bios path/to/hss.bin -sd path/to/sdcard.img \
97
+ * SiFive PWM
92
+ -nic user,model=cadence_gem \
98
+ *
93
+ -nic tap,ifname=tap,model=cadence_gem,script=no \
99
+ * Copyright (c) 2020 Western Digital
94
+ -display none -serial stdio \
100
+ *
95
+ -chardev socket,id=serial1,path=serial1.sock,server=on,wait=on \
101
+ * Author: Alistair Francis <alistair.francis@wdc.com>
96
+ -serial chardev:serial1
102
+ *
97
+
103
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
98
+With above command line, current terminal session will be used for the first
104
+ * of this software and associated documentation files (the "Software"), to deal
99
+serial port. Open another terminal window, and use `minicom` to connect the
105
+ * in the Software without restriction, including without limitation the rights
100
+second serial port.
106
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
101
+
107
+ * copies of the Software, and to permit persons to whom the Software is
102
+.. code-block:: bash
108
+ * furnished to do so, subject to the following conditions:
103
+
109
+ *
104
+ $ minicom -D unix\#serial1.sock
110
+ * The above copyright notice and this permission notice shall be included in
105
+
111
+ * all copies or substantial portions of the Software.
106
+HSS output is on the first serial port (stdio) and U-Boot outputs on the
112
+ *
107
+second serial port. U-Boot will automatically load the Linux kernel from
113
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
108
+the SD card image.
114
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
109
+
115
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
110
+.. _HSS: https://github.com/polarfire-soc/hart-software-services
116
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
111
diff --git a/docs/system/target-riscv.rst b/docs/system/target-riscv.rst
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
112
index XXXXXXX..XXXXXXX 100644
565
index XXXXXXX..XXXXXXX 100644
113
--- a/docs/system/target-riscv.rst
566
--- a/hw/timer/Kconfig
114
+++ b/docs/system/target-riscv.rst
567
+++ b/hw/timer/Kconfig
115
@@ -XXX,XX +XXX,XX @@ undocumented; you can get a complete list by running
568
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_A10_PIT
116
.. toctree::
569
bool
117
:maxdepth: 1
570
select PTIMER
118
571
119
+ riscv/microchip-icicle-kit
572
+config SIFIVE_PWM
120
riscv/sifive_u
573
+ bool
121
574
+
122
RISC-V CPU features
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
123
--
603
--
124
2.30.1
604
2.31.1
125
605
126
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: Jim Shu <cwshu@andestech.com>
1
From: Anup Patel <anup.patel@wdc.com>
2
2
3
Currently, PMP permission checking of TLB page is bypassed if TLB hits
3
The RISC-V ACLINT is more modular and backward compatible with
4
Fix it by propagating PMP permission to TLB page permission.
4
original SiFive CLINT so instead of duplicating the original
5
SiFive CLINT implementation we upgrade the current SiFive CLINT
6
implementation to RISC-V ACLINT implementation.
5
7
6
PMP permission checking also use MMU-style API to change TLB permission
8
Signed-off-by: Anup Patel <anup.patel@wdc.com>
7
and size.
8
9
Signed-off-by: Jim Shu <cwshu@andestech.com>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
11
Message-id: 1613916082-19528-2-git-send-email-cwshu@andestech.com
10
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
11
Message-id: 20210831110603.338681-3-anup.patel@wdc.com
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
13
---
14
target/riscv/pmp.h | 4 +-
14
include/hw/intc/riscv_aclint.h | 54 +++--
15
target/riscv/cpu_helper.c | 84 +++++++++++++++++++++++++++++----------
15
hw/intc/riscv_aclint.c | 373 +++++++++++++++++++++++----------
16
target/riscv/pmp.c | 80 +++++++++++++++++++++++++++----------
16
hw/riscv/microchip_pfsoc.c | 9 +-
17
3 files changed, 125 insertions(+), 43 deletions(-)
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(-)
18
23
19
diff --git a/target/riscv/pmp.h b/target/riscv/pmp.h
24
diff --git a/include/hw/intc/riscv_aclint.h b/include/hw/intc/riscv_aclint.h
20
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
21
--- a/target/riscv/pmp.h
26
--- a/include/hw/intc/riscv_aclint.h
22
+++ b/target/riscv/pmp.h
27
+++ b/include/hw/intc/riscv_aclint.h
23
@@ -XXX,XX +XXX,XX @@ void pmpaddr_csr_write(CPURISCVState *env, uint32_t addr_index,
28
@@ -XXX,XX +XXX,XX @@
24
target_ulong val);
29
/*
25
target_ulong pmpaddr_csr_read(CPURISCVState *env, uint32_t addr_index);
30
- * SiFive CLINT (Core Local Interruptor) interface
26
bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr,
31
+ * RISC-V ACLINT (Advanced Core Local Interruptor) interface
27
- target_ulong size, pmp_priv_t priv, target_ulong mode);
32
*
28
+ target_ulong size, pmp_priv_t privs, pmp_priv_t *allowed_privs,
33
* Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
29
+ target_ulong mode);
34
* Copyright (c) 2017 SiFive, Inc.
30
bool pmp_is_range_in_tlb(CPURISCVState *env, hwaddr tlb_sa,
35
+ * Copyright (c) 2021 Western Digital Corporation or its affiliates.
31
target_ulong *tlb_size);
36
*
32
void pmp_update_rule_addr(CPURISCVState *env, uint32_t pmp_index);
37
* This program is free software; you can redistribute it and/or modify it
33
void pmp_update_rule_nums(CPURISCVState *env);
38
* under the terms and conditions of the GNU General Public License,
34
uint32_t pmp_get_num_rules(CPURISCVState *env);
39
@@ -XXX,XX +XXX,XX @@
35
+int pmp_priv_to_page_prot(pmp_priv_t pmp_priv);
40
* this program. If not, see <http://www.gnu.org/licenses/>.
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
};
36
118
37
#endif
119
#endif
38
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
120
diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c
39
index XXXXXXX..XXXXXXX 100644
121
index XXXXXXX..XXXXXXX 100644
40
--- a/target/riscv/cpu_helper.c
122
--- a/hw/intc/riscv_aclint.c
41
+++ b/target/riscv/cpu_helper.c
123
+++ b/hw/intc/riscv_aclint.c
42
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
124
@@ -XXX,XX +XXX,XX @@
43
env->load_res = -1;
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]);
44
}
206
}
45
207
46
+/*
208
-/* CPU wants to read rtc or timecmp register */
47
+ * get_physical_address_pmp - check PMP permission for this physical address
209
-static uint64_t sifive_clint_read(void *opaque, hwaddr addr, unsigned size)
48
+ *
210
+/* CPU read MTIMER register */
49
+ * Match the PMP region and check permission for this physical address and it's
211
+static uint64_t riscv_aclint_mtimer_read(void *opaque, hwaddr addr,
50
+ * TLB page. Returns 0 if the permission checking was successful
212
+ unsigned size)
51
+ *
213
{
52
+ * @env: CPURISCVState
214
- SiFiveCLINTState *clint = opaque;
53
+ * @prot: The returned protection attributes
215
- if (addr >= clint->sip_base &&
54
+ * @tlb_size: TLB page size containing addr. It could be modified after PMP
216
- addr < clint->sip_base + (clint->num_harts << 2)) {
55
+ * permission checking. NULL if not set TLB page for addr.
217
- size_t hartid = clint->hartid_base + ((addr - clint->sip_base) >> 2);
56
+ * @addr: The physical address to be checked permission
218
- CPUState *cpu = qemu_get_cpu(hartid);
57
+ * @access_type: The type of MMU access
219
- CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
58
+ * @mode: Indicates current privilege level.
220
- if (!env) {
59
+ */
221
- error_report("clint: invalid timecmp hartid: %zu", hartid);
60
+static int get_physical_address_pmp(CPURISCVState *env, int *prot,
222
- } else if ((addr & 0x3) == 0) {
61
+ target_ulong *tlb_size, hwaddr addr,
223
- return (env->mip & MIP_MSIP) > 0;
62
+ int size, MMUAccessType access_type,
224
- } else {
63
+ int mode)
225
- error_report("clint: invalid read: %08x", (uint32_t)addr);
64
+{
226
- return 0;
65
+ pmp_priv_t pmp_priv;
227
- }
66
+ target_ulong tlb_size_pmp = 0;
228
- } else if (addr >= clint->timecmp_base &&
67
+
229
- addr < clint->timecmp_base + (clint->num_harts << 3)) {
68
+ if (!riscv_feature(env, RISCV_FEATURE_PMP)) {
230
- size_t hartid = clint->hartid_base +
69
+ *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
231
- ((addr - clint->timecmp_base) >> 3);
70
+ return TRANSLATE_SUCCESS;
232
+ RISCVAclintMTimerState *mtimer = opaque;
71
+ }
233
+
72
+
234
+ if (addr >= mtimer->timecmp_base &&
73
+ if (!pmp_hart_has_privs(env, addr, size, 1 << access_type, &pmp_priv,
235
+ addr < (mtimer->timecmp_base + (mtimer->num_harts << 3))) {
74
+ mode)) {
236
+ size_t hartid = mtimer->hartid_base +
75
+ *prot = 0;
237
+ ((addr - mtimer->timecmp_base) >> 3);
76
+ return TRANSLATE_PMP_FAIL;
238
CPUState *cpu = qemu_get_cpu(hartid);
77
+ }
239
CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
78
+
240
if (!env) {
79
+ *prot = pmp_priv_to_page_prot(pmp_priv);
241
- error_report("clint: invalid timecmp hartid: %zu", hartid);
80
+ if (tlb_size != NULL) {
242
+ qemu_log_mask(LOG_GUEST_ERROR,
81
+ if (pmp_is_range_in_tlb(env, addr & ~(*tlb_size - 1), &tlb_size_pmp)) {
243
+ "aclint-mtimer: invalid hartid: %zu", hartid);
82
+ *tlb_size = tlb_size_pmp;
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);
403
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
404
405
s->timer_irqs = g_malloc(sizeof(qemu_irq) * s->num_harts);
406
qdev_init_gpio_out(dev, s->timer_irqs, s->num_harts);
407
408
- s->soft_irqs = g_malloc(sizeof(qemu_irq) * s->num_harts);
409
- qdev_init_gpio_out(dev, s->soft_irqs, s->num_harts);
410
+ /* Claim timer interrupt bits */
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);
83
+ }
416
+ }
84
+ }
417
+ }
85
+
86
+ return TRANSLATE_SUCCESS;
87
+}
88
+
89
/* get_physical_address - get the physical address for this virtual address
90
*
91
* Do a page table walk to obtain the physical address corresponding to a
92
@@ -XXX,XX +XXX,XX @@ restart:
93
pte_addr = base + idx * ptesize;
94
}
95
96
- if (riscv_feature(env, RISCV_FEATURE_PMP) &&
97
- !pmp_hart_has_privs(env, pte_addr, sizeof(target_ulong),
98
- 1 << MMU_DATA_LOAD, PRV_S)) {
99
+ int pmp_prot;
100
+ int pmp_ret = get_physical_address_pmp(env, &pmp_prot, NULL, pte_addr,
101
+ sizeof(target_ulong),
102
+ MMU_DATA_LOAD, PRV_S);
103
+ if (pmp_ret != TRANSLATE_SUCCESS) {
104
return TRANSLATE_PMP_FAIL;
105
}
106
107
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
108
#ifndef CONFIG_USER_ONLY
109
vaddr im_address;
110
hwaddr pa = 0;
111
- int prot, prot2;
112
+ int prot, prot2, prot_pmp;
113
bool pmp_violation = false;
114
bool first_stage_error = true;
115
bool two_stage_lookup = false;
116
int ret = TRANSLATE_FAIL;
117
int mode = mmu_idx;
118
- target_ulong tlb_size = 0;
119
+ /* default TLB page size */
120
+ target_ulong tlb_size = TARGET_PAGE_SIZE;
121
122
env->guest_phys_fault_addr = 0;
123
124
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
125
126
prot &= prot2;
127
128
- if (riscv_feature(env, RISCV_FEATURE_PMP) &&
129
- (ret == TRANSLATE_SUCCESS) &&
130
- !pmp_hart_has_privs(env, pa, size, 1 << access_type, mode)) {
131
- ret = TRANSLATE_PMP_FAIL;
132
+ if (ret == TRANSLATE_SUCCESS) {
133
+ ret = get_physical_address_pmp(env, &prot_pmp, &tlb_size, pa,
134
+ size, access_type, mode);
135
+ prot &= prot_pmp;
136
}
137
138
if (ret != TRANSLATE_SUCCESS) {
139
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
140
"%s address=%" VADDR_PRIx " ret %d physical "
141
TARGET_FMT_plx " prot %d\n",
142
__func__, address, ret, pa, prot);
143
- }
144
145
- if (riscv_feature(env, RISCV_FEATURE_PMP) &&
146
- (ret == TRANSLATE_SUCCESS) &&
147
- !pmp_hart_has_privs(env, pa, size, 1 << access_type, mode)) {
148
- ret = TRANSLATE_PMP_FAIL;
149
+ if (ret == TRANSLATE_SUCCESS) {
150
+ ret = get_physical_address_pmp(env, &prot_pmp, &tlb_size, pa,
151
+ size, access_type, mode);
152
+ prot &= prot_pmp;
153
+ }
154
}
155
+
156
if (ret == TRANSLATE_PMP_FAIL) {
157
pmp_violation = true;
158
}
159
160
if (ret == TRANSLATE_SUCCESS) {
161
- if (pmp_is_range_in_tlb(env, pa & TARGET_PAGE_MASK, &tlb_size)) {
162
- tlb_set_page(cs, address & ~(tlb_size - 1), pa & ~(tlb_size - 1),
163
- prot, mmu_idx, tlb_size);
164
- } else {
165
- tlb_set_page(cs, address & TARGET_PAGE_MASK, pa & TARGET_PAGE_MASK,
166
- prot, mmu_idx, TARGET_PAGE_SIZE);
167
- }
168
+ tlb_set_page(cs, address & ~(tlb_size - 1), pa & ~(tlb_size - 1),
169
+ prot, mmu_idx, tlb_size);
170
return true;
171
} else if (probe) {
172
return false;
173
diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
174
index XXXXXXX..XXXXXXX 100644
175
--- a/target/riscv/pmp.c
176
+++ b/target/riscv/pmp.c
177
@@ -XXX,XX +XXX,XX @@ static int pmp_is_in_range(CPURISCVState *env, int pmp_index, target_ulong addr)
178
return result;
179
}
418
}
180
419
181
+/*
420
-static void sifive_clint_class_init(ObjectClass *klass, void *data)
182
+ * Check if the address has required RWX privs when no PMP entry is matched.
421
+static void riscv_aclint_mtimer_class_init(ObjectClass *klass, void *data)
183
+ */
184
+static bool pmp_hart_has_privs_default(CPURISCVState *env, target_ulong addr,
185
+ target_ulong size, pmp_priv_t privs, pmp_priv_t *allowed_privs,
186
+ target_ulong mode)
187
+{
188
+ bool ret;
189
+
190
+ if ((!riscv_feature(env, RISCV_FEATURE_PMP)) || (mode == PRV_M)) {
191
+ /*
192
+ * Privileged spec v1.10 states if HW doesn't implement any PMP entry
193
+ * or no PMP entry matches an M-Mode access, the access succeeds.
194
+ */
195
+ ret = true;
196
+ *allowed_privs = PMP_READ | PMP_WRITE | PMP_EXEC;
197
+ } else {
198
+ /*
199
+ * Other modes are not allowed to succeed if they don't * match a rule,
200
+ * but there are rules. We've checked for no rule earlier in this
201
+ * function.
202
+ */
203
+ ret = false;
204
+ *allowed_privs = 0;
205
+ }
206
+
207
+ return ret;
208
+}
209
+
210
211
/*
212
* Public Interface
213
@@ -XXX,XX +XXX,XX @@ static int pmp_is_in_range(CPURISCVState *env, int pmp_index, target_ulong addr)
214
* Check if the address has required RWX privs to complete desired operation
215
*/
216
bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr,
217
- target_ulong size, pmp_priv_t privs, target_ulong mode)
218
+ target_ulong size, pmp_priv_t privs, pmp_priv_t *allowed_privs,
219
+ target_ulong mode)
220
{
422
{
221
int i = 0;
423
DeviceClass *dc = DEVICE_CLASS(klass);
222
int ret = -1;
424
- dc->realize = sifive_clint_realize;
223
int pmp_size = 0;
425
- device_class_set_props(dc, sifive_clint_properties);
224
target_ulong s = 0;
426
+ dc->realize = riscv_aclint_mtimer_realize;
225
target_ulong e = 0;
427
+ device_class_set_props(dc, riscv_aclint_mtimer_properties);
226
- pmp_priv_t allowed_privs = 0;
227
228
/* Short cut if no rules */
229
if (0 == pmp_get_num_rules(env)) {
230
- return (env->priv == PRV_M) ? true : false;
231
+ return pmp_hart_has_privs_default(env, addr, size, privs,
232
+ allowed_privs, mode);
233
}
234
235
if (size == 0) {
236
@@ -XXX,XX +XXX,XX @@ bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr,
237
* check
238
*/
239
if (((s + e) == 2) && (PMP_AMATCH_OFF != a_field)) {
240
- allowed_privs = PMP_READ | PMP_WRITE | PMP_EXEC;
241
+ *allowed_privs = PMP_READ | PMP_WRITE | PMP_EXEC;
242
if ((mode != PRV_M) || pmp_is_locked(env, i)) {
243
- allowed_privs &= env->pmp_state.pmp[i].cfg_reg;
244
+ *allowed_privs &= env->pmp_state.pmp[i].cfg_reg;
245
}
246
247
- if ((privs & allowed_privs) == privs) {
248
- ret = 1;
249
- break;
250
- } else {
251
- ret = 0;
252
- break;
253
- }
254
+ ret = ((privs & *allowed_privs) == privs);
255
+ break;
256
}
257
}
258
259
/* No rule matched */
260
if (ret == -1) {
261
- if (mode == PRV_M) {
262
- ret = 1; /* Privileged spec v1.10 states if no PMP entry matches an
263
- * M-Mode access, the access succeeds */
264
- } else {
265
- ret = 0; /* Other modes are not allowed to succeed if they don't
266
- * match a rule, but there are rules. We've checked for
267
- * no rule earlier in this function. */
268
- }
269
+ return pmp_hart_has_privs_default(env, addr, size, privs,
270
+ allowed_privs, mode);
271
}
272
273
return ret == 1 ? true : false;
274
}
428
}
275
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)
276
-
447
-
277
/*
448
/*
278
* Handle a write to a pmpcfg CSP
449
- * Create CLINT device.
450
+ * Create ACLINT MTIMER device.
279
*/
451
*/
280
@@ -XXX,XX +XXX,XX @@ bool pmp_is_range_in_tlb(CPURISCVState *env, hwaddr tlb_sa,
452
-DeviceState *sifive_clint_create(hwaddr addr, hwaddr size,
281
453
- uint32_t hartid_base, uint32_t num_harts, uint32_t sip_base,
282
return false;
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;
283
}
503
}
284
+
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
+
285
+/*
611
+/*
286
+ * Convert PMP privilege to TLB page privilege.
612
+ * Create ACLINT [M|S]SWI device.
287
+ */
613
+ */
288
+int pmp_priv_to_page_prot(pmp_priv_t pmp_priv)
614
+DeviceState *riscv_aclint_swi_create(hwaddr addr, uint32_t hartid_base,
615
+ uint32_t num_harts, bool sswi)
289
+{
616
+{
290
+ int prot = 0;
617
+ int i;
291
+
618
+ DeviceState *dev = qdev_new(TYPE_RISCV_ACLINT_SWI);
292
+ if (pmp_priv & PMP_READ) {
619
+
293
+ prot |= PAGE_READ;
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));
294
+ }
636
+ }
295
+ if (pmp_priv & PMP_WRITE) {
637
+
296
+ prot |= PAGE_WRITE;
638
+ return dev;
297
+ }
298
+ if (pmp_priv & PMP_EXEC) {
299
+ prot |= PAGE_EXEC;
300
+ }
301
+
302
+ return prot;
303
+}
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);
304
--
798
--
305
2.30.1
799
2.31.1
306
800
307
801
diff view generated by jsdifflib
1
From: Asherah Connor <ashe@kivikakk.ee>
1
From: Anup Patel <anup.patel@wdc.com>
2
2
3
Allow ramfb on virt. This lets `-device ramfb' work.
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
Signed-off-by: Asherah Connor <ashe@kivikakk.ee>
7
Signed-off-by: Anup Patel <anup.patel@wdc.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
6
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
9
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Message-id: 20210831110603.338681-4-anup.patel@wdc.com
8
Message-id: 20210318235041.17175-3-ashe@kivikakk.ee
9
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
10
---
12
---
11
hw/riscv/virt.c | 3 +++
13
hw/riscv/virt.c | 527 ++++++++++++++++++++++++++++++------------------
12
1 file changed, 3 insertions(+)
14
1 file changed, 327 insertions(+), 200 deletions(-)
13
15
14
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
16
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/riscv/virt.c
18
--- a/hw/riscv/virt.c
17
+++ b/hw/riscv/virt.c
19
+++ b/hw/riscv/virt.c
18
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ static void create_pcie_irq_map(void *fdt, char *nodename,
19
#include "sysemu/sysemu.h"
21
0x1800, 0, 0, 0x7);
20
#include "hw/pci/pci.h"
21
#include "hw/pci-host/gpex.h"
22
+#include "hw/display/ramfb.h"
23
24
static const MemMapEntry virt_memmap[] = {
25
[VIRT_DEBUG] = { 0x0, 0x100 },
26
@@ -XXX,XX +XXX,XX @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
27
mc->cpu_index_to_instance_props = riscv_numa_cpu_index_to_props;
28
mc->get_default_cpu_node_id = riscv_numa_get_default_cpu_node_id;
29
mc->numa_mem_supported = true;
30
+
31
+ machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
32
}
22
}
33
23
34
static const TypeInfo virt_machine_typeinfo = {
24
-static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap,
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];
374
}
375
}
376
377
- riscv_socket_fdt_write_distance_matrix(mc, fdt);
378
+ riscv_socket_fdt_write_distance_matrix(mc, mc->fdt);
379
+}
380
+
381
+static void create_fdt_virtio(RISCVVirtState *s, const MemMapEntry *memmap,
382
+ uint32_t irq_virtio_phandle)
383
+{
384
+ int i;
385
+ char *name;
386
+ MachineState *mc = MACHINE(s);
387
388
for (i = 0; i < VIRTIO_COUNT; i++) {
389
name = g_strdup_printf("/soc/virtio_mmio@%lx",
390
(long)(memmap[VIRT_VIRTIO].base + i * memmap[VIRT_VIRTIO].size));
391
- qemu_fdt_add_subnode(fdt, name);
392
- qemu_fdt_setprop_string(fdt, name, "compatible", "virtio,mmio");
393
- qemu_fdt_setprop_cells(fdt, name, "reg",
394
+ qemu_fdt_add_subnode(mc->fdt, name);
395
+ qemu_fdt_setprop_string(mc->fdt, name, "compatible", "virtio,mmio");
396
+ qemu_fdt_setprop_cells(mc->fdt, name, "reg",
397
0x0, memmap[VIRT_VIRTIO].base + i * memmap[VIRT_VIRTIO].size,
398
0x0, memmap[VIRT_VIRTIO].size);
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);
406
}
407
+}
408
+
409
+static void create_fdt_pcie(RISCVVirtState *s, const MemMapEntry *memmap,
410
+ uint32_t irq_pcie_phandle)
411
+{
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
}
638
}
639
35
--
640
--
36
2.30.1
641
2.31.1
37
642
38
643
diff view generated by jsdifflib
1
From: Asherah Connor <ashe@kivikakk.ee>
1
From: Anup Patel <anup.patel@wdc.com>
2
2
3
Provides fw_cfg for the virt machine on riscv. This enables
3
We extend virt machine to emulate ACLINT devices only when "aclint=on"
4
using e.g. ramfb later.
4
parameter is passed along with machine name in QEMU command-line.
5
5
6
Signed-off-by: Asherah Connor <ashe@kivikakk.ee>
6
Signed-off-by: Anup Patel <anup.patel@wdc.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
8
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Message-id: 20210831110603.338681-5-anup.patel@wdc.com
9
Message-id: 20210318235041.17175-2-ashe@kivikakk.ee
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
---
11
---
12
include/hw/riscv/virt.h | 2 ++
12
docs/system/riscv/virt.rst | 10 ++++
13
hw/riscv/virt.c | 30 ++++++++++++++++++++++++++++++
13
include/hw/riscv/virt.h | 2 +
14
hw/riscv/Kconfig | 1 +
14
hw/riscv/virt.c | 113 ++++++++++++++++++++++++++++++++++++-
15
3 files changed, 33 insertions(+)
15
3 files changed, 124 insertions(+), 1 deletion(-)
16
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
17
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
38
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
18
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/riscv/virt.h
40
--- a/include/hw/riscv/virt.h
20
+++ b/include/hw/riscv/virt.h
41
+++ b/include/hw/riscv/virt.h
21
@@ -XXX,XX +XXX,XX @@ struct RISCVVirtState {
42
@@ -XXX,XX +XXX,XX @@ struct RISCVVirtState {
22
RISCVHartArrayState soc[VIRT_SOCKETS_MAX];
43
FWCfgState *fw_cfg;
23
DeviceState *plic[VIRT_SOCKETS_MAX];
24
PFlashCFI01 *flash[2];
25
+ FWCfgState *fw_cfg;
26
44
27
int fdt_size;
45
int fdt_size;
46
+ bool have_aclint;
28
};
47
};
48
49
enum {
29
@@ -XXX,XX +XXX,XX @@ enum {
50
@@ -XXX,XX +XXX,XX @@ enum {
51
VIRT_TEST,
52
VIRT_RTC,
53
VIRT_CLINT,
54
+ VIRT_ACLINT_SSWI,
30
VIRT_PLIC,
55
VIRT_PLIC,
31
VIRT_UART0,
56
VIRT_UART0,
32
VIRT_VIRTIO,
57
VIRT_VIRTIO,
33
+ VIRT_FW_CFG,
34
VIRT_FLASH,
35
VIRT_DRAM,
36
VIRT_PCIE_MMIO,
37
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
58
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
38
index XXXXXXX..XXXXXXX 100644
59
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/riscv/virt.c
60
--- a/hw/riscv/virt.c
40
+++ b/hw/riscv/virt.c
61
+++ b/hw/riscv/virt.c
41
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry virt_memmap[] = {
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 },
42
[VIRT_PLIC] = { 0xc000000, VIRT_PLIC_SIZE(VIRT_CPUS_MAX * 2) },
68
[VIRT_PLIC] = { 0xc000000, VIRT_PLIC_SIZE(VIRT_CPUS_MAX * 2) },
43
[VIRT_UART0] = { 0x10000000, 0x100 },
69
[VIRT_UART0] = { 0x10000000, 0x100 },
44
[VIRT_VIRTIO] = { 0x10001000, 0x1000 },
70
@@ -XXX,XX +XXX,XX @@ static void create_fdt_socket_clint(RISCVVirtState *s,
45
+ [VIRT_FW_CFG] = { 0x10100000, 0x18 },
71
g_free(clint_cells);
46
[VIRT_FLASH] = { 0x20000000, 0x4000000 },
47
[VIRT_PCIE_ECAM] = { 0x30000000, 0x10000000 },
48
[VIRT_PCIE_MMIO] = { 0x40000000, 0x40000000 },
49
@@ -XXX,XX +XXX,XX @@ static inline DeviceState *gpex_pcie_init(MemoryRegion *sys_mem,
50
return dev;
51
}
72
}
52
73
53
+static FWCfgState *create_fw_cfg(const MachineState *mc)
74
+static void create_fdt_socket_aclint(RISCVVirtState *s,
75
+ const MemMapEntry *memmap, int socket,
76
+ uint32_t *intc_phandles)
54
+{
77
+{
55
+ hwaddr base = virt_memmap[VIRT_FW_CFG].base;
78
+ int cpu;
56
+ hwaddr size = virt_memmap[VIRT_FW_CFG].size;
79
+ char *name;
57
+ FWCfgState *fw_cfg;
80
+ unsigned long addr;
58
+ char *nodename;
81
+ uint32_t aclint_cells_size;
59
+
82
+ uint32_t *aclint_mswi_cells;
60
+ fw_cfg = fw_cfg_init_mem_wide(base + 8, base, 8, base + 16,
83
+ uint32_t *aclint_sswi_cells;
61
+ &address_space_memory);
84
+ uint32_t *aclint_mtimer_cells;
62
+ fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)mc->smp.cpus);
85
+ MachineState *mc = MACHINE(s);
63
+
86
+
64
+ nodename = g_strdup_printf("/fw-cfg@%" PRIx64, base);
87
+ aclint_mswi_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
65
+ qemu_fdt_add_subnode(mc->fdt, nodename);
88
+ aclint_mtimer_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
66
+ qemu_fdt_setprop_string(mc->fdt, nodename,
89
+ aclint_sswi_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
67
+ "compatible", "qemu,fw-cfg-mmio");
90
+
68
+ qemu_fdt_setprop_sized_cells(mc->fdt, nodename, "reg",
91
+ for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
69
+ 2, base, 2, size);
92
+ aclint_mswi_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
70
+ qemu_fdt_setprop(mc->fdt, nodename, "dma-coherent", NULL, 0);
93
+ aclint_mswi_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_SOFT);
71
+ g_free(nodename);
94
+ aclint_mtimer_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
72
+ return fw_cfg;
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);
73
+}
148
+}
74
+
149
+
75
static void virt_machine_init(MachineState *machine)
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)
76
{
182
{
77
const MemMapEntry *memmap = virt_memmap;
183
}
78
@@ -XXX,XX +XXX,XX @@ static void virt_machine_init(MachineState *machine)
184
79
start_addr = virt_memmap[VIRT_FLASH].base;
185
+static bool virt_get_aclint(Object *obj, Error **errp)
80
}
186
+{
81
187
+ MachineState *ms = MACHINE(obj);
82
+ /*
188
+ RISCVVirtState *s = RISCV_VIRT_MACHINE(ms);
83
+ * Init fw_cfg. Must be done before riscv_load_fdt, otherwise the device
189
+
84
+ * tree cannot be altered and we get FDT_ERR_NOSPACE.
190
+ return s->have_aclint;
85
+ */
191
+}
86
+ s->fw_cfg = create_fw_cfg(machine);
192
+
87
+ rom_set_fw(s->fw_cfg);
193
+static void virt_set_aclint(Object *obj, bool value, Error **errp)
88
+
194
+{
89
/* Compute the fdt load address in dram */
195
+ MachineState *ms = MACHINE(obj);
90
fdt_load_addr = riscv_load_fdt(memmap[VIRT_DRAM].base,
196
+ RISCVVirtState *s = RISCV_VIRT_MACHINE(ms);
91
machine->ram_size, machine->fdt);
197
+
92
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
198
+ s->have_aclint = value;
93
index XXXXXXX..XXXXXXX 100644
199
+}
94
--- a/hw/riscv/Kconfig
200
+
95
+++ b/hw/riscv/Kconfig
201
static void virt_machine_class_init(ObjectClass *oc, void *data)
96
@@ -XXX,XX +XXX,XX @@ config RISCV_VIRT
202
{
97
select SIFIVE_PLIC
203
MachineClass *mc = MACHINE_CLASS(oc);
98
select SIFIVE_TEST
204
@@ -XXX,XX +XXX,XX @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
99
select VIRTIO_MMIO
205
mc->numa_mem_supported = true;
100
+ select FW_CFG_DMA
206
101
207
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
102
config SIFIVE_E
208
+
103
bool
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 = {
104
--
217
--
105
2.30.1
218
2.31.1
106
219
107
220
diff view generated by jsdifflib
1
From: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
1
From: Frank Chang <frank.chang@sifive.com>
2
2
3
When decode_insn16() fails, we fall back to decode_RV32_64C() for
3
Setting Control.claim clears all of the chanel's Next registers.
4
further compressed instruction decoding. However, prior to this change,
4
This is effective only when Control.claim is set from 0 to 1.
5
we did not raise an illegal instruction exception, if decode_RV32_64C()
6
fails to decode the instruction. This means that we skipped illegal
7
compressed instructions instead of raising an illegal instruction
8
exception.
9
5
10
Instead of patching decode_RV32_64C(), we can just remove it,
6
Signed-off-by: Frank Chang <frank.chang@sifive.com>
11
as it is dead code since f330433b363 anyway.
7
Tested-by: Max Hsu <max.hsu@sifive.com>
12
8
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
13
Signed-off-by: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
9
Tested-by: Bin Meng <bmeng.cn@gmail.com>
14
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Message-id: 20210912130553.179501-2-frank.chang@sifive.com
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20210322121609.3097928-1-georg.kotheimer@kernkonzept.com
17
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
18
---
12
---
19
target/riscv/translate.c | 179 +--------------------------------------
13
hw/dma/sifive_pdma.c | 19 +++++++++++++++++++
20
1 file changed, 1 insertion(+), 178 deletions(-)
14
1 file changed, 19 insertions(+)
21
15
22
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
16
diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c
23
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
24
--- a/target/riscv/translate.c
18
--- a/hw/dma/sifive_pdma.c
25
+++ b/target/riscv/translate.c
19
+++ b/hw/dma/sifive_pdma.c
26
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
20
@@ -XXX,XX +XXX,XX @@
27
CPUState *cs;
21
#define DMA_EXEC_DST 0x110
28
} DisasContext;
22
#define DMA_EXEC_SRC 0x118
29
23
30
-#ifdef TARGET_RISCV64
24
+/*
31
-/* convert riscv funct3 to qemu memop for load/store */
25
+ * FU540/FU740 docs are incorrect with NextConfig.wsize/rsize reset values.
32
-static const int tcg_memop_lookup[8] = {
26
+ * The reset values tested on Unleashed/Unmatched boards are 6 instead of 0.
33
- [0 ... 7] = -1,
27
+ */
34
- [0] = MO_SB,
28
+#define CONFIG_WRSZ_DEFAULT 6
35
- [1] = MO_TESW,
29
+#define CONFIG_RDSZ_DEFAULT 6
36
- [2] = MO_TESL,
30
+
37
- [3] = MO_TEQ,
31
enum dma_chan_state {
38
- [4] = MO_UB,
32
DMA_CHAN_STATE_IDLE,
39
- [5] = MO_TEUW,
33
DMA_CHAN_STATE_STARTED,
40
- [6] = MO_TEUL,
34
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_write(void *opaque, hwaddr offset,
41
-};
42
-#endif
43
-
44
#ifdef TARGET_RISCV64
45
#define CASE_OP_32_64(X) case X: case glue(X, W)
46
#else
47
@@ -XXX,XX +XXX,XX @@ static void gen_jal(DisasContext *ctx, int rd, target_ulong imm)
48
ctx->base.is_jmp = DISAS_NORETURN;
49
}
50
51
-#ifdef TARGET_RISCV64
52
-static void gen_load_c(DisasContext *ctx, uint32_t opc, int rd, int rs1,
53
- target_long imm)
54
-{
55
- TCGv t0 = tcg_temp_new();
56
- TCGv t1 = tcg_temp_new();
57
- gen_get_gpr(t0, rs1);
58
- tcg_gen_addi_tl(t0, t0, imm);
59
- int memop = tcg_memop_lookup[(opc >> 12) & 0x7];
60
-
61
- if (memop < 0) {
62
- gen_exception_illegal(ctx);
63
- return;
64
- }
65
-
66
- tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, memop);
67
- gen_set_gpr(rd, t1);
68
- tcg_temp_free(t0);
69
- tcg_temp_free(t1);
70
-}
71
-
72
-static void gen_store_c(DisasContext *ctx, uint32_t opc, int rs1, int rs2,
73
- target_long imm)
74
-{
75
- TCGv t0 = tcg_temp_new();
76
- TCGv dat = tcg_temp_new();
77
- gen_get_gpr(t0, rs1);
78
- tcg_gen_addi_tl(t0, t0, imm);
79
- gen_get_gpr(dat, rs2);
80
- int memop = tcg_memop_lookup[(opc >> 12) & 0x7];
81
-
82
- if (memop < 0) {
83
- gen_exception_illegal(ctx);
84
- return;
85
- }
86
-
87
- tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx, memop);
88
- tcg_temp_free(t0);
89
- tcg_temp_free(dat);
90
-}
91
-#endif
92
-
93
#ifndef CONFIG_USER_ONLY
94
/* The states of mstatus_fs are:
95
* 0 = disabled, 1 = initial, 2 = clean, 3 = dirty
96
@@ -XXX,XX +XXX,XX @@ static void mark_fs_dirty(DisasContext *ctx)
97
static inline void mark_fs_dirty(DisasContext *ctx) { }
98
#endif
99
100
-#if !defined(TARGET_RISCV64)
101
-static void gen_fp_load(DisasContext *ctx, uint32_t opc, int rd,
102
- int rs1, target_long imm)
103
-{
104
- TCGv t0;
105
-
106
- if (ctx->mstatus_fs == 0) {
107
- gen_exception_illegal(ctx);
108
- return;
109
- }
110
-
111
- t0 = tcg_temp_new();
112
- gen_get_gpr(t0, rs1);
113
- tcg_gen_addi_tl(t0, t0, imm);
114
-
115
- switch (opc) {
116
- case OPC_RISC_FLW:
117
- if (!has_ext(ctx, RVF)) {
118
- goto do_illegal;
119
- }
120
- tcg_gen_qemu_ld_i64(cpu_fpr[rd], t0, ctx->mem_idx, MO_TEUL);
121
- /* RISC-V requires NaN-boxing of narrower width floating point values */
122
- tcg_gen_ori_i64(cpu_fpr[rd], cpu_fpr[rd], 0xffffffff00000000ULL);
123
- break;
124
- case OPC_RISC_FLD:
125
- if (!has_ext(ctx, RVD)) {
126
- goto do_illegal;
127
- }
128
- tcg_gen_qemu_ld_i64(cpu_fpr[rd], t0, ctx->mem_idx, MO_TEQ);
129
- break;
130
- do_illegal:
131
- default:
132
- gen_exception_illegal(ctx);
133
- break;
134
- }
135
- tcg_temp_free(t0);
136
-
137
- mark_fs_dirty(ctx);
138
-}
139
-
140
-static void gen_fp_store(DisasContext *ctx, uint32_t opc, int rs1,
141
- int rs2, target_long imm)
142
-{
143
- TCGv t0;
144
-
145
- if (ctx->mstatus_fs == 0) {
146
- gen_exception_illegal(ctx);
147
- return;
148
- }
149
-
150
- t0 = tcg_temp_new();
151
- gen_get_gpr(t0, rs1);
152
- tcg_gen_addi_tl(t0, t0, imm);
153
-
154
- switch (opc) {
155
- case OPC_RISC_FSW:
156
- if (!has_ext(ctx, RVF)) {
157
- goto do_illegal;
158
- }
159
- tcg_gen_qemu_st_i64(cpu_fpr[rs2], t0, ctx->mem_idx, MO_TEUL);
160
- break;
161
- case OPC_RISC_FSD:
162
- if (!has_ext(ctx, RVD)) {
163
- goto do_illegal;
164
- }
165
- tcg_gen_qemu_st_i64(cpu_fpr[rs2], t0, ctx->mem_idx, MO_TEQ);
166
- break;
167
- do_illegal:
168
- default:
169
- gen_exception_illegal(ctx);
170
- break;
171
- }
172
-
173
- tcg_temp_free(t0);
174
-}
175
-#endif
176
-
177
static void gen_set_rm(DisasContext *ctx, int rm)
178
{
35
{
179
TCGv_i32 t0;
36
SiFivePDMAState *s = opaque;
180
@@ -XXX,XX +XXX,XX @@ static void gen_set_rm(DisasContext *ctx, int rm)
37
int ch = SIFIVE_PDMA_CHAN_NO(offset);
181
tcg_temp_free_i32(t0);
38
+ bool claimed;
182
}
39
183
40
if (ch >= SIFIVE_PDMA_CHANS) {
184
-static void decode_RV32_64C0(DisasContext *ctx, uint16_t opcode)
41
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid channel no %d\n",
185
-{
42
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_write(void *opaque, hwaddr offset,
186
- uint8_t funct3 = extract16(opcode, 13, 3);
43
offset &= 0xfff;
187
- uint8_t rd_rs2 = GET_C_RS2S(opcode);
44
switch (offset) {
188
- uint8_t rs1s = GET_C_RS1S(opcode);
45
case DMA_CONTROL:
189
-
46
+ claimed = !!s->chan[ch].control & CONTROL_CLAIM;
190
- switch (funct3) {
47
+
191
- case 3:
48
+ if (!claimed && (value & CONTROL_CLAIM)) {
192
-#if defined(TARGET_RISCV64)
49
+ /* reset Next* registers */
193
- /* C.LD(RV64/128) -> ld rd', offset[7:3](rs1')*/
50
+ s->chan[ch].next_config = (CONFIG_RDSZ_DEFAULT << CONFIG_RDSZ_SHIFT) |
194
- gen_load_c(ctx, OPC_RISC_LD, rd_rs2, rs1s,
51
+ (CONFIG_WRSZ_DEFAULT << CONFIG_WRSZ_SHIFT);
195
- GET_C_LD_IMM(opcode));
52
+ s->chan[ch].next_bytes = 0;
196
-#else
53
+ s->chan[ch].next_dst = 0;
197
- /* C.FLW (RV32) -> flw rd', offset[6:2](rs1')*/
54
+ s->chan[ch].next_src = 0;
198
- gen_fp_load(ctx, OPC_RISC_FLW, rd_rs2, rs1s,
55
+ }
199
- GET_C_LW_IMM(opcode));
56
+
200
-#endif
57
s->chan[ch].control = value;
201
- break;
58
202
- case 7:
59
if (value & CONTROL_RUN) {
203
-#if defined(TARGET_RISCV64)
204
- /* C.SD (RV64/128) -> sd rs2', offset[7:3](rs1')*/
205
- gen_store_c(ctx, OPC_RISC_SD, rs1s, rd_rs2,
206
- GET_C_LD_IMM(opcode));
207
-#else
208
- /* C.FSW (RV32) -> fsw rs2', offset[6:2](rs1')*/
209
- gen_fp_store(ctx, OPC_RISC_FSW, rs1s, rd_rs2,
210
- GET_C_LW_IMM(opcode));
211
-#endif
212
- break;
213
- }
214
-}
215
-
216
-static void decode_RV32_64C(DisasContext *ctx, uint16_t opcode)
217
-{
218
- uint8_t op = extract16(opcode, 0, 2);
219
-
220
- switch (op) {
221
- case 0:
222
- decode_RV32_64C0(ctx, opcode);
223
- break;
224
- }
225
-}
226
-
227
static int ex_plus_1(DisasContext *ctx, int nf)
228
{
229
return nf + 1;
230
@@ -XXX,XX +XXX,XX @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
231
} else {
232
ctx->pc_succ_insn = ctx->base.pc_next + 2;
233
if (!decode_insn16(ctx, opcode)) {
234
- /* fall back to old decoder */
235
- decode_RV32_64C(ctx, opcode);
236
+ gen_exception_illegal(ctx);
237
}
238
}
239
} else {
240
--
60
--
241
2.30.1
61
2.31.1
242
62
243
63
diff view generated by jsdifflib
1
From: Alexander Wagner <alexander.wagner@ulal.de>
1
From: Frank Chang <frank.chang@sifive.com>
2
2
3
Not disabling the UART leads to QEMU overwriting the UART receive buffer with
3
Real PDMA must have Control.claim bit to be set before
4
the newest received byte. The rx_level variable is added to allow the use of
4
Control.run bit is set to start any DMA transactions.
5
the existing OpenTitan driver libraries.
5
Otherwise nothing will be transferred.
6
6
7
Signed-off-by: Alexander Wagner <alexander.wagner@ulal.de>
7
The following result is PDMA tested in U-Boot on Unmatched board:
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
9
Message-id: 20210309152130.13038-1-alexander.wagner@ulal.de
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
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
36
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
---
37
---
12
include/hw/char/ibex_uart.h | 4 ++++
38
hw/dma/sifive_pdma.c | 9 +++++++++
13
hw/char/ibex_uart.c | 23 ++++++++++++++++++-----
39
1 file changed, 9 insertions(+)
14
2 files changed, 22 insertions(+), 5 deletions(-)
15
40
16
diff --git a/include/hw/char/ibex_uart.h b/include/hw/char/ibex_uart.h
41
diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c
17
index XXXXXXX..XXXXXXX 100644
42
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/char/ibex_uart.h
43
--- a/hw/dma/sifive_pdma.c
19
+++ b/include/hw/char/ibex_uart.h
44
+++ b/hw/dma/sifive_pdma.c
20
@@ -XXX,XX +XXX,XX @@ REG32(FIFO_CTRL, 0x1c)
45
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_write(void *opaque, hwaddr offset,
21
FIELD(FIFO_CTRL, RXILVL, 2, 3)
46
22
FIELD(FIFO_CTRL, TXILVL, 5, 2)
47
s->chan[ch].control = value;
23
REG32(FIFO_STATUS, 0x20)
48
24
+ FIELD(FIFO_STATUS, TXLVL, 0, 5)
49
+ /*
25
+ FIELD(FIFO_STATUS, RXLVL, 16, 5)
50
+ * If channel was not claimed before run bit is set,
26
REG32(OVRD, 0x24)
51
+ * DMA won't run.
27
REG32(VAL, 0x28)
52
+ */
28
REG32(TIMEOUT_CTRL, 0x2c)
53
+ if (!claimed) {
29
@@ -XXX,XX +XXX,XX @@ struct IbexUartState {
54
+ s->chan[ch].control &= ~CONTROL_RUN;
30
uint8_t tx_fifo[IBEX_UART_TX_FIFO_SIZE];
55
+ return;
31
uint32_t tx_level;
56
+ }
32
33
+ uint32_t rx_level;
34
+
57
+
35
QEMUTimer *fifo_trigger_handle;
58
if (value & CONTROL_RUN) {
36
uint64_t char_tx_time;
59
sifive_pdma_run(s, ch);
37
38
diff --git a/hw/char/ibex_uart.c b/hw/char/ibex_uart.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/hw/char/ibex_uart.c
41
+++ b/hw/char/ibex_uart.c
42
@@ -XXX,XX +XXX,XX @@ static int ibex_uart_can_receive(void *opaque)
43
{
44
IbexUartState *s = opaque;
45
46
- if (s->uart_ctrl & R_CTRL_RX_ENABLE_MASK) {
47
+ if ((s->uart_ctrl & R_CTRL_RX_ENABLE_MASK)
48
+ && !(s->uart_status & R_STATUS_RXFULL_MASK)) {
49
return 1;
50
}
51
52
@@ -XXX,XX +XXX,XX @@ static void ibex_uart_receive(void *opaque, const uint8_t *buf, int size)
53
54
s->uart_status &= ~R_STATUS_RXIDLE_MASK;
55
s->uart_status &= ~R_STATUS_RXEMPTY_MASK;
56
+ /* The RXFULL is set after receiving a single byte
57
+ * as the FIFO buffers are not yet implemented.
58
+ */
59
+ s->uart_status |= R_STATUS_RXFULL_MASK;
60
+ s->rx_level += 1;
61
62
if (size > rx_fifo_level) {
63
s->uart_intr_state |= R_INTR_STATE_RX_WATERMARK_MASK;
64
@@ -XXX,XX +XXX,XX @@ static void ibex_uart_reset(DeviceState *dev)
65
s->uart_timeout_ctrl = 0x00000000;
66
67
s->tx_level = 0;
68
+ s->rx_level = 0;
69
70
s->char_tx_time = (NANOSECONDS_PER_SECOND / 230400) * 10;
71
72
@@ -XXX,XX +XXX,XX @@ static uint64_t ibex_uart_read(void *opaque, hwaddr addr,
73
74
case R_RDATA:
75
retvalue = s->uart_rdata;
76
- if (s->uart_ctrl & R_CTRL_RX_ENABLE_MASK) {
77
+ if ((s->uart_ctrl & R_CTRL_RX_ENABLE_MASK) && (s->rx_level > 0)) {
78
qemu_chr_fe_accept_input(&s->chr);
79
80
- s->uart_status |= R_STATUS_RXIDLE_MASK;
81
- s->uart_status |= R_STATUS_RXEMPTY_MASK;
82
+ s->rx_level -= 1;
83
+ s->uart_status &= ~R_STATUS_RXFULL_MASK;
84
+ if (s->rx_level == 0) {
85
+ s->uart_status |= R_STATUS_RXIDLE_MASK;
86
+ s->uart_status |= R_STATUS_RXEMPTY_MASK;
87
+ }
88
}
89
break;
90
case R_WDATA:
91
@@ -XXX,XX +XXX,XX @@ static uint64_t ibex_uart_read(void *opaque, hwaddr addr,
92
case R_FIFO_STATUS:
93
retvalue = s->uart_fifo_status;
94
95
- retvalue |= s->tx_level & 0x1F;
96
+ retvalue |= (s->rx_level & 0x1F) << R_FIFO_STATUS_RXLVL_SHIFT;
97
+ retvalue |= (s->tx_level & 0x1F) << R_FIFO_STATUS_TXLVL_SHIFT;
98
99
qemu_log_mask(LOG_UNIMP,
100
"%s: RX fifos are not supported\n", __func__);
101
@@ -XXX,XX +XXX,XX @@ static void ibex_uart_write(void *opaque, hwaddr addr,
102
s->uart_fifo_ctrl = value;
103
104
if (value & R_FIFO_CTRL_RXRST_MASK) {
105
+ s->rx_level = 0;
106
qemu_log_mask(LOG_UNIMP,
107
"%s: RX fifos are not supported\n", __func__);
108
}
60
}
109
--
61
--
110
2.30.1
62
2.31.1
111
63
112
64
diff view generated by jsdifflib
1
From: Bin Meng <bin.meng@windriver.com>
1
From: Green Wan <green.wan@sifive.com>
2
2
3
Per SST25VF016B datasheet [1], SST flash requires a dummy byte after
3
Real PDMA is able to deal with non-multiple transaction size transactions.
4
the address bytes. Note only SPI mode is supported by SST flashes.
5
4
6
[1] http://ww1.microchip.com/downloads/en/devicedoc/s71271_04.pdf
5
The following result is PDMA tested in U-Boot on Unmatched board:
7
6
8
Signed-off-by: Bin Meng <bin.meng@windriver.com>
7
=> mw.l 0x3000000 0x0 <= Disclaim channel 0
9
Acked-by: Alistair Francis <alistair.francis@wdc.com>
8
=> mw.l 0x3000000 0x1 <= Claim channel 0
10
Message-id: 20210306060152.7250-1-bmeng.cn@gmail.com
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
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
36
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
37
---
13
hw/block/m25p80.c | 3 +++
38
hw/dma/sifive_pdma.c | 16 ++++++++++------
14
1 file changed, 3 insertions(+)
39
1 file changed, 10 insertions(+), 6 deletions(-)
15
40
16
diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
41
diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c
17
index XXXXXXX..XXXXXXX 100644
42
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/block/m25p80.c
43
--- a/hw/dma/sifive_pdma.c
19
+++ b/hw/block/m25p80.c
44
+++ b/hw/dma/sifive_pdma.c
20
@@ -XXX,XX +XXX,XX @@ static void decode_fast_read_cmd(Flash *s)
45
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch)
21
s->needed_bytes = get_addr_length(s);
46
uint64_t dst = s->chan[ch].next_dst;
22
switch (get_man(s)) {
47
uint64_t src = s->chan[ch].next_src;
23
/* Dummy cycles - modeled with bytes writes instead of bits */
48
uint32_t config = s->chan[ch].next_config;
24
+ case MAN_SST:
49
- int wsize, rsize, size;
25
+ s->needed_bytes += 1;
50
+ int wsize, rsize, size, remainder;
26
+ break;
51
uint8_t buf[64];
27
case MAN_WINBOND:
52
int n;
28
s->needed_bytes += 8;
53
29
break;
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;
30
--
82
--
31
2.30.1
83
2.31.1
32
84
33
85
diff view generated by jsdifflib
1
From: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
1
From: Frank Chang <frank.chang@sifive.com>
2
2
3
According to the specification the "field SPVP of hstatus controls the
3
Real PDMA doesn't set Control.error if there are 0 bytes to be
4
privilege level of the access" for the hypervisor virtual-machine load
4
transferred. The DMA transfer is still success.
5
and store instructions HLV, HLVX and HSV.
6
5
7
Signed-off-by: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
6
The following result is PDMA tested in U-Boot on Unmatched board:
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
9
Message-id: 20210311103005.1400718-1-georg.kotheimer@kernkonzept.com
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
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
35
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
---
36
---
12
target/riscv/cpu_helper.c | 25 ++++++++++++++-----------
37
hw/dma/sifive_pdma.c | 12 ++++++------
13
1 file changed, 14 insertions(+), 11 deletions(-)
38
1 file changed, 6 insertions(+), 6 deletions(-)
14
39
15
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
40
diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c
16
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
17
--- a/target/riscv/cpu_helper.c
42
--- a/hw/dma/sifive_pdma.c
18
+++ b/target/riscv/cpu_helper.c
43
+++ b/hw/dma/sifive_pdma.c
19
@@ -XXX,XX +XXX,XX @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
44
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch)
20
use_background = true;
45
46
/* do nothing if bytes to transfer is zero */
47
if (!bytes) {
48
- goto error;
49
+ goto done;
21
}
50
}
22
51
23
- if (mode == PRV_M && access_type != MMU_INST_FETCH) {
52
/*
24
+ /* MPRV does not affect the virtual-machine load/store
53
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch)
25
+ instructions, HLV, HLVX, and HSV. */
54
s->chan[ch].exec_bytes -= remainder;
26
+ if (riscv_cpu_two_stage_lookup(mmu_idx)) {
27
+ mode = get_field(env->hstatus, HSTATUS_SPVP);
28
+ } else if (mode == PRV_M && access_type != MMU_INST_FETCH) {
29
if (get_field(env->mstatus, MSTATUS_MPRV)) {
30
mode = get_field(env->mstatus, MSTATUS_MPP);
31
}
32
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
33
qemu_log_mask(CPU_LOG_MMU, "%s ad %" VADDR_PRIx " rw %d mmu_idx %d\n",
34
__func__, address, access_type, mmu_idx);
35
36
- if (mode == PRV_M && access_type != MMU_INST_FETCH) {
37
- if (get_field(env->mstatus, MSTATUS_MPRV)) {
38
- mode = get_field(env->mstatus, MSTATUS_MPP);
39
+ /* MPRV does not affect the virtual-machine load/store
40
+ instructions, HLV, HLVX, and HSV. */
41
+ if (riscv_cpu_two_stage_lookup(mmu_idx)) {
42
+ mode = get_field(env->hstatus, HSTATUS_SPVP);
43
+ } else if (mode == PRV_M && access_type != MMU_INST_FETCH &&
44
+ get_field(env->mstatus, MSTATUS_MPRV)) {
45
+ mode = get_field(env->mstatus, MSTATUS_MPP);
46
+ if (riscv_has_ext(env, RVH) && get_field(env->mstatus, MSTATUS_MPV)) {
47
+ two_stage_lookup = true;
48
}
49
}
55
}
50
56
51
- if (riscv_has_ext(env, RVH) && env->priv == PRV_M &&
57
- /* indicate a DMA transfer is done */
52
- access_type != MMU_INST_FETCH &&
58
- s->chan[ch].state = DMA_CHAN_STATE_DONE;
53
- get_field(env->mstatus, MSTATUS_MPRV) &&
59
- s->chan[ch].control &= ~CONTROL_RUN;
54
- get_field(env->mstatus, MSTATUS_MPV)) {
60
- s->chan[ch].control |= CONTROL_DONE;
55
- two_stage_lookup = true;
56
- }
57
-
61
-
58
if (riscv_cpu_virt_enabled(env) ||
62
/* reload exec_ registers if repeat is required */
59
((riscv_cpu_two_stage_lookup(mmu_idx) || two_stage_lookup) &&
63
if (s->chan[ch].next_config & CONFIG_REPEAT) {
60
access_type != MMU_INST_FETCH)) {
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:
61
--
77
--
62
2.30.1
78
2.31.1
63
79
64
80
diff view generated by jsdifflib
1
From: Jim Shu <cwshu@andestech.com>
1
From: Bin Meng <bmeng.cn@gmail.com>
2
2
3
If PMP permission of any address has been changed by updating PMP entry,
3
In U-Boot v2021.07 release, there were 2 major changes for the
4
flush all TLB pages to prevent from getting old permission.
4
SiFive Unleashed board support:
5
5
6
Signed-off-by: Jim Shu <cwshu@andestech.com>
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>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
16
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Message-id: 1613916082-19528-4-git-send-email-cwshu@andestech.com
17
Message-id: 20210911153431.10362-1-bmeng.cn@gmail.com
9
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
18
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
10
---
19
---
11
target/riscv/pmp.c | 4 ++++
20
docs/system/riscv/sifive_u.rst | 49 ++++++++++++++++++----------------
12
1 file changed, 4 insertions(+)
21
1 file changed, 26 insertions(+), 23 deletions(-)
13
22
14
diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
23
diff --git a/docs/system/riscv/sifive_u.rst b/docs/system/riscv/sifive_u.rst
15
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
16
--- a/target/riscv/pmp.c
25
--- a/docs/system/riscv/sifive_u.rst
17
+++ b/target/riscv/pmp.c
26
+++ b/docs/system/riscv/sifive_u.rst
18
@@ -XXX,XX +XXX,XX @@
27
@@ -XXX,XX +XXX,XX @@ command line options with ``qemu-system-riscv32``.
19
#include "qapi/error.h"
28
Running U-Boot
20
#include "cpu.h"
29
--------------
21
#include "trace.h"
30
22
+#include "exec/exec-all.h"
31
-U-Boot mainline v2021.01 release is tested at the time of writing. To build a
23
32
+U-Boot mainline v2021.07 release is tested at the time of writing. To build a
24
static void pmp_write_cfg(CPURISCVState *env, uint32_t addr_index,
33
U-Boot mainline bootloader that can be booted by the ``sifive_u`` machine, use
25
uint8_t val);
34
-the sifive_fu540_defconfig with similar commands as described above for Linux:
26
@@ -XXX,XX +XXX,XX @@ void pmpcfg_csr_write(CPURISCVState *env, uint32_t reg_index,
35
+the sifive_unleashed_defconfig with similar commands as described above for
27
cfg_val = (val >> 8 * i) & 0xff;
36
+Linux:
28
pmp_write_cfg(env, (reg_index * 4) + i, cfg_val);
37
29
}
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.
30
+
56
+
31
+ /* If PMP permission of any addr has been changed, flush TLB pages. */
57
+However sometimes we want to have a quick test of booting U-Boot on QEMU
32
+ tlb_flush(env_cpu(env));
58
+without the needs of preparing the SPI flash or SD card images, an alternate
33
}
59
+way can be used, which is to create a U-Boot S-mode image by modifying the
34
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:
35
115
36
--
116
--
37
2.30.1
117
2.31.1
38
118
39
119
diff view generated by jsdifflib
1
From: Jim Shu <cwshu@andestech.com>
1
From: Frank Chang <frank.chang@sifive.com>
2
2
3
Like MMU translation, add qemu log of PMP permission checking for
3
When virtual registers are swapped, mstatus.SD bit should also be
4
debugging.
4
backed up/restored. Otherwise, mstatus.SD bit will be incorrectly kept
5
across the world switches.
5
6
6
Signed-off-by: Jim Shu <cwshu@andestech.com>
7
Signed-off-by: Frank Chang <frank.chang@sifive.com>
8
Reviewed-by: Vincent Chen <vincent.chen@sifive.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Message-id: 1613916082-19528-3-git-send-email-cwshu@andestech.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
]
9
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
14
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
10
---
15
---
11
target/riscv/cpu_helper.c | 12 ++++++++++++
16
target/riscv/cpu_helper.c | 3 ++-
12
1 file changed, 12 insertions(+)
17
1 file changed, 2 insertions(+), 1 deletion(-)
13
18
14
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
19
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
15
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
16
--- a/target/riscv/cpu_helper.c
21
--- a/target/riscv/cpu_helper.c
17
+++ b/target/riscv/cpu_helper.c
22
+++ b/target/riscv/cpu_helper.c
18
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
23
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_fp_enabled(CPURISCVState *env)
19
if (ret == TRANSLATE_SUCCESS) {
24
20
ret = get_physical_address_pmp(env, &prot_pmp, &tlb_size, pa,
25
void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env)
21
size, access_type, mode);
26
{
22
+
27
+ uint64_t sd = riscv_cpu_is_32bit(env) ? MSTATUS32_SD : MSTATUS64_SD;
23
+ qemu_log_mask(CPU_LOG_MMU,
28
uint64_t mstatus_mask = MSTATUS_MXR | MSTATUS_SUM | MSTATUS_FS |
24
+ "%s PMP address=" TARGET_FMT_plx " ret %d prot"
29
MSTATUS_SPP | MSTATUS_SPIE | MSTATUS_SIE |
25
+ " %d tlb_size " TARGET_FMT_lu "\n",
30
- MSTATUS64_UXL;
26
+ __func__, pa, ret, prot_pmp, tlb_size);
31
+ MSTATUS64_UXL | sd;
27
+
32
bool current_virt = riscv_cpu_virt_enabled(env);
28
prot &= prot_pmp;
33
29
}
34
g_assert(riscv_has_ext(env, RVH));
30
31
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
32
if (ret == TRANSLATE_SUCCESS) {
33
ret = get_physical_address_pmp(env, &prot_pmp, &tlb_size, pa,
34
size, access_type, mode);
35
+
36
+ qemu_log_mask(CPU_LOG_MMU,
37
+ "%s PMP address=" TARGET_FMT_plx " ret %d prot"
38
+ " %d tlb_size " TARGET_FMT_lu "\n",
39
+ __func__, pa, ret, prot_pmp, tlb_size);
40
+
41
prot &= prot_pmp;
42
}
43
}
44
--
35
--
45
2.30.1
36
2.31.1
46
37
47
38
diff view generated by jsdifflib
1
From: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
1
From: Bin Meng <bmeng.cn@gmail.com>
2
2
3
Signed-off-by: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
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>
4
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
5
Message-id: 20210311094902.1377593-1-georg.kotheimer@kernkonzept.com
9
Message-id: 20210915084601.24304-1-bmeng.cn@gmail.com
6
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
7
---
11
---
8
target/riscv/csr.c | 7 ++++---
12
target/riscv/cpu_bits.h | 8 ++++----
9
1 file changed, 4 insertions(+), 3 deletions(-)
13
target/riscv/csr.c | 24 ++++++++++++------------
14
2 files changed, 16 insertions(+), 16 deletions(-)
10
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
11
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
35
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
12
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
13
--- a/target/riscv/csr.c
37
--- a/target/riscv/csr.c
14
+++ b/target/riscv/csr.c
38
+++ b/target/riscv/csr.c
15
@@ -XXX,XX +XXX,XX @@ static const target_ulong sstatus_v1_10_mask = SSTATUS_SIE | SSTATUS_SPIE |
39
@@ -XXX,XX +XXX,XX @@ static RISCVException ctr(CPURISCVState *env, int csrno)
16
SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS |
40
if (riscv_cpu_virt_enabled(env)) {
17
SSTATUS_SUM | SSTATUS_MXR | SSTATUS_SD;
41
switch (csrno) {
18
static const target_ulong sip_writable_mask = SIP_SSIP | MIP_USIP | MIP_UEIP;
42
case CSR_CYCLE:
19
-static const target_ulong hip_writable_mask = MIP_VSSIP | MIP_VSTIP | MIP_VSEIP;
43
- if (!get_field(env->hcounteren, HCOUNTEREN_CY) &&
20
+static const target_ulong hip_writable_mask = MIP_VSSIP;
44
- get_field(env->mcounteren, HCOUNTEREN_CY)) {
21
+static const target_ulong hvip_writable_mask = MIP_VSSIP | MIP_VSTIP | MIP_VSEIP;
45
+ if (!get_field(env->hcounteren, COUNTEREN_CY) &&
22
static const target_ulong vsip_writable_mask = MIP_VSSIP;
46
+ get_field(env->mcounteren, COUNTEREN_CY)) {
23
47
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
24
static const char valid_vm_1_10_32[16] = {
48
}
25
@@ -XXX,XX +XXX,XX @@ static int rmw_hvip(CPURISCVState *env, int csrno, target_ulong *ret_value,
49
break;
26
target_ulong new_value, target_ulong write_mask)
50
case CSR_TIME:
27
{
51
- if (!get_field(env->hcounteren, HCOUNTEREN_TM) &&
28
int ret = rmw_mip(env, 0, ret_value, new_value,
52
- get_field(env->mcounteren, HCOUNTEREN_TM)) {
29
- write_mask & hip_writable_mask);
53
+ if (!get_field(env->hcounteren, COUNTEREN_TM) &&
30
+ write_mask & hvip_writable_mask);
54
+ get_field(env->mcounteren, COUNTEREN_TM)) {
31
55
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
32
- *ret_value &= hip_writable_mask;
56
}
33
+ *ret_value &= hvip_writable_mask;
57
break;
34
58
case CSR_INSTRET:
35
return ret;
59
- if (!get_field(env->hcounteren, HCOUNTEREN_IR) &&
36
}
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;
37
--
93
--
38
2.30.1
94
2.31.1
39
95
40
96
diff view generated by jsdifflib
1
From: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
1
From: Alistair Francis <alistair.francis@wdc.com>
2
2
3
The current condition for the use of background registers only
3
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
4
considers the hypervisor load and store instructions,
4
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
5
but not accesses from M mode via MSTATUS_MPRV+MPV.
5
Message-id: d6cb4dfe75a2f536f217d7075b750ece3acb1535.1631767043.git.alistair.francis@wdc.com
6
7
Signed-off-by: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Message-id: 20210311103036.1401073-1-georg.kotheimer@kernkonzept.com
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
6
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
---
7
---
12
target/riscv/cpu_helper.c | 2 +-
8
hw/riscv/opentitan.c | 2 +-
13
1 file changed, 1 insertion(+), 1 deletion(-)
9
1 file changed, 1 insertion(+), 1 deletion(-)
14
10
15
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
11
diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
16
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
17
--- a/target/riscv/cpu_helper.c
13
--- a/hw/riscv/opentitan.c
18
+++ b/target/riscv/cpu_helper.c
14
+++ b/hw/riscv/opentitan.c
19
@@ -XXX,XX +XXX,XX @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
15
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry ibex_memmap[] = {
20
* was called. Background registers will be used if the guest has
16
[IBEX_DEV_TIMER] = { 0x40100000, 0x1000 },
21
* forced a two stage translation to be on (in HS or M mode).
17
[IBEX_DEV_SENSOR_CTRL] = { 0x40110000, 0x1000 },
22
*/
18
[IBEX_DEV_OTP_CTRL] = { 0x40130000, 0x4000 },
23
- if (!riscv_cpu_virt_enabled(env) && riscv_cpu_two_stage_lookup(mmu_idx)) {
19
+ [IBEX_DEV_USBDEV] = { 0x40150000, 0x1000 },
24
+ if (!riscv_cpu_virt_enabled(env) && two_stage) {
20
[IBEX_DEV_PWRMGR] = { 0x40400000, 0x1000 },
25
use_background = true;
21
[IBEX_DEV_RSTMGR] = { 0x40410000, 0x1000 },
26
}
22
[IBEX_DEV_CLKMGR] = { 0x40420000, 0x1000 },
27
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 },
28
--
29
--
29
2.30.1
30
2.31.1
30
31
31
32
diff view generated by jsdifflib