

メモリ管理ユニット(MMU)、またはページングメモリ管理ユニット(PMMU)[ 1 ]は、メモリへのすべての参照を調べ、参照されているメモリ アドレス(仮想メモリ アドレスとして知られる)をメイン メモリの物理アドレスに変換するコンピュータ ハードウェアユニットです。
現代のシステムでは、プログラムのアドレスは一般的に、コンピュータアーキテクチャの理論上の最大メモリ容量(32ビットまたは64 ビット)にアクセスします。MMU(メモリ管理ユニット)は、各プログラムのアドレスを物理メモリ内の別々の領域にマッピングしますが、この物理メモリの容量は通常、理論上の最大容量よりもはるかに小さくなります。これは、プログラムが一度に大量のメモリを使用することがほとんどないためです。
ほとんどの最新のオペレーティングシステム(OS) は、仮想メモリ(VM) サポートを提供するために MMU と連携して動作します。MMU は、ページと呼ばれる固定サイズのブロックでメモリの使用状況を追跡します。プログラムが物理メモリに存在しないページ内の場所を参照すると、MMU はオペレーティングシステムに割り込みを送信します。OS は、メモリ内で使用頻度の低いブロックを選択し、読み込まれた後に変更されている場合はハードドライブなどのバックアップストレージに書き込み、バックアップストレージからそのブロックにページを読み込み、プログラムが使用できるように、ブロックを元の要求されたページにマッピングするように MMU を設定します。これはデマンドページングと呼ばれます。一部のより単純なリアルタイムオペレーティングシステムは仮想メモリをサポートしておらず、MMU を必要としませんが、ハードウェアメモリ保護ユニットは必要です。
MMU(メモリ管理ユニット)は一般的に、プログラムが以前に要求していないメモリにアクセスしようとする試みをブロックするメモリ保護機能を提供し、不正なプログラムや悪意のあるプログラムが他のプログラムに属するデータを変更したり読み取ったりすることを防ぎます。
初期のマイクロプロセッサ設計では、メモリ管理は、 VLSI Technology VI475 (1986 年)、Macintosh IIのMotorola 68020 CPUで使用されたMotorola 68851 (1984 年)、 Zilog Z8000ファミリーのプロセッサで使用されたZ8010 [ 2 ]および Z8015 (1985 年) [ 3 ] [ 4 ]などの独立した集積回路によって実行されていました。後のマイクロプロセッサ ( Motorola 68030やZilog Z280など) では、 Intel 80286やそれ以降のx86マイクロプロセッサと同様に、MMU と CPU が同じ集積回路上に配置されました。
初期のシステム、特に8ビットシステムでは、バンク切り替えを実行するために非常にシンプルなMMUが使用されていた。
初期のシステムでは、ベースアドレス指定と境界アドレス指定が使用され、それが後にセグメンテーションへと発展しました。あるいは、必要に応じてロードするのではなく、固定のブロックセットを使用していました。これら2つのアプローチの違いは、連続したメモリブロックのサイズです。ページングシステムではメインメモリが等サイズのブロックの連続に分割されますが、セグメント化システムでは一般的に可変サイズが許容されます。[ 5 ]
セグメント化変換では、メモリ アドレスにはセグメント番号とセグメント内のオフセットが含まれます。セグメントは可変長で、読み取り、書き込み、実行などの権限が関連付けられている場合があります。[ 6 ]セグメントは、物理メモリの連続した領域にロードされます。通常、セグメント番号はセグメント テーブルへのインデックスとして使用されます。セグメント テーブルの各エントリには、物理メモリ領域のアドレス、セグメントの長さ、および権限フラグなどのその他の情報が格納されます。
この方式の利点はシンプルさです。メモリブロックは連続しているため、マッピングの目的で保存する必要があるのは、ベース値とリミット値の2つだけです。
このアプローチの欠点は、外部断片化と呼ばれる現象を引き起こすことです。これは、メモリ割り当てが解放されるものの、それらが連続していない場合に発生します。この場合、要求を処理するのに十分なメモリが利用可能であっても、メモリが分散しているため、単一のセグメントに割り当てることができません。プログラムが時間とともに起動と停止を繰り返すシステムでは、最終的にメモリが高度に断片化され、大きなブロックが残らなくなる可能性があります。この場合、セグメントをメモリ内で移動し、セグメントテーブルのエントリを新しい物理アドレスに合わせて変更して、セグメントを収容できる十分な大きさの連続した領域を確保する必要があります。
PDP-11 16ビットミニコンピュータの一部のモデルには、ページアドレスレジスタ(PAR)とページ記述レジスタ(PDR)のセットを備えたセグメント化されたメモリ管理ユニットがあり、16ビットの仮想アドレスを18ビットの物理アドレスにマッピングします。PDP -11/70では、これを拡張して22ビットの物理アドレスを生成します。[ 7 ]
セグメンテーションは1980年代のマイクロコンピュータプラットフォームで広く使用されていました。この概念を使用したMMUには、Motorola 68451 [ 5 ]やZilog Z8010などがありますが、他にも多くの例があります。
Intel 8086、Intel 8088、Intel 80186、およびIntel 80188は、粗雑なメモリセグメンテーションを提供し、メモリ保護はありません。(すべてのセグメントのすべてのバイトは、常にどのプログラムでも使用できます。) 16 ビットのセグメント レジスタにより、65,536 個のセグメントが使用できます。各セグメントは、セグメント番号の 16 倍に等しい固定オフセットから始まります。セグメントの開始アドレスの粒度は 16 バイトです。各セグメントは、64 KiB (65,536 バイト) のアドレス空間への読み書きアクセスを許可します (この制限は 16 ビットの PC レジスタと SP レジスタによって設定され、プロセッサは境界チェックを行いません)。オフセット + アドレスが 0xFFFFF を超えると、0x00000 にラップアラウンドします。各 64 KiB セグメントは、次の 4,095 個のセグメントと重複します。各物理アドレスは、4,096 組のセグメント - オフセットで表すことができます。この方式では、1 MiB (1024 KiB) の物理メモリ(およびメモリマップドI/O)しかアドレス指定できません。(オプションの拡張メモリハードウェアを使用すると、ソフトウェア制御でバンク切り替えメモリを追加できます。)Intel 80286以降のx86プロセッサでは、セグメントテーブルを使用した真のセグメントマッピングがサポートされました。

ページ変換では、アドレス空間(プロセッサが使用するアドレスの範囲)はページに分割され、各ページのサイズは2のべき乗で、通常は数キロバイトですが、それよりはるかに大きくなる場合もあります。プログラムは、マシンの自然なアドレスサイズ(現代のシステムでは通常32ビットまたは64ビット)を使用してメモリを参照します。アドレスの下位ビット(ページ内のオフセット)は変更されません。上位アドレスビットは仮想ページ番号です。[ 9 ]
ほとんどのMMUは、仮想ページ番号をメインメモリ内の物理ページ番号にマッピングするために、仮想ページごとに1つのページテーブルエントリ(PTE)を含むページテーブルと呼ばれるインメモリテーブルを使用します。マルチレベルページテーブルは、ページテーブルのサイズを小さくするためによく使用されます。PTEの連想キャッシュは、変換ルックアサイドバッファ(TLB)と呼ばれ、仮想アドレスがマッピングされるたびにメインメモリにアクセスする必要性を回避するために使用されます。[ 5 ]
他のMMUは、マッピング情報を格納するために、メモリのプライベート配列[ 10 ] 、レジスタのセット[ 11 ]、または1つ以上のレベルのスタティックRAM配列[ 12 ]を持つ場合があります。
MMUは仮想アドレスを仮想ページ番号とページ内のオフセットに分割します。仮想ページ番号はページテーブルエントリを選択するために使用され、ページテーブルエントリが見つかり、ページがメモリ内にあるとマークされている場合、ページテーブルエントリ内の物理ページ番号とオフセットを組み合わせて、仮想アドレスに対応する物理アドレスを構築します。[ 9 ]
仮想ページ番号は、ページテーブルやその他のマッピング情報へのインデックスとして直接使用することも、さらに分割して、特定のレベルのビットを下位レベルのテーブルのインデックスとして使用し、そのテーブルの次のレベルのビットをインデックスとして使用するなど、2 つ以上のレベルのインデックス付けを行うこともできます。
ページ変換の問題の 1 つは、仮想アドレス空間が拡大するにつれて、マッピングを保持するために必要なメモリ量も増加することです。たとえば、68020ではアドレスは 32 ビット幅であるため、8 kB ページサイズの仮想ページ番号はアドレスの上位 19 ビットとなり、シングルレベルのページ テーブルは 512 kB になります。[ 5 ] 1980 年代には、インメモリ ページ テーブルの場合、これはマシンのメイン メモリのかなりの割合を占める可能性があり、静的 RAM にページ マップを保持する MMU の場合は、高価な静的 RAM が必要になる可能性がありました。この問題は、ページを大きくして、たとえば 8 kB ではなく 64 kB にすることで軽減できます。これで、ページ インデックスは 16 ビットを使用し、結果として得られるページ テーブルは 64 kB となり、扱いやすくなります。ページ サイズを大きくすると、2 番目の問題、つまり内部断片化の増加が発生します。小さなブロックに対する一連の要求を生成するプログラムには大きなブロックが割り当てられ、大量のメモリが無駄になります。[ 5 ]
アドレス空間が疎で、そのすべての領域が割り当てられていない場合、マルチレベルページテーブルまたはスタティックRAMマップを使用し、空き領域に必要なすべてのページテーブルエントリを割り当てないようにすることで、問題を軽減できます。
ページング変換方式は、1970年代から1980年代にかけてマイクロプロセッサのMMUで広く使用されており、68020の68851や68030のオンチップMMU 、Zilog Z8000のZ8015、NS32000シリーズのNS16082などが挙げられる。
ページ テーブル エントリやその他のページごとの情報には、ページが書き込まれたかどうか (ダーティ ビット)、最後に使用された日時(LRUページ置換アルゴリズムの場合、アクセス ビット)、どのような種類のプロセス (ユーザー モードまたはスーパーバイザ モード) が読み書きできるか、キャッシュする必要があるかどうかなどの情報も含まれる場合があります。[ 13 ]
ページ テーブル エントリやその他のページごとの情報によって、特定の仮想ページへのアクセスが禁止される場合があります。これは、その仮想ページに物理的なランダム アクセス メモリ(RAM) が割り当てられていないことが原因である可能性があります。この場合、MMU はCPU にページ フォルトを通知します。オペレーティングシステム(OS) は、おそらく RAM の空きフレームを見つけて、それを要求された仮想アドレスにマッピングするようにページ マップを設定することによって、この状況に対処します。空き RAM がない場合は、何らかの置換アルゴリズムを使用して既存のページ (犠牲ページと呼ばれる) を選択し、それをディスクに保存する必要がある場合があります (ページングと呼ばれるプロセス)。一部の MMU では、PTE が不足することもあり、その場合は OS が新しいマッピングのために 1 つを解放する必要があります。[ 13 ] [ 9 ]
MMUは、不正なメモリアクセスや存在しないメモリアクセスが発生した場合に、それぞれ不正アクセスエラー状態や無効なページフォルトを生成する可能性があり、オペレーティングシステムによって処理される際に、セグメンテーションフォルトやバスエラー状態につながる可能性があります。
ページング変換は、メモリの外部断片化の問題を軽減します。メモリブロックが割り当てられて解放された後、空きメモリが断片化(不連続)して、最大の連続空きメモリブロックが総量よりはるかに小さくなる場合があります。仮想メモリでは、連続した仮想アドレスの範囲を、物理メモリの複数の非連続ブロックにマッピングできます。この非連続割り当ては、ページングの利点の1つです。[ 13 ] [ 9 ]
しかし、ページ変換は別の問題、内部断片化を引き起こします。これは、プログラムがページにきれいにマッピングされないメモリブロックを要求する場合に発生します。たとえば、プログラムが ファイル作業を実行するために 1 KB のバッファを要求する場合です。この場合、要求の結果、ページ全体 の 1 KB しか使用されないにもかかわらず、ページ全体が確保されます。ページが 1 KB より大きい場合は 、ページの残りの部分が無駄になります。このような小さな割り当てが多数行われると、メモリの大部分が空いたままであっても、メモリが使い果たされる可能性があります。[ 5 ]
GE 645とその後継機種など、一部のシステムではセグメンテーションとページングの両方が使用されていました。セグメントテーブルには、セグメントごとの物理ベースアドレスとセグメントの長さを示すエントリではなく、セグメントの長さに加えて、そのセグメントのページテーブルの物理ベースアドレスを示すエントリが含まれています。物理メモリは固定サイズのページに分割され、純粋なページベースのデマンドページングで使用されるのと同じ手法が、セグメントとページの両方をベースとしたデマンドページングにも使用されます。
モトローラ68000、68010、68012マイクロプロセッサ向けに設計されたSignetics 68905 MMU は、セグメンテーションとページングをサポートしていました。[ 14 ] Signetics とPhilips は、プロセッサと同じ物理チップ上に 68905 を組み合わせた 68000 のバージョンである 68070 を製造しました。[ 5 ]
MMUはメモリ保護機能を提供するため、コードがアクセス権限のないデータにアクセスしたり変更しようとしたりすると失敗します。これにより、ソフトウェアのバグと、そのデータにアクセスしたり変更したりしようとする意図的な試みの両方を検出できます。通常、オペレーティングシステムは各プログラムに独自の仮想アドレス空間を割り当てます。[ 9 ]
MMUは、仮想アドレスが小さすぎる場合に物理アドレスのサイズを拡張するためにも使用できます。たとえば、PDP-11は当初16ビットのアドレスを持っていましたが、1970年代にメモリサイズが増加するにつれて小さすぎるようになりました。これは、物理メモリバスを18ビットに拡張し、プロセッサバス上の他のピンに基づいて2ビットを追加してどのプログラムがメモリにアクセスしているかを示すMMUを使用することで解決されました。[ 15 ]
Signetics 68905などの一部のMMUには、プロセッサキャッシュを管理するコントローラも含まれており、最近アクセスされたデータを非常に高速なメモリに格納することで、低速なメインメモリとの通信の必要性を減らします。[ 14 ]一部の実装では、MMUはバスアービトレーションも担当し、アクセスを希望するコンピュータの多くの部分間でメモリバスへのアクセスを制御します。
直接メモリアクセスを実行するハードウェアは、CPUのMMUを完全にバイパスします。一部のI/Oシステムでは、DMAハードウェアが物理アドレスを使用して、物理RAM内の任意の場所を制限なく直接読み書きできます。他のI/Oシステムには、入出力メモリ管理ユニット(IOMMU)と呼ばれる独立したMMUがあり、OSによってプログラム可能で、 DMAハードウェアからのデバイスアドレスを、OSが選択した特定の限られた物理ページに変換します。IOMMUは、DMA攻撃をブロックするために使用できます。
現代のシステムのほとんどは、メモリを4~64KBのページに分割し、多くの場合、 2MBまたは1GBのいわゆる巨大ページを使用する機能を備えています(多くの場合、両方のサイズが可能です)。ページ変換は、変換ルックアサイドバッファ(TLB)にキャッシュされます。一部のシステム(主に古いRISC設計)は、 TLBにページ変換が見つからない場合にOSにトラップします。ほとんどのシステムはハードウェアベースのツリーウォーカーを使用します。ほとんどのシステムではMMUを無効化できますが、OSコードにトラップする際にMMUを無効化するシステムもあります。
1965 年 8 月に発表された IBM System/360 モデル 67 には、動的アドレス変換 (DAT) ボックスと呼ばれる MMU が含まれていました。[ 16 ] [ 17 ]このモデルに は、アクセスされたビットとダーティ ビットをページ テーブルの外に格納するという珍しい機能があります (すべての S/360 プロセッサの 4 ビット保護キーとともに)。これらは仮想メモリではなく物理メモリを参照し、専用命令によってアクセスされます。[ 17 ] これにより、アクセスされたビットとダーティ ビットをページ テーブルからより物理的に指向したデータ構造に伝播する必要があった OS のオーバーヘッドが削減されます。これにより、後に準仮想化と呼ばれるOS レベルの仮想化が容易になります。
1972年8月から、IBM System/370にも同様のMMUが搭載されましたが、当初はSystem/360 Model 67の32ビット仮想アドレス空間ではなく、24ビット仮想アドレス空間のみをサポートしていました。また、アクセスされたビットとダーティビットはページテーブルの外に格納されていました。1983年初頭、System/370-XAアーキテクチャでは仮想アドレス空間が31ビットに拡張され、2000年には64ビットz/Architectureが導入され、アドレス空間は64ビットに拡張されました。これらのアーキテクチャでも、アクセスされたビットとダーティビットは引き続きページテーブルの外に格納されています。
VAXのページサイズは512バイト[ 18 ] : 199と非常に小さい。OSによっては、複数のページを1つの大きなページとして扱う場合がある。例えば、 VAX上のLinuxは8つのページをまとめて処理する。そのため、システムは4KBのページを持つものとして扱われる。VAXはメモリを4つの固定用途領域に分割し、各領域のサイズは1GBである。それらは[ 18 ] : 200–201である。
ページ テーブルは大きな線形配列です。[ 18 ] : 209–215通常、アドレスが可能な範囲の両端で使用される場合、これは非常に無駄になりますが、P0 および P1 空間のページ テーブルは、ページングされた S0 空間に格納されます。[ 18 ] : 211–212そのため、実質的に 2 レベルのツリーがあり、アプリケーションは未使用のページ テーブル エントリに多くのスペースを浪費することなく、疎なメモリ レイアウトを持つことができます。ほとんどの MMU のページ テーブル エントリとは異なり、VAX MMU のページ テーブル エントリにはアクセス ビットがありません。[ 18 ] : 203–205ページングを実装する OS は、効率的に動作するために、アクセス ビットをエミュレートする方法を見つける必要があります。通常、OS は定期的にページをアンマップして、ページが存在しない障害を使用してアクセス ビットを設定できるようにします。
ARMアーキテクチャベースのアプリケーションプロセッサは、ARMの仮想メモリシステムアーキテクチャ(VMSA)で定義されたMMUを実装しています。現在のアーキテクチャでは、 4KBおよび64KBページ、1MBセクション、16MBスーパーセクションを記述するためのPTEが定義されています。旧バージョンでは、 1KBのタイニーページも定義されていました。ARMは、 4KBおよび64KBページを使用する場合は2レベルのページテーブルを使用し、 1MBセクションおよび16MBセクションを使用する場合は1レベルのページテーブルを使用します。
TLB の更新は、ページ テーブル ウォーキング ハードウェアによって自動的に実行されます。PTE には、権限に基づく読み取り/書き込みアクセス権限、キャッシュ可能性情報、NX ビット、および非セキュア ビットが含まれます。[ 19 ]
DEC Alphaプロセッサはメモリを8 KB、16 KB、32 KB、または64 KBに分割します。ページ サイズはプロセッサによって異なります。[ 20 ] : 3–2 [ 21 ] : 3–2 TLB ミスの後、低レベルのファームウェアマシン コード (ここではPALcodeと呼ばれます) がページ テーブルを走査します。
OpenVMS AXP PALcode とDEC OSF/1 PALcode は、 3 レベルのツリー構造のページ テーブルを走査します。アドレスは、未使用のビット セット (ツリーのルート レベルのインデックスの最上位ビットと同じ値を含む)、ツリーのルート レベルをインデックスするビット セット、ツリーの中間レベルをインデックスするビット セット、ツリーのリーフ レベルをインデックスするビット セット、および物理アドレスにそのまま渡され、ページ内の 1 バイトをインデックスする残りのビットに分割されます。フィールドのサイズはページ サイズに依存します。3 つのツリー インデックス フィールドはすべて同じサイズです。[ 20 ] : 3-2–3-3 [ 21 ] : 3-1–3-2 OpenVMS AXP PALcode は、ユーザー、スーパーバイザー、エグゼクティブ、カーネル モードの完全な読み取りおよび書き込み権限ビットをサポートし、読み取り/書き込み/実行ビットの障害もサポートしています。[ 20 ]: 3-3-3-6 DEC OSF/1 PALコードは、ユーザーモードとカーネルモードの両方で完全な読み取りおよび書き込み権限ビットをサポートし、読み取り/書き込み/実行ビットでの障害もサポートします。[ 21 ]:( II-B)3-3-3-6
Windows NT AXP PALコードは、仮想アドレス空間内の単一レベルページテーブル、または物理アドレス空間内の2レベルページテーブルを走査できます。アドレスの上位32ビットは無視されます。単一レベルページテーブルの場合、アドレスはページテーブルをインデックスするためのビットセットと、変更せずに物理アドレスに渡される残りのビットに分割され、ページ内のバイトをインデックスします。2レベルページテーブルの場合、アドレスはツリーのルートレベルをインデックスするためのビットセット、ツリーのトップレベルをインデックスするためのビットセット、ツリーのリーフレベルをインデックスするためのビットセット、および変更せずに物理アドレスに渡される残りのビットに分割され、ページ内のバイトをインデックスします。フィールドのサイズはページサイズに依存します。[ 22 ]: 3-2-3-4 Windows NT AXP PALコードは、ページがカーネルモードからのみアクセス可能であるか、ユーザーモードとカーネルモードの両方からアクセス可能であるかをサポートし、書き込みビットのフォルトもサポートします。[ 22 ]: 3-5
MIPSアーキテクチャは、 TLBに1~64個のエントリをサポートします。TLBエントリの数は、合成前にCPU構成で設定可能です。TLBエントリはデュアルです。各TLBエントリは、仮想アドレスのうちページマスクに含まれない最下位ビットに応じて、仮想ページ番号(VPN2)を2つのページフレーム番号(PFN0またはPFN1)のいずれかにマッピングします。このビットとページマスクビットはVPN2には格納されません。各TLBエントリには独自のページサイズがあり、1KBから256MBまでの4の倍数の任意の値を取ることができます。TLBエントリ内の各PFNには、キャッシュ属性、ダーティステータスビット、および有効ステータスビットがあります。VPN2にはグローバルステータスビットとOS割り当てIDがあり、グローバルステータスビットがゼロに設定されている場合、仮想アドレスTLBエントリのマッチングに参加します。PFNには、ページマスクビットを含まない物理アドレスが格納されます。
TLB にマッピングされた仮想アドレスに一致するエントリがない場合、TLB リフィル例外が発生します。一致するエントリは存在するが、そのエントリが無効としてマークされている場合、TLB 無効例外が発生します。ストア命令がマッピングされたアドレスを参照し、一致するエントリのダーティ状態が設定されていない場合、TLB 変更例外が発生します。TLB 例外の処理中に TLB 例外が発生した場合、二重フォールト TLB 例外は、その例外ハンドラにディスパッチされます。
MIPS32およびMIPS32r2は、32ビットの仮想アドレス空間と最大36ビットの物理アドレス空間をサポートします。MIPS64は、最大64ビットの仮想アドレス空間と最大59ビットの物理アドレス空間をサポートします。
オリジナルのSun-1は、Motorola 68000マイクロプロセッサを搭載したシングルボードコンピュータで、1982年に発表されました。Sun-1には、CPU上で動作する複数のプロセスに対してアドレス変換、メモリ保護、メモリ共有、メモリ割り当てを提供するオリジナルのSun-1メモリ管理ユニット(MMU)が搭載されています。CPUからオンボードのプライベートRAM、外部マルチバスメモリ、オンボードI/O、マルチバスI/OへのすべてのアクセスはMMUを経由し、そこでアドレス変換と保護が統一的に行われます。MMUはCPUボード上にハードウェアで実装されています。
MMUは、コンテキストレジスタ、セグメントマップ、およびページマップで構成されます。CPUからの仮想アドレスはセグメントマップによって中間アドレスに変換され、さらにページマップによって物理アドレスに変換されます。ページサイズは2KB、セグメントサイズは32KBで、1セグメントあたり16ページです。最大16個のコンテキストを同時にマッピングできます。コンテキストの最大論理アドレス空間は1024ページ、つまり2MBです。 同時にマッピングできる最大物理アドレスも2MBです。
コンテキストレジスタは、マルチタスクオペレーティングシステムにおいて重要です。なぜなら、CPUがすべての変換状態情報を再読み込みすることなく、プロセス間を切り替えることができるからです。4ビットのコンテキストレジスタは、スーパーバイザの制御下でセグメントマップの16セクションを切り替えることができ、これにより16個のコンテキストを同時にマッピングできます。各コンテキストは独自の仮想アドレス空間を持ちます。仮想アドレス空間の共有とコンテキスト間の通信は、異なるコンテキストのセグメントマップまたはページマップに同じ値を書き込むことで実現できます。追加のコンテキストは、セグメントマップをコンテキストキャッシュとして扱い、使用頻度の低い順に古いコンテキストを置き換えることで処理できます。
コンテキストレジスタは、ユーザー状態とスーパーバイザ状態を区別しません。割り込みとトラップはコンテキストを切り替えないため、有効な割り込みベクタはすべて、有効なスーパーバイザスタックと同様に、常にコンテキストのページ 0 にマッピングされる必要があります。[ 23 ]
Sun -2ワークステーションも同様で、Motorola 68010マイクロプロセッサを中心に構築されており、 2KBページと32KBセグメントを備えた同様のメモリ管理ユニットを備えています。コンテキストレジスタには、スーパーバイザ状態で使用される3ビットのシステムコンテキストと、ユーザー状態で使用される3ビットのユーザーコンテキストがあります。[ 24 ]
Sun -3ワークステーションは、Sun-3/80、Sun-3/460、Sun-3/470、Sun-3/480を除き、Motorola 68020をベースに構築されており、同様のメモリ管理ユニットを備えています。ページサイズは8KBに拡張されています。(後期モデルはMotorola 68030をベースに構築されており、68030のオンチップMMUを使用しています。)
Sun -4ワークステーションは、様々なSPARCマイクロプロセッサを中心に構築されており、Sun-3ワークステーションと同様のメモリ管理ユニットを備えている。
PowerPCでは、G1、G2、G3、G4ページは通常4KBです。TLBミスが発生すると、標準のPowerPC MMUは2つの同時ルックアップを開始します。1つのルックアップでは、アドレスを4つまたは8つのデータブロックアドレス変換(DBAT)レジスタ、あるいは4つまたは8つの命令ブロックアドレス変換(IBAT)レジスタのいずれかと照合します。BATレジスタは最大256MBのリニアメモリチャンクをマッピングでき、通常はOSがOSカーネル自身の使用のためにアドレス空間の大部分をマッピングするために使用されます。BATルックアップが成功した場合、もう一方のルックアップは停止され、無視されます。
このファミリのすべてのプロセッサで直接サポートされているわけではないもう1つのルックアップ方法は、いわゆる反転ページテーブルを介するものです。これは、TLBのハッシュ化されたオフチップ拡張機能として機能します。まず、アドレスの上位4ビットを使用して、16個のセグメントレジスタのうちの1つを選択します。次に、セグメントレジスタの24ビットがその4ビットを置き換え、52ビットのアドレスを生成します。セグメントレジスタを使用することで、複数のプロセスが同じハッシュテーブルを共有できます。
52 ビットのアドレスがハッシュ化され、オフチップ テーブルへのインデックスとして使用されます。そこで、8 ページ分のテーブル エントリのグループがスキャンされ、一致するエントリが検索されます。ハッシュの衝突が多すぎて一致するエントリがない場合、プロセッサはわずかに異なるハッシュ関数を使用して再度試行します。これも失敗した場合、CPU は OS にトラップし (MMU は無効)、問題が解決される可能性があります。OS は、新しいエントリのためのスペースを確保するために、ハッシュ テーブルからエントリを破棄する必要があります。OS は、より一般的なツリー状のページ テーブルまたはマッピングごとのデータ構造から新しいエントリを生成する可能性がありますが、これらは処理速度が遅く、スペース効率が高くなります。セグメント レジスタには実行禁止制御のサポートがあり、 256 MB の粒度を実現しています。
この設計における大きな問題点は、ハッシュ関数によってキャッシュの局所性が低下することです。ツリーベースの設計では、隣接するページのページテーブルエントリを隣接する場所に配置することで、この問題を回避します。PowerPC上で動作するオペレーティングシステムは、この問題を軽減するためにハッシュテーブルのサイズを最小限に抑える場合があります。
プロセスのページ テーブル エントリを削除するのもやや時間がかかります。OS は、この問題に直面するのを遅らせるためにセグメント値の再利用を避けるか、プロセスごとのハッシュ テーブルに関連するメモリの無駄を許容することを選択する場合があります。G1 チップはページ テーブル エントリを検索しませんが、ハッシュを生成します。これは、OS がソフトウェアを介して標準ハッシュ テーブルを検索することを想定しています。OS は TLB に書き込むことができます。G2、G3、および初期の G4 チップは、ハードウェアを使用してハッシュ テーブルを検索します。最新のチップでは、OS がどちらの方法も選択できます。これをオプションにするかまったくサポートしないチップでは、OS はツリー ベースのページ テーブルのみを使用することを選択する場合があります。
x86アーキテクチャは、OSコードも含め、ソフトウェアの完全な互換性を維持しながら、非常に長い時間をかけて進化してきました。そのため、MMUは非常に複雑で、さまざまな動作モードが存在します。
8086/8088および80186/80188にはメモリ管理ユニットがありません。セグメンテーションはサポートしていますが、16ビットアドレスでサポートできる以上の物理メモリをサポートするためだけです。セグメントレジスタ内のセグメント番号に16を掛け、セグメントオフセットに加算することで物理アドレスが生成されます。
80286では、セグメンテーションをサポートするがページングはサポートしない MMU が追加されました。保護モードをオンにしてセグメンテーションを有効にすると、セグメント番号はセグメント記述子のテーブルへのインデックスとして機能します。セグメント記述子には、ベース物理アドレス、セグメント長、セグメントが現在メモリ内にあるかどうかを示すプレゼンスビット、パーミッションビット、および制御ビットが含まれます。セグメント内のオフセットがセグメント記述子で指定された範囲内にある場合、そのオフセットがベース物理アドレスに追加されて物理アドレスが生成されます。
x86の32ビットIA-32バージョンを導入した80386と、その後のx86 CPUは、セグメンテーションとページングをサポートしています。ページングが有効になっている場合、セグメント記述子のベースアドレスは、 4KBのページに分割された線形ページングアドレス空間内のアドレスです。そのため、セグメント内のオフセットにこのアドレスを追加すると、結果として得られるアドレスはそのアドレス空間内の線形アドレスになります。IA-32では、このアドレスは32ビットを超えないようにマスクされます。結果は、ツリー構造のページテーブルを介して検索できます。アドレスのビットは、ツリーのブランチに10ビット、ブランチのリーフに10ビット、そして結果に直接コピーされる下位12ビットに分割されます。
80386以前のCPUでアドレス空間を拡張するために使用されていたセグメントレジスタは、現代のOSでは使用されていません。ただし、アプリケーションのスレッド固有データやOSカーネルのCPU固有データへのアクセスは例外で、これはFSおよびGSセグメントレジスタを明示的に使用して行われます。すべてのメモリアクセスには、実行されるコードに応じて選択されたセグメントレジスタが関与します。FSまたはGSを使用する場合を除き、OSはオフセットがゼロであることを保証します。OpenBSDのW ^X機能や、 Exec ShieldまたはPaXパッチを備えたLinuxなど、一部のオペレーティングシステムでは、CSレジスタで指定されるコードセグメントの長さを制限して、アドレス空間の変更可能な領域でのコードの実行を禁止する場合もあります。
Pentiumで導入された MMU のマイナーな改訂により、ツリーの最下層をスキップすることで、非常に大きな4 MBページが実現しました (これにより、ページ階層の最初のレベルのインデックスに 10 ビットが残り、残りの 10+12 ビットが結果に直接コピーされます)。 Pentium Proで導入された MMU のマイナーな改訂により、物理アドレス拡張(PAE) 機能が導入され、3 レベルのページ テーブルに 2+9+9 ビット、最下位 12 ビットが結果に直接コピーされる 36 ビットの物理アドレスが実現しました。ツリーの最下層をスキップすることで、大きなページ ( 2 MB ) も利用可能になりました (結果として、2 レベルのテーブル階層に 2+9 ビット、残りの最下位 9+12 ビットが直接コピーされます)。さらに、ページ属性テーブルにより、小さなオン CPU テーブルで上位数ビットを検索することで、キャッシュ可能性を指定できるようになりました。
当初、実行不可サポートはセグメント単位でのみ提供されていたため、非常に使いづらいものでした。最近のx86チップでは、PAEモードでページ単位のNXビット(実行不可ビット)が提供されています。上記で説明したW^X、Exec Shield、およびPaXメカニズムは、NXビットを持たないx86プロセッサ搭載マシンで、コードセグメントの長さを設定することでページ単位の非実行サポートをエミュレートしますが、パフォーマンスの低下と利用可能なアドレス空間の減少を伴います。

x86-64 は、x86 アーキテクチャの 64 ビット版で、 386 以降のプロセッサのほとんどすべてのオペレーティングシステムで使用されているフラット メモリ モデルを採用し、セグメンテーションをほぼ完全に排除しています。ロング モードでは、FS セグメントと GS セグメントを除き、すべてのセグメント オフセットは無視されます。リニア アドレスは 32 ビットではなく 64 ビットで、アドレスの下位 48 ビットが有効です。4 KBページで使用する場合、ページ テーブル ツリーは、より大きなリニア アドレスを処理するために、3 レベルではなく 4 レベルになります。一部の新しい x86-64 プロセッサでは、 57 ビットのリニア アドレスをサポートするために、 5 番目のページ テーブル レベルを有効にすることができます。ページ テーブルのすべてのレベルで、ページ テーブル エントリには NX ビットが含まれます。
48 ビットの線形アドレスは次のように分割されます。16 ビットは未使用、4 つのツリー レベルそれぞれに 9 ビット (合計 36 ビット)、そして結果に直接コピーされる最下位 12 ビット。2 MBページの場合、ページ テーブルは 3 レベルのみで、ページングに使用されるビットは合計 27 ビット、オフセットは 21 ビットです。一部の新しい CPU では、2 レベルのページングと30 ビットのオフセットを備えた1 GBページもサポートしています。[ 25 ] CPUID を使用して、 1 GBページがサポートされているかどうかを判断できます。
いずれの場合も、上位16ビットは48ビット目と等しくなければなりません。つまり、下位48ビットは符号拡張されて上位ビットに反映されます。これは、下位互換性を損なうことなく、アドレス指定可能な範囲をさらに拡張できるようにするためです。
57ビットの線形アドレスは次のように分割されます。7ビットは未使用、5つのツリーレベルそれぞれに9ビット(合計45ビット)、そして結果に直接コピーされる最下位12ビット。下位57ビットは符号拡張されます。[ 26 ]
1961年のBurroughs B5000は、 (Atlasに次いで)仮想メモリをサポートする最初の商用システムであり、外部MMUを必要としません。[ 27 ] B5000とその後継機から現在のUnisys ClearPath MCP(Libra)システムに至るまで、MMUの2つの機能(仮想メモリアドレスとメモリ保護)を異なるアーキテクチャアプローチで提供しています。仮想メモリ用に設計されていないプロセッサに仮想メモリを追加するのではなく、プロセッサ/システムのコア設計に統合されているため、アドレス変換や境界チェックの機能を追加するための外部ユニットは不要で、これまでにないメモリの安全性とセキュリティを実現しています。
まず、仮想メモリ アドレスのマッピングでは、MMU を必要とする代わりに、マシンはディスクリプタベースです。[ 28 ] [ 29 ] Burroughs B5000 シリーズ システムでは、48 ビット メモリ ワードの最上位ビットは、そのワードがユーザー データかディスクリプタ/制御ワードかを示します。ディスクリプタはユーザー プロセスに対して読み取り専用であり、システム (ハードウェアまたはオペレーティングシステム) によってのみ更新できます。B6x00/B7x00/B5900/A シリーズ/Unisys MCP システムのメモリ ワードは、48 データ ビットと 3 タグ ビットを持ちます (それ以降のシステムでは、タグ ビットは 4 つになります)。タグが奇数のワードは、ユーザー プロセスに対して読み取り専用です。ディスクリプタのタグは 5、コード ワードのタグは 3 です。
割り当てられた各メモリブロックには、ブロックのプロパティ(物理アドレス、サイズ、メインメモリに存在するかどうか)を示すマスターディスクリプタが割り当てられます。メインメモリに存在する場合は、初回アクセス時にブロックを割り当てる必要があります。アドレスが存在する場合は、二次記憶装置上のアドレスであるため、メインメモリにロードする必要があります。コードとデータへのすべての参照は、ディスクリプタを使用して行われます。ブロックの読み取りまたは書き込み要求が行われると、ハードウェアはディスクリプタの存在ビット(pbit)を介してブロックの存在を確認します。
pbit [ 30 ]が 1 の場合、ブロックが存在することを示します。この場合、ブロックはディスクリプタ内の物理メインメモリ アドレスを介してアクセスできます。pbit がゼロの場合、ブロックを存在させるためにMCP (オペレーティングシステム) に pbit 割り込み[ 31 ]が生成されます。アドレス フィールドがゼロの場合、これはこのブロックへの最初のアクセスであり、ブロックが割り当てられます (init (初期) pbit)。アドレス フィールドがゼロでない場合、それは以前にロールアウトされたブロックのディスク アドレスです。ブロックはディスクからフェッチされ、pbit が 1 に設定され、物理メモリ アドレスが更新されてメモリ内のブロックを指すようになります。これにより、ディスクリプタは MMU システムのページ テーブル エントリと同等になりますが、ディスクリプタにはテーブルがありません。
したがって、すべてのメモリ割り当ては完全に自動で行われ(最新システムの特長の 1 つです[ 32 ])、このメカニズム以外でブロックを割り当てる方法はありません。メモリ ブロックは pbit 割り込み時にも自動的に割り当てられるか破棄されるため、 mallocや dealloc のような呼び出しはありません。この方式は遅延評価でもあり、ブロックは実際に参照されるまで割り当てられません。メモリがほぼ満杯になると、MCP はワーキング セットを調べ、圧縮(システムはページングではなくセグメント化されているため)、読み取り専用セグメント(元のコピーから復元できるコード セグメントなど)の解放、そして最終手段として、ダーティ(つまり更新された)データ セグメントをディスクにロールアウトします。
これらのシステムがMMUの機能を提供するもう一つの方法は、保護機能です。すべてのアクセスはディスクリプタを介して行われるため、ハードウェアはすべてのアクセスが範囲内にあること、そして書き込みの場合はプロセスが書き込み権限を持っていることをチェックできます。MCPシステムは本質的に安全であるため、このレベルのメモリ保護を提供するためにMMUは必要ありません。
ブロックは、プロセススタック内のコピー記述子を介してプロセス間で共有できます(スタックは、プロセスの実行状態を表す特殊なシステム構造です)。そのため、一部のプロセスは書き込み権限を持ち、他のプロセスは持たない場合があります。コードセグメントは読み取り専用であるため、再入可能であり、プロセス間で共有されます。コピー記述子には、マスター記述子配列内のマスター記述子のインデックスを示す20ビットのアドレスフィールドが含まれています。これにより、非常に効率的で安全なプロセス間通信(IPC)メカニズムも実現されます。ブロックの状態が変更されたときに更新する必要があるのはマスター記述子のみであるため、ブロックは容易に再配置できます。
もう一つの側面はパフォーマンスです。MMUベースのシステムと非MMUベースのシステムでは、どちらが優れたパフォーマンスを発揮するのでしょうか? MCPシステムは、MMUを搭載した標準的なハードウェア(例えば、標準的なPC)上に実装できます。システム実装で何らかの形でMMUが使用されている場合でも、MCPレベルでは全く見えません。
バンク切り替えと呼ばれる単純な技術は、MOS 6502のような初期の 8 ビットマイクロプロセッサで広く使用されていました。たとえば、Atari MMU はアドレス バスに追加のビットを表示して、現在アクティブなチップ (通常は CPU またはANTIC)に基づいて、複数のDRAMメモリバンクから選択していました。これは、 Atari 130XEで使用可能なメモリを128 kBに拡張するために使用されました。 [ 33 ] Commodore 128 も同様のアプローチを使用していました。