On 30 October 2014 11:20, Jens Wiklander jens.wiklander@linaro.org wrote:
Hi toolchain champions,
[please keep me in cc as I'm not subscribed to linaro-toolchain@lists.linaro.org]
In OP-TEE we are going to activate a pager which is an integrated part of the statically linked secure OS binary (compiled for ARMv7/Aarch32 now, but at some point also Aarch64).
The pager in OP-TEE allows use of more memory than the amount of available physical memory. This makes it possible to for instance have an OP-TEE binary that requires more memory than the amount of available memory. What the pager does is to map a physical page at the virtual address where the memory is needed and populate it which what is expected on demand. The pager also unmaps physical pages that hasn't been used in a while to be able to recycle it.
The code used by the pager to map and populate a page must always be mapped since we would otherwise get a deadlock. The problem is that the pager is also part of OP-TEE so we need to partition the binary in a way that all code needed to handle a page fault is in one area in the binary and always mapped.
Annotating functions and such as it's done in the Linux kernel with __init will not scale here since the pager will need routines from "third-party" libraries. We can make small changes to the libraries but identifying and annotating everything needed by the pager is too much. We would also run into troubles with strings.
I have a couple ideas below that I need help exploring.
What if we do an incremental linking of the entire TEE Core with garbage collect only keeping the entry functions of the pager? Then we would get an object file with everything the pager depends on included but not much more. It would be easy to put this single object file in a separate part of the OP-TEE binary. The procedure would be something like:
Compile everything with -ffunction-sections -fdata-sections ld -i --gc-sections -u pager_entry -o pager_code.o $(objs) $(link-ldadd) $(libgcc) ld $(link-ldflags) pager_code.o $(objs) $(link-ldadd) $(libgcc)
But the problem comes with linking in the rest of the code in the last step, we would get lots of multiple defined symbols. We could create a libtee_core.a file where we put all the $(objs) files and the linker would only use the needed object files. But we would still have some multiple defined symbols left since each .o file contains more than just one section.
Any ideas how to solve this?
If you can confirm that the first step correctly produces a kernel with all the pager dependencies, couldn't you wrap all remaining code into a static library and link against that? This would solve the multiple definition issue as the archive members will be pulled in on demand. The only thing you need to ensure is that the granularity is sufficient, i.e., if the linker decides to pull a .o from the static lib, it will pull all contents including symbols that may conflict, but I would expect the -ffunction-sections -fdata-sections to take care of that.
Another trick that I know bionic uses for the loader is to prefix all symbols using objcopy --prefix-symbols=... That way, you can work around the multiple definitions, but you may end up with duplicate data which is a bit of a hazard.