In my opinion, Arm TF-A (EL3) has higher privileges than Linux Kernel (EL1), and Secure World should be able to access all memory address in Normal World. To verify this feature, I added a new SMC call in Arm TF-A and wrote a kernel module to test it (on a Hikey960 Development Board). But the program does not run as expected that Arm TF-A stucked while accessing the memory address passed by Linux Kernel.
Here is my kernel module, which uses `alloc_pages` to acquire a physical address, and uses `page_address` converting it to a virtual address. And the module passes the physical address and the virtual address to Arm TF-A using `smc #0`:
```cpp static int __init smc_testing_init(void) { uintptr_t phys_addr, virt_addr;
pr_info("Mmodule loaded\n");
phys_addr = (uintptr_t) alloc_pages(GFP_KERNEL, 2); virt_addr = (uintptr_t) page_address((struct page *) phys_addr); memset((void *) virt_addr, 'A', PAGE_SIZE << 2); printk("phys_addr: 0x%llx, virt_addr: 0x%llx\n", (uint64_t) phys_addr, (uint64_t) virt_addr);
asm volatile( "ldr x0, =0xC8000003\n" "mov x1, %0\n" "mov x2, %1\n" "smc #0\n" : : "r" (phys_addr), "r" (virt_addr) : "x0", "x1", "x2" );
__free_pages((struct page *) phys_addr, 2);
return 0; }
static void __exit smc_testing_exit(void) {
pr_info("Module unloaded\n"); } ```
And here is the handler's code in Arm TF-A, which prints the addresses of physical address and virtual address, and access the first element of the memory address:
```cpp if (0xC8000003 == smc_fid) { uintptr_t virt_addr = x3;
NOTICE("phys_addr: 0x%lx, virt_addr: 0x%lx\n", phys_addr, virt_addr); NOTICE("virt_addr[0] = 0x%x\n", *((uint32_t *)virt_addr)); NOTICE("phys_addr[0] = 0x%x\n", *((uint32_t *)phys_addr));
SMC_RET0(handle); } ```
Here is the output, Arm TF-A handles the request successfully, but failed to access the memory address passed by Linux Kernel:
```bash # insmod ./smc_testing.ko [ 75.259590] smc_testing: loading out-of-tree module taints kernel. [ 75.266682] Mmodule loaded [ 75.269404] phys_addr: 0xfffffc0002dc5e00, virt_addr: 0xffff0000b7178000 NOTICE: phys_addr: 0xfffffc0002dc5e00, virt_addr: 0xffff0000b7178000 [ 96.276605] rcu: INFO: rcu_preempt detected stalls on CPUs/tasks: [ 96.282741] rcu: 4-...0: (1 ticks this GP) idle=72ec/1/0x4000000000000000 softirq=204/204 fqs=2592 [ 96.291835] (detected by 0, t=5253 jiffies, g=-643, q=16 ncpus=8) [ 96.298044] Task dump for CPU 4: [ 96.301287] task:insmod state:R running task stack:0 pid:201 ppid:185 flags:0x00000006 [ 96.311254] Call trace: [ 96.313713] __switch_to+0xe4/0x160 [ 96.317241] printk_rb_static+0x30/0x58 ```