-
Notifications
You must be signed in to change notification settings - Fork 13
ARC MMU features ASID and SASID
This page gives a quick summary of the Address Space Identifier and Shared Address Space Identifier features of the ARC MMU.
ARC MMU TLB entries are "tagged" with a unique ASID per task allowing entries with same virtual address (vadr) to co-exist without need to flush the TLB on every OS context switch. OS manages ASID and assigns each task with a unique value.
MMU PID register contains the "current" ASID which is used by MMU to restrict its search through the TLB at the time of a vaddr lookup.
The TLB entries with Global bit set ignore the ASID and are always considered for match during a lookup (based on vaddr of course)
SASID is orthogonal and effectively opposite to ASID. It is a unique optimization feature of ARC MMU which allows for sharing and reusing of TLB entries between tasks. In a nutshell, ASID allows segregation of TLB entries per task (even for same vaddr) while SASID allows aggregation of TLB entries between tasks.
It is useful for a high level OS (not an RTOS) which supports features such as mmap, Shared libraries and Dynamic loading of libraries [^1]
The issue it addresses is as follows: When a shared library is loaded and mapped by multiple tasks, the underlying code and rodata pages are shared and by definition only 1 copy exists in physical memory (and possibly cache) with each task simply "mmap" it in it's virtual address space. However at the MMU TLB level, the same library page requires distinct translation entries per task, due to ASID, even if mapping virtual address is the same.
Consider a libc code page containing code for malloc (assume it fits in 1 MMU page and also assume this page is dynamically loaded and mapped at same vaddr in each task). Every task that maps libc and calls malloc will incur a TLB Miss for that page, leading to a unique entry in MMU with same vaddr (and paddr since only 1 physical page exists) but distinct task ASID. SASID alleviates this extra TLB Miss / capacity overhead by decoupling the shared TLB entries from TLB entries.
In terms of programming model: * SASID mechanism in only enabled on PID.S being set. * Shared TLB entries have TLB.S bit set and TLB.ASID actually contains SASID value (e.g. 0 for libc, 1 for libm, 2 for libpthead, 3 for libssp) * MMU SASID1:SASID0 is bitmap allowing up to 64 libraries to be shared and contains pow2 of library SASID values (e.g. 0x1 for libc, 0x8 for libssp etc)
The value of SASID1:SASID0 register defines the task shared library ¿subscription¿: e.g. if it maps only libc and libpthread it would be 0x5.
The requirement from OS is that libraries need to ba mapped at same virtual address across tasks.
Support for SASID feature was added in 2.6.35 kernel (out of tree) but the changes never made it to upstream kernel. It also required pairing changes in uClibc dynamic loader
The 2.6.35 kernel implementation can be found at: https://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc.git/log/?h=arc-history-pre-upstream&ofs=400
The image below shows the high level MMU lookup flow:

[^1]:
Note to be confused with ARC MMUv5 dyanmic loading feature which allows overlay like functionality.