Skip to content

Commit

Permalink
[racl] Static ROT_PRIVATE protection of racl_ctrl
Browse files Browse the repository at this point in the history
Signed-off-by: Robert Schilling <[email protected]>
  • Loading branch information
Razer6 committed Jan 8, 2025
1 parent 4ed8390 commit 69f3aaa
Show file tree
Hide file tree
Showing 10 changed files with 96 additions and 23 deletions.
2 changes: 1 addition & 1 deletion hw/ip_templates/racl_ctrl/data/racl_ctrl.hjson.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
{clock: "clk_i", reset: "rst_ni"},
]
bus_interfaces: [
{ protocol: "tlul", direction: "device" }
{ protocol: "tlul", direction: "device", static_racl_support: true }
],
alert_list: [
% if enable_shadow_reg:
Expand Down
41 changes: 25 additions & 16 deletions hw/ip_templates/racl_ctrl/rtl/racl_ctrl.sv.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

module ${module_instance_name} import ${module_instance_name}_reg_pkg::*; #(
parameter logic [NumAlerts-1:0] AlertAsyncOn = {NumAlerts{1'b1}},
parameter int unsigned NumSubscribingIps = 1
parameter int unsigned NumSubscribingIps = 1,
parameter bit RaclErrorRsp = 1'b1
) (
input logic clk_i,
input logic rst_ni,
Expand Down Expand Up @@ -38,21 +39,26 @@ module ${module_instance_name} import ${module_instance_name}_reg_pkg::*; #(
% if enable_shadow_reg:
// SEC_CM: RACL_POLICY.CONFIG.SHADOW
% endif
${module_instance_name}_reg_top u_racl_ctrl_reg (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
${module_instance_name}_reg_top u_racl_ctrl_reg #(
.EnableRacl ( 1'b1 ),
.RaclErrorRsp ( RaclErrorRsp )
u_racl_ctrl_reg (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
% if enable_shadow_reg:
.rst_shadowed_ni ( rst_shadowed_ni ),
.rst_shadowed_ni ( rst_shadowed_ni ),
% endif
.tl_i ( tl_i ),
.tl_o ( tl_o ),
.reg2hw ( reg2hw ),
.hw2reg ( hw2reg ),
.tl_i ( tl_i ),
.tl_o ( tl_o ),
.reg2hw ( reg2hw ),
.hw2reg ( hw2reg ),
% if enable_shadow_reg:
.shadowed_storage_err_o ( shadowed_storage_err ),
.shadowed_update_err_o ( shadowed_update_err ),
.shadowed_storage_err_o ( shadowed_storage_err ),
.shadowed_update_err_o ( shadowed_update_err ),
% endif
.intg_err_o ( reg_intg_error )
.racl_error_o ( racl_ctrl_racl_error ),
.racl_error_log_o ( racl_ctrl_racl_error_log ),
.intg_err_o ( reg_intg_error )
);

//////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -130,7 +136,8 @@ module ${module_instance_name} import ${module_instance_name}_reg_pkg::*; #(
`ASSERT(OneHotRaclError_A, $onehot0(racl_error_i))
logic racl_error;
assign racl_error = |racl_error_i;
// A combined RACL error from external subscribing IPs in the racl_ctrl internal reg_top
assign racl_error = |racl_error_i | racl_ctrl_racl_error;
top_racl_pkg::racl_role_t racl_error_role;
top_racl_pkg::ctn_uid_t racl_error_ctn_uid;
Expand All @@ -139,9 +146,11 @@ module ${module_instance_name} import ${module_instance_name}_reg_pkg::*; #(
// Reduce all incoming error vectors to a single role and write/read bit.
// Only a single IP can have a RACL error at one time.
always_comb begin
racl_error_role = '0;
racl_error_ctn_uid = '0;
racl_error_read_not_write = 1'b0;
// Default to the racl_ctrl reg_top error information. Possible since only
// one error allowed at a time.
racl_error_role = racl_ctrl_racl_error_log.racl_role;
racl_error_ctn_uid = racl_ctrl_racl_error_log.ctn_uid;
racl_error_read_not_write = racl_ctrl_racl_error_log.read_not_write;
for (int i = 0; i < NumSubscribingIps; i++) begin
racl_error_role |= racl_error_log_i[i].racl_role;
racl_error_ctn_uid |= racl_error_log_i[i].ctn_uid;
Expand Down
6 changes: 6 additions & 0 deletions hw/top_darjeeling/rtl/autogen/top_racl_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ package top_racl_pkg;
// Default policy vector for unconnected RACL IPs
parameter racl_policy_vec_t RACL_POLICY_VEC_DEFAULT = '0;

// Default ROT Private read policy value
parameter racl_policy_vec_t RACL_POLICY_ROT_PRIVATE_RD = 16'h0;

// Default ROT Private write policy value
parameter racl_policy_vec_t RACL_POLICY_ROT_PRIVATE_WR = 16'h0;

// RACL information logged in case of a denial
typedef struct packed {
racl_role_t racl_role;
Expand Down
3 changes: 3 additions & 0 deletions hw/top_darjeeling/templates/toplevel.sv.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,9 @@ max_intrwidth = (max(len(x.name) for x in block.interrupts)
.RaclPolicySelVec(top_racl_pkg::RACL_POLICY_SEL_${m["name"].upper()}${if_prefix}),
% endfor
% endif
% if m['type'].startswith('racl_ctrl'):
.RaclErrorRsp(${"1'b1" if top['racl']['error_response'] else "1'b0"}),
% endif
% if block.alerts:
<%
w = len(block.alerts)
Expand Down
6 changes: 6 additions & 0 deletions hw/top_earlgrey/rtl/autogen/top_racl_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ package top_racl_pkg;
// Default policy vector for unconnected RACL IPs
parameter racl_policy_vec_t RACL_POLICY_VEC_DEFAULT = '0;

// Default ROT Private read policy value
parameter racl_policy_vec_t RACL_POLICY_ROT_PRIVATE_RD = 16'h0;

// Default ROT Private write policy value
parameter racl_policy_vec_t RACL_POLICY_ROT_PRIVATE_WR = 16'h0;

// RACL information logged in case of a denial
typedef struct packed {
racl_role_t racl_role;
Expand Down
3 changes: 3 additions & 0 deletions hw/top_earlgrey/templates/toplevel.sv.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,9 @@ max_intrwidth = (max(len(x.name) for x in block.interrupts)
.RaclPolicySelVec(top_racl_pkg::RACL_POLICY_SEL_${m["name"].upper()}${if_prefix}),
% endfor
% endif
% if m['type'].startswith('racl_ctrl'):
.RaclErrorRsp(${"1'b1" if top['racl']['error_response'] else "1'b0"}),
% endif
% if block.alerts:
<%
w = len(block.alerts)
Expand Down
15 changes: 15 additions & 0 deletions util/raclgen/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
DEFAULT_RACL_CONFIG = {
'nr_policies': 1,
'policies': {},
'rot_private_policy_rd': 0,
'rot_private_policy_wr': 0
}


Expand All @@ -45,6 +47,7 @@ def parse_racl_config(config_path: str) -> Dict[str, object]:
# RTL needs to create the vectors based on the largest group
racl_config['nr_policies'] = max(len(policies) for policies in racl_config['policies'].values())

rot_private_policy = None
for racl_group, policies in racl_config['policies'].items():
for policy in policies:
def compute_policy_value(permission: str) -> int:
Expand All @@ -56,6 +59,18 @@ def compute_policy_value(permission: str) -> int:

policy['rd_default'] = compute_policy_value('allowed_rd')
policy['wr_default'] = compute_policy_value('allowed_wr')
if policy.get('rot_private'):
if rot_private_policy:
raise ValueError('Only one policy can be the ROT_PRIVATE policy')
rot_private_policy = policy

if not rot_private_policy:
raise ValueError('No ROT_PRIVATE policy defined')

# Get the default ROT private policy for static RACL protection of the racl_ctrl IP(s)
racl_config['rot_private_policy_rd'] = rot_private_policy['rd_default']
racl_config['rot_private_policy_wr'] = rot_private_policy['wr_default']

return racl_config


Expand Down
17 changes: 14 additions & 3 deletions util/reggen/bus_interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ def __init__(self,
named_devices: List[str],
device_async: Dict[Optional[str], str],
device_hier_paths: Dict[Optional[str], str],
racl_support: Dict[Optional[str], bool]):
racl_support: Dict[Optional[str], bool],
static_racl_support: Dict[Optional[str], bool]):
assert has_unnamed_device or named_devices
assert len(named_hosts) == len(set(named_hosts))
assert len(named_devices) == len(set(named_devices))
Expand All @@ -32,6 +33,7 @@ def __init__(self,
self.device_async = device_async
self.device_hier_paths = device_hier_paths
self.racl_support = racl_support
self.static_racl_support = static_racl_support

@staticmethod
def from_raw(raw: object, where: str) -> 'BusInterfaces':
Expand All @@ -44,12 +46,14 @@ def from_raw(raw: object, where: str) -> 'BusInterfaces':
device_async = {}
device_hier_paths = {}
racl_support_map = {}
static_racl_support_map = {}

for idx, raw_entry in enumerate(check_list(raw, where)):
entry_what = 'entry {} of {}'.format(idx + 1, where)
ed = check_keys(raw_entry, entry_what,
['protocol', 'direction'],
['name', 'async', 'hier_path', 'racl_support'])
['name', 'async', 'hier_path',
'racl_support', 'static_racl_support'])

protocol = check_str(ed['protocol'],
'protocol field of ' + entry_what)
Expand All @@ -74,6 +78,8 @@ def from_raw(raw: object, where: str) -> 'BusInterfaces':

racl_support = check_optional_bool(ed.get('racl_support'),
'racl_support field of ' + entry_what)
static_racl_support = check_optional_bool(ed.get('static_racl_support'),
'static_racl_support field of ' + entry_what)

if direction == 'host':
if name is None:
Expand Down Expand Up @@ -117,14 +123,19 @@ def from_raw(raw: object, where: str) -> 'BusInterfaces':
else:
device_hier_paths[name] = 'u_reg'

if racl_support and static_racl_support:
raise ValueError("Device interface cannot support both static and dynamic RACL")

racl_support_map[name] = bool(racl_support)
static_racl_support_map[name] = bool(static_racl_support)

if not (has_unnamed_device or named_devices):
raise ValueError('No device interface at ' + where)

return BusInterfaces(has_unnamed_host, named_hosts, host_async,
has_unnamed_device, named_devices,
device_async, device_hier_paths, racl_support_map)
device_async, device_hier_paths,
racl_support_map, static_racl_support_map)

def has_host(self) -> bool:
return bool(self.has_unnamed_host or self.named_hosts)
Expand Down
20 changes: 17 additions & 3 deletions util/reggen/reg_top.sv.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@
reg2hw_t = gen_rtl.get_iface_tx_type(block, if_name, False)
hw2reg_t = gen_rtl.get_iface_tx_type(block, if_name, True)

racl_support = block.bus_interfaces.racl_support[if_name]
dynamic_racl_support = block.bus_interfaces.racl_support[if_name]
static_racl_support = block.bus_interfaces.static_racl_support[if_name]
racl_support = dynamic_racl_support or static_racl_support

win_array_decl = f' [{num_wins}]' if num_wins > 1 else ''

Expand Down Expand Up @@ -121,8 +123,10 @@ module ${mod_name}${' (' if not racl_support else ''}
% if racl_support:
# (
parameter bit EnableRacl = 1'b0,
parameter bit RaclErrorRsp = 1'b1,
parameter bit RaclErrorRsp = 1'b1${"," if dynamic_racl_support else ""}
% if dynamic_racl_support:
parameter int unsigned RaclPolicySelVec[${len(rb.flat_regs)}] = '{${len(rb.flat_regs)}{0}}
% endif
) (
% endif
input clk_i,
Expand Down Expand Up @@ -158,7 +162,9 @@ module ${mod_name}${' (' if not racl_support else ''}
%endif
% if racl_support:
// RACL interface
% if dynamic_racl_support:
input top_racl_pkg::racl_policy_vec_t racl_policies_i,
% endif
output logic racl_error_o,
output top_racl_pkg::racl_error_log_t racl_error_log_o,

Expand Down Expand Up @@ -700,12 +706,20 @@ ${finst_gen(sr, field, finst_name, fsig_name, fidx)}

if (EnableRacl) begin : gen_racl_hit
for (int unsigned slice_idx = 0; slice_idx < ${len(regs_flat)}; slice_idx++) begin
% if dynamic_racl_support:
racl_addr_hit_read[slice_idx] =
addr_hit[slice_idx] & (|(racl_policies_i[RaclPolicySelVec[slice_idx]].read_perm
& racl_role_vec));
racl_addr_hit_write[slice_idx] =
addr_hit[slice_idx] & (|(racl_policies_i[RaclPolicySelVec[slice_idx]].write_perm
& racl_role_vec));
% else:
// Static RACL protection with ROT_PRIVATE policy
racl_addr_hit_read[slice_idx] =
addr_hit[slice_idx] & (|(top_racl_pkg::RACL_POLICY_ROT_PRIVATE_RD & racl_role_vec));
racl_addr_hit_write[slice_idx] =
addr_hit[slice_idx] & (|(top_racl_pkg::RACL_POLICY_ROT_PRIVATE_WR & racl_role_vec));
% endif
end
end else begin : gen_no_racl
racl_addr_hit_read = addr_hit;
Expand Down Expand Up @@ -916,7 +930,7 @@ ${rdata_gen(f, r.name.lower() + "_" + f.name.lower())}\
assign unused_wdata = ^reg_wdata;
assign unused_be = ^reg_be;
% endif
% if racl_support:
% if dynamic_racl_support:
logic unused_policy_sel;
assign unused_policy_sel = ^racl_policies_i;
% endif
Expand Down
6 changes: 6 additions & 0 deletions util/topgen/templates/toplevel_racl_pkg.sv.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ package top_racl_pkg;
// Default policy vector for unconnected RACL IPs
parameter racl_policy_vec_t RACL_POLICY_VEC_DEFAULT = '0;

// Default ROT Private read policy value
parameter racl_policy_vec_t RACL_POLICY_ROT_PRIVATE_RD = 16'h${f"{racl_config['rot_private_policy_rd']:x}"};

// Default ROT Private write policy value
parameter racl_policy_vec_t RACL_POLICY_ROT_PRIVATE_WR = 16'h${f"{racl_config['rot_private_policy_wr']:x}"};

// RACL information logged in case of a denial
typedef struct packed {
racl_role_t racl_role;
Expand Down

0 comments on commit 69f3aaa

Please sign in to comment.