ARM MMU page tables in TCM memory - armv6

A (hopefully) simple question.
Can I create my MMU page tables in ARM tightly coupled memory, or is there a restriction that prevents me doing this.
I have 16k of data TCM that seems quite suitable for this task (the instruction TCM will contain my secure world code), but I'm getting abort exceptions when enabling the MMU.
When I compile my secure world code to target SRAM everything works as expected. The problem is that on this SoC SRAM is available from an FPGA-like device that does not respect TrustZone at all.
Am I missing something here, or do I need to carve off a small piece of RAM for myself to get this all working?
I'm working on an ARM1176JZ-S.

So, many years later I found my answer in the ARM Architecture Reference Manual for ARMv6 while browsing around for something completely different!
In section B4.7.3, Page table translation in VMSAv6 (page B4-25), the answer is mentioned just after discussing whether L1 cache is used in the page table walk, and it says:
Hardware page table walks cannot cause reads from TCM.

Related

What is a TRAMPOLINE_ADDR for ARM and ARM64(aarch64)?

I am writing a basic check-pointing mechanism for ARM64 using PTrace in order to do so I am using some code from cryopid and I found a TRAMPOLINE_ADDR macro like the following:
#define TRAMPOLINE_ADDR 0x00800000 /* 8MB mark */ for x86
#define TRAMPOLINE_ADDR 0x00300000 /* 3MB mark */ for x86_64
So when I read about trampolines it is something related to jump statements. But my questions is from where the above values came and what would the corresponding values for the ARM and ARM64 platform.
Thank you
Just read the wikipedia page.
There is nothing magic about a trampoline or certainly a particular address, any address where you can have code that executes can hold a trampoline. there are many use cases for them...for example
say you are booting off of a flash, a spi flash, running at some safe rate so that the chip boots for all users. But you want to increase the rate of the spi flash and the spi peripheral does not allow you to change while executing code. So you would copy some code to ram, that code boosts the spi flash rate to a faster rate so you can use and/or run the flash faster, then you bounce back to running from the flash. you have bounced or trampolined off of that little bit of code in ram.
you have a chip that boots from flash, but has the ability to re-map that address space to ram for example, so you copy some code to some other ram, branch to it that little bit of trampoline code remaps the address space, then bounces you back or bounces you to where the flash is now mapped to or whatever.
you will see the gnu linker sometimes add a small trampoline, say you compile some modules as thumb and some others for arm, you no longer have to use that interwork thing, the linker takes care of cleaning this up, it may add an instruction or two to trampoline you between modes, sometimes it modifies the code to just go where it needs to sometimes it modifies the code to branch link somewhere close and that somewhere close is a trampoline.
I assume there may be a need to do the same thing for aarch64 if/when switching to that mode.
so there should be no magic. your specific application might have one or many trampolines, and the one you are interested might not even be called that, but is probably application specific, absolutely no reason why there would be one address for everyone, unless it is some very rigid operating specific (again "application specific") thing and one specific trampoline for that operating system is at some DEFINEd address.

How do modern OS kernels (UNIX, Windows) distinguish between page faults? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 7 years ago.
Improve this question
I'm trying to understand how page faults are handled by the OS kernel. The wikipedia article at https://en.wikipedia.org/wiki/Page_fault distinguishes between Minor, Major and Invalid page faults.
A major page fault is one where the virtual->real address mapping is not yet present in main memory, but the real address is present on disk, and for this page fault exception, the exception handler searches the disk and brings the page frame to main memory and does the virtual->real address mapping.
An invalid page fault is when an application tries to access an unmapped address, for example, a rogue pointer. The same page fault exception is raised, but the exception handler now decides to terminate the program, mostly with a Seg Fault (core dumped) error.
My question is, how does the kernel distinguish between these two types of page faults? I'd like the answer to go into a bit of depth about this, and hopefully link me to more elaborate articles if possible. Please ask me for any clarifications!
Thanks.
Grossly speaking, the kernel has some representation of the virtual address space of the (current) process. It knows for each segment of pages how to handle page faults for it. It works in physical addresses (so its address space is not the user-mode address space), but maintain some complex data structures to efficiently represent the mapping between virtual and physical addresses (if any) and configure the MMU according to these.
See for example Gorman's book understanding the Linux virtual memory manager (some details are probably outdated).
Read also about GNU Hurd external pager mechanism.
A page fault is given the relevant (physical and/or virtual) addresses at fault (e.g. by MMU hardware). See the paging web page of osdev, and read about page tables. The kernel handles all page faults (it gets the same hardware exception for every page faults, with data describing the fault - including faulting virtual address) and determine what kind of fault it is.
On Linux you could even handle (in a non-portable, ABI & processor specific manner) the SIGSEGV signal. (Hence the kernel has gathered all the information it is able to give to your SIGSEGV handler. But read carefully signal(7)). But it is usually not worth the pain.
Look also inside the mm/ subtree of the Linux kernel source.
Read also the extensive documentation of Intel processors. Perhaps read some books on processor architecture and on operating systems, and study simpler architectures (like MMIX or RISC-V).
See Operating Systems : Three Easy Pieces notably its introduction to paging.
I would ignore the model in the Wikipedia article. An invalid page fault, is not a page fault at all but rather a failure of logical memory translation.
The concept of a major and minor page fault, IMHO is confusing. In fact, the Wikipedia article describes two different things as being a minor page fault. I even wonder if something different was intended than how the text reads.
I would rethink as this:
A process accesses a memory address.
The memory management unit attempts to translate the referenced LOGICAL PAGE to a PHYSICAL PAGE FRAME using the page tables.
If no such translation is possible (no corresponding table table entry, page table entry is marked as invalid), an access violation fault exception of some kind is generated (Invalid Page Fault in the Wiki article).
If there is already a direct mapping between the logical page and the physical page frame, we're all done.
If the page table indicates there is no physical page frame corresponding to the logical page at the moment, the CPU triggers a page fault exception.
The page fault handler executes.
The page fault handler has to find where the logical (now a virtual) page is stored.
During this process, the page fault handler may find that the page is sitting in physical memory already. There are a number of ways in which this can occur. Be this the case, all the page fault handler has to do is update the page table to reference the physical page frame and restart the instruction (This is one of the circumstances the wiki article calls "minor page fault"). All done.
The other alternative is that the virtual page is stored on disk in a page file, executable file, or shared file. In that case, the handler needs to allocate a physical page frame, read the virtual page from disk into the page frame, update the page table, then restart the instruction (what the wiki calls a "major page fault"). Because of the disk read, the "major" fault takes much longer to handle than the "minor" fault.
One of the functions of the operating system is to keep track of where all the virtual pages are stored. The specific mechanism used to find the page will depend upon a nmber of factors.

Handling MMU translation faults in instruction stream - what happens to MMU?

This question is not specific to any CPU implementation, but CPU-specific answers are welcomed.
I am currently implementing a full MMU-enabled CPU, and a simple issue arose.
So, imagine the situation where a simple TLB miss happens caused by the instruction stream (or instruction cache). This would trigger a TLB miss. Now, if the PTE is not found, some exception will be triggered, like a "Page Translation Fault". So far, no problem at all.
Now, in order to call the fault handler, the instruction stream (or cache) needs to fetch the exception handler code. For that it will need to search again for the relevant PTE entry in TLB, and eventually another table walk.
Imagine that, again, the PTE entry is not found. One would expect some other exception handler to be called.
Now, on this last exception handler, since the handler itself might not be found or be valid, does MMU gets disabled before the handler is fetched and executed (thus bypassing everyting MMU does, including Phys-Virt mapping), or is there another technique (non-fatal) to deal with this situation ?
Alvie
I can't say this with certainty about real world operating system, but from the little experience in looking at small kernels, the emphasis always seems to be in ensuring that the page fault handler by itself is never paged out and is always in a location that never raises a page fault. This would make sure that a situation as described in your problem never arises.
In general, it seems to make sense that some part of the core kernel code resides statically on the physical memory with known mapping; but given that you were anyway trying to write a full blown virtual memory enabled OS, I guess you would know be knowing that.
There are two ways I'm aware of:
MMU is disabled automatically when interrupt/exception occur. So fault handler (data abort handler) has to be placed at known physical address and spurious MMU faults are out of question. That's a responsibility of a handler to reenable MMU before returning from an exception or for handler usage itself. That behaviour, in real life, quite a pain in an ass...
For example 'Microblaze' arch does exactly that.
MMU is not disabled automatically. The trick is to have 2 set of TLB tables. TLB1 has kernel mapping tables, TLB0 is made for an user apps mapping tables. Respectively kernel & user apps should have appropriate linkage to exclude the overlapping of virtual addresses between each other.
When user app does a sh** and cause a MMU fault, exception occurs. Abort/fault handler is in kernel memory space so handler code will be accessed with different TLB. You should be damn sure that kernel TLB is correct :)
If kernel exception handler generates exception itself then there is a probability of spurious data and/or instruction aborts.
In practice however, "ARM-Ax" CPUs, for instance, mask exceptions/interrupts when they are taken. I think spurious exceptions do not occur, I've never tested that in practice though.
And well HW watchdog might give you a favour...

Can I dump/modify the content of x86 CPU cache/TLB

any apps or the system kernel can access or even modify the content of CPU cahce and/or TLB?
I found a short description about the CPU cache from this webiste:
"No programming language has direct access to CPU cache. Reading and writing the cache is something done automatically by the hardware; there's NO way to write instructions which treat the cache as any kind of separate entity. Reads and writes to the cache happen as side-effect to all instructions that touch memory."
From this message, it seems there is no way to read/write the content of CPU cahce/TLB.
However, I also got another information that conflicts with the above one. That information implies that a debug tool may be able to dump/show the content of CPU cache.
Currently I'm confused. so please help me.
I got some answers from another post: dump the contents of TLB buffer of x86 CPU. Thanks adamdunson.
People could read this document about test registers, but it is only available on very old x86 machines test registers
Another descriptions from wiki https://en.wikipedia.org/wiki/Test_register:
A test register, in the Intel 80486 processor, was a register used by
the processor, usually to do a self-test. Most of these registers were
undocumented, and used by specialized software. The test registers
were named TR3 to TR7. Regular programs don't usually require these
registers to work. With the Pentium, the test registers were replaced
by a variety of model-specific registers (MSRs).
Two test registers, TR6 and TR7, were provided for the purpose of
testing. TR6 was the test command register, and TR7 was the test data
register. These registers were accessed by variants of the MOV
instruction. A test register may either be the source operand or the
destination operand. The MOV instructions are defined in both
real-address mode and protected mode. The test registers are
privileged resources. In protected mode, the MOV instructions that
access them can only be executed at privilege level 0. An attempt to
read or write the test registers when executing at any other privilege
level causes a general protection exception. Also, those instructions
generate invalid opcode exception on any CPU newer than 80486.
In fact, I'm still expecting some similar functions on Intel i7 or i5. Unfortunately, I do not find any related document about that. If anyone has such information, please let me know.

How different in management page table entries (PTE) in kernel space and user space?

In Linux OS, after enable the page table, kernel will only map PTEs belong to kernel space once and never remap them again ? This action is opposite with PTEs in the user space which needs to remap every time process switching happening ?
So, I want know the difference in management of PTEs in kernel and user space.
This question is a extended part from the question at:
Page table in Linux kernel space during boot
Each process has its own page tables (although the parts that describe the kernel's address space are the same and are shared.)
On a process switch, the CPU is told the address of the new table (this is a single pointer which is written to the CR3 register on x86 CPUs).
So, I want know the difference in management of PTEs in kernel and user space.
See these related questions,
Does Linux use self map for page tables?
Linux Virtual memory
Kernel developer on memory management
Position independent code and shared libraries
There are many optimizations to this,
Each task has a different PGD, but PTE values maybe shared between processes, so large chunks of memory can be mapped the same for each process; only the top-level directory (CR3 on x86, TTB on ARM) is updated.
Also, many CPUs have a TLB and cache. These need to be maintained with the memory mapping. Some caches are VIVT, VIPT and PIPT. The first two have to have some cache flushing iff the PGD and/or PTE change. Often a CPU will support a process, thread or domain id. The OS only needs to switch this register during a context switch. The hardware cache and TLB entries must contains tags with the process, thread, or domain id. This is an implementation detail for each architecture.
So it is possible that TLB flushes could be needed when a top level page registers changes. The CPU could flush the entire TLB when this happens. However, this would be a disadvantage to pages that remain mapped.
Also, sub-sections of memory can be the same. A loader or other library can use mmap to create code that is similar between processes. This common code may not need to be swapped at the page table level, depending on architecture, loader and Linux version. It could of course have a virtual alias and then it needs to be swapped.
And the final point to the answer; kernel pages are always mapped. Only a non-preemptive OS could not map the kernel, but that would make little sense as every process wants to call the kernel. I guess the micro-kernel paradigm allows for device drivers to unload when they are not in use. Linux uses module loading to handle this.

Resources