Assuming I have a system with a TrustZone enabled CPU and off-SoC DRAM that can be protected with a TZASC (e.g. TZC-400). How is access to the TZASC registers that are used to configure the access permissions for the DRAM regions controlled?
If I configure the permissions during boot up but do not lock them down because I might want to change them during run-time, can every code running in secure mode reconfigure the TZASC or is only the code running in privileged secure mode(monitor code, secure OS kernel) able to do that?
TZASC register access is also 'on the bus'. Typical ARM TrustZone solutions have two type of access control. One for memory devices and another for device mapped memory. The TZASC register set is a device. So, the access control to it will be through the 'device mapped memory' control. For example on Freescale/NXP iMx product this is controlled by the CSU.
Locking the TZASC during secure boot insures that the mapping can not change. If you need a dynamic mapping then you have the flexiblity to use whatever the device memory control support. This is different for every ARM Soc.
Related
What is partition checker in ARM Secure Mode
ARM TrustZone, connecting peripherals?
Related
Trying to understand user mode vs kernel mode and which instruction can run in unprivileged mode.
Per Abraham-Siberschatz, all of these may require SysCall.
It depends on which CPU it is and how the OS configured it.
For example; for 80x86 the in and out instructions can be executed in user mode if:
the IOPL field (IO privilege level) is set to be not less than the current privilege level.
the IO Permission Bitmap (in the current Task State Segment) is configured to allow access to the specific IO port/s.
Of course a lot of IO is memory mapped, and that also allows a kernel to map any "memory mapped IO" areas into user space.
In general; a monolithic kernel will run device drivers in kernel space and won't allow user mode code to access any kind of IO directly; and a micro-kernel will run device drivers in user space and will explicitly configure things so that a device driver process can do input/output for the device it is driving (but not any other device).
I have a Samsun DRAM with a K4A8G085WB-BCTD DDR4.
The device operation specification (here) says you can work with mode register through the MRS instruction [section 1.4].
I'd like to know if TRR (target row refresh) [section 2.34] is enabled or not. It says I can read the MR4 register discovering if it is active or I can write into it to activate it. However, How can I write/read the mode register practically? What kind of register is MR4?
As far as I can tell, this is not a command that would be issued from software on the host cpu to the DRAM module, but either by the DDR controller on the motherboard (or integrated with the cpu) to the DRAM module, or by a controller chip on the module to the individual DDR chips. There might be some way to get Intel's controller to pass commands through, but it's more likely that there's some Intel model-specific register (documented or undocumented, possibly exposed only through BIOS/firmware) to control the feature at a higher level.
I am using Trusted Firmware Image(LSK and Android filesystem) provided by Linaro on Juno board r1. In my case, I just want to some trivial test in EL3, e.g., reading specific memory.
To make things easier, I didn't do anything until the system is completely booted. Then I load a kernel module which sends a SMC instruction and the SMC exception will be handled in BL3-1 by a custom handler. In the handler, I disabled MMU for EL3 and attempted to access a physical address directly. But I found that if the physical address is larger than 0xffffffff(4G), the content I got will be all 0. The physical address lower than 0xffffffff works perfectly. And If I mapped that physical address into a virtual address smaller than 0xffffffff(Linaro's EL3 only support virtual address lower than 0xffffffff), it also works.
So, why I can not get the correct content of a physical address larger than 0xffffffff after I disabled MMU in EL3?
Is there anyone know the details?
Thanks a lot for helping me!
The stock Juno firmware sets up the TrustZone controller such that 16MB of DRAM from 0x0ff000000 to 0x0ffffffff is reserved for the Secure world, and the rest is Non-Secure only. The specific TZC configuration is such that the Non-Secure regions just read as zero and ignore writes, rather than aborting, for Secure accesses.
Thus it's not that you can't access physical addresses above 4GB per se, it's just that the only thing that happens to be up there is DRAM, which is the thing the secure world has specifically denied itself access to the majority of.
The relevant part of the firmware source can be found here.
I'm planning to run an RTOS e.g Nuttx as a Process of another RTOS e.g FreeRTOS such that freertos tasks and the Nuttx running as a Freertos task would co-exist.
Would this be feasible implementation given that the underlying hardware is an ARM cortex A8 single core processor? What changes could be required if the implementation is not based on VM concept?
Your requirement, in a nutshell, is to allow a GUEST RTOS to completely work within the realms of an underlying HOST RTOS. First answer would be to use virtualization extension, but A8 processor does not have that, hence will rule this option out. Without Virtualization extensions you have to resort to one of the following methods and would require a lot of code changes.
Option 1 - Port your GUEST OS API's
Take all your GUEST OS API's and replace their implementation, so that it mimics the required API behavior by making use of HOST OS's API's. Technically now your GUEST OS will not have a scheduler, and will be reduced to a porting layer on top of your HOST OS. This method is used by companies when they need their software solutions to work across multiple RTOS's. They would write their software solution based on an RTOS. When a customer comes to them with a requirement to run the software on their RTOS, they would simply port the RTOS API implementations on to the customer's RTOS.
Option 2 - Para-virtualization
Your guest RTOS user and kernel space should both work inside the userspace of your host RTOS. Let us break the problem into a few parts.
Handling Privileged Instructions
When your Guest OS, while executing in "Kernel mode" tries to execute a privileged instruction, will cause an undef instruction abort. You have to modify the undef instruction abort handler of your host kernel to trap/intercept these instructions and act on them. Every single privileged instructions has to be trapped/intercepted and 'simulated'. There are some instructions that wouldn't trap but would need to be handled by modifying code. Eg. If your kernel code reads CPSR to confirm the execution mode, CPSR would say the mode is User mode. (This instruction wouldn't cause an instruction abort, so you could not follow the trap and simulate model. The only way is to identify, search and replace these instructions in your GUEST OS codebase.)
Memory Management Unit
If a privilege violation happens the Data Abort will be triggered to your host OS. It has to be forwarded to your guest OS.
Interrupts
You would have to replace your GUEST OS's interrupt controller driver with dummy SVC calls that would call into your HOST OS to setup interrupts.
Timers
You would have to modify your GUEST timer driver to account for 'lost' ticks when you were running your HOST OS tasks.
Hardware Drivers
All other hardware drivers used by your GUEST OS have to be modified to allow device sharing between GUEST and HOST.
Schedulers
Your GUEST OS scheduler now works inside (and thus is at the mercy of ) another scheduler (HOST OS Scheduler).
It is feasible.
You need to separate resources: memory, timers, IRQs, etc. So that, "Host" OS (FreeRTOS) don't even "know" about resources used by "Guest" OS (Nuttx).
For Cortex-A8 you may want to use IRQ for FreeRTOS and FIQ for GuestOS. It will let you not to rewrite IRQ controller (but again, make sure Host does not control FIQ after GuestOS started).
And some changes might be required for context switch: you need to differ Host-Host context switch, Host-Guest (and Guest-Host) and Guest-Guest context switch.
Though not direct answer to your question, address this problem at design level, do a separation of code that depends hardware (create API) and make the application level code independent of the underlying OS or runtime i.e rather depend on particular implementation let it depend on the API.
where ever needed port the hardware (OS) dependent code to the underlying OS/Runtime
Can a Linux module be written that denies write permissions to the BIOS? (I assume that there is no legitimate reason for write permissions unless you are flashing the BIOS.) What can I query to get the BIOS port? Is that port used only for the BIOS or is it multi-purpose? Is there a system call that can be overridden to check for write permissions on that particular port?
Flashing the BIOS is typcially done not by using some driver but by accessing the SPI or I²C controller hardware directly.
Some mainboards have hardware write protection switches/jumpers.
Neither the kernel nor a rootkit could do anything about that.
Some flash chips have a write protection that can only be enabled, but cannot be disabled without a reset, i.e., only the BIOS can do or allow flashing.
Neither the kernel nor a rootkit could do anything about that.
On most mainboards, the flash hardware has no write protection.
There is nothing the kernel can do about that; any rootkit that has the capability to access the hardware is already in complete control and is also able to reverse any software protection measures attempted by the kernel.