Skip to content

Commit 7b4ad6f

Browse files
authored
Merge pull request riscv-collab#1152 from fk-sc/translation-drivers
target/riscv: added translation drivers
2 parents bc68bd7 + 6a27d9f commit 7b4ad6f

File tree

6 files changed

+162
-62
lines changed

6 files changed

+162
-62
lines changed

doc/openocd.texi

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11356,16 +11356,18 @@ This command can be used to change the memory access methods if the default
1135611356
behavior is not suitable for a particular target.
1135711357
@end deffn
1135811358

11359-
@deffn {Command} {riscv set_enable_virtual} on|off
11360-
When on, memory accesses are performed on physical or virtual memory depending
11361-
on the current system configuration. When off (default), all memory accessses are performed
11362-
on physical memory.
11363-
@end deffn
11364-
11365-
@deffn {Command} {riscv set_enable_virt2phys} on|off
11366-
When on (default), memory accesses are performed on physical or virtual memory
11367-
depending on the current satp configuration. When off, all memory accessses are
11368-
performed on physical memory.
11359+
@deffn {Command} {riscv virt2phys_mode} [@option{hw}|@option{sw}|@option{off}]
11360+
Configure how OpenOCD translates virtual addresses to physical:
11361+
@itemize @bullet
11362+
@item @option{sw} - OpenOCD translates virtual addresses explicitly by
11363+
traversing the page table entries (by performing physical memory accesses to
11364+
read the respective entries). This is the default mode.
11365+
@item @option{hw} - Virtual addresses are translated implicitly by hardware.
11366+
(Virtual memory access will fail with an error if the hardware doesn't
11367+
support the necessary functionality.)
11368+
@item @option{off} - Virtual addresses are not translated (identity mapping is assumed).
11369+
@end itemize
11370+
Returns current translation mode if called without arguments.
1136911371
@end deffn
1137011372

1137111373
@deffn {Command} {riscv resume_order} normal|reversed

src/target/riscv/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,5 @@ noinst_LTLIBRARIES += %D%/libriscv.la
2626
%D%/riscv_semihosting.c \
2727
%D%/debug_defines.c \
2828
%D%/debug_reg_printer.c
29+
30+
STARTUP_TCL_SRCS += %D%/startup.tcl

src/target/riscv/riscv-013.c

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1995,11 +1995,11 @@ static int examine(struct target *target)
19951995
info->impebreak);
19961996
}
19971997

1998-
if (info->progbufsize < 4 && riscv_enable_virtual) {
1999-
LOG_TARGET_ERROR(target, "set_enable_virtual is not available on this target. It "
2000-
"requires a program buffer size of at least 4. (progbufsize=%d) "
2001-
"Use `riscv set_enable_virtual off` to continue."
2002-
, info->progbufsize);
1998+
if (info->progbufsize < 4 && riscv_virt2phys_mode_is_hw(target)) {
1999+
LOG_TARGET_ERROR(target, "software address translation "
2000+
"is not available on this target. It requires a "
2001+
"program buffer size of at least 4. (progbufsize=%d) "
2002+
"Use `riscv set_enable_virtual off` to continue.", info->progbufsize);
20032003
}
20042004

20052005
/* Don't call any riscv_* functions until after we've counted the number of
@@ -3075,7 +3075,8 @@ static int read_sbcs_nonbusy(struct target *target, uint32_t *sbcs)
30753075

30763076
static int modify_privilege(struct target *target, uint64_t *mstatus, uint64_t *mstatus_old)
30773077
{
3078-
if (riscv_enable_virtual && has_sufficient_progbuf(target, 5)) {
3078+
if (riscv_virt2phys_mode_is_hw(target)
3079+
&& has_sufficient_progbuf(target, 5)) {
30793080
/* Read DCSR */
30803081
uint64_t dcsr;
30813082
if (register_read_direct(target, &dcsr, GDB_REGNO_DCSR) != ERROR_OK)
@@ -4280,7 +4281,8 @@ read_memory_progbuf(struct target *target, target_addr_t address,
42804281
if (modify_privilege(target, &mstatus, &mstatus_old) != ERROR_OK)
42814282
return MEM_ACCESS_FAILED_PRIV_MOD_FAILED;
42824283

4283-
const bool mprven = riscv_enable_virtual && get_field(mstatus, MSTATUS_MPRV);
4284+
const bool mprven = riscv_virt2phys_mode_is_hw(target)
4285+
&& get_field(mstatus, MSTATUS_MPRV);
42844286
const struct memory_access_info access = {
42854287
.target_address = address,
42864288
.increment = increment,
@@ -4852,7 +4854,8 @@ write_memory_progbuf(struct target *target, target_addr_t address,
48524854
if (modify_privilege(target, &mstatus, &mstatus_old) != ERROR_OK)
48534855
return MEM_ACCESS_FAILED_PRIV_MOD_FAILED;
48544856

4855-
const bool mprven = riscv_enable_virtual && get_field(mstatus, MSTATUS_MPRV);
4857+
const bool mprven = riscv_virt2phys_mode_is_hw(target)
4858+
&& get_field(mstatus, MSTATUS_MPRV);
48564859

48574860
int result = write_memory_progbuf_inner(target, address, size, count, buffer, mprven);
48584861

src/target/riscv/riscv.c

Lines changed: 72 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,35 @@ struct tdata1_cache {
139139
struct list_head elem_tdata1;
140140
};
141141

142+
bool riscv_virt2phys_mode_is_hw(const struct target *target)
143+
{
144+
assert(target);
145+
RISCV_INFO(r);
146+
return r->virt2phys_mode == RISCV_VIRT2PHYS_MODE_HW;
147+
}
148+
149+
bool riscv_virt2phys_mode_is_sw(const struct target *target)
150+
{
151+
assert(target);
152+
RISCV_INFO(r);
153+
return r->virt2phys_mode == RISCV_VIRT2PHYS_MODE_SW;
154+
}
155+
156+
const char *riscv_virt2phys_mode_to_str(riscv_virt2phys_mode_t mode)
157+
{
158+
assert(mode == RISCV_VIRT2PHYS_MODE_OFF
159+
|| mode == RISCV_VIRT2PHYS_MODE_SW
160+
|| mode == RISCV_VIRT2PHYS_MODE_HW);
161+
162+
static const char *const names[] = {
163+
[RISCV_VIRT2PHYS_MODE_HW] = "hw",
164+
[RISCV_VIRT2PHYS_MODE_SW] = "sw",
165+
[RISCV_VIRT2PHYS_MODE_OFF] = "off",
166+
};
167+
168+
return names[mode];
169+
}
170+
142171
/* Wall-clock timeout for a command/access. Settable via RISC-V Target commands.*/
143172
static int riscv_command_timeout_sec_value = DEFAULT_COMMAND_TIMEOUT_SEC;
144173

@@ -150,10 +179,6 @@ int riscv_get_command_timeout_sec(void)
150179
return MAX(riscv_command_timeout_sec_value, riscv_reset_timeout_sec);
151180
}
152181

153-
static bool riscv_enable_virt2phys = true;
154-
155-
bool riscv_enable_virtual;
156-
157182
static enum {
158183
RO_NORMAL,
159184
RO_REVERSED
@@ -2714,7 +2739,7 @@ static int riscv_mmu(struct target *target, int *enabled)
27142739
{
27152740
*enabled = 0;
27162741

2717-
if (!riscv_enable_virt2phys)
2742+
if (!riscv_virt2phys_mode_is_sw(target))
27182743
return ERROR_OK;
27192744

27202745
/* Don't use MMU in explicit or effective M (machine) mode */
@@ -3938,16 +3963,6 @@ COMMAND_HANDLER(riscv_set_mem_access)
39383963
return ERROR_OK;
39393964
}
39403965

3941-
COMMAND_HANDLER(riscv_set_enable_virtual)
3942-
{
3943-
if (CMD_ARGC != 1) {
3944-
LOG_ERROR("Command takes exactly 1 parameter");
3945-
return ERROR_COMMAND_SYNTAX_ERROR;
3946-
}
3947-
COMMAND_PARSE_ON_OFF(CMD_ARGV[0], riscv_enable_virtual);
3948-
return ERROR_OK;
3949-
}
3950-
39513966
static int parse_ranges(struct list_head *ranges, const char *tcl_arg, const char *reg_type, unsigned int max_val)
39523967
{
39533968
char *args = strdup(tcl_arg);
@@ -4459,16 +4474,6 @@ COMMAND_HANDLER(riscv_set_maskisr)
44594474
return ERROR_OK;
44604475
}
44614476

4462-
COMMAND_HANDLER(riscv_set_enable_virt2phys)
4463-
{
4464-
if (CMD_ARGC != 1) {
4465-
LOG_ERROR("Command takes exactly 1 parameter");
4466-
return ERROR_COMMAND_SYNTAX_ERROR;
4467-
}
4468-
COMMAND_PARSE_ON_OFF(CMD_ARGV[0], riscv_enable_virt2phys);
4469-
return ERROR_OK;
4470-
}
4471-
44724477
COMMAND_HANDLER(riscv_set_ebreakm)
44734478
{
44744479
struct target *target = get_current_target(CMD_CTX);
@@ -5093,6 +5098,36 @@ COMMAND_HANDLER(handle_reserve_trigger)
50935098
return ERROR_OK;
50945099
}
50955100

5101+
COMMAND_HANDLER(handle_riscv_virt2phys_mode)
5102+
{
5103+
struct riscv_info *info = riscv_info(get_current_target(CMD_CTX));
5104+
if (CMD_ARGC == 0) {
5105+
riscv_virt2phys_mode_t mode = info->virt2phys_mode;
5106+
command_print(CMD, "%s", riscv_virt2phys_mode_to_str(mode));
5107+
return ERROR_OK;
5108+
}
5109+
5110+
if (CMD_ARGC != 1)
5111+
return ERROR_COMMAND_SYNTAX_ERROR;
5112+
5113+
// TODO: add auto mode to allow OpenOCD choose translation mode
5114+
if (!strcmp(CMD_ARGV[0],
5115+
riscv_virt2phys_mode_to_str(RISCV_VIRT2PHYS_MODE_SW))) {
5116+
info->virt2phys_mode = RISCV_VIRT2PHYS_MODE_SW;
5117+
} else if (!strcmp(CMD_ARGV[0],
5118+
riscv_virt2phys_mode_to_str(RISCV_VIRT2PHYS_MODE_HW))) {
5119+
info->virt2phys_mode = RISCV_VIRT2PHYS_MODE_HW;
5120+
} else if (!strcmp(CMD_ARGV[0],
5121+
riscv_virt2phys_mode_to_str(RISCV_VIRT2PHYS_MODE_OFF))) {
5122+
info->virt2phys_mode = RISCV_VIRT2PHYS_MODE_OFF;
5123+
} else {
5124+
command_print(CMD, "Unsupported address translation mode: %s", CMD_ARGV[0]);
5125+
return ERROR_COMMAND_ARGUMENT_INVALID;
5126+
}
5127+
5128+
return ERROR_OK;
5129+
}
5130+
50965131
static const struct command_registration riscv_exec_command_handlers[] = {
50975132
{
50985133
.name = "dump_sample_buf",
@@ -5144,15 +5179,6 @@ static const struct command_registration riscv_exec_command_handlers[] = {
51445179
.help = "Set which memory access methods shall be used and in which order "
51455180
"of priority. Method can be one of: 'progbuf', 'sysbus' or 'abstract'."
51465181
},
5147-
{
5148-
.name = "set_enable_virtual",
5149-
.handler = riscv_set_enable_virtual,
5150-
.mode = COMMAND_ANY,
5151-
.usage = "on|off",
5152-
.help = "When on, memory accesses are performed on physical or virtual "
5153-
"memory depending on the current system configuration. "
5154-
"When off (default), all memory accessses are performed on physical memory."
5155-
},
51565182
{
51575183
.name = "expose_csrs",
51585184
.handler = riscv_set_expose_csrs,
@@ -5277,14 +5303,6 @@ static const struct command_registration riscv_exec_command_handlers[] = {
52775303
.help = "mask riscv interrupts",
52785304
.usage = "['off'|'steponly']",
52795305
},
5280-
{
5281-
.name = "set_enable_virt2phys",
5282-
.handler = riscv_set_enable_virt2phys,
5283-
.mode = COMMAND_ANY,
5284-
.usage = "on|off",
5285-
.help = "When on (default), enable translation from virtual address to "
5286-
"physical address."
5287-
},
52885306
{
52895307
.name = "set_ebreakm",
52905308
.handler = riscv_set_ebreakm,
@@ -5353,6 +5371,16 @@ static const struct command_registration riscv_exec_command_handlers[] = {
53535371
.usage = "[index ('on'|'off')]",
53545372
.help = "Controls which RISC-V triggers shall not be touched by OpenOCD.",
53555373
},
5374+
{
5375+
.name = "virt2phys_mode",
5376+
.handler = handle_riscv_virt2phys_mode,
5377+
.mode = COMMAND_ANY,
5378+
.usage = "['sw'|'hw'|'off']",
5379+
.help = "Configure the virtual address translation mode: "
5380+
"sw - translate vaddr to paddr by manually traversing page tables, "
5381+
"hw - translate vaddr to paddr by hardware, "
5382+
"off - no address translation."
5383+
},
53565384
COMMAND_REGISTRATION_DONE
53575385
};
53585386

@@ -5469,6 +5497,8 @@ static void riscv_info_init(struct target *target, struct riscv_info *r)
54695497

54705498
r->xlen = -1;
54715499

5500+
r->virt2phys_mode = RISCV_VIRT2PHYS_MODE_SW;
5501+
54725502
r->isrmask_mode = RISCV_ISRMASK_OFF;
54735503

54745504
r->mem_access_methods[0] = RISCV_MEM_ACCESS_PROGBUF;

src/target/riscv/riscv.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,14 @@ typedef enum riscv_mem_access_method {
5757
RISCV_MEM_ACCESS_MAX_METHODS_NUM
5858
} riscv_mem_access_method_t;
5959

60+
typedef enum riscv_virt2phys_mode {
61+
RISCV_VIRT2PHYS_MODE_HW,
62+
RISCV_VIRT2PHYS_MODE_SW,
63+
RISCV_VIRT2PHYS_MODE_OFF
64+
} riscv_virt2phys_mode_t;
65+
66+
const char *riscv_virt2phys_mode_to_str(riscv_virt2phys_mode_t mode);
67+
6068
enum riscv_halt_reason {
6169
RISCV_HALT_INTERRUPT,
6270
RISCV_HALT_EBREAK,
@@ -165,6 +173,9 @@ struct riscv_info {
165173
* most recent halt was not caused by a trigger, then this is -1. */
166174
int64_t trigger_hit;
167175

176+
/* The configured approach to translate virtual addresses to physical */
177+
riscv_virt2phys_mode_t virt2phys_mode;
178+
168179
bool triggers_enumerated;
169180

170181
/* Decremented every scan, and when it reaches 0 we clear the learned
@@ -331,11 +342,12 @@ typedef struct {
331342
unsigned int pa_ppn_mask[PG_MAX_LEVEL];
332343
} virt2phys_info_t;
333344

345+
bool riscv_virt2phys_mode_is_hw(const struct target *target);
346+
bool riscv_virt2phys_mode_is_sw(const struct target *target);
347+
334348
/* Wall-clock timeout for a command/access. Settable via RISC-V Target commands.*/
335349
int riscv_get_command_timeout_sec(void);
336350

337-
extern bool riscv_enable_virtual;
338-
339351
/* Everything needs the RISC-V specific info structure, so here's a nice macro
340352
* that provides that. */
341353
static inline struct riscv_info *riscv_info(const struct target *target) __attribute__((unused));

src/target/riscv/startup.tcl

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# SPDX-License-Identifier: GPL-2.0-or-later
2+
3+
lappend _telnet_autocomplete_skip "riscv set_enable_virtual"
4+
proc {riscv set_enable_virtual} on_off {
5+
echo {DEPRECATED! use 'riscv virt2phys_mode' not 'riscv set_enable_virtual'}
6+
foreach t [target names] {
7+
if {[$t cget -type] ne "riscv"} { continue }
8+
switch -- [$t riscv virt2phys_mode] {
9+
off -
10+
hw {
11+
switch -- $on_off {
12+
on {$t riscv virt2phys_mode hw}
13+
off {$t riscv virt2phys_mode off}
14+
}
15+
}
16+
sw {
17+
if {$on_off eq "on"} {
18+
error {Can't enable virtual while translation mode is SW}
19+
}
20+
}
21+
}
22+
}
23+
return {}
24+
}
25+
26+
lappend _telnet_autocomplete_skip "riscv set_enable_virt2phys"
27+
proc {riscv set_enable_virt2phys} on_off {
28+
echo {DEPRECATED! use 'riscv virt2phys_mode' not 'riscv set_enable_virt2phys'}
29+
foreach t [target names] {
30+
if {[$t cget -type] ne "riscv"} { continue }
31+
switch -- [riscv virt2phys_mode] {
32+
off -
33+
sw {
34+
switch -- $on_off {
35+
on {riscv virt2phys_mode sw}
36+
off {riscv virt2phys_mode off}
37+
}
38+
}
39+
hw {
40+
if {$on_off eq "on"} {
41+
error {Can't enable virt2phys while translation mode is HW}
42+
}
43+
}
44+
}
45+
}
46+
return {}
47+
}
48+
49+
proc riscv {cmd args} {
50+
tailcall "riscv $cmd" {*}$args
51+
}

0 commit comments

Comments
 (0)