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
24 changes: 24 additions & 0 deletions submissions/gs-chaitanya/README_for_project
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# PMP Checker

This is a simple Python script that simulates a RISC-V Physical Memory Protection (PMP) check. It reads a PMP configuration from a text file and then checks whether a given physical address would be allowed for a specified privilege mode and access type.

## Overview

- **PMP Configuration:** The config file contains 128 lines. The first 64 lines are configuration bytes - one per PMP entry that define permissions (read, write, execute), address matching mode (TOR, NA4, or NAPOT), and whether the entry is locked. The next 64 lines are the corresponding PMP address registers.
- **Access Check:** The script goes through each active PMP entry, computes the effective address range, and then determines if the given physical address falls into one of these regions. If it does, the appropriate permission is checked.
- **Privilege Modes:** Machine mode (`M`) typically bypasses PMP checks unless the entry is locked. Supervisor (`S`) and User (`U`) modes follow the PMP rules strictly.

## Files

- **pmp_check.py:** The main script that reads the configuration file, parses the command-line arguments, and prints whether the access is allowed or not.
- **pmp_config.txt:** A sample configuration file. In this sample, only the first PMP entry is active (using TOR mode with read enabled), while the other entries are disabled.


## Example Usage

```./pmp_check.py pmp_config.txt 0x3000 S R ```

Output :

``` Access Allowed ```

95 changes: 95 additions & 0 deletions submissions/gs-chaitanya/pmp_check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#!/usr/bin/env python3
import sys

PMP_ENTRIES = 64

def count_trailing_ones(n):
cnt = 0
while n & 1:
cnt += 1
n //= 2
return cnt

def load_pmp_config(fname):
with open(fname, 'r') as f:
lines = [line.strip() for line in f if line.strip()]
if len(lines) != 128:
sys.exit("Config file must have 128 lines")
configs = []
for i in range(PMP_ENTRIES):
try:
val = int(lines[i], 16)
except:
sys.exit(f"Bad config on line {i+1}")
configs.append({
'read': bool(val & 0x01),
'write': bool(val & 0x02),
'exec': bool(val & 0x04),
'mode': (val & 0x18) >> 3,
'locked': bool(val & 0x80)
})
addrs = []
for i in range(PMP_ENTRIES, 128):
try:
addrs.append(int(lines[i], 16))
except:
sys.exit(f"Bad addr on line {i+1}")
return configs, addrs

def compute_range(idx, cfg, addrs):
m = cfg['mode']
if m == 1: # TOR
lo = 0 if idx == 0 else addrs[idx-1] << 2
hi = addrs[idx] << 2
return lo, hi
elif m == 2: # NA4
base = addrs[idx] << 2
return base, base + 4
elif m == 3: # NAPOT
raw = addrs[idx]
n = count_trailing_ones(raw)
if n < 1: n = 1
size = 8 << (n - 1)
base = (raw & ~((1 << n) - 1)) << 2
return base, base + size
else:
return None, None

def check_access(configs, addrs, addr, priv, op):
any_enabled = False
for i in range(PMP_ENTRIES):
cfg = configs[i]
if cfg['mode'] == 0:
continue
any_enabled = True
lo, hi = compute_range(i, cfg, addrs)
if lo <= addr < hi:
if priv == 'M' and not cfg['locked']:
return True
if op == 'R' and cfg['read']: return True
if op == 'W' and cfg['write']: return True
if op == 'X' and cfg['exec']: return True
return False
return True if priv == 'M' else not any_enabled

def main():
if len(sys.argv) != 5:
sys.exit("Usage: pmp_check.py <config_file> <addr> <priv> <op>")
config_file, addr_str, priv, op = sys.argv[1:5]
priv, op = priv.upper(), op.upper()
if not addr_str.startswith("0x"):
sys.exit("Address must start with 0x")
try:
addr = int(addr_str, 16)
except:
sys.exit("Invalid address")
if priv not in ('M', 'S', 'U'):
sys.exit("Invalid privilege")
if op not in ('R', 'W', 'X'):
sys.exit("Invalid op")
configs, addrs = load_pmp_config(config_file)
allowed = check_access(configs, addrs, addr, priv, op)
print("Access allowed" if allowed else "Access fault")

if __name__ == '__main__':
main()
128 changes: 128 additions & 0 deletions submissions/gs-chaitanya/pmp_config.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
0x09
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x1000
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0