Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compatibility with the new SSA convention #33

Merged
merged 33 commits into from
Oct 8, 2021
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
f4af149
Adding linker and stub changes for SSA modification
Aug 14, 2020
4610beb
Adding sm-config feature through yaml file and sm_isr_basic stub
Oct 19, 2020
efca2ec
Simplified sm_entry stack setup, add caller id and renamed sm_sp
Oct 20, 2020
1eba6cc
Adding SSA data section symbols to sym map in linker
Nov 23, 2020
c268832
Adding improved configuration parser and option for peripheral offset
Nov 23, 2020
33e96c8
adjusted SM entry for new clix instruction
Jan 12, 2021
f67e8b5
Bugfix for empty configurations
Jan 15, 2021
b359af4
Move untrusted variable in memory for peripheral offset
Jan 15, 2021
7c4ea61
Adjusting clix length to 100 on SM ENTRY
Jan 21, 2021
ca013a1
Compiler support for interrupt-restart crypto.
jovanbulck Jan 28, 2021
d90fb26
Merge branch 'master' into irq_ssa
jovanbulck Jan 28, 2021
56d59a2
Adding restartable crypto and fixing r2 pop
Jan 30, 2021
4c7fc60
Merge branch 'irq_ssa' of github.com:fritzalder/sancus-compiler into …
Jan 30, 2021
1efad0a
Overwrite ssa_caller_id after OCALL return
Oct 1, 2021
86cb32a
More documentation and clear markings on clix ends
Oct 1, 2021
0470bf6
Add draft for sancus_disable warning
Oct 1, 2021
5f2f8fb
Proposal for compiler intrinsic get_caller_id
Oct 1, 2021
ffcb6e7
sancus_support: Update sancus_disable atomicity note.
jovanbulck Oct 1, 2021
6ce7416
Merge branch 'irq_ssa' of github.com:fritzalder/sancus-compiler into …
jovanbulck Oct 1, 2021
7b51d8e
sm_entry: fill sm_ssa_caller_id on ocall return
jovanbulck Oct 1, 2021
392ed98
Revert "Overwrite ssa_caller_id after OCALL return"
jovanbulck Oct 1, 2021
f734b0e
llvm: simplify sancus_get_caller_id intrinsic
jovanbulck Oct 1, 2021
33a1d1a
Remove support for sancus_verify_caller.
jovanbulck Oct 1, 2021
3602b14
For returns, the compiler may use r12 and not r15.
Oct 7, 2021
7630fa3
Verify caller ID on ECALL and on OCALL return
Oct 7, 2021
1dd1beb
sm_entry: proposal to disallow nested ecalls.
jovanbulck Oct 7, 2021
fa95a6c
sm_entry: sanitize r6 ret_entry idx
jovanbulck Oct 8, 2021
efb3b98
sm_entry: simplify stack initialization out of atomic entry.
jovanbulck Oct 8, 2021
2610b35
sm_entry: fix r6 sanitization and->or
jovanbulck Oct 8, 2021
9b01837
sm_entry: fixes + provoke violation on error
jovanbulck Oct 8, 2021
63c2700
Revert "sm_entry: simplify stack initialization out of atomic entry."
jovanbulck Oct 8, 2021
c9dc870
use sm_sp as OCALL marker
Oct 8, 2021
160c7fd
Remove unused ssa_thread_id
Oct 8, 2021
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
1 change: 1 addition & 0 deletions src/drivers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ set(PY_LIBS
sancus/crypto.py
sancus/paths.py
sancus/config.py
sancus/sancus_config.py
)

install(FILES ${FILES} DESTINATION ${INSTALL_BASE_DIR})
Expand Down
4 changes: 3 additions & 1 deletion src/drivers/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,9 @@ def call_prog(prog, arguments=[], get_output=False):


def fatal_error(msg):
error(msg)
W = '\033[0m' # white (normal)
R = '\033[31m' # red
error(R + msg + W)
sys.exit(1)


Expand Down
137 changes: 120 additions & 17 deletions src/drivers/linker.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import re
import os
from pathlib import Path
import string
from collections import defaultdict

Expand All @@ -10,6 +11,7 @@

import sancus.config
import sancus.paths
from sancus.sancus_config import SmParserError, SmConfigMalformedError, SmConfigParser, SmConfig

from common import *

Expand Down Expand Up @@ -181,6 +183,17 @@ def sort_key(entry):
'libraries that are given as a full path (-l:/path/to/file.a). '
'As such, it does not scan -lm style libraries unnecessarily.',
action='store_true')
parser.add_argument('--sm-config-file',
help='Use a config file for SMs to specify which asm stubs to use.'
'This is useful if multiple SMs have different roles (e.g. Scheduler and '
'normal modules. This is also useful if one wants to use different stubs '
'than the ones provided by the scheduler. See sm-config-example.yaml for documentation.',
type=Path)
parser.add_argument('--project-path', type=Path, default=os.getcwd(),
help='To allow some flexibility in sm-config-files, we allow the special parameter '
'$PROJECT that is substituted for this Path in the linker. This allows projects '
'to give the linker the correct path at compile time while still supporting a generic, '
'project-dependent configuration file.')

args, cli_ld_args = parser.parse_known_args()
set_args(args)
Expand Down Expand Up @@ -444,9 +457,36 @@ def sort_key(entry):
debug('Not checking {} for SMs because it is not a valid '
'ELF file ({})'.format(file_name, e))


"""
Now, we parse the YAML file if given.
The YAML file allows to set the following things:
1) warn whenever an ocall is performed and abort linking process
2) Swap out assembly stubs for custom project dependent values
3) Set a peripheral offset for the first SM to
"""
try:
file_path = ''
if args.sm_config_file:
file_path = args.sm_config_file
configparser = SmConfigParser(str(file_path), list(sms) + list(mmio_sms), str(args.project_path), sancus.paths.get_data_path())
except Exception as e:
fatal_error("Encountered error during YAML configuration parsing:" + e)

sm_config = configparser.sm_config

# On debug output, print yaml config
debug("YAML SM config:..")
for k,v in sm_config.items():
debug("%s: %s" % (k, str(v)))
debug("YAML config end.")

for sm in sms_entries:
sort_entries(sms_entries[sm])

# any SM wanting to continue secret section in peripheral space, should be first
sms = sorted(sms, key=configparser.sort_sm_name)

if len(sms) > 0:
info('Found new Sancus modules:')
for sm in sms:
Expand Down Expand Up @@ -478,6 +518,8 @@ def sort_key(entry):
if sm in sms_with_isr:
info(' - Can be used as ISR ({})'
.format(', '.join(sms_irq_handlers[sm])))

info(' - YAML SM Configuration: {}'.format(str(sm_config[sm])))
else:
info('No new Sancus modules found')

Expand All @@ -501,9 +543,21 @@ def sort_key(entry):
cid = mmio_sms[sm]['caller_id'] if 'caller_id' in mmio_sms[sm] else 'any'
info(' - Config: callerID={}, private data=[{:#x}, {:#x}['.format(
cid, mmio_sms[sm]['secret_start'], mmio_sms[sm]['secret_end']))
info(' - YAML SM Configuration: {}'.format(str(sm_config[sm])))
else:
info('No asm Sancus modules found')

# Warn if disallowed outcalls happened
for name,config in sm_config.items():
if hasattr(config, 'disallow_outcalls') and config.disallow_outcalls:
# Warn if there are outcalls
if len(sms_unprotected_calls[name]) > 0:
info("ERROR: %s has outcalls disallowed according to sm config file %s." % (name, args.sm_config_file))
info("However, %s has these outcalls:" % name)
info(' - SM calls: {}'.format(', '.join(sms_calls[name])))
fatal_error("Aborting since this constraint is violated.")
else:
info("Outcalls are disabled in %s and I encountered none." % name)

if args.inline_arithmetic:
# create sm_mul asm stub for each unique SM multiplication symbol
Expand Down Expand Up @@ -597,23 +651,36 @@ def sort_key(entry):
}}'''

data_section = '''. = ALIGN(2);
__sm_{0}_secret_start = .;
{5} /* Placeholder for data_section_start (optional offset of data section in case of peripheral offset) */
*(.sm.{0}.data)
. = ALIGN(2);
{1}
. += {2};
. = ALIGN(2);
__sm_{0}_stack_init = .;
. += 2;
__sm_{0}_sp = .;
. += 2;
__sm_{0}_ssa_end = .;
. += 26;
__sm_{0}_ssa_sp = .;
. += 2;
__sm_{0}_ssa_base = .;
__sm_{0}_pc = .;
. += 2;
__sm_{0}_ssa_thread_id = .;
. += 2;
__sm_{0}_ssa_caller_id = .;
. += 2;
__sm_{0}_irq_sp = .;
. += 2;
__sm_{0}_tmp = .;
. += 2;
. = ALIGN(2);
{3}
{4}
__sm_{0}_sp_addr = .; /* make sure this is the last address in data
section, as HW IRQ logic will store SP here */
__sm_{0}_ssa_base_addr = .; /* make sure this is the last address in data
section, as HW IRQ logic will look for SSA base pointer here */
. += 2;
. = ALIGN(2);
__sm_{0}_secret_end = .;'''
Expand Down Expand Up @@ -669,15 +736,22 @@ def sort_key(entry):
'__sm_isr_func' : '__sm_{}_isr_func'.format(sm),
'__sm_nentries' : nentries,
'__sm_table' : '__sm_{}_table'.format(sm),
'__sm_sp_addr' : '__sm_{}_sp_addr'.format(sm),
'__sm_ssa_base_addr' : '__sm_{}_ssa_base_addr'.format(sm),
'__sm_ssa_base' : '__sm_{}_ssa_base'.format(sm),
'__sm_ssa_end' : '__sm_{}_ssa_end'.format(sm),
'__sm_ssa_sp' : '__sm_{}_ssa_sp'.format(sm),
'__sm_sp' : '__sm_{}_sp'.format(sm),
'__sm_pc' : '__sm_{}_pc'.format(sm),
'__sm_ssa_thread_id' : '__sm_{}_ssa_thread_id'.format(sm),
'__sm_ssa_caller_id' : '__sm_{}_ssa_caller_id'.format(sm),
'__sm_irq_sp' : '__sm_{}_irq_sp'.format(sm),
'__sm_tmp' : '__sm_{}_tmp'.format(sm),
'__ret_entry' : '__sm_{}_ret_entry'.format(sm),
'__reti_entry' : '__sm_{}_reti_entry'.format(sm),
'__sm_exit' : '__sm_{}_exit'.format(sm),
'__sm_stack_init' : '__sm_{}_stack_init'.format(sm),
'__sm_verify' : '__sm_{}_verify'.format(sm)}
'__sm_verify' : '__sm_{}_verify'.format(sm)
}
sect_map = {'.sm.text' : '.sm.{}.text'.format(sm)}

tables = []
Expand All @@ -695,13 +769,28 @@ def sort_key(entry):
verify_file = rename_syms_sects(object, sym_map, sect_map)
generated_object_files.append(verify_file)

entry_file = rename_syms_sects(sancus.paths.get_data_path() + '/sm_entry.o',
sym_map, sect_map)
entry_file_name = sancus.paths.get_data_path() + '/' + 'sm_entry.o'
isr_file_name = 'sm_isr.o' if sm in sms_with_isr else 'sm_isr_dummy.o'
isr_file = rename_syms_sects(
sancus.paths.get_data_path() + '/' + isr_file_name, sym_map, sect_map)
exit_file = rename_syms_sects(sancus.paths.get_data_path() + '/sm_exit.o',
sym_map, sect_map)
isr_file_name = sancus.paths.get_data_path() + '/' + isr_file_name
exit_file_name = sancus.paths.get_data_path() + '/' + 'sm_exit.o'

# Get config for sm and see if there are options that overwrite the defaults:
if hasattr(sm_config[sm], "sm_entry"):
entry_file_name = sm_config[sm].sm_entry
info("%s: SM entry swapped out for %s" % (sm, entry_file_name))

if hasattr(sm_config[sm], "sm_isr"):
isr_file_name = sm_config[sm].sm_isr
info("%s: SM ISR swapped out for %s" % (sm, isr_file_name))

if hasattr(sm_config[sm], "sm_exit"):
exit_file_name = sm_config[sm].sm_exit
info("%s: SM exit swapped out for %s" % (sm, exit_file_name))

entry_file = rename_syms_sects(entry_file_name, sym_map, sect_map)
isr_file = rename_syms_sects(isr_file_name, sym_map, sect_map)
exit_file = rename_syms_sects(exit_file_name, sym_map, sect_map)

generated_object_files += [entry_file, isr_file, exit_file]

extra_labels = ['__isr_{} = .;'.format(n) for n in sms_irq_handlers[sm]]
Expand Down Expand Up @@ -759,13 +848,22 @@ def sort_key(entry):
outputs_nonce += ' . += 2;\n'
outputs_nonce += ' . = ALIGN(2);'

# Set data section offset if peripheral access is set
# in that case, optionally provide first SM with exclusive access to last peripheral
data_section_start = ''
data_section_start = '__sm_{}_secret_start = .;'.format(sm)
if hasattr(sm_config[sm], 'peripheral_offset'):
data_section_start = '__sm_{0}_secret_start = (. - {1});'.format(sm, sm_config[sm].peripheral_offset)

text_sections.append(text_section.format(sm, entry_file, isr_file,
exit_file, '\n '.join(tables),
input_callbacks,
'\n '.join(extra_labels)))

data_sections.append(data_section.format(sm, '\n '.join(id_syms),
args.sm_stack_size, io_keys,
outputs_nonce))
outputs_nonce,
data_section_start))

if sm in sms_entries:
num_entries = len(sms_entries[sm])
Expand Down Expand Up @@ -805,12 +903,17 @@ def sort_key(entry):
for entry in sms_entries[sm]]

verifyCaller = 'caller_id' in mmio_sms[sm]
entry_file = '/sm_mmio_exclusive.o' if verifyCaller else '/sm_mmio_entry.o'
entry_file = rename_syms_sects(sancus.paths.get_data_path() + entry_file,
sym_map, sect_map)
entry_file_name = '/sm_mmio_exclusive.o' if verifyCaller else '/sm_mmio_entry.o'
entry_file_name = sancus.paths.get_data_path() + entry_file_name

# Get config for sm and see if there are options that overwrite the defaults:
if hasattr(sm_config[sm],"sm_mmio_entry"):
entry_file_name = sm_config[sm].sm_mmio_entry
info("%s: MMIO entry swapped out for %s" % (sm, entry_file_name))

entry_file = rename_syms_sects(entry_file_name, sym_map, sect_map)
args.in_files += entry_file
text_sections.append(mmio_text_section.format(sm, entry_file,
'\n '.join(tables)))
text_sections.append(mmio_text_section.format(sm, entry_file, '\n '.join(tables)))

# create symbol table with values known at link time
m = mmio_sms[sm]
Expand Down
26 changes: 13 additions & 13 deletions src/drivers/msp430.x
Original file line number Diff line number Diff line change
Expand Up @@ -80,28 +80,28 @@ SECTIONS
$sm_mac_sections
$sm_wrap_info_sections
_etext = .; /* Past last read-only (loadable) segment */
.bss :
{
PROVIDE (__bss_start = .) ;
$sm_data_sections
__unprotected_sp = .;
. += 2;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(2);
PROVIDE (__bss_end = .) ;
} > REGION_DATA AT > REGION_TEXT
PROVIDE (__bss_size = SIZEOF(.bss) );
.data :
{
. = ALIGN(2);
PROVIDE (__data_start = .) ;
*(.data .data.* .gnu.linkonce.d.*)
. = ALIGN(2);
} > REGION_DATA AT > REGION_TEXT
} > REGION_DATA
_edata = . ; /* Past last read-write (loadable) segment */
PROVIDE (__data_load_start = LOADADDR(.data) );
PROVIDE (__data_size = _edata - __data_start );
.bss :
{
PROVIDE (__bss_start = .) ;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(2);
__unprotected_sp = .;
. += 2;
$sm_data_sections
PROVIDE (__bss_end = .) ;
} > REGION_DATA
PROVIDE (__bss_size = SIZEOF(.bss) );
.noinit :
{
PROVIDE (__noinit_start = .) ;
Expand Down
Loading