1
The following changes since commit 3c8c36c9087da957f580a9bb5ebf7814a753d1c6:
1
The following changes since commit c95bd5ff1660883d15ad6e0005e4c8571604f51a:
2
2
3
Merge remote-tracking branch 'remotes/kraxel/tags/ui-20201104-pull-request' into staging (2020-11-04 16:52:17 +0000)
3
Merge remote-tracking branch 'remotes/philmd/tags/mips-fixes-20210322' into staging (2021-03-22 14:26:13 +0000)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
git@github.com:alistair23/qemu.git tags/pull-riscv-to-apply-20201109
7
git@github.com:alistair23/qemu.git tags/pull-riscv-to-apply-20210322-2
8
8
9
for you to fetch changes up to 96338fefc19a143abdc91f6c44f37683274b08d4:
9
for you to fetch changes up to 9a27f69bd668d9d71674407badc412ce1231c7d5:
10
10
11
hw/intc/ibex_plic: Clear the claim register when read (2020-11-09 15:09:53 -0800)
11
target/riscv: Prevent lost illegal instruction exceptions (2021-03-22 21:54:40 -0400)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
This fixes two bugs in the RISC-V port. One is a bug in the
14
RISC-V PR for 6.0
15
Ibex PLIC, the other fixes the Hypvervisor access functions.
15
16
This PR includes:
17
- Fix for vector CSR access
18
- Improvements to the Ibex UART device
19
- PMP improvements and bug fixes
20
- Hypervisor extension bug fixes
21
- ramfb support for the virt machine
22
- Fast read support for SST flash
23
- Improvements to the microchip_pfsoc machine
16
24
17
----------------------------------------------------------------
25
----------------------------------------------------------------
18
Alistair Francis (6):
26
Alexander Wagner (1):
19
target/riscv: Add a virtualised MMU Mode
27
hw/char: disable ibex uart receive if the buffer is full
20
target/riscv: Set the virtualised MMU mode when doing hyp accesses
21
target/riscv: Remove the HS_TWO_STAGE flag
22
target/riscv: Remove the hyp load and store functions
23
target/riscv: Split the Hypervisor execute load helpers
24
hw/intc/ibex_plic: Clear the claim register when read
25
28
26
target/riscv/cpu-param.h | 11 ++-
29
Asherah Connor (2):
27
target/riscv/cpu.h | 19 ++++-
30
hw/riscv: Add fw_cfg support to virt
28
target/riscv/cpu_bits.h | 1 -
31
hw/riscv: allow ramfb on virt
29
target/riscv/helper.h | 5 +-
30
hw/intc/ibex_plic.c | 3 +
31
target/riscv/cpu_helper.c | 62 ++++++--------
32
target/riscv/op_helper.c | 124 ++-------------------------
33
target/riscv/translate.c | 2 +
34
target/riscv/insn_trans/trans_rvh.c.inc | 143 ++++++++++++--------------------
35
9 files changed, 115 insertions(+), 255 deletions(-)
36
32
33
Bin Meng (3):
34
hw/block: m25p80: Support fast read for SST flashes
35
hw/riscv: microchip_pfsoc: Map EMMC/SD mux register
36
docs/system: riscv: Add documentation for 'microchip-icicle-kit' machine
37
38
Frank Chang (1):
39
target/riscv: fix vs() to return proper error code
40
41
Georg Kotheimer (6):
42
target/riscv: Adjust privilege level for HLV(X)/HSV instructions
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
49
Jim Shu (3):
50
target/riscv: propagate PMP permission to TLB page
51
target/riscv: add log of PMP permission checking
52
target/riscv: flush TLB pages if PMP permission has been changed
53
54
docs/system/riscv/microchip-icicle-kit.rst | 89 ++++++++++++++
55
docs/system/target-riscv.rst | 1 +
56
include/hw/char/ibex_uart.h | 4 +
57
include/hw/riscv/microchip_pfsoc.h | 1 +
58
include/hw/riscv/virt.h | 2 +
59
target/riscv/cpu.h | 4 +
60
target/riscv/pmp.h | 4 +-
61
hw/block/m25p80.c | 3 +
62
hw/char/ibex_uart.c | 23 +++-
63
hw/riscv/microchip_pfsoc.c | 6 +
64
hw/riscv/virt.c | 33 ++++++
65
target/riscv/cpu.c | 1 +
66
target/riscv/cpu_helper.c | 144 +++++++++++++++--------
67
target/riscv/csr.c | 77 +++++++------
68
target/riscv/pmp.c | 84 ++++++++++----
69
target/riscv/translate.c | 179 +----------------------------
70
hw/riscv/Kconfig | 1 +
71
17 files changed, 367 insertions(+), 289 deletions(-)
72
create mode 100644 docs/system/riscv/microchip-icicle-kit.rst
73
diff view generated by jsdifflib
New patch
1
From: Frank Chang <frank.chang@sifive.com>
1
2
3
vs() should return -RISCV_EXCP_ILLEGAL_INST instead of -1 if rvv feature
4
is not enabled.
5
6
If -1 is returned, exception will be raised and cs->exception_index will
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
10
Signed-off-by: Frank Chang <frank.chang@sifive.com>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
13
Message-id: 20210223065935.20208-1-frank.chang@sifive.com
14
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
15
---
16
target/riscv/csr.c | 2 +-
17
1 file changed, 1 insertion(+), 1 deletion(-)
18
19
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/riscv/csr.c
22
+++ b/target/riscv/csr.c
23
@@ -XXX,XX +XXX,XX @@ static int vs(CPURISCVState *env, int csrno)
24
if (env->misa & RVV) {
25
return 0;
26
}
27
- return -1;
28
+ return -RISCV_EXCP_ILLEGAL_INST;
29
}
30
31
static int ctr(CPURISCVState *env, int csrno)
32
--
33
2.30.1
34
35
diff view generated by jsdifflib
New patch
1
From: Alexander Wagner <alexander.wagner@ulal.de>
1
2
3
Not disabling the UART leads to QEMU overwriting the UART receive buffer with
4
the newest received byte. The rx_level variable is added to allow the use of
5
the existing OpenTitan driver libraries.
6
7
Signed-off-by: Alexander Wagner <alexander.wagner@ulal.de>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Message-id: 20210309152130.13038-1-alexander.wagner@ulal.de
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
---
12
include/hw/char/ibex_uart.h | 4 ++++
13
hw/char/ibex_uart.c | 23 ++++++++++++++++++-----
14
2 files changed, 22 insertions(+), 5 deletions(-)
15
16
diff --git a/include/hw/char/ibex_uart.h b/include/hw/char/ibex_uart.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/char/ibex_uart.h
19
+++ b/include/hw/char/ibex_uart.h
20
@@ -XXX,XX +XXX,XX @@ REG32(FIFO_CTRL, 0x1c)
21
FIELD(FIFO_CTRL, RXILVL, 2, 3)
22
FIELD(FIFO_CTRL, TXILVL, 5, 2)
23
REG32(FIFO_STATUS, 0x20)
24
+ FIELD(FIFO_STATUS, TXLVL, 0, 5)
25
+ FIELD(FIFO_STATUS, RXLVL, 16, 5)
26
REG32(OVRD, 0x24)
27
REG32(VAL, 0x28)
28
REG32(TIMEOUT_CTRL, 0x2c)
29
@@ -XXX,XX +XXX,XX @@ struct IbexUartState {
30
uint8_t tx_fifo[IBEX_UART_TX_FIFO_SIZE];
31
uint32_t tx_level;
32
33
+ uint32_t rx_level;
34
+
35
QEMUTimer *fifo_trigger_handle;
36
uint64_t char_tx_time;
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
}
109
--
110
2.30.1
111
112
diff view generated by jsdifflib
New patch
1
1
From: Jim Shu <cwshu@andestech.com>
2
3
Currently, PMP permission checking of TLB page is bypassed if TLB hits
4
Fix it by propagating PMP permission to TLB page permission.
5
6
PMP permission checking also use MMU-style API to change TLB permission
7
and size.
8
9
Signed-off-by: Jim Shu <cwshu@andestech.com>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
11
Message-id: 1613916082-19528-2-git-send-email-cwshu@andestech.com
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
14
target/riscv/pmp.h | 4 +-
15
target/riscv/cpu_helper.c | 84 +++++++++++++++++++++++++++++----------
16
target/riscv/pmp.c | 80 +++++++++++++++++++++++++++----------
17
3 files changed, 125 insertions(+), 43 deletions(-)
18
19
diff --git a/target/riscv/pmp.h b/target/riscv/pmp.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/riscv/pmp.h
22
+++ b/target/riscv/pmp.h
23
@@ -XXX,XX +XXX,XX @@ void pmpaddr_csr_write(CPURISCVState *env, uint32_t addr_index,
24
target_ulong val);
25
target_ulong pmpaddr_csr_read(CPURISCVState *env, uint32_t addr_index);
26
bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr,
27
- target_ulong size, pmp_priv_t priv, target_ulong mode);
28
+ target_ulong size, pmp_priv_t privs, pmp_priv_t *allowed_privs,
29
+ target_ulong mode);
30
bool pmp_is_range_in_tlb(CPURISCVState *env, hwaddr tlb_sa,
31
target_ulong *tlb_size);
32
void pmp_update_rule_addr(CPURISCVState *env, uint32_t pmp_index);
33
void pmp_update_rule_nums(CPURISCVState *env);
34
uint32_t pmp_get_num_rules(CPURISCVState *env);
35
+int pmp_priv_to_page_prot(pmp_priv_t pmp_priv);
36
37
#endif
38
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/riscv/cpu_helper.c
41
+++ b/target/riscv/cpu_helper.c
42
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
43
env->load_res = -1;
44
}
45
46
+/*
47
+ * get_physical_address_pmp - check PMP permission for this physical address
48
+ *
49
+ * Match the PMP region and check permission for this physical address and it's
50
+ * TLB page. Returns 0 if the permission checking was successful
51
+ *
52
+ * @env: CPURISCVState
53
+ * @prot: The returned protection attributes
54
+ * @tlb_size: TLB page size containing addr. It could be modified after PMP
55
+ * permission checking. NULL if not set TLB page for addr.
56
+ * @addr: The physical address to be checked permission
57
+ * @access_type: The type of MMU access
58
+ * @mode: Indicates current privilege level.
59
+ */
60
+static int get_physical_address_pmp(CPURISCVState *env, int *prot,
61
+ target_ulong *tlb_size, hwaddr addr,
62
+ int size, MMUAccessType access_type,
63
+ int mode)
64
+{
65
+ pmp_priv_t pmp_priv;
66
+ target_ulong tlb_size_pmp = 0;
67
+
68
+ if (!riscv_feature(env, RISCV_FEATURE_PMP)) {
69
+ *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
70
+ return TRANSLATE_SUCCESS;
71
+ }
72
+
73
+ if (!pmp_hart_has_privs(env, addr, size, 1 << access_type, &pmp_priv,
74
+ mode)) {
75
+ *prot = 0;
76
+ return TRANSLATE_PMP_FAIL;
77
+ }
78
+
79
+ *prot = pmp_priv_to_page_prot(pmp_priv);
80
+ if (tlb_size != NULL) {
81
+ if (pmp_is_range_in_tlb(env, addr & ~(*tlb_size - 1), &tlb_size_pmp)) {
82
+ *tlb_size = tlb_size_pmp;
83
+ }
84
+ }
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
}
180
181
+/*
182
+ * Check if the address has required RWX privs when no PMP entry is matched.
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
{
221
int i = 0;
222
int ret = -1;
223
int pmp_size = 0;
224
target_ulong s = 0;
225
target_ulong e = 0;
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
}
275
276
-
277
/*
278
* Handle a write to a pmpcfg CSP
279
*/
280
@@ -XXX,XX +XXX,XX @@ bool pmp_is_range_in_tlb(CPURISCVState *env, hwaddr tlb_sa,
281
282
return false;
283
}
284
+
285
+/*
286
+ * Convert PMP privilege to TLB page privilege.
287
+ */
288
+int pmp_priv_to_page_prot(pmp_priv_t pmp_priv)
289
+{
290
+ int prot = 0;
291
+
292
+ if (pmp_priv & PMP_READ) {
293
+ prot |= PAGE_READ;
294
+ }
295
+ if (pmp_priv & PMP_WRITE) {
296
+ prot |= PAGE_WRITE;
297
+ }
298
+ if (pmp_priv & PMP_EXEC) {
299
+ prot |= PAGE_EXEC;
300
+ }
301
+
302
+ return prot;
303
+}
304
--
305
2.30.1
306
307
diff view generated by jsdifflib
New patch
1
From: Jim Shu <cwshu@andestech.com>
1
2
3
Like MMU translation, add qemu log of PMP permission checking for
4
debugging.
5
6
Signed-off-by: Jim Shu <cwshu@andestech.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Message-id: 1613916082-19528-3-git-send-email-cwshu@andestech.com
9
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
10
---
11
target/riscv/cpu_helper.c | 12 ++++++++++++
12
1 file changed, 12 insertions(+)
13
14
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/riscv/cpu_helper.c
17
+++ b/target/riscv/cpu_helper.c
18
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
19
if (ret == TRANSLATE_SUCCESS) {
20
ret = get_physical_address_pmp(env, &prot_pmp, &tlb_size, pa,
21
size, access_type, mode);
22
+
23
+ qemu_log_mask(CPU_LOG_MMU,
24
+ "%s PMP address=" TARGET_FMT_plx " ret %d prot"
25
+ " %d tlb_size " TARGET_FMT_lu "\n",
26
+ __func__, pa, ret, prot_pmp, tlb_size);
27
+
28
prot &= prot_pmp;
29
}
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
--
45
2.30.1
46
47
diff view generated by jsdifflib
New patch
1
From: Jim Shu <cwshu@andestech.com>
1
2
3
If PMP permission of any address has been changed by updating PMP entry,
4
flush all TLB pages to prevent from getting old permission.
5
6
Signed-off-by: Jim Shu <cwshu@andestech.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Message-id: 1613916082-19528-4-git-send-email-cwshu@andestech.com
9
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
10
---
11
target/riscv/pmp.c | 4 ++++
12
1 file changed, 4 insertions(+)
13
14
diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/riscv/pmp.c
17
+++ b/target/riscv/pmp.c
18
@@ -XXX,XX +XXX,XX @@
19
#include "qapi/error.h"
20
#include "cpu.h"
21
#include "trace.h"
22
+#include "exec/exec-all.h"
23
24
static void pmp_write_cfg(CPURISCVState *env, uint32_t addr_index,
25
uint8_t val);
26
@@ -XXX,XX +XXX,XX @@ void pmpcfg_csr_write(CPURISCVState *env, uint32_t reg_index,
27
cfg_val = (val >> 8 * i) & 0xff;
28
pmp_write_cfg(env, (reg_index * 4) + i, cfg_val);
29
}
30
+
31
+ /* If PMP permission of any addr has been changed, flush TLB pages. */
32
+ tlb_flush(env_cpu(env));
33
}
34
35
36
--
37
2.30.1
38
39
diff view generated by jsdifflib
New patch
1
From: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
1
2
3
According to the specification the "field SPVP of hstatus controls the
4
privilege level of the access" for the hypervisor virtual-machine load
5
and store instructions HLV, HLVX and HSV.
6
7
Signed-off-by: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Message-id: 20210311103005.1400718-1-georg.kotheimer@kernkonzept.com
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
---
12
target/riscv/cpu_helper.c | 25 ++++++++++++++-----------
13
1 file changed, 14 insertions(+), 11 deletions(-)
14
15
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/riscv/cpu_helper.c
18
+++ b/target/riscv/cpu_helper.c
19
@@ -XXX,XX +XXX,XX @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
20
use_background = true;
21
}
22
23
- if (mode == PRV_M && access_type != MMU_INST_FETCH) {
24
+ /* MPRV does not affect the virtual-machine load/store
25
+ instructions, HLV, HLVX, and HSV. */
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
}
50
51
- if (riscv_has_ext(env, RVH) && env->priv == PRV_M &&
52
- access_type != MMU_INST_FETCH &&
53
- get_field(env->mstatus, MSTATUS_MPRV) &&
54
- get_field(env->mstatus, MSTATUS_MPV)) {
55
- two_stage_lookup = true;
56
- }
57
-
58
if (riscv_cpu_virt_enabled(env) ||
59
((riscv_cpu_two_stage_lookup(mmu_idx) || two_stage_lookup) &&
60
access_type != MMU_INST_FETCH)) {
61
--
62
2.30.1
63
64
diff view generated by jsdifflib
New patch
1
From: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
1
2
3
Signed-off-by: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
4
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
5
Message-id: 20210311094902.1377593-1-georg.kotheimer@kernkonzept.com
6
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
7
---
8
target/riscv/csr.c | 7 ++++---
9
1 file changed, 4 insertions(+), 3 deletions(-)
10
11
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/riscv/csr.c
14
+++ b/target/riscv/csr.c
15
@@ -XXX,XX +XXX,XX @@ static const target_ulong sstatus_v1_10_mask = SSTATUS_SIE | SSTATUS_SPIE |
16
SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS |
17
SSTATUS_SUM | SSTATUS_MXR | SSTATUS_SD;
18
static const target_ulong sip_writable_mask = SIP_SSIP | MIP_USIP | MIP_UEIP;
19
-static const target_ulong hip_writable_mask = MIP_VSSIP | MIP_VSTIP | MIP_VSEIP;
20
+static const target_ulong hip_writable_mask = MIP_VSSIP;
21
+static const target_ulong hvip_writable_mask = MIP_VSSIP | MIP_VSTIP | MIP_VSEIP;
22
static const target_ulong vsip_writable_mask = MIP_VSSIP;
23
24
static const char valid_vm_1_10_32[16] = {
25
@@ -XXX,XX +XXX,XX @@ static int rmw_hvip(CPURISCVState *env, int csrno, target_ulong *ret_value,
26
target_ulong new_value, target_ulong write_mask)
27
{
28
int ret = rmw_mip(env, 0, ret_value, new_value,
29
- write_mask & hip_writable_mask);
30
+ write_mask & hvip_writable_mask);
31
32
- *ret_value &= hip_writable_mask;
33
+ *ret_value &= hvip_writable_mask;
34
35
return ret;
36
}
37
--
38
2.30.1
39
40
diff view generated by jsdifflib
1
Add a new MMU mode that includes the current virt mode.
1
From: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
2
2
3
The current condition for the use of background registers only
4
considers the hypervisor load and store instructions,
5
but not accesses from M mode via MSTATUS_MPRV+MPV.
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
3
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 4b301bc0ea36da962fc1605371b65019ac3073df.1604464950.git.alistair.francis@wdc.com
6
---
11
---
7
target/riscv/cpu-param.h | 11 ++++++++++-
12
target/riscv/cpu_helper.c | 2 +-
8
target/riscv/cpu.h | 4 +++-
13
1 file changed, 1 insertion(+), 1 deletion(-)
9
target/riscv/cpu_helper.c | 2 +-
10
3 files changed, 14 insertions(+), 3 deletions(-)
11
14
12
diff --git a/target/riscv/cpu-param.h b/target/riscv/cpu-param.h
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/riscv/cpu-param.h
15
+++ b/target/riscv/cpu-param.h
16
@@ -XXX,XX +XXX,XX @@
17
# define TARGET_VIRT_ADDR_SPACE_BITS 32 /* sv32 */
18
#endif
19
#define TARGET_PAGE_BITS 12 /* 4 KiB Pages */
20
-#define NB_MMU_MODES 4
21
+/*
22
+ * The current MMU Modes are:
23
+ * - U mode 0b000
24
+ * - S mode 0b001
25
+ * - M mode 0b011
26
+ * - U mode HLV/HLVX/HSV 0b100
27
+ * - S mode HLV/HLVX/HSV 0b101
28
+ * - M mode HLV/HLVX/HSV 0b111
29
+ */
30
+#define NB_MMU_MODES 8
31
32
#endif
33
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/riscv/cpu.h
36
+++ b/target/riscv/cpu.h
37
@@ -XXX,XX +XXX,XX @@ void QEMU_NORETURN riscv_raise_exception(CPURISCVState *env,
38
target_ulong riscv_cpu_get_fflags(CPURISCVState *env);
39
void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong);
40
41
-#define TB_FLAGS_MMU_MASK 3
42
+#define TB_FLAGS_MMU_MASK 7
43
+#define TB_FLAGS_PRIV_MMU_MASK 3
44
+#define TB_FLAGS_PRIV_HYP_ACCESS_MASK (1 << 2)
45
#define TB_FLAGS_MSTATUS_FS MSTATUS_FS
46
47
typedef CPURISCVState CPUArchState;
48
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
15
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
49
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
50
--- a/target/riscv/cpu_helper.c
17
--- a/target/riscv/cpu_helper.c
51
+++ b/target/riscv/cpu_helper.c
18
+++ b/target/riscv/cpu_helper.c
52
@@ -XXX,XX +XXX,XX @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
19
@@ -XXX,XX +XXX,XX @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
53
* (riscv_cpu_do_interrupt) is correct */
20
* was called. Background registers will be used if the guest has
54
MemTxResult res;
21
* forced a two stage translation to be on (in HS or M mode).
55
MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
22
*/
56
- int mode = mmu_idx;
23
- if (!riscv_cpu_virt_enabled(env) && riscv_cpu_two_stage_lookup(mmu_idx)) {
57
+ int mode = mmu_idx & TB_FLAGS_PRIV_MMU_MASK;
24
+ if (!riscv_cpu_virt_enabled(env) && two_stage) {
58
bool use_background = false;
25
use_background = true;
59
26
}
60
/*
27
61
--
28
--
62
2.29.2
29
2.30.1
63
30
64
31
diff view generated by jsdifflib
New patch
1
From: Asherah Connor <ashe@kivikakk.ee>
1
2
3
Provides fw_cfg for the virt machine on riscv. This enables
4
using e.g. ramfb later.
5
6
Signed-off-by: Asherah Connor <ashe@kivikakk.ee>
7
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Message-id: 20210318235041.17175-2-ashe@kivikakk.ee
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
---
12
include/hw/riscv/virt.h | 2 ++
13
hw/riscv/virt.c | 30 ++++++++++++++++++++++++++++++
14
hw/riscv/Kconfig | 1 +
15
3 files changed, 33 insertions(+)
16
17
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/riscv/virt.h
20
+++ b/include/hw/riscv/virt.h
21
@@ -XXX,XX +XXX,XX @@ struct RISCVVirtState {
22
RISCVHartArrayState soc[VIRT_SOCKETS_MAX];
23
DeviceState *plic[VIRT_SOCKETS_MAX];
24
PFlashCFI01 *flash[2];
25
+ FWCfgState *fw_cfg;
26
27
int fdt_size;
28
};
29
@@ -XXX,XX +XXX,XX @@ enum {
30
VIRT_PLIC,
31
VIRT_UART0,
32
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
38
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/riscv/virt.c
40
+++ b/hw/riscv/virt.c
41
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry virt_memmap[] = {
42
[VIRT_PLIC] = { 0xc000000, VIRT_PLIC_SIZE(VIRT_CPUS_MAX * 2) },
43
[VIRT_UART0] = { 0x10000000, 0x100 },
44
[VIRT_VIRTIO] = { 0x10001000, 0x1000 },
45
+ [VIRT_FW_CFG] = { 0x10100000, 0x18 },
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
}
52
53
+static FWCfgState *create_fw_cfg(const MachineState *mc)
54
+{
55
+ hwaddr base = virt_memmap[VIRT_FW_CFG].base;
56
+ hwaddr size = virt_memmap[VIRT_FW_CFG].size;
57
+ FWCfgState *fw_cfg;
58
+ char *nodename;
59
+
60
+ fw_cfg = fw_cfg_init_mem_wide(base + 8, base, 8, base + 16,
61
+ &address_space_memory);
62
+ fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)mc->smp.cpus);
63
+
64
+ nodename = g_strdup_printf("/fw-cfg@%" PRIx64, base);
65
+ qemu_fdt_add_subnode(mc->fdt, nodename);
66
+ qemu_fdt_setprop_string(mc->fdt, nodename,
67
+ "compatible", "qemu,fw-cfg-mmio");
68
+ qemu_fdt_setprop_sized_cells(mc->fdt, nodename, "reg",
69
+ 2, base, 2, size);
70
+ qemu_fdt_setprop(mc->fdt, nodename, "dma-coherent", NULL, 0);
71
+ g_free(nodename);
72
+ return fw_cfg;
73
+}
74
+
75
static void virt_machine_init(MachineState *machine)
76
{
77
const MemMapEntry *memmap = virt_memmap;
78
@@ -XXX,XX +XXX,XX @@ static void virt_machine_init(MachineState *machine)
79
start_addr = virt_memmap[VIRT_FLASH].base;
80
}
81
82
+ /*
83
+ * Init fw_cfg. Must be done before riscv_load_fdt, otherwise the device
84
+ * tree cannot be altered and we get FDT_ERR_NOSPACE.
85
+ */
86
+ s->fw_cfg = create_fw_cfg(machine);
87
+ rom_set_fw(s->fw_cfg);
88
+
89
/* Compute the fdt load address in dram */
90
fdt_load_addr = riscv_load_fdt(memmap[VIRT_DRAM].base,
91
machine->ram_size, machine->fdt);
92
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
93
index XXXXXXX..XXXXXXX 100644
94
--- a/hw/riscv/Kconfig
95
+++ b/hw/riscv/Kconfig
96
@@ -XXX,XX +XXX,XX @@ config RISCV_VIRT
97
select SIFIVE_PLIC
98
select SIFIVE_TEST
99
select VIRTIO_MMIO
100
+ select FW_CFG_DMA
101
102
config SIFIVE_E
103
bool
104
--
105
2.30.1
106
107
diff view generated by jsdifflib
1
Split the hypervisor execute load functions into two seperate functions.
1
From: Asherah Connor <ashe@kivikakk.ee>
2
This avoids us having to pass the memop to the C helper functions.
3
2
3
Allow ramfb on virt. This lets `-device ramfb' work.
4
5
Signed-off-by: Asherah Connor <ashe@kivikakk.ee>
6
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Message-id: 20210318235041.17175-3-ashe@kivikakk.ee
4
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
9
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 5b1550f0faa3c435cc77f3c1ae811dea98ab9e36.1604464950.git.alistair.francis@wdc.com
7
---
10
---
8
target/riscv/helper.h | 3 ++-
11
hw/riscv/virt.c | 3 +++
9
target/riscv/op_helper.c | 36 +++++++------------------
12
1 file changed, 3 insertions(+)
10
target/riscv/insn_trans/trans_rvh.c.inc | 20 +++++---------
11
3 files changed, 17 insertions(+), 42 deletions(-)
12
13
13
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
14
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/target/riscv/helper.h
16
--- a/hw/riscv/virt.c
16
+++ b/target/riscv/helper.h
17
+++ b/hw/riscv/virt.c
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_1(tlb_flush, void, env)
18
@@ -XXX,XX +XXX,XX @@
18
#ifndef CONFIG_USER_ONLY
19
#include "sysemu/sysemu.h"
19
DEF_HELPER_1(hyp_tlb_flush, void, env)
20
#include "hw/pci/pci.h"
20
DEF_HELPER_1(hyp_gvma_tlb_flush, void, env)
21
#include "hw/pci-host/gpex.h"
21
-DEF_HELPER_4(hyp_x_load, tl, env, tl, tl, tl)
22
+#include "hw/display/ramfb.h"
22
+DEF_HELPER_2(hyp_hlvx_hu, tl, env, tl)
23
23
+DEF_HELPER_2(hyp_hlvx_wu, tl, env, tl)
24
static const MemMapEntry virt_memmap[] = {
24
#endif
25
[VIRT_DEBUG] = { 0x0, 0x100 },
25
26
@@ -XXX,XX +XXX,XX @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
26
/* Vector functions */
27
mc->cpu_index_to_instance_props = riscv_numa_cpu_index_to_props;
27
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
28
mc->get_default_cpu_node_id = riscv_numa_get_default_cpu_node_id;
28
index XXXXXXX..XXXXXXX 100644
29
mc->numa_mem_supported = true;
29
--- a/target/riscv/op_helper.c
30
+
30
+++ b/target/riscv/op_helper.c
31
+ machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
31
@@ -XXX,XX +XXX,XX @@ void helper_hyp_gvma_tlb_flush(CPURISCVState *env)
32
helper_hyp_tlb_flush(env);
33
}
32
}
34
33
35
-target_ulong helper_hyp_x_load(CPURISCVState *env, target_ulong address,
34
static const TypeInfo virt_machine_typeinfo = {
36
- target_ulong attrs, target_ulong memop)
37
+target_ulong helper_hyp_hlvx_hu(CPURISCVState *env, target_ulong address)
38
{
39
- if (env->priv == PRV_M ||
40
- (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) ||
41
- (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) &&
42
- get_field(env->hstatus, HSTATUS_HU))) {
43
- target_ulong pte;
44
- int mmu_idx = cpu_mmu_index(env, false) | TB_FLAGS_PRIV_HYP_ACCESS_MASK;
45
-
46
- switch (memop) {
47
- case MO_TEUW:
48
- pte = cpu_lduw_mmuidx_ra(env, address, mmu_idx, GETPC());
49
- break;
50
- case MO_TEUL:
51
- pte = cpu_ldl_mmuidx_ra(env, address, mmu_idx, GETPC());
52
- break;
53
- default:
54
- g_assert_not_reached();
55
- }
56
+ int mmu_idx = cpu_mmu_index(env, true) | TB_FLAGS_PRIV_HYP_ACCESS_MASK;
57
58
- return pte;
59
- }
60
+ return cpu_lduw_mmuidx_ra(env, address, mmu_idx, GETPC());
61
+}
62
63
- if (riscv_cpu_virt_enabled(env)) {
64
- riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC());
65
- } else {
66
- riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
67
- }
68
- return 0;
69
+target_ulong helper_hyp_hlvx_wu(CPURISCVState *env, target_ulong address)
70
+{
71
+ int mmu_idx = cpu_mmu_index(env, true) | TB_FLAGS_PRIV_HYP_ACCESS_MASK;
72
+
73
+ return cpu_ldl_mmuidx_ra(env, address, mmu_idx, GETPC());
74
}
75
76
#endif /* !CONFIG_USER_ONLY */
77
diff --git a/target/riscv/insn_trans/trans_rvh.c.inc b/target/riscv/insn_trans/trans_rvh.c.inc
78
index XXXXXXX..XXXXXXX 100644
79
--- a/target/riscv/insn_trans/trans_rvh.c.inc
80
+++ b/target/riscv/insn_trans/trans_rvh.c.inc
81
@@ -XXX,XX +XXX,XX @@ static bool trans_hlvx_hu(DisasContext *ctx, arg_hlvx_hu *a)
82
#ifndef CONFIG_USER_ONLY
83
TCGv t0 = tcg_temp_new();
84
TCGv t1 = tcg_temp_new();
85
- TCGv mem_idx = tcg_temp_new();
86
- TCGv memop = tcg_temp_new();
87
+
88
+ check_access(ctx);
89
90
gen_get_gpr(t0, a->rs1);
91
- tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
92
- tcg_gen_movi_tl(memop, MO_TEUW);
93
94
- gen_helper_hyp_x_load(t1, cpu_env, t0, mem_idx, memop);
95
+ gen_helper_hyp_hlvx_hu(t1, cpu_env, t0);
96
gen_set_gpr(a->rd, t1);
97
98
tcg_temp_free(t0);
99
tcg_temp_free(t1);
100
- tcg_temp_free(mem_idx);
101
- tcg_temp_free(memop);
102
return true;
103
#else
104
return false;
105
@@ -XXX,XX +XXX,XX @@ static bool trans_hlvx_wu(DisasContext *ctx, arg_hlvx_wu *a)
106
#ifndef CONFIG_USER_ONLY
107
TCGv t0 = tcg_temp_new();
108
TCGv t1 = tcg_temp_new();
109
- TCGv mem_idx = tcg_temp_new();
110
- TCGv memop = tcg_temp_new();
111
+
112
+ check_access(ctx);
113
114
gen_get_gpr(t0, a->rs1);
115
- tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
116
- tcg_gen_movi_tl(memop, MO_TEUL);
117
118
- gen_helper_hyp_x_load(t1, cpu_env, t0, mem_idx, memop);
119
+ gen_helper_hyp_hlvx_wu(t1, cpu_env, t0);
120
gen_set_gpr(a->rd, t1);
121
122
tcg_temp_free(t0);
123
tcg_temp_free(t1);
124
- tcg_temp_free(mem_idx);
125
- tcg_temp_free(memop);
126
return true;
127
#else
128
return false;
129
--
35
--
130
2.29.2
36
2.30.1
131
37
132
38
diff view generated by jsdifflib
1
Remove the special Virtulisation load and store functions and just use
1
From: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
2
the standard tcg tcg_gen_qemu_ld_tl() and tcg_gen_qemu_st_tl() functions
3
instead.
4
2
5
As part of this change we ensure we still run an access check to make
3
The previous implementation was broken in many ways:
6
sure we can perform the operations.
4
- Used mideleg instead of hideleg to mask accesses
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
7
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
8
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 189ac3e53ef2854824d18aad7074c6649f17de2c.1604464950.git.alistair.francis@wdc.com
11
---
12
---
12
target/riscv/cpu.h | 12 +++
13
target/riscv/csr.c | 68 +++++++++++++++++++++++-----------------------
13
target/riscv/helper.h | 2 -
14
1 file changed, 34 insertions(+), 34 deletions(-)
14
target/riscv/op_helper.c | 86 -----------------
15
target/riscv/translate.c | 2 +
16
target/riscv/insn_trans/trans_rvh.c.inc | 123 +++++++++---------------
17
5 files changed, 59 insertions(+), 166 deletions(-)
18
15
19
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
16
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
20
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
21
--- a/target/riscv/cpu.h
18
--- a/target/riscv/csr.c
22
+++ b/target/riscv/cpu.h
19
+++ b/target/riscv/csr.c
23
@@ -XXX,XX +XXX,XX @@ FIELD(TB_FLAGS, VL_EQ_VLMAX, 2, 1)
20
@@ -XXX,XX +XXX,XX @@ static int write_sstatus(CPURISCVState *env, int csrno, target_ulong val)
24
FIELD(TB_FLAGS, LMUL, 3, 2)
21
return write_mstatus(env, CSR_MSTATUS, newval);
25
FIELD(TB_FLAGS, SEW, 5, 3)
22
}
26
FIELD(TB_FLAGS, VILL, 8, 1)
23
27
+/* Is a Hypervisor instruction load/store allowed? */
24
+static int read_vsie(CPURISCVState *env, int csrno, target_ulong *val)
28
+FIELD(TB_FLAGS, HLSX, 9, 1)
25
+{
29
26
+ /* Shift the VS bits to their S bit location in vsie */
30
/*
27
+ *val = (env->mie & env->hideleg & VS_MODE_INTERRUPTS) >> 1;
31
* A simplification for VLMAX
28
+ return 0;
32
@@ -XXX,XX +XXX,XX @@ static inline void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
29
+}
33
if (riscv_cpu_fp_enabled(env)) {
30
+
34
flags |= env->mstatus & MSTATUS_FS;
31
static int read_sie(CPURISCVState *env, int csrno, target_ulong *val)
32
{
33
if (riscv_cpu_virt_enabled(env)) {
34
- /* Tell the guest the VS bits, shifted to the S bit locations */
35
- *val = (env->mie & env->mideleg & VS_MODE_INTERRUPTS) >> 1;
36
+ read_vsie(env, CSR_VSIE, val);
37
} else {
38
*val = env->mie & env->mideleg;
35
}
39
}
40
return 0;
41
}
42
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
+}
36
+
87
+
37
+ if (riscv_has_ext(env, RVH)) {
88
static int rmw_sip(CPURISCVState *env, int csrno, target_ulong *ret_value,
38
+ if (env->priv == PRV_M ||
89
target_ulong new_value, target_ulong write_mask)
39
+ (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) ||
90
{
40
+ (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) &&
91
int ret;
41
+ get_field(env->hstatus, HSTATUS_HU))) {
92
42
+ flags = FIELD_DP32(flags, TB_FLAGS, HLSX, 1);
93
if (riscv_cpu_virt_enabled(env)) {
43
+ }
94
- /* Shift the new values to line up with the VS bits */
44
+ }
95
- ret = rmw_mip(env, CSR_MSTATUS, ret_value, new_value << 1,
45
#endif
96
- (write_mask & sip_writable_mask) << 1 & env->mideleg);
46
+
97
- ret &= vsip_writable_mask;
47
*pflags = flags;
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;
48
}
105
}
49
106
50
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
107
-static int rmw_vsip(CPURISCVState *env, int csrno, target_ulong *ret_value,
51
index XXXXXXX..XXXXXXX 100644
108
- target_ulong new_value, target_ulong write_mask)
52
--- a/target/riscv/helper.h
53
+++ b/target/riscv/helper.h
54
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_1(tlb_flush, void, env)
55
#ifndef CONFIG_USER_ONLY
56
DEF_HELPER_1(hyp_tlb_flush, void, env)
57
DEF_HELPER_1(hyp_gvma_tlb_flush, void, env)
58
-DEF_HELPER_4(hyp_load, tl, env, tl, tl, tl)
59
-DEF_HELPER_5(hyp_store, void, env, tl, tl, tl, tl)
60
DEF_HELPER_4(hyp_x_load, tl, env, tl, tl, tl)
61
#endif
62
63
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/target/riscv/op_helper.c
66
+++ b/target/riscv/op_helper.c
67
@@ -XXX,XX +XXX,XX @@ void helper_hyp_gvma_tlb_flush(CPURISCVState *env)
68
helper_hyp_tlb_flush(env);
69
}
70
71
-target_ulong helper_hyp_load(CPURISCVState *env, target_ulong address,
72
- target_ulong attrs, target_ulong memop)
73
-{
109
-{
74
- if (env->priv == PRV_M ||
110
- int ret = rmw_mip(env, 0, ret_value, new_value,
75
- (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) ||
111
- write_mask & env->mideleg & vsip_writable_mask);
76
- (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) &&
112
- return ret;
77
- get_field(env->hstatus, HSTATUS_HU))) {
113
-}
78
- target_ulong pte;
79
- int mmu_idx = cpu_mmu_index(env, false) | TB_FLAGS_PRIV_HYP_ACCESS_MASK;
80
-
114
-
81
- switch (memop) {
115
-static int read_vsie(CPURISCVState *env, int csrno, target_ulong *val)
82
- case MO_SB:
116
-{
83
- pte = cpu_ldsb_mmuidx_ra(env, address, mmu_idx, GETPC());
117
- *val = env->mie & env->mideleg & VS_MODE_INTERRUPTS;
84
- break;
85
- case MO_UB:
86
- pte = cpu_ldub_mmuidx_ra(env, address, mmu_idx, GETPC());
87
- break;
88
- case MO_TESW:
89
- pte = cpu_ldsw_mmuidx_ra(env, address, mmu_idx, GETPC());
90
- break;
91
- case MO_TEUW:
92
- pte = cpu_lduw_mmuidx_ra(env, address, mmu_idx, GETPC());
93
- break;
94
- case MO_TESL:
95
- pte = cpu_ldl_mmuidx_ra(env, address, mmu_idx, GETPC());
96
- break;
97
- case MO_TEUL:
98
- pte = cpu_ldl_mmuidx_ra(env, address, mmu_idx, GETPC());
99
- break;
100
- case MO_TEQ:
101
- pte = cpu_ldq_mmuidx_ra(env, address, mmu_idx, GETPC());
102
- break;
103
- default:
104
- g_assert_not_reached();
105
- }
106
-
107
- return pte;
108
- }
109
-
110
- if (riscv_cpu_virt_enabled(env)) {
111
- riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC());
112
- } else {
113
- riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
114
- }
115
- return 0;
118
- return 0;
116
-}
119
-}
117
-
120
-
118
-void helper_hyp_store(CPURISCVState *env, target_ulong address,
121
-static int write_vsie(CPURISCVState *env, int csrno, target_ulong val)
119
- target_ulong val, target_ulong attrs, target_ulong memop)
120
-{
122
-{
121
- if (env->priv == PRV_M ||
123
- target_ulong newval = (env->mie & ~env->mideleg) | (val & env->mideleg & MIP_VSSIP);
122
- (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) ||
124
- return write_mie(env, CSR_MIE, newval);
123
- (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) &&
124
- get_field(env->hstatus, HSTATUS_HU))) {
125
- int mmu_idx = cpu_mmu_index(env, false) | TB_FLAGS_PRIV_HYP_ACCESS_MASK;
126
-
127
- switch (memop) {
128
- case MO_SB:
129
- case MO_UB:
130
- cpu_stb_mmuidx_ra(env, address, val, mmu_idx, GETPC());
131
- break;
132
- case MO_TESW:
133
- case MO_TEUW:
134
- cpu_stw_mmuidx_ra(env, address, val, mmu_idx, GETPC());
135
- break;
136
- case MO_TESL:
137
- case MO_TEUL:
138
- cpu_stl_mmuidx_ra(env, address, val, mmu_idx, GETPC());
139
- break;
140
- case MO_TEQ:
141
- cpu_stq_mmuidx_ra(env, address, val, mmu_idx, GETPC());
142
- break;
143
- default:
144
- g_assert_not_reached();
145
- }
146
-
147
- return;
148
- }
149
-
150
- if (riscv_cpu_virt_enabled(env)) {
151
- riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC());
152
- } else {
153
- riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
154
- }
155
-}
125
-}
156
-
126
-
157
target_ulong helper_hyp_x_load(CPURISCVState *env, target_ulong address,
127
static int read_vstvec(CPURISCVState *env, int csrno, target_ulong *val)
158
target_ulong attrs, target_ulong memop)
159
{
128
{
160
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
129
*val = env->vstvec;
161
index XXXXXXX..XXXXXXX 100644
162
--- a/target/riscv/translate.c
163
+++ b/target/riscv/translate.c
164
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
165
to reset this known value. */
166
int frm;
167
bool ext_ifencei;
168
+ bool hlsx;
169
/* vector extension */
170
bool vill;
171
uint8_t lmul;
172
@@ -XXX,XX +XXX,XX @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
173
ctx->frm = -1; /* unknown rounding mode */
174
ctx->ext_ifencei = cpu->cfg.ext_ifencei;
175
ctx->vlen = cpu->cfg.vlen;
176
+ ctx->hlsx = FIELD_EX32(tb_flags, TB_FLAGS, HLSX);
177
ctx->vill = FIELD_EX32(tb_flags, TB_FLAGS, VILL);
178
ctx->sew = FIELD_EX32(tb_flags, TB_FLAGS, SEW);
179
ctx->lmul = FIELD_EX32(tb_flags, TB_FLAGS, LMUL);
180
diff --git a/target/riscv/insn_trans/trans_rvh.c.inc b/target/riscv/insn_trans/trans_rvh.c.inc
181
index XXXXXXX..XXXXXXX 100644
182
--- a/target/riscv/insn_trans/trans_rvh.c.inc
183
+++ b/target/riscv/insn_trans/trans_rvh.c.inc
184
@@ -XXX,XX +XXX,XX @@
185
* this program. If not, see <http://www.gnu.org/licenses/>.
186
*/
187
188
+#ifndef CONFIG_USER_ONLY
189
+static void check_access(DisasContext *ctx) {
190
+ if (!ctx->hlsx) {
191
+ if (ctx->virt_enabled) {
192
+ generate_exception(ctx, RISCV_EXCP_VIRT_INSTRUCTION_FAULT);
193
+ } else {
194
+ generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST);
195
+ }
196
+ }
197
+}
198
+#endif
199
+
200
static bool trans_hlv_b(DisasContext *ctx, arg_hlv_b *a)
201
{
202
REQUIRE_EXT(ctx, RVH);
203
#ifndef CONFIG_USER_ONLY
204
TCGv t0 = tcg_temp_new();
205
TCGv t1 = tcg_temp_new();
206
- TCGv mem_idx = tcg_temp_new();
207
- TCGv memop = tcg_temp_new();
208
+
209
+ check_access(ctx);
210
211
gen_get_gpr(t0, a->rs1);
212
- tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
213
- tcg_gen_movi_tl(memop, MO_SB);
214
215
- gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop);
216
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_SB);
217
gen_set_gpr(a->rd, t1);
218
219
tcg_temp_free(t0);
220
tcg_temp_free(t1);
221
- tcg_temp_free(mem_idx);
222
- tcg_temp_free(memop);
223
return true;
224
#else
225
return false;
226
@@ -XXX,XX +XXX,XX @@ static bool trans_hlv_h(DisasContext *ctx, arg_hlv_h *a)
227
#ifndef CONFIG_USER_ONLY
228
TCGv t0 = tcg_temp_new();
229
TCGv t1 = tcg_temp_new();
230
- TCGv mem_idx = tcg_temp_new();
231
- TCGv memop = tcg_temp_new();
232
+
233
+ check_access(ctx);
234
235
gen_get_gpr(t0, a->rs1);
236
- tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
237
- tcg_gen_movi_tl(memop, MO_TESW);
238
239
- gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop);
240
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TESW);
241
gen_set_gpr(a->rd, t1);
242
243
tcg_temp_free(t0);
244
tcg_temp_free(t1);
245
- tcg_temp_free(mem_idx);
246
- tcg_temp_free(memop);
247
return true;
248
#else
249
return false;
250
@@ -XXX,XX +XXX,XX @@ static bool trans_hlv_w(DisasContext *ctx, arg_hlv_w *a)
251
#ifndef CONFIG_USER_ONLY
252
TCGv t0 = tcg_temp_new();
253
TCGv t1 = tcg_temp_new();
254
- TCGv mem_idx = tcg_temp_new();
255
- TCGv memop = tcg_temp_new();
256
+
257
+ check_access(ctx);
258
259
gen_get_gpr(t0, a->rs1);
260
- tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
261
- tcg_gen_movi_tl(memop, MO_TESL);
262
263
- gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop);
264
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TESL);
265
gen_set_gpr(a->rd, t1);
266
267
tcg_temp_free(t0);
268
tcg_temp_free(t1);
269
- tcg_temp_free(mem_idx);
270
- tcg_temp_free(memop);
271
return true;
272
#else
273
return false;
274
@@ -XXX,XX +XXX,XX @@ static bool trans_hlv_bu(DisasContext *ctx, arg_hlv_bu *a)
275
#ifndef CONFIG_USER_ONLY
276
TCGv t0 = tcg_temp_new();
277
TCGv t1 = tcg_temp_new();
278
- TCGv mem_idx = tcg_temp_new();
279
- TCGv memop = tcg_temp_new();
280
+
281
+ check_access(ctx);
282
283
gen_get_gpr(t0, a->rs1);
284
- tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
285
- tcg_gen_movi_tl(memop, MO_UB);
286
287
- gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop);
288
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_UB);
289
gen_set_gpr(a->rd, t1);
290
291
tcg_temp_free(t0);
292
tcg_temp_free(t1);
293
- tcg_temp_free(mem_idx);
294
- tcg_temp_free(memop);
295
return true;
296
#else
297
return false;
298
@@ -XXX,XX +XXX,XX @@ static bool trans_hlv_hu(DisasContext *ctx, arg_hlv_hu *a)
299
#ifndef CONFIG_USER_ONLY
300
TCGv t0 = tcg_temp_new();
301
TCGv t1 = tcg_temp_new();
302
- TCGv mem_idx = tcg_temp_new();
303
- TCGv memop = tcg_temp_new();
304
305
- gen_get_gpr(t0, a->rs1);
306
- tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
307
- tcg_gen_movi_tl(memop, MO_TEUW);
308
+ check_access(ctx);
309
310
- gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop);
311
+ gen_get_gpr(t0, a->rs1);
312
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TEUW);
313
gen_set_gpr(a->rd, t1);
314
315
tcg_temp_free(t0);
316
tcg_temp_free(t1);
317
- tcg_temp_free(mem_idx);
318
- tcg_temp_free(memop);
319
return true;
320
#else
321
return false;
322
@@ -XXX,XX +XXX,XX @@ static bool trans_hsv_b(DisasContext *ctx, arg_hsv_b *a)
323
#ifndef CONFIG_USER_ONLY
324
TCGv t0 = tcg_temp_new();
325
TCGv dat = tcg_temp_new();
326
- TCGv mem_idx = tcg_temp_new();
327
- TCGv memop = tcg_temp_new();
328
+
329
+ check_access(ctx);
330
331
gen_get_gpr(t0, a->rs1);
332
gen_get_gpr(dat, a->rs2);
333
- tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
334
- tcg_gen_movi_tl(memop, MO_SB);
335
336
- gen_helper_hyp_store(cpu_env, t0, dat, mem_idx, memop);
337
+ tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_SB);
338
339
tcg_temp_free(t0);
340
tcg_temp_free(dat);
341
- tcg_temp_free(mem_idx);
342
- tcg_temp_free(memop);
343
return true;
344
#else
345
return false;
346
@@ -XXX,XX +XXX,XX @@ static bool trans_hsv_h(DisasContext *ctx, arg_hsv_h *a)
347
#ifndef CONFIG_USER_ONLY
348
TCGv t0 = tcg_temp_new();
349
TCGv dat = tcg_temp_new();
350
- TCGv mem_idx = tcg_temp_new();
351
- TCGv memop = tcg_temp_new();
352
+
353
+ check_access(ctx);
354
355
gen_get_gpr(t0, a->rs1);
356
gen_get_gpr(dat, a->rs2);
357
- tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
358
- tcg_gen_movi_tl(memop, MO_TESW);
359
360
- gen_helper_hyp_store(cpu_env, t0, dat, mem_idx, memop);
361
+ tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TESW);
362
363
tcg_temp_free(t0);
364
tcg_temp_free(dat);
365
- tcg_temp_free(mem_idx);
366
- tcg_temp_free(memop);
367
return true;
368
#else
369
return false;
370
@@ -XXX,XX +XXX,XX @@ static bool trans_hsv_w(DisasContext *ctx, arg_hsv_w *a)
371
#ifndef CONFIG_USER_ONLY
372
TCGv t0 = tcg_temp_new();
373
TCGv dat = tcg_temp_new();
374
- TCGv mem_idx = tcg_temp_new();
375
- TCGv memop = tcg_temp_new();
376
+
377
+ check_access(ctx);
378
379
gen_get_gpr(t0, a->rs1);
380
gen_get_gpr(dat, a->rs2);
381
- tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
382
- tcg_gen_movi_tl(memop, MO_TESL);
383
384
- gen_helper_hyp_store(cpu_env, t0, dat, mem_idx, memop);
385
+ tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TESL);
386
387
tcg_temp_free(t0);
388
tcg_temp_free(dat);
389
- tcg_temp_free(mem_idx);
390
- tcg_temp_free(memop);
391
return true;
392
#else
393
return false;
394
@@ -XXX,XX +XXX,XX @@ static bool trans_hlv_wu(DisasContext *ctx, arg_hlv_wu *a)
395
#ifndef CONFIG_USER_ONLY
396
TCGv t0 = tcg_temp_new();
397
TCGv t1 = tcg_temp_new();
398
- TCGv mem_idx = tcg_temp_new();
399
- TCGv memop = tcg_temp_new();
400
+
401
+ check_access(ctx);
402
403
gen_get_gpr(t0, a->rs1);
404
- tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
405
- tcg_gen_movi_tl(memop, MO_TEUL);
406
407
- gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop);
408
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TEUL);
409
gen_set_gpr(a->rd, t1);
410
411
tcg_temp_free(t0);
412
tcg_temp_free(t1);
413
- tcg_temp_free(mem_idx);
414
- tcg_temp_free(memop);
415
return true;
416
#else
417
return false;
418
@@ -XXX,XX +XXX,XX @@ static bool trans_hlv_d(DisasContext *ctx, arg_hlv_d *a)
419
#ifndef CONFIG_USER_ONLY
420
TCGv t0 = tcg_temp_new();
421
TCGv t1 = tcg_temp_new();
422
- TCGv mem_idx = tcg_temp_new();
423
- TCGv memop = tcg_temp_new();
424
+
425
+ check_access(ctx);
426
427
gen_get_gpr(t0, a->rs1);
428
- tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
429
- tcg_gen_movi_tl(memop, MO_TEQ);
430
431
- gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop);
432
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TEQ);
433
gen_set_gpr(a->rd, t1);
434
435
tcg_temp_free(t0);
436
tcg_temp_free(t1);
437
- tcg_temp_free(mem_idx);
438
- tcg_temp_free(memop);
439
return true;
440
#else
441
return false;
442
@@ -XXX,XX +XXX,XX @@ static bool trans_hsv_d(DisasContext *ctx, arg_hsv_d *a)
443
#ifndef CONFIG_USER_ONLY
444
TCGv t0 = tcg_temp_new();
445
TCGv dat = tcg_temp_new();
446
- TCGv mem_idx = tcg_temp_new();
447
- TCGv memop = tcg_temp_new();
448
+
449
+ check_access(ctx);
450
451
gen_get_gpr(t0, a->rs1);
452
gen_get_gpr(dat, a->rs2);
453
- tcg_gen_movi_tl(mem_idx, ctx->mem_idx);
454
- tcg_gen_movi_tl(memop, MO_TEQ);
455
456
- gen_helper_hyp_store(cpu_env, t0, dat, mem_idx, memop);
457
+ tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TEQ);
458
459
tcg_temp_free(t0);
460
tcg_temp_free(dat);
461
- tcg_temp_free(mem_idx);
462
- tcg_temp_free(memop);
463
return true;
464
#else
465
return false;
466
--
130
--
467
2.29.2
131
2.30.1
468
132
469
133
diff view generated by jsdifflib
1
The HS_TWO_STAGE flag is no longer required as the MMU index contains
1
From: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
2
the information if we are performing a two stage access.
3
2
3
The current two-stage lookup detection in riscv_cpu_do_interrupt falls
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
8
What we really need instead is whether two-stage address translation was
9
active when the exception was raised. However, in riscv_cpu_do_interrupt
10
we do not have the information to reliably detect this. Therefore, when
11
we raise a memory fault exception we have to record whether two-stage
12
address translation is active.
13
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
4
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
17
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: f514b128b1ff0fb41c85f914cee18f905007a922.1604464950.git.alistair.francis@wdc.com
7
---
18
---
8
target/riscv/cpu.h | 3 +-
19
target/riscv/cpu.h | 4 ++++
9
target/riscv/cpu_bits.h | 1 -
20
target/riscv/cpu.c | 1 +
10
target/riscv/cpu_helper.c | 60 ++++++++++++++++-----------------------
21
target/riscv/cpu_helper.c | 21 ++++++++-------------
11
target/riscv/op_helper.c | 12 --------
22
3 files changed, 13 insertions(+), 13 deletions(-)
12
4 files changed, 25 insertions(+), 51 deletions(-)
13
23
14
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
24
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
15
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
16
--- a/target/riscv/cpu.h
26
--- a/target/riscv/cpu.h
17
+++ b/target/riscv/cpu.h
27
+++ b/target/riscv/cpu.h
18
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_virt_enabled(CPURISCVState *env);
28
@@ -XXX,XX +XXX,XX @@ struct CPURISCVState {
19
void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable);
29
target_ulong satp_hs;
20
bool riscv_cpu_force_hs_excep_enabled(CPURISCVState *env);
30
uint64_t mstatus_hs;
21
void riscv_cpu_set_force_hs_excep(CPURISCVState *env, bool enable);
31
22
-bool riscv_cpu_two_stage_lookup(CPURISCVState *env);
32
+ /* Signals whether the current exception occurred with two-stage address
23
-void riscv_cpu_set_two_stage_lookup(CPURISCVState *env, bool enable);
33
+ translation active. */
24
+bool riscv_cpu_two_stage_lookup(int mmu_idx);
34
+ bool two_stage_lookup;
25
int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch);
35
+
26
hwaddr riscv_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
36
target_ulong scounteren;
27
void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
37
target_ulong mcounteren;
28
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
38
39
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
29
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
30
--- a/target/riscv/cpu_bits.h
41
--- a/target/riscv/cpu.c
31
+++ b/target/riscv/cpu_bits.h
42
+++ b/target/riscv/cpu.c
32
@@ -XXX,XX +XXX,XX @@
43
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_reset(DeviceState *dev)
33
* page table fault.
44
env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
34
*/
45
env->mcause = 0;
35
#define FORCE_HS_EXCEP 2
46
env->pc = env->resetvec;
36
-#define HS_TWO_STAGE 4
47
+ env->two_stage_lookup = false;
37
48
#endif
38
/* RV32 satp CSR field masks */
49
cs->exception_index = EXCP_NONE;
39
#define SATP32_MODE 0x80000000
50
env->load_res = -1;
40
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
51
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
41
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
42
--- a/target/riscv/cpu_helper.c
53
--- a/target/riscv/cpu_helper.c
43
+++ b/target/riscv/cpu_helper.c
54
+++ b/target/riscv/cpu_helper.c
44
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_set_force_hs_excep(CPURISCVState *env, bool enable)
55
@@ -XXX,XX +XXX,XX @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
45
env->virt = set_field(env->virt, FORCE_HS_EXCEP, enable);
56
g_assert_not_reached();
57
}
58
env->badaddr = address;
59
+ env->two_stage_lookup = two_stage;
46
}
60
}
47
61
48
-bool riscv_cpu_two_stage_lookup(CPURISCVState *env)
62
hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
49
+bool riscv_cpu_two_stage_lookup(int mmu_idx)
63
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
50
{
64
}
51
- if (!riscv_has_ext(env, RVH)) {
65
52
- return false;
66
env->badaddr = addr;
53
- }
67
+ env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
54
-
68
+ riscv_cpu_two_stage_lookup(mmu_idx);
55
- return get_field(env->virt, HS_TWO_STAGE);
69
riscv_raise_exception(&cpu->env, cs->exception_index, retaddr);
56
-}
57
-
58
-void riscv_cpu_set_two_stage_lookup(CPURISCVState *env, bool enable)
59
-{
60
- if (!riscv_has_ext(env, RVH)) {
61
- return;
62
- }
63
-
64
- env->virt = set_field(env->virt, HS_TWO_STAGE, enable);
65
+ return mmu_idx & TB_FLAGS_PRIV_HYP_ACCESS_MASK;
66
}
70
}
67
71
68
int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts)
72
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
69
@@ -XXX,XX +XXX,XX @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
73
g_assert_not_reached();
70
* was called. Background registers will be used if the guest has
71
* forced a two stage translation to be on (in HS or M mode).
72
*/
73
- if (riscv_cpu_two_stage_lookup(env) && access_type != MMU_INST_FETCH) {
74
+ if (!riscv_cpu_virt_enabled(env) && riscv_cpu_two_stage_lookup(mmu_idx)) {
75
use_background = true;
76
}
74
}
77
75
env->badaddr = addr;
78
@@ -XXX,XX +XXX,XX @@ restart:
76
+ env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
79
77
+ riscv_cpu_two_stage_lookup(mmu_idx);
80
static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
78
riscv_raise_exception(env, cs->exception_index, retaddr);
81
MMUAccessType access_type, bool pmp_violation,
79
}
82
- bool first_stage)
80
#endif /* !CONFIG_USER_ONLY */
83
+ bool first_stage, bool two_stage)
84
{
85
CPUState *cs = env_cpu(env);
86
int page_fault_exceptions;
87
@@ -XXX,XX +XXX,XX @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
88
}
89
break;
90
case MMU_DATA_LOAD:
91
- if ((riscv_cpu_virt_enabled(env) || riscv_cpu_two_stage_lookup(env)) &&
92
- !first_stage) {
93
+ if (two_stage && !first_stage) {
94
cs->exception_index = RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT;
95
} else {
96
cs->exception_index = page_fault_exceptions ?
97
@@ -XXX,XX +XXX,XX @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
98
}
99
break;
100
case MMU_DATA_STORE:
101
- if ((riscv_cpu_virt_enabled(env) || riscv_cpu_two_stage_lookup(env)) &&
102
- !first_stage) {
103
+ if (two_stage && !first_stage) {
104
cs->exception_index = RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT;
105
} else {
106
cs->exception_index = page_fault_exceptions ?
107
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
108
int prot, prot2;
109
bool pmp_violation = false;
110
bool first_stage_error = true;
111
+ bool two_stage_lookup = false;
112
int ret = TRANSLATE_FAIL;
113
int mode = mmu_idx;
114
target_ulong tlb_size = 0;
115
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
116
access_type != MMU_INST_FETCH &&
117
get_field(env->mstatus, MSTATUS_MPRV) &&
118
get_field(env->mstatus, MSTATUS_MPV)) {
119
- riscv_cpu_set_two_stage_lookup(env, true);
120
+ two_stage_lookup = true;
121
}
122
123
if (riscv_cpu_virt_enabled(env) ||
124
- (riscv_cpu_two_stage_lookup(env) && access_type != MMU_INST_FETCH)) {
125
+ ((riscv_cpu_two_stage_lookup(mmu_idx) || two_stage_lookup) &&
126
+ access_type != MMU_INST_FETCH)) {
127
/* Two stage lookup */
128
ret = get_physical_address(env, &pa, &prot, address,
129
&env->guest_phys_fault_addr, access_type,
130
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
131
__func__, address, ret, pa, prot);
132
}
133
134
- /* We did the two stage lookup based on MPRV, unset the lookup */
135
- if (riscv_has_ext(env, RVH) && env->priv == PRV_M &&
136
- access_type != MMU_INST_FETCH &&
137
- get_field(env->mstatus, MSTATUS_MPRV) &&
138
- get_field(env->mstatus, MSTATUS_MPV)) {
139
- riscv_cpu_set_two_stage_lookup(env, false);
140
- }
141
-
142
if (riscv_feature(env, RISCV_FEATURE_PMP) &&
143
(ret == TRANSLATE_SUCCESS) &&
144
!pmp_hart_has_privs(env, pa, size, 1 << access_type, mode)) {
145
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
146
} else if (probe) {
147
return false;
148
} else {
149
- raise_mmu_exception(env, address, access_type, pmp_violation, first_stage_error);
150
+ raise_mmu_exception(env, address, access_type, pmp_violation,
151
+ first_stage_error,
152
+ riscv_cpu_virt_enabled(env) ||
153
+ riscv_cpu_two_stage_lookup(mmu_idx));
154
riscv_raise_exception(env, cs->exception_index, retaddr);
155
}
156
157
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_interrupt(CPUState *cs)
81
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_interrupt(CPUState *cs)
158
/* handle the trap in S-mode */
82
/* handle the trap in S-mode */
159
if (riscv_has_ext(env, RVH)) {
83
if (riscv_has_ext(env, RVH)) {
160
target_ulong hdeleg = async ? env->hideleg : env->hedeleg;
84
target_ulong hdeleg = async ? env->hideleg : env->hedeleg;
161
+ bool two_stage_lookup = false;
85
- bool two_stage_lookup = false;
162
+
86
163
+ if (env->priv == PRV_M ||
87
- if (env->priv == PRV_M ||
164
+ (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) ||
88
- (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) ||
165
+ (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) &&
89
- (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) &&
166
+ get_field(env->hstatus, HSTATUS_HU))) {
90
- get_field(env->hstatus, HSTATUS_HU))) {
167
+ two_stage_lookup = true;
91
- two_stage_lookup = true;
168
+ }
92
- }
169
93
-
170
- if ((riscv_cpu_virt_enabled(env) ||
94
- if ((riscv_cpu_virt_enabled(env) || two_stage_lookup) && write_tval) {
171
- riscv_cpu_two_stage_lookup(env)) && write_tval) {
95
+ if (env->two_stage_lookup && write_tval) {
172
+ if ((riscv_cpu_virt_enabled(env) || two_stage_lookup) && write_tval) {
173
/*
96
/*
174
* If we are writing a guest virtual address to stval, set
97
* If we are writing a guest virtual address to stval, set
175
* this to 1. If we are trapping to VS we will set this to 0
98
* this to 1. If we are trapping to VS we will set this to 0
176
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_interrupt(CPUState *cs)
99
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_interrupt(CPUState *cs)
177
riscv_cpu_set_force_hs_excep(env, 0);
100
riscv_cpu_set_force_hs_excep(env, 0);
178
} else {
101
} else {
179
/* Trap into HS mode */
102
/* Trap into HS mode */
180
- if (!riscv_cpu_two_stage_lookup(env)) {
103
- if (!two_stage_lookup) {
181
+ if (!two_stage_lookup) {
104
- env->hstatus = set_field(env->hstatus, HSTATUS_SPV,
182
env->hstatus = set_field(env->hstatus, HSTATUS_SPV,
105
- riscv_cpu_virt_enabled(env));
183
riscv_cpu_virt_enabled(env));
106
- }
184
}
107
+ env->hstatus = set_field(env->hstatus, HSTATUS_SPV, false);
185
- riscv_cpu_set_two_stage_lookup(env, false);
186
htval = env->guest_phys_fault_addr;
108
htval = env->guest_phys_fault_addr;
187
}
109
}
188
}
110
}
189
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
111
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_interrupt(CPUState *cs)
190
index XXXXXXX..XXXXXXX 100644
112
* RISC-V ISA Specification.
191
--- a/target/riscv/op_helper.c
113
*/
192
+++ b/target/riscv/op_helper.c
114
193
@@ -XXX,XX +XXX,XX @@ target_ulong helper_hyp_load(CPURISCVState *env, target_ulong address,
115
+ env->two_stage_lookup = false;
194
target_ulong pte;
116
#endif
195
int mmu_idx = cpu_mmu_index(env, false) | TB_FLAGS_PRIV_HYP_ACCESS_MASK;
117
cs->exception_index = EXCP_NONE; /* mark handled to qemu */
196
118
}
197
- riscv_cpu_set_two_stage_lookup(env, true);
198
-
199
switch (memop) {
200
case MO_SB:
201
pte = cpu_ldsb_mmuidx_ra(env, address, mmu_idx, GETPC());
202
@@ -XXX,XX +XXX,XX @@ target_ulong helper_hyp_load(CPURISCVState *env, target_ulong address,
203
g_assert_not_reached();
204
}
205
206
- riscv_cpu_set_two_stage_lookup(env, false);
207
-
208
return pte;
209
}
210
211
@@ -XXX,XX +XXX,XX @@ void helper_hyp_store(CPURISCVState *env, target_ulong address,
212
get_field(env->hstatus, HSTATUS_HU))) {
213
int mmu_idx = cpu_mmu_index(env, false) | TB_FLAGS_PRIV_HYP_ACCESS_MASK;
214
215
- riscv_cpu_set_two_stage_lookup(env, true);
216
-
217
switch (memop) {
218
case MO_SB:
219
case MO_UB:
220
@@ -XXX,XX +XXX,XX @@ void helper_hyp_store(CPURISCVState *env, target_ulong address,
221
g_assert_not_reached();
222
}
223
224
- riscv_cpu_set_two_stage_lookup(env, false);
225
-
226
return;
227
}
228
229
@@ -XXX,XX +XXX,XX @@ target_ulong helper_hyp_x_load(CPURISCVState *env, target_ulong address,
230
target_ulong pte;
231
int mmu_idx = cpu_mmu_index(env, false) | TB_FLAGS_PRIV_HYP_ACCESS_MASK;
232
233
- riscv_cpu_set_two_stage_lookup(env, true);
234
-
235
switch (memop) {
236
case MO_TEUW:
237
pte = cpu_lduw_mmuidx_ra(env, address, mmu_idx, GETPC());
238
@@ -XXX,XX +XXX,XX @@ target_ulong helper_hyp_x_load(CPURISCVState *env, target_ulong address,
239
g_assert_not_reached();
240
}
241
242
- riscv_cpu_set_two_stage_lookup(env, false);
243
-
244
return pte;
245
}
246
247
--
119
--
248
2.29.2
120
2.30.1
249
121
250
122
diff view generated by jsdifflib
1
After claiming the interrupt by reading the claim register we want to
1
From: Bin Meng <bin.meng@windriver.com>
2
clear the register to make sure the interrupt doesn't appear at the next
3
read.
4
2
5
This matches the documentation for the claim register as when an interrupt
3
Per SST25VF016B datasheet [1], SST flash requires a dummy byte after
6
is claimed by a target the relevant bit of IP is cleared (which we already
4
the address bytes. Note only SPI mode is supported by SST flashes.
7
do): https://docs.opentitan.org/hw/ip/rv_plic/doc/index.html
8
5
9
This also matches the current hardware.
6
[1] http://ww1.microchip.com/downloads/en/devicedoc/s71271_04.pdf
10
7
8
Signed-off-by: Bin Meng <bin.meng@windriver.com>
9
Acked-by: Alistair Francis <alistair.francis@wdc.com>
10
Message-id: 20210306060152.7250-1-bmeng.cn@gmail.com
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Message-id: 68d4575deef2559b7a747f3bda193fcf43af4558.1604629928.git.alistair.francis@wdc.com
14
---
12
---
15
hw/intc/ibex_plic.c | 3 +++
13
hw/block/m25p80.c | 3 +++
16
1 file changed, 3 insertions(+)
14
1 file changed, 3 insertions(+)
17
15
18
diff --git a/hw/intc/ibex_plic.c b/hw/intc/ibex_plic.c
16
diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
19
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/intc/ibex_plic.c
18
--- a/hw/block/m25p80.c
21
+++ b/hw/intc/ibex_plic.c
19
+++ b/hw/block/m25p80.c
22
@@ -XXX,XX +XXX,XX @@ static uint64_t ibex_plic_read(void *opaque, hwaddr addr,
20
@@ -XXX,XX +XXX,XX @@ static void decode_fast_read_cmd(Flash *s)
23
/* Return the current claimed interrupt */
21
s->needed_bytes = get_addr_length(s);
24
ret = s->claim;
22
switch (get_man(s)) {
25
23
/* Dummy cycles - modeled with bytes writes instead of bits */
26
+ /* Clear the claimed interrupt */
24
+ case MAN_SST:
27
+ s->claim = 0x00000000;
25
+ s->needed_bytes += 1;
28
+
26
+ break;
29
/* Update the interrupt status after the claim */
27
case MAN_WINBOND:
30
ibex_plic_update(s);
28
s->needed_bytes += 8;
31
}
29
break;
32
--
30
--
33
2.29.2
31
2.30.1
34
32
35
33
diff view generated by jsdifflib
New patch
1
From: Bin Meng <bin.meng@windriver.com>
1
2
3
Since HSS commit c20a89f8dcac, the Icicle Kit reference design has
4
been updated to use a register mapped at 0x4f000000 instead of a
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
11
With this commit, HSS image built from 2020.12 release boots again.
12
13
Signed-off-by: Bin Meng <bin.meng@windriver.com>
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
24
--- a/include/hw/riscv/microchip_pfsoc.h
25
+++ b/include/hw/riscv/microchip_pfsoc.h
26
@@ -XXX,XX +XXX,XX @@ enum {
27
MICROCHIP_PFSOC_ENVM_DATA,
28
MICROCHIP_PFSOC_QSPI_XIP,
29
MICROCHIP_PFSOC_IOSCB,
30
+ MICROCHIP_PFSOC_EMMC_SD_MUX,
31
MICROCHIP_PFSOC_DRAM_LO,
32
MICROCHIP_PFSOC_DRAM_LO_ALIAS,
33
MICROCHIP_PFSOC_DRAM_HI,
34
diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/riscv/microchip_pfsoc.c
37
+++ 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)
47
sysbus_mmio_map(SYS_BUS_DEVICE(&s->ioscb), 0,
48
memmap[MICROCHIP_PFSOC_IOSCB].base);
49
50
+ /* eMMC/SD mux */
51
+ create_unimplemented_device("microchip.pfsoc.emmc_sd_mux",
52
+ memmap[MICROCHIP_PFSOC_EMMC_SD_MUX].base,
53
+ memmap[MICROCHIP_PFSOC_EMMC_SD_MUX].size);
54
+
55
/* QSPI Flash */
56
memory_region_init_rom(qspi_xip_mem, OBJECT(dev),
57
"microchip.pfsoc.qspi_xip",
58
--
59
2.30.1
60
61
diff view generated by jsdifflib
1
When performing the hypervisor load/store operations set the MMU mode to
1
From: Bin Meng <bin.meng@windriver.com>
2
indicate that we are virtualised.
3
2
3
This adds the documentation to describe what is supported for the
4
'microchip-icicle-kit' machine, and how to boot the machine in QEMU.
5
6
Signed-off-by: Bin Meng <bin.meng@windriver.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Message-id: 20210322075248.136255-2-bmeng.cn@gmail.com
4
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
9
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: e411c61a1452cad16853f13cac2fb86dc91ebee8.1604464950.git.alistair.francis@wdc.com
7
---
10
---
8
target/riscv/op_helper.c | 30 +++++++++++++++++-------------
11
docs/system/riscv/microchip-icicle-kit.rst | 89 ++++++++++++++++++++++
9
1 file changed, 17 insertions(+), 13 deletions(-)
12
docs/system/target-riscv.rst | 1 +
13
2 files changed, 90 insertions(+)
14
create mode 100644 docs/system/riscv/microchip-icicle-kit.rst
10
15
11
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
16
diff --git a/docs/system/riscv/microchip-icicle-kit.rst b/docs/system/riscv/microchip-icicle-kit.rst
17
new file mode 100644
18
index XXXXXXX..XXXXXXX
19
--- /dev/null
20
+++ b/docs/system/riscv/microchip-icicle-kit.rst
21
@@ -XXX,XX +XXX,XX @@
22
+Microchip PolarFire SoC Icicle Kit (``microchip-icicle-kit``)
23
+=============================================================
24
+
25
+Microchip PolarFire SoC Icicle Kit integrates a PolarFire SoC, with one
26
+SiFive's E51 plus four U54 cores and many on-chip peripherals and an FPGA.
27
+
28
+For more details about Microchip PolarFire SoC, please see:
29
+https://www.microsemi.com/product-directory/soc-fpgas/5498-polarfire-soc-fpga
30
+
31
+The Icicle Kit board information can be found here:
32
+https://www.microsemi.com/existing-parts/parts/152514
33
+
34
+Supported devices
35
+-----------------
36
+
37
+The ``microchip-icicle-kit`` machine supports the following devices:
38
+
39
+ * 1 E51 core
40
+ * 4 U54 cores
41
+ * Core Level Interruptor (CLINT)
42
+ * Platform-Level Interrupt Controller (PLIC)
43
+ * L2 Loosely Integrated Memory (L2-LIM)
44
+ * DDR memory controller
45
+ * 5 MMUARTs
46
+ * 1 DMA controller
47
+ * 2 GEM Ethernet controllers
48
+ * 1 SDHC storage controller
49
+
50
+Boot options
51
+------------
52
+
53
+The ``microchip-icicle-kit`` machine can start using the standard -bios
54
+functionality for loading its BIOS image, aka Hart Software Services (HSS_).
55
+HSS loads the second stage bootloader U-Boot from an SD card. It does not
56
+support direct kernel loading via the -kernel option. One has to load kernel
57
+from U-Boot.
58
+
59
+The memory is set to 1537 MiB by default which is the minimum required high
60
+memory size by HSS. A sanity check on ram size is performed in the machine
61
+init routine to prompt user to increase the RAM size to > 1537 MiB when less
62
+than 1537 MiB ram is detected.
63
+
64
+Boot the machine
65
+----------------
66
+
67
+HSS 2020.12 release is tested at the time of writing. To build an HSS image
68
+that can be booted by the ``microchip-icicle-kit`` machine, type the following
69
+in the HSS source tree:
70
+
71
+.. code-block:: bash
72
+
73
+ $ export CROSS_COMPILE=riscv64-linux-
74
+ $ cp boards/mpfs-icicle-kit-es/def_config .config
75
+ $ make BOARD=mpfs-icicle-kit-es
76
+
77
+Download the official SD card image released by Microchip and prepare it for
78
+QEMU usage:
79
+
80
+.. code-block:: bash
81
+
82
+ $ wget ftp://ftpsoc.microsemi.com/outgoing/core-image-minimal-dev-icicle-kit-es-sd-20201009141623.rootfs.wic.gz
83
+ $ gunzip core-image-minimal-dev-icicle-kit-es-sd-20201009141623.rootfs.wic.gz
84
+ $ qemu-img resize core-image-minimal-dev-icicle-kit-es-sd-20201009141623.rootfs.wic 4G
85
+
86
+Then we can boot the machine by:
87
+
88
+.. code-block:: bash
89
+
90
+ $ qemu-system-riscv64 -M microchip-icicle-kit -smp 5 \
91
+ -bios path/to/hss.bin -sd path/to/sdcard.img \
92
+ -nic user,model=cadence_gem \
93
+ -nic tap,ifname=tap,model=cadence_gem,script=no \
94
+ -display none -serial stdio \
95
+ -chardev socket,id=serial1,path=serial1.sock,server=on,wait=on \
96
+ -serial chardev:serial1
97
+
98
+With above command line, current terminal session will be used for the first
99
+serial port. Open another terminal window, and use `minicom` to connect the
100
+second serial port.
101
+
102
+.. code-block:: bash
103
+
104
+ $ minicom -D unix\#serial1.sock
105
+
106
+HSS output is on the first serial port (stdio) and U-Boot outputs on the
107
+second serial port. U-Boot will automatically load the Linux kernel from
108
+the SD card image.
109
+
110
+.. _HSS: https://github.com/polarfire-soc/hart-software-services
111
diff --git a/docs/system/target-riscv.rst b/docs/system/target-riscv.rst
12
index XXXXXXX..XXXXXXX 100644
112
index XXXXXXX..XXXXXXX 100644
13
--- a/target/riscv/op_helper.c
113
--- a/docs/system/target-riscv.rst
14
+++ b/target/riscv/op_helper.c
114
+++ b/docs/system/target-riscv.rst
15
@@ -XXX,XX +XXX,XX @@ target_ulong helper_hyp_load(CPURISCVState *env, target_ulong address,
115
@@ -XXX,XX +XXX,XX @@ undocumented; you can get a complete list by running
16
(env->priv == PRV_U && !riscv_cpu_virt_enabled(env) &&
116
.. toctree::
17
get_field(env->hstatus, HSTATUS_HU))) {
117
:maxdepth: 1
18
target_ulong pte;
118
19
+ int mmu_idx = cpu_mmu_index(env, false) | TB_FLAGS_PRIV_HYP_ACCESS_MASK;
119
+ riscv/microchip-icicle-kit
20
120
riscv/sifive_u
21
riscv_cpu_set_two_stage_lookup(env, true);
121
22
122
RISC-V CPU features
23
switch (memop) {
24
case MO_SB:
25
- pte = cpu_ldsb_data_ra(env, address, GETPC());
26
+ pte = cpu_ldsb_mmuidx_ra(env, address, mmu_idx, GETPC());
27
break;
28
case MO_UB:
29
- pte = cpu_ldub_data_ra(env, address, GETPC());
30
+ pte = cpu_ldub_mmuidx_ra(env, address, mmu_idx, GETPC());
31
break;
32
case MO_TESW:
33
- pte = cpu_ldsw_data_ra(env, address, GETPC());
34
+ pte = cpu_ldsw_mmuidx_ra(env, address, mmu_idx, GETPC());
35
break;
36
case MO_TEUW:
37
- pte = cpu_lduw_data_ra(env, address, GETPC());
38
+ pte = cpu_lduw_mmuidx_ra(env, address, mmu_idx, GETPC());
39
break;
40
case MO_TESL:
41
- pte = cpu_ldl_data_ra(env, address, GETPC());
42
+ pte = cpu_ldl_mmuidx_ra(env, address, mmu_idx, GETPC());
43
break;
44
case MO_TEUL:
45
- pte = cpu_ldl_data_ra(env, address, GETPC());
46
+ pte = cpu_ldl_mmuidx_ra(env, address, mmu_idx, GETPC());
47
break;
48
case MO_TEQ:
49
- pte = cpu_ldq_data_ra(env, address, GETPC());
50
+ pte = cpu_ldq_mmuidx_ra(env, address, mmu_idx, GETPC());
51
break;
52
default:
53
g_assert_not_reached();
54
@@ -XXX,XX +XXX,XX @@ void helper_hyp_store(CPURISCVState *env, target_ulong address,
55
(env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) ||
56
(env->priv == PRV_U && !riscv_cpu_virt_enabled(env) &&
57
get_field(env->hstatus, HSTATUS_HU))) {
58
+ int mmu_idx = cpu_mmu_index(env, false) | TB_FLAGS_PRIV_HYP_ACCESS_MASK;
59
+
60
riscv_cpu_set_two_stage_lookup(env, true);
61
62
switch (memop) {
63
case MO_SB:
64
case MO_UB:
65
- cpu_stb_data_ra(env, address, val, GETPC());
66
+ cpu_stb_mmuidx_ra(env, address, val, mmu_idx, GETPC());
67
break;
68
case MO_TESW:
69
case MO_TEUW:
70
- cpu_stw_data_ra(env, address, val, GETPC());
71
+ cpu_stw_mmuidx_ra(env, address, val, mmu_idx, GETPC());
72
break;
73
case MO_TESL:
74
case MO_TEUL:
75
- cpu_stl_data_ra(env, address, val, GETPC());
76
+ cpu_stl_mmuidx_ra(env, address, val, mmu_idx, GETPC());
77
break;
78
case MO_TEQ:
79
- cpu_stq_data_ra(env, address, val, GETPC());
80
+ cpu_stq_mmuidx_ra(env, address, val, mmu_idx, GETPC());
81
break;
82
default:
83
g_assert_not_reached();
84
@@ -XXX,XX +XXX,XX @@ target_ulong helper_hyp_x_load(CPURISCVState *env, target_ulong address,
85
(env->priv == PRV_U && !riscv_cpu_virt_enabled(env) &&
86
get_field(env->hstatus, HSTATUS_HU))) {
87
target_ulong pte;
88
+ int mmu_idx = cpu_mmu_index(env, false) | TB_FLAGS_PRIV_HYP_ACCESS_MASK;
89
90
riscv_cpu_set_two_stage_lookup(env, true);
91
92
switch (memop) {
93
case MO_TEUW:
94
- pte = cpu_lduw_data_ra(env, address, GETPC());
95
+ pte = cpu_lduw_mmuidx_ra(env, address, mmu_idx, GETPC());
96
break;
97
case MO_TEUL:
98
- pte = cpu_ldl_data_ra(env, address, GETPC());
99
+ pte = cpu_ldl_mmuidx_ra(env, address, mmu_idx, GETPC());
100
break;
101
default:
102
g_assert_not_reached();
103
--
123
--
104
2.29.2
124
2.30.1
105
125
106
126
diff view generated by jsdifflib
New patch
1
1
From: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
2
3
When decode_insn16() fails, we fall back to decode_RV32_64C() for
4
further compressed instruction decoding. However, prior to this change,
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
10
Instead of patching decode_RV32_64C(), we can just remove it,
11
as it is dead code since f330433b363 anyway.
12
13
Signed-off-by: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
14
Reviewed-by: Alistair Francis <alistair.francis@wdc.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>
18
---
19
target/riscv/translate.c | 179 +--------------------------------------
20
1 file changed, 1 insertion(+), 178 deletions(-)
21
22
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/target/riscv/translate.c
25
+++ b/target/riscv/translate.c
26
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
27
CPUState *cs;
28
} DisasContext;
29
30
-#ifdef TARGET_RISCV64
31
-/* convert riscv funct3 to qemu memop for load/store */
32
-static const int tcg_memop_lookup[8] = {
33
- [0 ... 7] = -1,
34
- [0] = MO_SB,
35
- [1] = MO_TESW,
36
- [2] = MO_TESL,
37
- [3] = MO_TEQ,
38
- [4] = MO_UB,
39
- [5] = MO_TEUW,
40
- [6] = MO_TEUL,
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
{
179
TCGv_i32 t0;
180
@@ -XXX,XX +XXX,XX @@ static void gen_set_rm(DisasContext *ctx, int rm)
181
tcg_temp_free_i32(t0);
182
}
183
184
-static void decode_RV32_64C0(DisasContext *ctx, uint16_t opcode)
185
-{
186
- uint8_t funct3 = extract16(opcode, 13, 3);
187
- uint8_t rd_rs2 = GET_C_RS2S(opcode);
188
- uint8_t rs1s = GET_C_RS1S(opcode);
189
-
190
- switch (funct3) {
191
- case 3:
192
-#if defined(TARGET_RISCV64)
193
- /* C.LD(RV64/128) -> ld rd', offset[7:3](rs1')*/
194
- gen_load_c(ctx, OPC_RISC_LD, rd_rs2, rs1s,
195
- GET_C_LD_IMM(opcode));
196
-#else
197
- /* C.FLW (RV32) -> flw rd', offset[6:2](rs1')*/
198
- gen_fp_load(ctx, OPC_RISC_FLW, rd_rs2, rs1s,
199
- GET_C_LW_IMM(opcode));
200
-#endif
201
- break;
202
- case 7:
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
--
241
2.30.1
242
243
diff view generated by jsdifflib