From 1b4f7ae0d30295a7efebeff50648826746d80ab6 Mon Sep 17 00:00:00 2001 From: Sebastian Sumpf Date: Wed, 10 Jan 2024 20:43:07 +0100 Subject: [PATCH] lx_emul: generate initcalls during build Functions registered with 'module_init' (i.e., '__define_initcalls'), 'OF_DECLARE', and 'DECLARE_PCI_FIXUP_CLASS_FINAL' used to be static constructors and had be explicitly registered using 'exec_static_constructors' before executing any Linux code. With this commit we remove the constructor attributes from these functions and create a global function pointer in the form of __initptr____ 'import-lx_emul_common.inc' will collect these '__initptr' symbols after the compile step and generate a 'lx_emul_register_initcalls' function that executes the functions pointed to. This step is now automatically performed in 'lx_emul_start_kernel'. This way a call to 'exec_static_constructors' can be omitted in case there are no other constructors in place. issue #5096 --- .../lib/import/import-lx_emul_common.inc | 54 +++++++++++++++++++ repos/dde_linux/src/include/lx_emul/init.h | 3 ++ .../lx_emul/shadow/include/linux/init.h | 15 ++++-- .../include/lx_emul/shadow/include/linux/of.h | 20 ++++--- .../lx_emul/shadow/include/linux/pci.h | 12 +++-- repos/dde_linux/src/lib/lx_emul/init.cc | 3 ++ repos/pc/lib/import/import-pc_lx_emul.mk | 2 +- 7 files changed, 92 insertions(+), 17 deletions(-) diff --git a/repos/dde_linux/lib/import/import-lx_emul_common.inc b/repos/dde_linux/lib/import/import-lx_emul_common.inc index e16ec1fa11..fc2a169083 100644 --- a/repos/dde_linux/lib/import/import-lx_emul_common.inc +++ b/repos/dde_linux/lib/import/import-lx_emul_common.inc @@ -211,3 +211,57 @@ GLOBAL_DEPS += $(wildcard $(addsuffix /linux/*.h,$(SHADOW_INC_DIR))) \ GLOBAL_DEPS += $(wildcard $(addsuffix /linux/*.h,$(SPEC_SHADOW_INC_DIR))) \ $(wildcard $(addsuffix /asm/*.h,$(SPEC_SHADOW_INC_DIR))) + +# +# Generate initcall_table.c and create 'lx_emul_register_initcalls' which calls +# global '__initptr_*' functions created by 'module_init' +# + +define print_file_header +echo "/*" > $(2); +echo " * \\brief Register initcalls from __initptr_*" >> $(2); +echo " * \\author Automatically generated file - do no edit" >> $(2); +echo " * \\date $(1)" >> $(2); +echo " */" >> $(2); +echo "" >> $(2); +echo "" >> $(2); +endef + +define print_declaration +echo "extern void * $(1);" >> $(2); +endef + +define print_function_start +echo "" >> $(1) +echo "void lx_emul_register_initcalls(void)" >> $(1); +echo "{" >> $(1); +echo " typedef void (*func)(void);" >> $(1); +endef + +define print_call +echo " ((func)$(1))();" >> $(2); +endef + +define print_function_end +echo "}" >> $(1); +endef + + +# 'module_init' calls should only be in C-sources +WAIT_FOR_OBJECTS = $(addsuffix .o,$(basename $(filter-out initcall_table.c,$(SRC_C)))) + +# retrieve 'initptr_*' using nm from object files +INITCALLS = $(sort $(shell $(NM) -U $(WAIT_FOR_OBJECTS) |\ + grep "__initptr" |\ + awk '{print $$3}')) + +SRC_C += initcall_table.c + +initcall_table.c: $(WAIT_FOR_OBJECTS) + $(MSG_CONFIG)$@ + @$(call print_file_header,$(shell date +"%F"),$@) + @$(foreach sym,$(INITCALLS),$(call print_declaration,$(sym),$@)) + @$(call print_function_start,$@) + @$(foreach sym,$(INITCALLS),$(call print_call,$(sym),$@)) + @$(call print_function_end,$@) + diff --git a/repos/dde_linux/src/include/lx_emul/init.h b/repos/dde_linux/src/include/lx_emul/init.h index 6a3a535ef9..fac92465bb 100644 --- a/repos/dde_linux/src/include/lx_emul/init.h +++ b/repos/dde_linux/src/include/lx_emul/init.h @@ -20,6 +20,9 @@ extern "C" { void lx_emul_initcalls(void); +/* this function is generated into 'initcall_table.c' */ +void lx_emul_register_initcalls(void); + void lx_emul_register_initcall(int (*initcall)(void), const char * name); void lx_emul_start_kernel(void * dtb); diff --git a/repos/dde_linux/src/include/lx_emul/shadow/include/linux/init.h b/repos/dde_linux/src/include/lx_emul/shadow/include/linux/init.h index 42f9f2db62..6cfa48491b 100644 --- a/repos/dde_linux/src/include/lx_emul/shadow/include/linux/init.h +++ b/repos/dde_linux/src/include/lx_emul/shadow/include/linux/init.h @@ -27,9 +27,16 @@ #undef ___define_initcall #undef __define_initcall -#define __define_initcall(fn, id) \ - static void __initcall_##fn##id(void)__attribute__((constructor)); \ - static void __initcall_##fn##id() { \ - lx_emul_register_initcall(fn, __func__); }; +/* + * Define local register function and global pointer to function in the form + * '__initptr____' + */ +#define __define_initcall(fn, id) \ + static void __initcall_##fn##id(void) { \ + lx_emul_register_initcall(fn, __func__); } \ + \ + void * __PASTE(__initptr_##fn##id##_, \ + __PASTE(__COUNTER__, \ + __PASTE(_,__LINE__))) = __initcall_##fn##id; #endif /* _LX_EMUL__SHADOW__LINUX__INIT_H_ */ diff --git a/repos/dde_linux/src/include/lx_emul/shadow/include/linux/of.h b/repos/dde_linux/src/include/lx_emul/shadow/include/linux/of.h index 4716fae6b6..f9e8466dba 100644 --- a/repos/dde_linux/src/include/lx_emul/shadow/include/linux/of.h +++ b/repos/dde_linux/src/include/lx_emul/shadow/include/linux/of.h @@ -21,15 +21,19 @@ #undef OF_DECLARE_2 /* used to populate __clk_of_table */ -#define OF_DECLARE_1(table, name, compat, fn) \ - static void __of_declare_initcall_##name(void) __attribute__((constructor)); \ - static void __of_declare_initcall_##name() { \ - lx_emul_register_of_##table##_initcall(compat, fn); }; +#define OF_DECLARE_1(table, name, compat, fn) \ + static void __of_declare_initcall_##name(void) { \ + lx_emul_register_of_##table##_initcall(compat, fn); }; \ + void * __PASTE(__initptr_of_declare_initcall_##name##_, \ + __PASTE(__COUNTER__, \ + __PASTE(_, __LINE__))) = __of_declare_initcall_##name; /* used to populate __irqchip_of_table */ -#define OF_DECLARE_2(table, name, compat, fn) \ - static void __of_declare_initcall_##name(void) __attribute__((constructor)); \ - static void __of_declare_initcall_##name() { \ - lx_emul_register_of_##table##_initcall(compat, fn); }; +#define OF_DECLARE_2(table, name, compat, fn) \ + static void __of_declare_initcall_##name(void) { \ + lx_emul_register_of_##table##_initcall(compat, fn); }; \ + void * __PASTE(__initptr_of_declare_initcall_##name##_, \ + __PASTE(__COUNTER__, \ + __PASTE(_, __LINE__))) = __of_declare_initcall_##name; #endif /* _LX_EMUL__SHADOW__LINUX__OF_H_ */ diff --git a/repos/dde_linux/src/include/lx_emul/shadow/include/linux/pci.h b/repos/dde_linux/src/include/lx_emul/shadow/include/linux/pci.h index c0e5b85356..4906a157cf 100644 --- a/repos/dde_linux/src/include/lx_emul/shadow/include/linux/pci.h +++ b/repos/dde_linux/src/include/lx_emul/shadow/include/linux/pci.h @@ -14,9 +14,13 @@ #undef DECLARE_PCI_FIXUP_CLASS_FINAL #define DECLARE_PCI_FIXUP_CLASS_FINAL(vendor, device, class, \ - class_shift, hook) \ -static void __pci_fixup_final_##hook(struct pci_dev *dev) __attribute__((constructor)); \ -static void __pci_fixup_final_##hook(struct pci_dev *dev) { \ - lx_emul_register_pci_fixup(hook, __func__); }; + class_shift, hook) \ +static void __pci_fixup_final_##hook(struct pci_dev *dev) { \ + lx_emul_register_pci_fixup(hook, __func__); }; \ + void * __PASTE(__initptr_pci_fixup_final_##hook##_, \ + __PASTE(__COUNTER__, \ + __PASTE(_, __LINE__))) = __pci_fixup_final_##hook; + + #endif /* _LINUX__PCI_H_ */ diff --git a/repos/dde_linux/src/lib/lx_emul/init.cc b/repos/dde_linux/src/lib/lx_emul/init.cc index 8ede087777..7d91b65abb 100644 --- a/repos/dde_linux/src/lib/lx_emul/init.cc +++ b/repos/dde_linux/src/lib/lx_emul/init.cc @@ -52,6 +52,9 @@ extern "C" void lx_emul_start_kernel(void * dtb) { using namespace Lx_kit; + /* register 'module_init' calls and friends */ + lx_emul_register_initcalls(); + new (env().heap) Task(lx_emul_init_task_function, dtb, lx_emul_init_task_struct, SWAPPER_PID, "swapper", env().scheduler, Task::TIME_HANDLER); diff --git a/repos/pc/lib/import/import-pc_lx_emul.mk b/repos/pc/lib/import/import-pc_lx_emul.mk index 4d804c0a09..d00bb5ddc8 100644 --- a/repos/pc/lib/import/import-pc_lx_emul.mk +++ b/repos/pc/lib/import/import-pc_lx_emul.mk @@ -44,7 +44,7 @@ SRC_C += lx_emul/shadow/drivers/pci/search.c SRC_C += lx_emul/shadow/drivers/pci/setup-irq.c SRC_C += lx_emul/shadow/drivers/pci/setup-res.c SRC_CC += lx_emul/pci.cc -SRC_CC += lx_emul/pci_bus.c +SRC_C += lx_emul/pci_bus.c SRC_CC += lx_kit/device.cc SRC_CC += lx_kit/memory_dma.cc