По понятному мне описанию, трансляция адресов работает примерно так: от виртуального адреса (в 32-битной машине адрес, очевидно, 32-битный) отщипываются эти 12 бит, остаётся 20-битный номер страницы. Он загоняется в блок трансляции, где разными методами (но чаще всего - при помощи кэша по принципу ассоциативной памяти, content-addressable memory - CAM) выясняется соответствие номера виртуальной страницы и её реального расположения. О том, куда что запихнуть (и находится ли оно вообще в ОЗУ или вообще где-то в свопе), должна заботится операционная система.
И вот тут есть интересный нюанс.
Чтобы изолировать процессы и предоставить каждому из них своё собственное адресное пространство, выглядящее сплошным и вполне настоящим, система - включая железо - должна добавлять к номеру виртуальной страницы некий идентификатор, однозначно отделяющий один процесс от другого. Натурально это будет сам pid, process identificator. Но в известных мне ОС для 32-битных машин оный pid имеет размер 16 бит. То есть 16 бит добавляется к 20 битам номера страницы и через CAM выясняется физический 32-битный адрес. Вроде ничего сверхсложного, но...
...например, в MIPS R2000 регистр входа системы трансляции имеет натуральный размер 32 бита. То есть 36 бит туда не влезут никак. То есть вместо 16-битного идентификатора процесса можно использовать только 12-битный. Такая же фигня, нассколько я знаю, почти во всех нынче применяемых процессорах с MMU. Есть некоторые (в семействе PowerPC) с 36-битным регистром и 36-битной же адресацией памяти, но это больше похоже на исключение.
Так как же умудряются разграничивать адресные пространства процессов, если вместо полновесного pid можно использовать только его огрызок? или там вообще какой-то другой идентификатор? если так, то какой, откуда он берётся и как сопоставляется с номером процесса?