Broadly speaking, I am wondering how the kernel (or the CPU) knows that a process has tried to access a memory location for which it lacks permission, and how the mysterious piece of hardware called MMU helps in doing that.
In particular: It seems to me that the MMU is agnostic towards the memory management model of the OS kernel (paging, memory zones, process adress spaces…) (I would presume that Linux and Windows pages are not exactly the same, for example. Correct me if I’m wrong). But then, how does my CPU find out whether the current code may access location x? And how does it signal this to the kernel?
This is probably too big a topic to completely answer satisfactorily here; you’ll do better to search for some papers/articles/books that discuss the hardware behind virtual memory implementations (probably starting with a specific architecture, since there are significant differences between e.g. x86, x86_64, sparc, etc…).
The short answer, though, is that the hardware handles this through the page tables. Every memory access that the MMU is asked to handle is verified through the page table structures. If the page table entry describing the page containing the address being requested is not marked to allow the type of access being requested (read/write/execute/…), the hardware generates a trap that Linux eventually calls a “segmentation fault”. Other OSes name them differently (e.g. general protection fault, …). The OS kernel then has to figure out the reason for the fault and whether anything can be done about it (many traps are handled by the kernel to swap in new pages from disk, map a new empty page, etc., but some, like null-pointer dereferences, the best thing the kernel can do is throw it at the application to say “you did something bad”).