9191
9292
9393class Application (Component ):
94+ # path of file where the names of functions called via gate are collected
95+ VMEPT_FUNC_LIST_PATH = "/tmp/flexos_vmept_rpc_id_data"
96+
97+ # name and path of auto-generated header file containing the function addresses
98+ VMEPT_ADDR_TABLE_NAME = "vmept_addr_table"
99+
100+ # where to put auto-generated header files (relative to the unikraft build directory)
101+ VMEPT_AUTOGEN_INCLUDE_PATH = "lib/flexos-core/include/flexos/impl"
102+
94103 _type = ComponentType .APP
95104
96105 _config = None
@@ -605,6 +614,29 @@ def fetch(ctx, self, verbose=False):
605614
606615 return self .make (extra , verbose )
607616
617+ # generate a header containing an array with the addresses of functions called via EPT-gate
618+ def vmept_gen_address_table_header (self , func_names , header_name , addr_map = {}, write_to_file = True ):
619+ include_guard = "%s_H" % header_name .upper ()
620+ header_code = "#ifndef %s\n " % include_guard
621+ header_code += "#define %s\n \n " % include_guard
622+ header_code += 'static const void* flexos_vmept_addr_table[] __attribute__((section (".rodata"))) = {\n '
623+ num_entries = len (func_names )
624+ i = 0
625+ for fname in func_names :
626+ i += 1
627+ sep = "," if i < num_entries else " "
628+ addr = addr_map [fname ] if fname in addr_map else 0
629+ header_code += "\t (void*) 0x%016x%s /* %s */\n " % (addr , sep , fname )
630+ header_code += "};\n \n "
631+ header_code += "#endif /* %s */" % include_guard
632+ if write_to_file :
633+ addr_table_path = os .path .join (self .unikraft .localdir , self .VMEPT_AUTOGEN_INCLUDE_PATH )
634+ addr_table_path = os .path .join (addr_table_path , self .VMEPT_ADDR_TABLE_NAME + ".h" )
635+ addr_table_file = open (addr_table_path , "w" )
636+ addr_table_file .write (header_code )
637+ addr_table_file .close ()
638+ return header_code
639+
608640 @click .pass_context
609641 def compartmentalize (ctx , self ):
610642 self .find_files ()
@@ -792,6 +824,12 @@ def simple_replace(template_path, path, marker, shstack_enabled=True):
792824 cmd = ["diff" , "-urNp" , backup_src , filep ]
793825 subprocess .call (cmd , stdout = fulldiff , stderr = subprocess .STDOUT )
794826
827+ is_ept = type (self .compartments [0 ].mechanism .driver ) == VMEPTDriver
828+ if is_ept and not os .path .isfile (self .VMEPT_FUNC_LIST_PATH ):
829+ # make sure this file exists
830+ rpc_id_file = open (self .VMEPT_FUNC_LIST_PATH , "w" )
831+ rpc_id_file .close ()
832+
795833 # now do library-specific rewrites
796834 for lib in self .libraries :
797835 # first add per-library linker scripts
@@ -810,6 +848,13 @@ def simple_replace(template_path, path, marker, shstack_enabled=True):
810848 str (lib .compartment .number ))
811849 gr_rule = ""
812850
851+ ept_rpc_id_prefix = "_RPC_ID_" if is_ept else ""
852+ if (is_ept ):
853+ rpc_id_gen_template = get_sec_rule ("rpc_id_gen.cocci.in" )
854+ rpc_id_gen_template = rpc_id_gen_template .replace ("{{ filename }}" ,
855+ "'" + self .VMEPT_FUNC_LIST_PATH + "'" )
856+ gr_rule = rpc_id_gen_template + "\n "
857+
813858 def gr_gen_rule (dest_name , dest_comp ):
814859 gr_rule = str (gr_rule_template )
815860 name = dest_name
@@ -825,6 +870,9 @@ def gr_gen_rule(dest_name, dest_comp):
825870 if dest_comp == lib .compartment :
826871 # FIXME magic value, put somewhere
827872 gr_gate = "flexos_nop_gate"
873+ gr_rule = gr_rule .replace ("{{ ept_id_prefix }}" , "" )
874+ else :
875+ gr_rule = gr_rule .replace ("{{ ept_id_prefix }}" , ept_rpc_id_prefix )
828876
829877 gr_rule = gr_rule .replace ("{{ gate }}" , gr_gate )
830878 gr_rule = gr_rule .replace ("{{ gate_r }}" , gr_gate + "_r" )
@@ -868,6 +916,7 @@ def cb_gen_rule(dest_name, dest_comp):
868916 # with future upstream releases of Coccinelle, talking about it with Julia
869917 whitelisted_libs = ["libvfscore" , "libuknetdev" , "newlib" ,
870918 "libuksched" , "libuksignal" , "libukboot" ]
919+
871920 for dest_lib in self .libraries :
872921 if (not dest_lib .compartment .default ) and (dest_lib .name != lib .name ):
873922 # this library is not in the default compartment, add a specific rule
@@ -920,6 +969,34 @@ def cb_gen_rule(dest_name, dest_comp):
920969
921970 coccinelle_rewrite (lib , rule_file , fulldiff )
922971
972+ # generate a header with macros defining IDs for all
973+ # functions given by function_names
974+ def vmept_gen_rpc_id_macro_header (function_names , header_name ):
975+ include_guard = "%s_H" % header_name .upper ()
976+ header_code = "#ifndef %s\n " % include_guard
977+ header_code += "#define %s\n \n " % include_guard
978+ rpc_id = 0
979+ for fname in function_names :
980+ header_code += "#define %s%s %d\n " % (ept_rpc_id_prefix , fname , rpc_id )
981+ rpc_id += 1
982+ header_code += "\n #define FLEXOS_VMEPT_RPCID_CNT %d\n \n " % rpc_id
983+ header_code += "#endif /* %s */" % include_guard
984+ return header_code
985+
986+ if (is_ept ):
987+ rpc_id_file = open (self .VMEPT_FUNC_LIST_PATH , "r" )
988+ fnames = list (map (str .strip , rpc_id_file .readlines ()))
989+ rpc_id_file .close ()
990+ id_header_name = "vmept_rpc_id"
991+ addr_table_name = "flexos_%s" % self .VMEPT_ADDR_TABLE_NAME
992+ id_header_code = vmept_gen_rpc_id_macro_header (fnames , id_header_name )
993+ addr_table_code = self .vmept_gen_address_table_header (fnames , addr_table_name , write_to_file = True )
994+ id_header_path = os .path .join (self .unikraft .localdir , self .VMEPT_AUTOGEN_INCLUDE_PATH )
995+ id_header_path = os .path .join (id_header_path , id_header_name + ".h" )
996+ id_header_file = open (id_header_path , "w" )
997+ id_header_file .write (id_header_code )
998+ id_header_file .close ()
999+
9231000 logger .info ("Full diff of rewritings: %s" % fulldifff )
9241001 fulldiff .close ()
9251002
0 commit comments