So these bounds are set by the software (and are guarded against manipulation). Then each read or write to memory is checked against these bounds by the "fine grained MMU" hardware.
Yes, though "software" is rather broad; where exactly the bounds setting happens is important as if you get it wrong it allows malicious software to not set bounds and be able to access memory outside of its allocations. Pushing it to the same place the actual allocation happens or, in the case of referencing global variables, the same place the loading and relocating happens, ensures that the only thing malicious software can do by not setting bounds is make itself insecure.
So these bounds are set by the software (and are guarded against manipulation). Then each read or write to memory is checked against these bounds by the "fine grained MMU" hardware.