Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 128 additions & 0 deletions config.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
0x5
0x8
0x81
0xe
0x9
0xc
0x1a
0x98
0x8d
0x19
0x16
0x5
0x18
0x98
0x88
0xd
0x97
0x6
0x9e
0x85
0x4
0x1e
0x8e
0x8b
0x87
0x81
0x9b
0x1b
0x88
0x90
0x80
0x4
0x80
0x1
0x1a
0xe
0x1e
0x96
0x99
0x9b
0x6
0x9c
0x1d
0x17
0xb
0x8b
0x8e
0x8b
0x99
0x8f
0x92
0x8f
0x90
0xa
0x83
0x81
0x4
0x8d
0x90
0x9b
0xb
0x18
0x9d
0x16
0x3ea1b10b
0xf5f85463
0x938d0cac
0xf5668bf5
0x92c9b788
0xe3342ec1
0x87fe14e4
0xcde1965d
0xffc732f7
0x2f5d9985
0xa7036d3
0x35a7951b
0xc70c114d
0xa5b5c0e8
0x82d9b130
0xd047735e
0xabda84de
0xe1133225
0xae1557fe
0x52ed43f7
0x5200c1ed
0x61cad969
0xc3b64ba5
0x7ecdf78
0xd6940c6b
0xd17b765d
0xbf118fc3
0xdd21e0b2
0x55e98b63
0x51b10bb1
0xbb51bae4
0x13babd74
0x4c4979da
0x40626e4b
0x77c27e18
0x371455ef
0x3c4fc2a4
0x9f75c5f7
0x42d1a9bc
0x6b64368f
0x66c71463
0xaf4e25bb
0x4f01628a
0x9e0357ff
0x39f4ed0d
0x5c610a0c
0x91e56dc2
0x654f9678
0x6cba35f5
0x8399baed
0x509d45b3
0xbf44df5f
0xa2a2e4cc
0x20b46f34
0x36d8e64e
0x2dd102e7
0x5333edf8
0xcc082ff
0xbeabde62
0xbf5d75fd
0x44070f87
0xb69cda41
0xf85d9a84
0x3d83c479
181 changes: 181 additions & 0 deletions pmp_access.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
import sys

def load_pmp_config(file_path):

pmp_config_addr = []
pmp_config_addr_0x = []
pmp_config_read = []
pmp_config_write = []
pmp_config_fetch = []
pmp_config_range = []
pmp_config_lock = []

with open(file_path,'r') as file:
for line_number, line in enumerate(file):
stripped_line = line.strip()
if stripped_line.startswith('0x'):
hex_value = stripped_line[2:]

if line_number < 64:
hexToInt = int(hex_value,16)
intToBin = [(hexToInt >> i) & 1 for i in range(7,-1,-1)]
read_config = intToBin[0]
write_config = intToBin[1]
fetch_config = intToBin[2]
range_config = 2*intToBin[4] + intToBin[3]
#No checking here, assume input of bit[6:5] is correct, i.e. 2'b0
lock_config = intToBin[7]
pmp_config_read.append(read_config)
pmp_config_write.append(write_config)
pmp_config_fetch.append(fetch_config)
pmp_config_range.append(range_config)
pmp_config_lock.append(lock_config)
else:
#print(f"Convert pmp[{line_number-64}] 0x:{hex_value} 0b:{format(int(hex_value,16), '032b')} Config lock:{pmp_config_lock[line_number-64]} range:{pmp_config_range[line_number-64]} read:{pmp_config_read[line_number-64]} write:{pmp_config_write[line_number-64]} fetch:{pmp_config_fetch[line_number-64]}")
pmp_config_addr.append(int(hex_value,16))
pmp_config_addr_0x.append(format(int(hex_value,16), '032b'))
else :
raise ValueError(f"Line {line_number+1} config format invalid at line:{stripped_line} ")

return pmp_config_read, pmp_config_write, pmp_config_fetch, pmp_config_range, pmp_config_lock, pmp_config_addr, pmp_config_addr_0x

def check_access(pmp_config_read, pmp_config_write, pmp_config_fetch, pmp_config_range, pmp_config_lock, pmp_config_addr, pmp_config_addr_0x, physical_addr,privilege_mode,operation) :
#initalize local variable:
# previous address as 0, anyPMPEnabled = 0
previous_addr = 0
any_PMP_enabled = 0
# for i from 0 to 63
for i in range(64):
addr_in_range = 0
# check if any PMP is enabled
# get address range of pmpaddr + pmp_config_range
# pmp_config_range:
# 0: disabled, skip, if anyone not 0, anyPMPEnabled = 1
# 1: Top of range, previous address <= addr < pmpaddr
# 2: NA4, 4-bytes start from pmp addr, pmpaddr <= addr < pmpaddr + 3
# 3: NAPOT: read pmpaddr as two parts, seperated by 0
# yyyy...y011: base = yyyy...y000, range: 2^(3 + count(number of 1 after 0))
# yyyy...y000 <= addr < yyyy...y000 + 2^(3+n)-1
# Remarks: remember to start reading from LSB, MSB may have 0s like 100111001...
if(pmp_config_range[i] == 0) :
continue
elif(pmp_config_range[i] == 1) :
if(previous_addr < pmp_config_addr[i]) :
any_PMP_enabled = 1
addr_in_range = (previous_addr <= physical_addr) & (physical_addr < pmp_config_addr[i])
elif(pmp_config_range[i] == 2) :
any_PMP_enabled = 1
addr_in_range = (pmp_config_addr[i] <= physical_addr) & (physical_addr < pmp_config_addr[i] + 4)
elif(pmp_config_range[i] == 3) :
any_PMP_enabled = 1
j = 31
num_of_byte = 8
while(pmp_config_addr_0x[i][j] != '0'):
pmp_config_addr_0x[i] = (pmp_config_addr_0x[i][:j] + '0' + pmp_config_addr_0x[i][j + 1:])
num_of_byte = num_of_byte * 2
j = j - 1
if j == -1:
break
start_addr = int(pmp_config_addr_0x[i], 2)
addr_in_range = (start_addr <= physical_addr) & (physical_addr < (start_addr + num_of_byte))
else :
print(f"PMP range config read error: value{pmp_config_range[i]} should be 0-3")

previous_addr = pmp_config_addr[i]

# check whether physical addr in range
# if not, skip to next one
# else, check permission
# 1.L bit, if L=1, M-mode need to check for R/W/X permission
# 1.1 if L=0, M-mode access always success, S/U-mode check R/W/X premission
# if the physical addr is not in range of any pmp addr config:
# M-mode success, S/U-mode success if all pmpconfig is disabled(create a flag to save whether atleast one is programmed), else fail
if addr_in_range :
#print(f"Address matched reg[{i}], request target:{physical_addr} config_addr:{pmp_config_addr[i]}")
#print(f"Config lock:{pmp_config_lock[i]} range:{pmp_config_range[i]} read:{pmp_config_read[i]} write:{pmp_config_write[i]} fetch:{pmp_config_fetch[i]}")
if(pmp_config_lock[i] == 1):
if(operation == 'R'):
if(pmp_config_read[i]) :
return 0
else :
return 1
elif(operation == 'W') :
if(pmp_config_write[i]) :
return 0
else :
return 1
elif(operation == 'X') :
if(pmp_config_fetch[i]) :
return 0
else :
return 1
else :
if(privilege_mode == 'M') :
return 0
else :
if(operation == 'R'):
if(pmp_config_read[i]) :
return 0
else :
return 1
elif(operation == 'W') :
if(pmp_config_write[i]) :
return 0
else :
return 1
elif(operation == 'X') :
if(pmp_config_fetch[i]) :
return 0
else :
return 1
else :
if (i == 63):
#print("No address matched, try pprivilege_mode checking or no register enabled checking")
if privilege_mode == 'M' :
return 0
else :
return any_PMP_enabled
else:
continue

def main(args):
if len(args) != 4:
print("Please provide exactly four arguments.")
return

config_file, physical_addr_str, privilege_mode, operation = args
#print("Arguments received:")
#print(f"1: {config_file}")
#print(f"2: {physical_addr_str}")
#print(f"3: {privilege_mode}")
#print(f"4: {operation}")

if not physical_addr_str.startswith("0x") :
print("Physical address must start with '0x'.")
return

if not privilege_mode.startswith(("M","S","U")) :
print("Privilege mode must be 'M', 'S', or 'U'.")
return

if not operation.startswith(("R","W","X")) :
print("Operation must be 'R', 'W', or 'X'.")
return

try:
pmp_config_read, pmp_config_write, pmp_config_fetch, pmp_config_range, pmp_config_lock, pmp_config_addr, pmp_config_addr_0x = load_pmp_config(config_file)
except ValueError as e:
print(f"Error loading config file: {e}")
return

physical_addr = int(physical_addr_str,16)

fault = check_access(pmp_config_read, pmp_config_write, pmp_config_fetch, pmp_config_range, pmp_config_lock, pmp_config_addr, pmp_config_addr_0x, physical_addr,privilege_mode,operation)

if fault:
print("Access failed")
else :
print("Access success")

if __name__ == "__main__":
main(sys.argv[1:])
63 changes: 63 additions & 0 deletions pmp_config_gen.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import random


# generate pmp address
# 1. 32-bit random
# 2. conversion




def generate_random_binary_parameters():
# Generate three random binary parameters (1 bit each)
lock = random.randint(0, 1)
range_0 = random.randint(0, 1)
range_1 = random.randint(0,1)
fetch = random.randint(0, 1)
write = random.randint(0, 1)
read = random.randint(0, 1)

return lock, range_1, range_0, fetch, write, read

def concatenate_to_binary(lock, range_1, range_0, fetch, write, read):
# Concatenate the binary parameters into a single binary number
x = f"{lock}00{range_1}{range_0}{fetch}{write}{read}" # This creates a string representation
return x

def convert_to_hexadecimal(binary_str):
# Convert the binary string to an integer, then to hexadecimal
x_int = int(binary_str, 2) # Convert binary string to integer
x_hex = hex(x_int) # Convert integer to hexadecimal
return x_hex

def write_to_file(hex_value):
with open('config.txt', 'w') as file:
file.write(hex_value + '\n') # Write the hex value to the file

def main():
hex_values = [] # List to store hex values for all iterations

for _ in range(64): # Loop for 64 times
lock, range_1, range_0, fetch, write, read = generate_random_binary_parameters() # Generate parameters
binary_str = concatenate_to_binary(lock, range_1, range_0, fetch, write, read) # Concatenate to binary
hex_value = convert_to_hexadecimal(binary_str) # Convert to hexadecimal
hex_values.append(hex_value) # Store hex value

#...another loop for line 64 to 128...
for _ in range(64):
addr = random.randint(0,2**32-1)
hex_value = hex(addr)
hex_values.append(hex_value)

# Write all hex values to the file, replacing previous content
with open('config.txt', 'w') as file:
for hex_value in hex_values:
print(f"writing{hex_value}")
file.write(hex_value + '\n') # Write each hex value to the file

#print("Generated hexadecimal values:")
#for hex_value in hex_values:
# print(hex_value)

if __name__ == "__main__":
main()