Skip to content

Commit

Permalink
tcl: generic pmp config detection for esp riscv chips
Browse files Browse the repository at this point in the history
  • Loading branch information
sobuch authored and erhankur committed Oct 23, 2024
1 parent ecbd5e8 commit 3fd7030
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 160 deletions.
32 changes: 10 additions & 22 deletions tcl/target/esp32c2.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -79,34 +79,22 @@ proc esp32c2_soc_reset { } {
}

proc esp32c2_memprot_is_enabled { } {
global _RISCV_ABS_CMD _RISCV_ABS_DATA0

# In order to determine if the IRAM region is protected against RWX/RW,
# it is necessary to read PMP configuration and address registers,
# and look for a chip-specific settings set by IDF.

set IRAM_LOW 0x40380000
set IRAM_HIGH 0x403C0000
set PMP_RWX 0x07
set PMP_RW 0x03
set PMP_A 0x18
set PMP_A_TOR 0x08

# Read pmpcfg0 and extract 8-bit pmp1cfg.
riscv dmi_write $_RISCV_ABS_CMD 0x2203a0
set pmpcfg0 [riscv dmi_read $_RISCV_ABS_DATA0]
set pmp1cfg [expr {($pmpcfg0 >> (8 * 1)) & 0xFF}]

# read PMPADDR 0-1
riscv dmi_write $_RISCV_ABS_CMD 0x2203b0
set pmpaddr0 [expr {[riscv dmi_read $_RISCV_ABS_DATA0] << 2}]
riscv dmi_write $_RISCV_ABS_CMD 0x2203b1
set pmpaddr1 [expr {[riscv dmi_read $_RISCV_ABS_DATA0] << 2}]

set pmp1cfg [pmp_read_pmpxcfg 1]
set pmp3cfg [pmp_read_pmpxcfg 3]

# Check IRAM access
if {($pmp1cfg & $PMP_RWX) != $PMP_RWX && ($pmp1cfg & $PMP_A) == $PMP_A_TOR} {
if {$pmpaddr0 >= $IRAM_LOW && $pmpaddr1 <= $IRAM_HIGH} {
return 1
}
return 1
}

# Check DRAM access
if {($pmp3cfg & $PMP_RW) != $PMP_RW && ($pmp3cfg & $PMP_A) == $PMP_A_TOR} {
return 1
}

return 0
Expand Down
30 changes: 1 addition & 29 deletions tcl/target/esp32c5.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -92,38 +92,10 @@ proc esp32c5_soc_reset { } {
}

proc esp32c5_memprot_is_enabled { } {
global _RISCV_ABS_CMD _RISCV_ABS_DATA0


# In order to determine if the RAM region is protected against RWX/RW,
# it is necessary to read PMP configuration and address registers,
# and look for a chip-specific settings set by IDF.

set RAM_LOW 0x40800000
set RAM_HIGH 0x40880000
set PMP_RWX 0x07
set PMP_RW 0x03
set PMP_A 0x18
set PMP_A_TOR 0x08

# Read pmpcfg1 and extract 8-bit pmp5cfg.
riscv dmi_write $_RISCV_ABS_CMD 0x2203a1
set pmpcfg1 [riscv dmi_read $_RISCV_ABS_DATA0]
set pmp5cfg [expr {($pmpcfg1 >> (8 * 1)) & 0xFF}]

# Read PMPADDR 4-5
riscv dmi_write $_RISCV_ABS_CMD 0x2203b4
set pmpaddr4 [expr {[riscv dmi_read $_RISCV_ABS_DATA0] << 2}]
riscv dmi_write $_RISCV_ABS_CMD 0x2203b5
set pmpaddr5 [expr {[riscv dmi_read $_RISCV_ABS_DATA0] << 2}]

if {($pmp6cfg & $PMP_RWX) != $PMP_RWX && ($pmp6cfg & $PMP_A) == $PMP_A_TOR} {
if {$pmpaddr4 >= $RAM_LOW && $pmpaddr5 <= $RAM_HIGH} {
return 1
}
}

return 0
return [pmp_check_region_protected $RAM_LOW $RAM_HIGH]
}

create_esp_target $_ESP_ARCH
Expand Down
28 changes: 1 addition & 27 deletions tcl/target/esp32c6.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -98,36 +98,10 @@ proc esp32c6_soc_reset { } {
}

proc esp32c6_memprot_is_enabled { } {
global _RISCV_ABS_CMD _RISCV_ABS_DATA0

# In order to determine if the RAM region is protected against RWX/RW,
# it is necessary to read PMP configuration and address registers,
# and look for a chip-specific settings set by IDF.

set RAM_LOW 0x40800000
set RAM_HIGH 0x40880000
set PMP_RWX 0x07
set PMP_A 0x18
set PMP_A_TOR 0x08

# Read pmpcfg1 and extract 8-bit pmp6cfg.
riscv dmi_write $_RISCV_ABS_CMD 0x2203a1
set pmpcfg1 [riscv dmi_read $_RISCV_ABS_DATA0]
set pmp6cfg [expr {($pmpcfg1 >> (8 * 2)) & 0xFF}]

# Read PMPADDR 5-6
riscv dmi_write $_RISCV_ABS_CMD 0x2203b5
set pmpaddr5 [expr {[riscv dmi_read $_RISCV_ABS_DATA0] << 2}]
riscv dmi_write $_RISCV_ABS_CMD 0x2203b6
set pmpaddr6 [expr {[riscv dmi_read $_RISCV_ABS_DATA0] << 2}]

if {($pmp6cfg & $PMP_RWX) != $PMP_RWX && ($pmp6cfg & $PMP_A) == $PMP_A_TOR} {
if {$pmpaddr5 >= $RAM_LOW && $pmpaddr6 <= $RAM_HIGH} {
return 1
}
}

return 0
return [pmp_check_region_protected $RAM_LOW $RAM_HIGH]
}

create_esp_target $_ESP_ARCH
Expand Down
29 changes: 1 addition & 28 deletions tcl/target/esp32c61.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -93,37 +93,10 @@ proc esp32c61_soc_reset { } {
}

proc esp32c61_memprot_is_enabled { } {
global _RISCV_ABS_CMD _RISCV_ABS_DATA0

# In order to determine if the RAM region is protected against RWX/RW,
# it is necessary to read PMP configuration and address registers,
# and look for a chip-specific settings set by IDF.

set RAM_LOW 0x40800000
set RAM_HIGH 0x40880000
set PMP_RWX 0x07
set PMP_RW 0x03
set PMP_A 0x18
set PMP_A_TOR 0x08

# Read pmpcfg1 and extract 8-bit pmp6cfg.
riscv dmi_write $_RISCV_ABS_CMD 0x2203a1
set pmpcfg1 [riscv dmi_read $_RISCV_ABS_DATA0]
set pmp6cfg [expr {($pmpcfg1 >> (8 * 2)) & 0xFF}]

# Read PMPADDR 5-6
riscv dmi_write $_RISCV_ABS_CMD 0x2203b5
set pmpaddr5 [expr {[riscv dmi_read $_RISCV_ABS_DATA0] << 2}]
riscv dmi_write $_RISCV_ABS_CMD 0x2203b6
set pmpaddr6 [expr {[riscv dmi_read $_RISCV_ABS_DATA0] << 2}]

if {($pmp6cfg & $PMP_RWX) != $PMP_RWX && ($pmp6cfg & $PMP_A) == $PMP_A_TOR} {
if {$pmpaddr5 >= $RAM_LOW && $pmpaddr6 <= $RAM_HIGH} {
return 1
}
}

return 0
return [pmp_check_region_protected $RAM_LOW $RAM_HIGH]
}

create_esp_target $_ESP_ARCH
Expand Down
28 changes: 1 addition & 27 deletions tcl/target/esp32h2.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -80,36 +80,10 @@ proc esp32h2_soc_reset { } {
}

proc esp32h2_memprot_is_enabled { } {
global _RISCV_ABS_CMD _RISCV_ABS_DATA0

# In order to determine if the RAM region is protected against RWX/RW,
# it is necessary to read PMP configuration and address registers,
# and look for a chip-specific settings set by IDF.

set RAM_LOW 0x40800000
set RAM_HIGH 0x40850000
set PMP_RWX 0x07
set PMP_A 0x18
set PMP_A_TOR 0x08

# Read pmpcfg1 and extract 8-bit pmp7cfg.
riscv dmi_write $_RISCV_ABS_CMD 0x2203a1
set pmpcfg1 [riscv dmi_read $_RISCV_ABS_DATA0]
set pmp7cfg [expr {($pmpcfg1 >> (8 * 3)) & 0xFF}]

# Read PMPADDR 4-5
riscv dmi_write $_RISCV_ABS_CMD 0x2203b6
set pmpaddr6 [expr {[riscv dmi_read $_RISCV_ABS_DATA0] << 2}]
riscv dmi_write $_RISCV_ABS_CMD 0x2203b7
set pmpaddr7 [expr {[riscv dmi_read $_RISCV_ABS_DATA0] << 2}]

if {($pmp7cfg & $PMP_RWX) != $PMP_RWX && ($pmp7cfg & $PMP_A) == $PMP_A_TOR} {
if {$pmpaddr6 >= $RAM_LOW && $pmpaddr7 <= $RAM_HIGH} {
return 1
}
}

return 0
return [pmp_check_region_protected $RAM_LOW $RAM_HIGH]
}

create_esp_target $_ESP_ARCH
Expand Down
28 changes: 1 addition & 27 deletions tcl/target/esp32p4.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -93,36 +93,10 @@ proc esp32p4_soc_reset { } {
}

proc esp32p4_memprot_is_enabled { } {
global _RISCV_ABS_CMD _RISCV_ABS_DATA0

# In order to determine if the RAM region is protected against RWX/RW,
# it is necessary to read PMP configuration and address registers,
# and look for a chip-specific settings set by IDF.

set RAM_LOW 0x4FF00000
set RAM_HIGH 0x4FFC0000
set PMP_RWX 0x07
set PMP_A 0x18
set PMP_A_TOR 0x08

# Read pmpcfg1 and extract 8-bit pmp5cfg.
riscv dmi_write $_RISCV_ABS_CMD 0x2203a1
set pmpcfg1 [riscv dmi_read $_RISCV_ABS_DATA0]
set pmp5cfg [expr {($pmpcfg1 >> (8 * 1)) & 0xFF}]

# Read PMPADDR 4-5
riscv dmi_write $_RISCV_ABS_CMD 0x2203b4
set pmpaddr4 [expr {[riscv dmi_read $_RISCV_ABS_DATA0] << 2}]
riscv dmi_write $_RISCV_ABS_CMD 0x2203b5
set pmpaddr5 [expr {[riscv dmi_read $_RISCV_ABS_DATA0] << 2}]

if {($pmp5cfg & $PMP_RWX) != $PMP_RWX && ($pmp5cfg & $PMP_A) == $PMP_A_TOR} {
if {$pmpaddr4 >= $RAM_LOW && $pmpaddr5 <= $RAM_HIGH} {
return 1
}
}

return 0
return [pmp_check_region_protected $RAM_LOW $RAM_HIGH]
}

proc create_esp32p4_jtag { } {
Expand Down
91 changes: 91 additions & 0 deletions tcl/target/esp_common.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -679,3 +679,94 @@ proc esp_semihost_basedir {dir} {
$tgt arm semihosting_basedir $dir
}
}

proc pmp_read_pmpaddrx { num } {
global _RISCV_ABS_CMD _RISCV_ABS_DATA0

set cmd [expr {0x2203b0 + $num}]
riscv dmi_write $_RISCV_ABS_CMD $cmd
return [riscv dmi_read $_RISCV_ABS_DATA0]
}

proc pmp_read_pmpxcfg { num } {
global _RISCV_ABS_CMD _RISCV_ABS_DATA0

set offset [expr {$num % 4}]
set num [expr {$num / 4}]

set cmd [expr {0x2203a0 + $num}]
riscv dmi_write $_RISCV_ABS_CMD $cmd
set pmpcfg [riscv dmi_read $_RISCV_ABS_DATA0]
return [expr {($pmpcfg >> (8 * $offset)) & 0xFF}]
}

proc pmp_check_tor_region_overlap { num addrl addrh } {
set pmpaddrh [expr {[pmp_read_pmpaddrx $num] << 2}]

if {$num == 0} {
set pmpaddrl 0
} else {
set num [expr {$num -1}]
set pmpaddrl [expr {[pmp_read_pmpaddrx $num] << 2}]
}

if {$pmpaddrl <= $addrh && $addrl <= $pmpaddrh} {
return 1
}

return 0
}

proc pmp_get_napot_size { num } {
set pmpaddr [expr {[pmp_read_pmpaddrx $num]}]

for { set i 1 } { $pmpaddr & 0x1 } { set i [expr {$i + 1}]} {
set pmpaddr [expr {$pmpaddr >> 1}]
}

return $i
}

proc pmp_check_napot_region_overlap { num size addrl addrh } {
set pmpaddrl [expr {([pmp_read_pmpaddrx $num] & (-1 << $size)) << 2}]
set pmpaddrh [expr {$pmpaddrl + (1 << $size + 2)}]

if {$pmpaddrl <= $addrh && $addrl < $pmpaddrh} {
return 1
}

return 0
}

proc pmp_check_region_protected { addrl addrh } {
set PMP_RWX 0x07
set PMP_A 0x18
set PMP_A_TOR 0x08
set PMP_A_NA4 0x10
set PMP_A_NAPOT 0x18

for { set i 0 } { $i < 16 } { set i [expr {$i + 1}]} {
set pmpcfg [pmp_read_pmpxcfg $i]

if {($pmpcfg & $PMP_RWX) != $PMP_RWX} {
if {($pmpcfg & $PMP_A) == $PMP_A_TOR} {
if { [pmp_check_tor_region_overlap $i $addrl $addrh] } {
return 1
}
}
if {($pmpcfg & $PMP_A) == $PMP_A_NA4} {
if { [pmp_check_napot_region_overlap $i 0 $addrl $addrh] } {
return 1
}
}
if {($pmpcfg & $PMP_A) == $PMP_A_NAPOT} {
set size [pmp_get_napot_size $i]
if { [pmp_check_napot_region_overlap $i $size $addrl $addrh] } {
return 1
}
}
}
}

return 0
}

0 comments on commit 3fd7030

Please sign in to comment.