コンテンツにスキップ

「プロテクトモード」の版間の差分

出典: フリー百科事典『ウィキペディア(Wikipedia)』
削除された内容 追加された内容
Dokomonta-Bot (会話 | 投稿記録)
Melan (会話 | 投稿記録)
(5人の利用者による、間の5版が非表示)
1行目: 1行目:
'''プロテクトモード'''とは、[[Intel 80286|80286]]以降の[[x86]]アーキテクチャの[[CPU]]の動作モードの一つ。正式名称は Protected Virtual Address Mode(保護仮想アドレスモード)である<ref name="'Protected virtual address mode' usage">{{Cite web | url = http://www.patentstorm.us/patents/5483646-claims.html | title = Memory access control method and system for realizing the same | work = US Patent 5483646 | accessdate = 2007-07-14 | date = May 23, 1995 | format = Patent | quote = The memory access control system according to claim 4, wherein said first address mode is a real address mode, and said second address mode is a protected virtual address mode. }}</ref>。メモリやI/Oの保護を行うと共に、アドレス空間の拡張を行ったモードである。このモードでは[[仮想記憶]]、[[ページング方式|ページング]]、安全な[[マルチタスク]]といった機能を[[システムソフトウェア]]が使えるようになり、[[アプリケーションソフトウェア]]への[[オペレーティングシステム]] (OS) の制御能力が向上するよう設計されている<ref name="i386 additions">{{Harvnb|Intel|2007|loc="2.1.3 The Intel 386 Processor (1985)" p.35}}</ref><ref name="Purpose of protected mode">{{Cite web| url = http://www.delorie.com/djgpp/doc/ug/basics/protected.html | title = Guide: What does protected mode mean? | accessdate = 2007-07-14 | last = | first = "root" | date = July 14, 2007 | format = Guide | publisher = Delorie software | quote = The purpose of protected mode is not to protect your program. The purpose is to protect everyone else (including the operating system) from your program. }}</ref>。
'''プロテクトモード'''とは、[[Intel 80286|80286]]以降の [[80x86|x86]]アーキテクチャのCPUの動作モードの一つで、メモリやI/Oの保護を行うと共に、アドレス空間の拡張を行ったモードである。


== 概要 ==
== 概要 ==
プロテクトモードとは80286以降のCPUの命令セットアーキテクチャの動作モードの一つであり、これらのCPUの本来の動作モードといえる物である。
プロテクトモードとは80286以降のCPUの命令セットアーキテクチャの動作モードの一つであり、これらのCPUの本来の動作モードといえる物である。特徴づけるものは、その名前の通り、階層的な特権管理([[リングプロテクション]])や、タスク間の[[メモリ保護]](プロテクト)を行う事が可能な事である。


プロテクトモードをサポートしているx86系プロセッサを起動したとき、それ以前のx86系プロセッサとの[[後方互換]]を保つため[[リアルモード]]で命令を実行する<ref name="Real mode on powered on">{{Harvnb|Intel|2007|loc="3.2 Modes of Operation" p.59}}</ref>。プロテクトモードに移行するには、システムソフトウェアがいくつかのディスクリプタテーブルを設定してから、コントロールレジスタ0 (CR0) のPE (Protection Enable) ビットをセットしなければならない<ref name="Entering protected mode">{{Cite web| url = ftp://ftp.utcluj.ro/pub/users/nedevschi/PMP/protected86/collinsprot.PDF | title = Protected Mode Basics | accessdate = 2009-07-31 | last = Collins | first = Robert | year = 2007 | format = PDF | publisher = ftp.utcluj.ro }}</ref>。
正式名称はProtected Virtual Address Mode(保護仮想アドレスモード)である。


プロテクトモードは1982年、[[インテル]]の [[Intel 80286|80286]] (286) プロセッサのリリースと共に[[x86]]アーキテクチャに追加され<ref name="i286 release date">{{Harvnb|Intel|2007|loc="2.1.2 The Intel 286 Processor (1982)" p.34}}</ref>、1985年の [[Intel 80386|80386]] (386) で拡張された<ref name="i386 release date">{{Cite web| url = http://www.intel.com/intel/finance/gcr03/39-years_of_innovation.htm | title = Intel Global Citizenship Report 2003 | accessdate = 2007-07-14 | format = Timeline | quote = 1985 Intel launches Intel386 processor | archiveurl = http://web.archive.org/web/20080322075839/http://www.intel.com/intel/finance/gcr03/39-years_of_innovation.htm | archivedate = 2008-03-22 }}</ref>。プロテクトモードの追加による機能向上によって広く採用され、同時にそれがその後のx86アーキテクチャの全ての強化の基礎となった<ref name="Foundation">{{Harvnb|Intel|2007|loc="2.1 Brief History of the IA-32 Architecture" p.31}}</ref>。
特徴づけるものは、その名前の通り、階層的な特権管理([[リングプロテクション]])や、タスク間の[[メモリ保護]](プロテクト)を行う事が可能な事である。


プロテクトモードにおいては、メモリ上の'''グローバルディスクリプタテーブル''' (GDT) および'''ローカルディスクリプタテーブル''' (LDT) という構造体の配列をそれぞれ最大8192個管理する。この構造体はそれぞれ、リニアアドレスのポインタおよび大きさおよび保護情報を持つセグメントディスクリプタや、タスクセグメントへのポインタとサイズ、保護情報を持つ'''タスクディスクリプタ'''、'''ローカルディスクリプタテーブル'''へのポインタを保持するもの、そして特権等を変更するための呼び先である、'''ゲートディスクリプタ'''等を持つ。セグメントレジスタはセレクタと呼ばれGDTまたはLDTのオフセットでセグメントディスクリプタを指すものとなる。無効なディスクリプタをセレクタにロードしたりすると例外を発生するようになった。タスクセグメントは、LDTRを含むレジスタ等の実行環境を保持する。
元々、[[Intel 8086|8086]]においては、[[セグメント方式]]の[[仮想記憶]]を意識したセグメントレジスタという概念があり、コード、データおよび[[スタック]]の量がそれぞれ64キロバイト以内であれば、ロードされた物理アドレスを意識すること無く、タスクの実行が可能であったが、論理アドレスから物理アドレスへの変換は単純にセグメントレジスタを4ビットシフトして足すと言うもので、タスク間の保護もなかった。


また、[[割り込み (コンピュータ)|割り込み]]/[[例外処理|例外]]ベクタも、最低位アドレスに固定される事無く、'''割り込みディスクリプタテーブル''' (IDT) にあるゲートディスクリプタの配列により設定されることになった。
プロテクトモードにおいては、メモリ上の'''グローバルディスクリプタテーブル''' (GDT)および'''ローカルディスクリプタテーブル''' (LDT)という構造体の配列をそれぞれ最大8192個管理する。この構造体はそれぞれ、リニアアドレスのポインタおよび大きさおよび保護情報を持つセグメントディスクリプタや、タスクセグメントへのポインタとサイズ、保護情報を持つ'''タスクディスクリプタ'''、'''ローカルディスクリプタテーブル'''へのポインタを保持するもの、そして特権等を変更するための呼び先である、'''ゲートディスクリプタ'''等を持つ。セグメントレジスタはセレクタと呼ばれGDTまたはLDTのオフセットでセグメントディスクリプタを指すものとなる。無効なディスクリプタをセレクタにロードしたりすると例外を発生するようになった。タスクセグメントは、LDTRを含むレジスタ等の実行環境を保持する。

また、[[割り込み (コンピュータ)|割り込み]]/[[例外処理|例外]]ベクタも、最低位アドレスに固定される事無く、'''割り込みディスクリプタテーブル''' (IDT)にあるゲートディスクリプタの配列により設定されることになった。

特権は数字が低い程高い特権で0,1,2,3の4段階である。高い特権のコードへの呼出はゲートディスクリプタや例外を通す必要がある。


80286以降で物理メモリの拡張も行われたが、100000h以降(1MB以降)のアドレスの物理メモリは、[[HMA]]を除けばプロテクトモードを使用しない限り、CPUからはアクセスできない領域であった。そのため、この実質的にプロテクトモード専用の1MB以降の物理メモリ領域は通称'''プロテクトメモリ'''と呼ばれた。
80286以降で物理メモリの拡張も行われたが、100000h以降(1MB以降)のアドレスの物理メモリは、[[HMA]]を除けばプロテクトモードを使用しない限り、CPUからはアクセスできない領域であった。そのため、この実質的にプロテクトモード専用の1MB以降の物理メモリ領域は通称'''プロテクトメモリ'''と呼ばれた。
20行目: 16行目:
プロテクトメモリを利用するためには、本来[[UNIX]]や[[OS/2]]等のマルチタスクOSが必要であるが、[[MS-DOS]]上でも[[Expanded Memory Specification|EMS]]・[[XMS]]ドライバ、[[DOSエクステンダ]]等を使用すれば利用可能であった。
プロテクトメモリを利用するためには、本来[[UNIX]]や[[OS/2]]等のマルチタスクOSが必要であるが、[[MS-DOS]]上でも[[Expanded Memory Specification|EMS]]・[[XMS]]ドライバ、[[DOSエクステンダ]]等を使用すれば利用可能であった。


== 歴史 ==
== 80286におけるプロテクトモード ==
286に先立つ [[Intel 8086]] での本来の設計では、メモリアクセス用[[アドレスバス]]は20[[ビット]]幅だった<ref name="Address bus">{{Cite web| url = http://www.brainbell.com/tutors/A+/Hardware/PC_Microprocessor_Developments_and_Features.htm | title = A+ - Hardware | work = PC Microprocessor Developments and Features Tutorials | accessdate = 2007-07-24 | format = Tutorial/Guide | publisher = BrainBell.com }}</ref>。これにより 2<sup>20</sup> [[バイト (情報)|バイト]]、すなわち1[[メガバイト]]のメモリにアクセス可能である<ref name="Address bus" />。当時は1メガバイトといえばかなり大容量のメモリという感覚だったので<ref name="1 MB large">{{Cite web| url = http://www.pcmech.com/show/processors/35/ | title = A CPU History | accessdate = 2007-07-24 | last = Risley | first = David | date = March 23, 2001 | format = Article | publisher = PCMechanic | quote = What is interesting is that the designers of the time never suspected anyone would ever need more than 1 MB of RAM. | archiveurl = http://web.archive.org/web/20080115220724/http://www.pcmech.com/article/a-cpu-history/ | archivedate = 2008-01-15 }}</ref>、[[IBM PC]] の設計者らは先頭640[[キロバイト]]をアプリケーションとオペレーティングシステムで使用し、[[Upper Memory Area|残る384キロバイト]]を[[Basic Input/Output System|BIOS]] (Basic Input/Output System) や[[周辺機器]]で使用する設計にした<ref name="Memory usage">{{Cite web| url = http://www.internals.com/articles/protmode/introduction.htm | title = Introduction to Protected-Mode | accessdate = 2007-07-24 | last = Kaplan | first = Yariv | year = 1997 | format = Article | publisher = Internals.com }}</ref>。
最初に導入された[[Intel 80286|80286]]においては[[24ビット]]の物理アドレス空間へのアクセス、そして1セグメントあたり最大64キロバイトの空間を提供していた。これまでに述べた機能を使ってセグメントレジスタを意識したセグメント方式の仮想記憶を使った[[オペレーティングシステム|OS]]環境を作成することが可能になった。

元々、[[Intel 8086|8086]]においては、[[セグメント方式]]の[[仮想記憶]]を意識したセグメントレジスタがあり、コード、データおよび[[スタック]]の量がそれぞれ64キロバイト以内であれば、ロードされた物理アドレスを意識すること無く、タスクの実行が可能であったが、論理アドレスから物理アドレスへの変換は単純にセグメントレジスタを4ビットシフトして足すと言うもので、タスク間の保護もなかった。

メモリ価格が低下し、メモリ使用量が増えてくると、1MBという制約が大きな問題となってきた。[[インテル]]はこの制限に対処するためもあって 286 をリリースした<ref name="Memory usage" />。

=== 286 ===
{{See also|Intel 80286}}
最初に導入された[[Intel 80286|80286]]においては[[24ビット]]の物理アドレス空間へのアクセス、そして1セグメントあたり最大64キロバイトの空間を提供していた。これまでに述べた機能を使ってセグメントレジスタを意識したセグメント方式の仮想記憶を使ったOS環境を作成することが可能になった。しかし286リリース当時、プロテクトモードはすぐに広く使われたわけではない<ref name="Memory usage"/>。プロセッサをリセットする以外にリアルモードに戻ることができないため、BIOSまたはDOSコールにアクセスすることができないなどの欠点があり、幅広い採用が妨げられた<ref name="286 failings">{{Cite book| last = Mueller | first = Scott | title = Upgrading and Repairing PCs, 17th Edition | date = March 24, 2006 | url = http://www.informit.com/store/product.aspx?isbn=0789734044 | format = Book | accessdate = July 2007 | edition = 17 | publisher = Que | isbn = 0-7897-3404-4 | chapter = P2 (286) Second-Generation Processors | chapterurl = http://www.informit.com/articles/article.aspx?p=481859&seqNum=13 }}</ref>。幅広い採用が見送られた他の要因として、286 では4本のセグメントレジスタでそれぞれ16ビットのセグメントしかアクセスできなかった。すなわち一度にアクセスできるメモリの範囲は 4*2<sup>16</sup> バイト(256[[キロバイト]])に限られていた<ref name="Memory usage"/>。

286 は 8086 との互換性を保つため、起動時には[[リアルモード]]で動作を開始するようになっていた<ref name="Real mode on powered on" />。リアルモードでは 8086 と全く同じ動作をするので、古い[[ソフトウェア]]も 286 で修正せずに動作することができる。286 の拡張機能にアクセスするには、オペレーティングシステムがプロセッサをプロテクトモードに移行させる必要がある。それによって24ビット・アドレッシングが可能になり、2<sup>24</sup> バイト(16[[メガバイト]])のメモリにアクセス可能となる<ref name="Address bus"/>。


保護された空間外へのメモリアクセスなどを行うと、たちどころに例外割り込みが発生して処理が停止する。80286の[[16ビット]] PVAMにおいて全ての保護違反例外はただひとつの割り込みベクタ…悪名高き「一般保護例外 (General Protection Fault)」INT#13 に割り当てられており、一旦これが起きてしまうとそのプロセス(あるいはタスクまたはスレッド)の処理を復帰させる方法がない。すなわち外部記憶装置を持つ仮想記憶システムにおいてページ違反を例外処理として検出し、ページスワップを行ってからプロセスを再開させることができない(セグメントディスクリプタには「不在ビット」の属性があり、これを用いた仮想記憶管理を行うことは可能なのだが、メモリアクセス違反を流用した仮想記憶管理ができない)。これはそもそも[[インテル]]が80286を[[Intel 80186|80186]]の上位機種であり「最高の信頼性を持つ制御用プロセッサ」として位置づけており、外部仮想記憶を持つような高度な処理は[[Intel iAPX 432|iAPX432]] 32ビット[[プロセッサ]]によって実現する構想を抱いていたことに起因する。80286は、工業用ミニコンピュータのアーキテクチャにならったもので、間違った前提のまま動き続けるよりは間違いを検出して止まったほうが被害が少ない、という思想に基づくものであった。
保護された空間外へのメモリアクセスなどを行うと、たちどころに例外割り込みが発生して処理が停止する。80286の[[16ビット]] PVAMにおいて全ての保護違反例外はただひとつの割り込みベクタ…悪名高き「一般保護例外 (General Protection Fault)」INT#13 に割り当てられており、一旦これが起きてしまうとそのプロセス(あるいはタスクまたはスレッド)の処理を復帰させる方法がない。すなわち外部記憶装置を持つ仮想記憶システムにおいてページ違反を例外処理として検出し、ページスワップを行ってからプロセスを再開させることができない(セグメントディスクリプタには「不在ビット」の属性があり、これを用いた仮想記憶管理を行うことは可能なのだが、メモリアクセス違反を流用した仮想記憶管理ができない)。これはそもそも[[インテル]]が80286を[[Intel 80186|80186]]の上位機種であり「最高の信頼性を持つ制御用プロセッサ」として位置づけており、外部仮想記憶を持つような高度な処理は[[Intel iAPX 432|iAPX432]] 32ビット[[プロセッサ]]によって実現する構想を抱いていたことに起因する。80286は、工業用ミニコンピュータのアーキテクチャにならったもので、間違った前提のまま動き続けるよりは間違いを検出して止まったほうが被害が少ない、という思想に基づくものであった。
27行目: 33行目:
しかし、インテルの思惑とは裏腹に、80286は汎用コンピュータである [[IBM PC/AT]]および[[IBM PS/2]]に搭載されてしまい、その上で汎用OSである[[OS/2]]を動かす必要に迫られ、80286は、本来の設計思想とは異なる領域で、アーキテクチャを無理にねじ曲げた使い方を強いられることになってしまい、「石頭」「こんだけ苦労してたった16MB」「しかも相変わらずセグメントあたり64KBの制限つき」「Brain Damaged CPU」などの悪名を高めてしまうことになる。
しかし、インテルの思惑とは裏腹に、80286は汎用コンピュータである [[IBM PC/AT]]および[[IBM PS/2]]に搭載されてしまい、その上で汎用OSである[[OS/2]]を動かす必要に迫られ、80286は、本来の設計思想とは異なる領域で、アーキテクチャを無理にねじ曲げた使い方を強いられることになってしまい、「石頭」「こんだけ苦労してたった16MB」「しかも相変わらずセグメントあたり64KBの制限つき」「Brain Damaged CPU」などの悪名を高めてしまうことになる。


=== 386 ===
== IA-32のプロテクトモード ==
[[ファイル:Ic-photo-intel-A80386DX-33-IV-(386DX).png|thumb|Intel 80386 マイクロプロセッサ]]
[[IA-32]]つまり[[Intel 80386|80386]]以降で使用可能なプロテクトモードにおいては、32ビットのリニアアドレス空間へのアクセス、1セグメントあたり最大4[[ギビバイト]]の空間を提供する上に、さらに物理アドレスへの変換に[[ページテーブル]]を通すことが可能で、[[ページング方式]]の仮想記憶を使用することが可能になった。
{{See also|Intel 80386}}

1985年<ref name="i386 release date" />にリリースされた 386 では、プロテクトモードの採用を妨げていた様々な問題への対処が行われている<ref name="Memory usage" />。386のアドレスバスは32ビット幅で、2<sup>32</sup> バイト(4[[ギガバイト]])のメモリにアクセス可能である<ref name="Memory increases">{{Cite book| title = Intel 80386 Programmer's Reference Manual 1986 | format = Manual | accessdate = July 2007 | year = 1986 | publisher = Intel | location = Santa Clara, CA | chapter = 2.1 Memory Organization and Segmentation }}</ref>。セグメントも32ビットに拡大され、複数のセグメントを切り換えることなく4ギガバイトのアドレス空間にアクセス可能となった<ref name="Memory increases" />。アドレスバスとセグメントレジスタの拡大に加えて、セキュリティと安定性を向上させるための様々な機能が追加されている<ref name="Enhancements">{{Harvnb|Intel|2007|loc="3.1 Modes of Operation" p.55}}</ref>。

プロテクトモードはその後、[[Microsoft Windows]] や[[Linux]]などほぼ全てのx86アーキテクチャ([[IA-32]])上の[[オペレーティングシステム]]で使われるようになった<ref name="Protected mode use">{{Cite book| title = Write Great Code | publisher = O'Reilly | first = Randall | last = Hyde | chapter = 12.10. Protected Mode Operation and Device Drivers | month = November | year = 2004 | isbn = 1-59327-003-8 }}</ref>。

== 386のプロテクトモードで追加された機能 ==
386のリリースに際し、以下の機能がプロテクトモードに追加された<ref name="i386 additions" />。

* [[ページング方式]]
* [[32ビット]]物理および仮想[[アドレス空間]](32ビット物理アドレス空間は [[Intel 80386|80386SX]] ではサポートされておらず、他の386派生プロセッサも古い286型のバスを使用していた<ref name="80386SX address bus">{{Cite web| url = http://www.cpu-world.com/CPUs/80386/index.html | title = Intel 80386 processor family | accessdate = 2007-07-24 | last = Shvets | first = Gennadiy | date = June 3, 2007 | format = Article | quote = 80386SX&nbsp;— low cost version of the 80386. This processor had 16 bit external data bus and 24-bit external address bus. }}</ref>)
* 32ビットの[[セグメント方式|セグメント]]オフセット
* リアルモードに戻せるようになった。
* [[仮想86モード]]

== プロテクトモードへの(からの)移行 ==
386がリリースされる以前は、プロテクトモードにいったん入った後、リアルモードに戻る直接的方法が提供されていなかった。[[IBM]]はその対処として、キーボードコントローラからCPUをリセットする技法を考案し、その際にシステムレジスタ群、[[コールスタック|スタックポインタ]]、割り込みマスクをリアルタイムクロックのチップにあるRAMにセーブするようにした。これによりBIOSがCPUをほぼ同じ状態に復旧することが可能となり、リセット前のコードの実行を続行できる。その後、トリプルフォールトを発生させて286CPUをリセットするという手段がとられた。こちらの方がキーボードコントローラを使うよりも高速できれいだった。

プロテクトモードにおいては、メモリ上の'''グローバルディスクリプタテーブル''' (GDT) および'''ローカルディスクリプタテーブル''' (LDT) という構造体の配列をそれぞれ最大8192個管理する。この構造体はそれぞれ、リニアアドレスのポインタおよび大きさおよび保護情報を持つセグメントディスクリプタや、タスクセグメントへのポインタとサイズ、保護情報を持つ'''タスクディスクリプタ'''、'''ローカルディスクリプタテーブル'''へのポインタを保持するもの、そして特権等を変更するための呼び先である、'''ゲートディスクリプタ'''等を持つ。セグメントレジスタはセレクタと呼ばれGDTまたはLDTのオフセットでセグメントディスクリプタを指すものとなる。無効なディスクリプタをセレクタにロードしたりすると例外を発生するようになった。タスクセグメントは、LDTRを含むレジスタ等の実行環境を保持する。

プロテクトモードに入るには、少なくとも3エントリ(ヌルディスクリプタ、コードセグメントディスクリプタ、データセグメントディスクリプタ)を持つGDTを作る必要がある。そして、アドレスバスのA20線(21番目のアドレス線)をイネーブルにし、1メガバイトを越えるメモリにアクセスできるようにする必要がある(電源投入直後は、古いソフトウェアの互換性を保証するため、20番目までのアドレス線しか使わない設定になっている)。この2段階を実行後、CR0レジスタのPEビットをセットして、far jump 命令を実行することで命令プリフェッチキューをクリアしなければならない。

<source lang="asm">
; set PE bit
mov eax, cr0
or eax, 1
mov cr0, eax

; far jump (cs = selector of code segment)
jmp cs:@pm

@pm:
; Now we are in PM.
</source>

386以降でプロテクトモードからリアルモードに移行するには、セグメントレジスタをリアルモードの値にし、A20 線をディセーブルし、CR0レジスタのPEビットをクリアすればよく、286で必要だった初期設定が不要になった。

== 機能と特徴 ==
プロテクトモードには、セキュリティとシステム安定性を向上させるべくOSのアプリケーションに対する制御を強化するよう設計された機能がいくつかある<ref name="Purpose of protected mode" />。それら追加機能により、適切なハードウェアサポートなしではかなり難しいか不可能なOS機能の実装が可能になった<ref name="Multitasking">{{Cite book| title = Intel 80386 Programmer's Reference Manual 1986 | format = Manual | accessdate = July 2007 | year = 1986 | publisher = Intel | location = Santa Clara, CA | chapter = 7 Multitasking }}</ref>。

=== 特権レベル ===
{{See also|リングプロテクション}}
[[ファイル:Priv rings.svg|thumb|特権リングの使用例。この例ではOSが全リングを使用している。]]

特権は数字が低い程高い特権で0,1,2,3の4段階の[[リングプロテクション|特権リング]]がある。リングの使用により、システムソフトウェアがタスクのデータや[[コールゲート]]へのアクセスまたは特権命令実行を制限できるようになった<ref name="Rings">{{Harvnb|Intel|2007|loc="6.3.5 Calls to Other Privilege Levels" p.162}}</ref>。大抵の環境では、OSと一部の[[デバイスドライバ]]がリング0で、アプリケーションがリング3で動作する<ref name="Rings"/>。高い特権のコードへの呼出はゲートディスクリプタや例外を通す必要がある。

=== リアルモードのアプリケーションの互換性 ===
''Intel 80286 Programmer's Reference Manual'' には以下のような記述がある<ref name="286 compatibility">{{Harvnb|Intel|1987|loc=1.2 Modes of Operation}}</ref>。

{{Cquote
| 80286は 8086および80186のほとんどのアプリケーションプログラムに対して上方互換を保っている。8086のほとんどのアプリケーションプログラムは、80286上で再コンパイルまたは再アセンブルすることでプロテクトモードで実行可能である。
}}

リアルモードのコードとのバイナリ互換性の観点で、アプリケーションプログラマにとって最も明白な変化は、物理メモリが最大16MBまでアクセス可能になった点と1GBの[[仮想記憶]]であった<ref name="286 compatibility">{{Harvnb|Intel|1987|loc=1.3.1 Memory Management}}</ref>。これには制限がなかったわけではなく、以下のような技法を使っていたアプリケーションはプロテクトモードでは動作しなかった<ref name="Compatibility limitations">{{Harvnb|Intel|1987|loc=Appendix C 8086/8088 Compatibility Considerations}}</ref>。

* セグメント計算
* 特権命令を使用
* ハードウェアへの直接アクセス
* [[自己書き換えコード|コードセグメントの書き換え]]
* データの実行
* セグメントのオーバーラップ
* インテルによって確保されているBIOS割り込みのためにBIOS関数を使用<ref name="BIOS only available through workarounds">{{Cite web| url = http://www.freepatentsonline.com/6105101.html | title = Memory access control method and system for realizing the same | work = US Patent 5483646 | accessdate = 2007-07-25 | date = May 6, 1998 | format = Patent | quote = This has been impossible to-date and has forced BIOS development teams to add support into the BIOS for 32 bit function calls from 32 bit applications. }}</ref>

実際にはほぼ全ての[[DOS (OS)|DOS]]アプリケーションプログラムがこれらのルールのいずれかに反していた<ref name="Incompatibilities">{{Cite web| url = http://osdev.berlios.de/v86.html | title = Virtual 8086 Mode | accessdate = 2007-07-25 | last = Robinson | first = Tim | date = August 26, 2002 | format = Guide | publisher = berliOS | quote = ...secondly, protected mode was also incompatible with the vast amount of real-mode code around at the time. }}</ref>。そのため、386では[[仮想86モード]]が導入された。そういった潜在的問題はあったが、Windows 3.0 とその後継では [[Microsoft Windows 2.0|Windows 2.x]] でのリアルモードの各種アプリケーションをプロテクトモードで動作させるのに互換性を利用している<ref name="Windows protected mode usage">{{Cite web| url = http://osdev.berlios.de/v86.html | title = Virtual 8086 Mode | accessdate = 2007-07-25 | last = Robinson | first = Tim | date = August 26, 2002 | format = Guide | publisher = berliOS }}</ref>。

=== 仮想86モード ===
{{Main|仮想86モード}}
386のプロテクトモードでは、インテルが仮想8086モード (virtual 8086 mode) と呼ぶものを提供している。仮想86モードは8086向けのコードを修正することなく、プロテクトモードのOS上のタスクの1つとして安全に動作させることができる<ref name="V8086 mode">{{Harvnb|Intel|2007|loc="15.2 Virtual 8086 Mode" p.560}}</ref>。ただし完全な後方互換性があるわけではない。セグメント操作や特権命令、ハードウェアへの直接アクセス、[[自己書き換えコード]]などを使っているプログラムの場合、[[例外処理|例外]]が発生するのでOSがそれに対処しなければならない<ref name="V8086 limitations">{{Harvnb|Intel|2007|loc="15.2.7 Sensitive Instructions" p.568}}</ref>。さらに仮想86モードで動作するアプリケーションが[[入出力]] (I/O) 関連命令を使用するとトラップ処理が行われるので、性能が低下する<ref name="V86 performance">{{Cite web| url = http://osdev.berlios.de/v86.html | title = Virtual 8086 Mode | accessdate = 2007-07-25 | last = Robinson | first = Tim | date = August 26, 2002 | format = Guide | publisher = berliOS | quote = A downside to using V86 mode is speed: every IOPL-sensitive instruction will cause the CPU to trap to kernel mode, as will I/O to ports which are masked out in the TSS. }}</ref>。そういった制約があるため、8086上のプログラムの一部は仮想86モードでは動作できない。結果としてシステムソフトウェアは、古いソフトウェアを扱う際にセキュリティか互換性のいずれかを犠牲にすることになった。例えば [[Microsoft Windows NT|Windows NT]] では互換性を犠牲にし、行儀の悪いDOSアプリケーションをサポートしなくなった<ref name="DOS and NT">{{Cite book| last = Dabak | first = Prasad | coauthors = Millind Borate | title = Undocumented Windows NT | format = Book | year = 1999 | month = October | publisher = Hungry Minds | isbn = 0-7645-4569-8 | chapterurl = Memory Management }}</ref>。

=== セグメント方式 ===
[[ファイル:080810-protected-286-segments.PNG|thumb|80286の仮想セグメント]]
{{See also|セグメント方式}}
リアルモードでは、論理アドレスは2つの16ビットの部分で構成されており、論理アドレスが直接物理的メモリ位置に対応している。論理アドレスのセグメント部は16バイトでセグメントのベースアドレスを指しており、セグメントは物理アドレス 0, 16, 32, ..., 2<sup>20</sup>-16 から始まる。論理アドレスのオフセット部はセグメント内のオフセットであり、物理アドレスは <code>physical_address : = segment_part × 16 + offset</code> という式で計算できる(アドレスバスのA20線がイネーブル状態の場合<ref>A20線がディセーブル状態なら (segment_part × 16 + offset) mod 2<sup>20</sup> となる</ref>)。各セグメントのサイズは 2<sup>16</sup> バイトである。

==== プロテクトモード ====
プロテクトモードでは、セグメント部が16ビットの「セレクタ」で置き換えられ、セレクタの上位13ビット(ビット 3 から ビット15)がディスクリプタテーブル内のエントリのインデックスとなっている。下位2ビット(ビット 0 とビット 1)は要求の特権レベルを定義しており、0から3までの値をとり、0が最も特権が高く、3が最も特権が低い。残るビット(ビット 2)はGDTかLDTの指定に使われる。

ディスクリプタテーブルのエントリには以下の情報が含まれる。

* セグメントの「リニア」アドレス
* セグメントの大きさを示すリミット値
* いくつかの属性ビット群(フラグ)

==== 286 ====
ディスクリプタテーブルのエントリ内のセグメントアドレスは24ビットであり、リアルモードとは異なり任意のアドレスからセグメントを開始できるようになった。リミット値は16ビット幅であり、セグメントの大きさは1バイトから 2<sup>16</sup> バイトまで指定可能である。これに基づいて計算したリニアアドレスは物理メモリアドレスとなる。

==== 386 ====
ディスクリプタテーブルのエントリ内のセグメントアドレスは32ビットに拡張されている。リミット値は20ビット幅に拡張され、しかもG-ビットで倍率を指定できる。

* G-ビットがゼロなら、リミット値の倍率は1であり、セグメントの大きさは1バイトから 2<sup>20</sup> バイトまでとなる。
* G-ビットが1なら、リミット値の倍率は4096倍であり、セグメントの大きさは 4096 の倍数で4096バイトから4ギガバイトまでとなる。

ページングを使わない場合、リニアアドレスはそのまま物理メモリアドレスとなるが、ページングを使う場合はリニアアドレスはページング機構への入力となる。

386プロセッサではアドレスオフセットとしても32ビットの値を使用する。

286のプロテクトモードとの互換性を維持するため、D-ビットが追加されている。D-ビットがオフとなっているコードセグメントは16ビット・セグメントと解釈され、その中の命令は16ビット命令として実行される。

==== セグメントディスクリプタのエントリの構造 ====

{| class="wikitable"
|-
! B
! ビット
! 80286
! 80386
! B
|-
! 0
| 00..07,0..7
| rowspan = 2 | リミット値
| rowspan = 2 | リミット値のビット0..15
! 0
|-
! 1
| 08..15,0..7
! 1
|-
! 2
| 16..23,0..7
| rowspan = 3 | セグメントベースアドレス
| rowspan = 3 | ベースアドレスのビット 0..23
! 2
|-
! 3
| 24..31,0..7
! 3
|-
! 4
| 32..39,0..7
! 4
|-
! 5
| 40..47,0..7
| colspan = 2 | 属性フラグ #1
! 5
|-
! rowspan = 2 | 6
| 48..51,0..3
| rowspan = 3 | 未使用
| リミット値のビット 16..19
! rowspan = 2 | 6
|-
| 52..55,4..7
| 属性フラグ #2
|-
! 7
| 56..63,0..7
| ベースアドレスのビット 24..31
! 7
|-
|}

* カラム '''B''': エントリ内のバイトオフセット
* カラム '''ビット''' の前半部: エントリ内のビットオフセット
* カラム '''ビット''' の後半部: バイト内のビットオフセット

{| class="wikitable"
|-
! colspan = 3 | 属性フラグ #2
|-
| 52
| 4
| 未使用でありOSで使用可能
|-
| 53
| 5
| 予約済み。常に0
|-
| 54
| 6
| D-ビット(0:16ビット・セグメント、1:32ビットセグメント)
|-
| 55
| 7
| G-bit(リミット値の倍率、1なら4096倍)
|}

=== ページング方式 ===
[[ファイル:Virtual address space and physical address space relationship.svg|thumb|ページングによる仮想記憶の概念図]]
[[ファイル:080810-protected-386-paging.svg|thumb|386における4Kページでの[[ページテーブル]]構成]]
{{See also|ページング方式}}

386では仮想86モードだけでなく、[[ページング方式]]がプロテクトモードに追加された<ref name="paging introduced">{{Cite web| url = http://www.deinmeister.de/x86modes.htm#c1 | title = ProtectedMode overview [deinmeister.de] | accessdate = 2007-07-29 | format = Website }}</ref>。ページングを使うことでシステムソフトウェアはページと呼ばれるメモリ単位毎にタスクのアクセスを制限し制御することができる。多くのOSでページングを使ってタスク毎の仮想アドレス空間を作成している。それによって、あるタスクが他のタスクのメモリを操作することを防ぐ。また、ページ単位で[[主記憶装置]]からより低速だが大容量の[[補助記憶装置]]([[ハードディスクドライブ|ハードディスク]]など)へ移すこともできる<ref name="Paging usage">{{Cite web| url = http://technet.microsoft.com/en-us/library/cc784574(WS.10).aspx | title = What Is PAE X86? | accessdate = 2007-07-29 | date = May 28, 2003 | format = Article | publisher = Microsoft TechNet | quote = The paging process allows the operating system to overcome the real physical memory limits. However, it also has a direct impact on performance because of the time necessary to write or retrieve data from disk. }}</ref>。それにより、主記憶装置の物理メモリ量以上のメモリを使用可能となる<ref name="Paging usage" />。x86アーキテクチャではページの制御をページディレクトリと[[ページテーブル]]という2段階の[[配列]]で行う。1ページは基本的には4キロバイトであり、ページテーブルはプロセッサによって直接読まれるため構造が決まっている。元々、ページディレクトリの大きさは1ページ、すなわち4キロバイトで、1,024個のページ・ディレクトリ・エントリ (PDE) がそこに格納されていた。PDEにはページテーブルへの[[ポインタ (プログラミング)|ポインタ]]が含まれている。ページテーブルも本来は4キロバイトの大きさで、1,024個のページ・テーブル・エントリ (PTE) で構成されている。PTEには実際の物理ページのアドレス(ポインタ)が含まれており、その場合の各ページは4キロバイトである。これで1024×1024×4096バイト、すなわち4GBの論理空間を全て指すことが可能になる。

[[Pentium Pro]]以降に導入された[[物理アドレス拡張]](PAE)が有効である場合は、一エントリあたりが8バイトとなり、もう一段4つのエントリを持つ32バイトのテーブルが追加される。これにより、64ビットの物理アドレス空間の任意のアドレスを4×512×512×4096バイトの32ビットの空間に配置することが可能になるが、実際の物理アドレス空間はもっと少ない。<ref>当初の上限は36ビット、x64命令セットをサポートしている場合は52ビット。x64命令セットではページテーブルの最上位ビットを[[NXビット]]に利用しているため、将来の拡張で残りを全部物理アドレスにしたとしても63ビットである</ref> このページエントリの構造は段数を増やして[[x64|AMD64]]でも継承されている。また、[[Pentium]]からは'''ページサイズ拡張''' (PSE) という拡張により、一部のページを一段へらして4メガバイト(PAEの時は2メガバイト)の大きなページとしてマップすることが可能になっている。[[Pentium II]]以降においては、PAEでない通常のページテーブルエントリの構造を保ちながら4MBのページに限り36ビットの物理空間にアクセス可能な'''36ビットPSE'''とよばれる機能も提供している。

=== マルチタスク ===
{{See also|マルチタスク}}
286で導入されたリング、特権[[コールゲート]]、{{仮リンク|タスク・ステート・セグメント|en|Task State Segment}} (TSS) により、x86アーキテクチャで[[プリエンプション|プリエンプティブ]][[マルチタスク]]が可能となった。TSSにより、他のタスクに影響を及ぼすことなく汎用レジスタ群、セグメントセレクタフィールド群、スタック群を書き換え可能となった。TSSはまた、タスク毎に特権レベルやI/Oポート許可マップを設定できる。

多くのOSはTSSの全機能を使ってはいない<ref name="TSS Usage">{{Cite web| url = http://neworder.box.sk/newsread.php?newsid=10562 | work = NewOrer | title = news: Multitasking for x86 explained #1 | accessdate = 2007-07-29 | first = "zwanderer" | date = May 2, 2004 | format = Article | publisher = NewOrder | quote = The reason why software task switching is so popular is that it can be faster than hardware task switching. Intel never actually developed the hardware task switching, they implemented it, saw that it worked, and just left it there. Advances in multitasking using software have made this form of task switching faster (some say up to 3 times faster) than the hardware method. Another reason is that the Intel way of switching tasks isn't portable at all | archiveurl = http://web.archive.org/web/20070212161434/http://neworder.box.sk/newsread.php?newsid=10562 | archivedate = 2007-02-12 }}</ref>。これは移植性を考慮したためでもあるし、ハードウェアによるタスク切り替えが性能問題を抱えているためでもある<ref name="TSS Usage" />。結果として多くのOSはハードウェアとソフトウェアを共に活用してマルチタスクを実現している<ref name="Uses both">{{Cite web| url = http://neworder.box.sk/newsread.php?newsid=10562 | work = NewOrer | title = news: Multitasking for x86 explained #1 | accessdate = 2007-07-29 | first = "zwanderer" | date = May 2, 2004 | format = Article | publisher = NewOrder | quote = ...both rely on the Intel processors ability to switch tasks, they rely on it in different ways. | archiveurl = http://web.archive.org/web/20070212161434/http://neworder.box.sk/newsread.php?newsid=10562 | archivedate = 2007-02-12 }}</ref>。

== OS ==
[[OS/2]] 1.x では、プロテクトモードとリアルモードの切り替えを試みている。しかしその技法は低速であり、リアルモードではコンピュータが容易に[[クラッシュ (コンピュータ)|クラッシュ]]するため、安全ではなかった。OS/2 1.x ではプログラミングに制約を課して、両方のモードで動作可能なプログラムを書ける方法を定義していた。初期の[[UNIX]]、[[OS/2]] 1.x、Windows でこのようなモードの使い方が見られた。[[Microsoft Windows 3.x|Windows 3.0]] ではリアルモードのプログラムを16ビット・プロテクトモードで動作させることができた。Windows 3.0 でプロテクトモードに切り換えたとき、リアルモードと同じ単一特権レベルのモデルを保持したため、Windows ではアプリケーションやDLLが割り込みにフックを仕掛けることができ、ハードウェアに直接アクセス可能になっていた。この方式は [[Windows 9x系]]でもそのまま維持されている。Windows 1.x や 2.x のプログラムが行儀よくプログラミングされていて、セグメントアドレスを計算で求めたりしていない場合、リアルモードでもプロテクトモードでも同じように動作可能だった。Windowsではソフトウェアによる仮想記憶を実装しており、プログラムが動作していないときにそのコードやデータのセグメントを移動させることがあったため、絶対アドレスを操作することは危険であり、一般に Windows プログラムはセグメント計算を避けていた。動作していないプログラムが保持できるのはメモリブロックのハンドルだけだった。プロテクトモードで動作中の Windows 3.0 で古いプログラムを起動すると、Windowsをリアルモードで動作させるかアプリケーションの新しいバージョンを取得することを推奨する警告ダイアログが表示されていた。Windows 3.1 ではリアルモードが廃止されている。

16ビットのプロテクトモードは今も一部アプリケーションで使われている。例えば[[DPMI]]互換の[[DOSエクステンダ]]プログラム([[仮想DOSマシン]]経由)、Windows 3.x 用アプリケーション({{仮リンク|Windows on Windows|en|Windows on Windows}} サブシステム経由)、OS/2 2.0 以降での一部の[[デバイスドライバ]](たとえばBIOS機能を使ってディスプレイの解像度を変更するもの)などであり、いずれも32ビットカーネルの制御下で動作する。

== 脚注 ==
{{Reflist|2}}


== 参考文献 ==
1ページは基本的には4キロバイトであり、ページテーブルはプロセッサによって直接読まれるため構造が決まっている。構造はページテーブルの大きさも4キロバイトであり、基本的には一エントリあたり4バイトで、1024エントリを保持することになる。これが2段で1024×1024×4096バイト、すなわち4GBの論理空間を全て指すことが可能になる。[[Pentium Pro]]以降に導入された[[物理アドレス拡張]](PAE)が有効である場合は、一エントリあたりが8バイトとなり、もう一段4つのエントリを持つ32バイトのテーブルが追加される。これにより、64ビットの物理アドレス空間の任意のアドレスを4×512×512×4096バイトの32ビットの空間に配置することが可能になるが、実際の物理アドレス空間は36ビットが上限である。 このページエントリの構造は段数を増やして[[x64|AMD64]]でも継承されている。また、[[Pentium]]からは'''ページサイズ拡張''' (PSE) という拡張により、一部のページを一段へらして4メガバイト(PAEの時は2メガバイト)の大きなページとしてマップすることが可能になっている。[[Pentium II]]以降においては、PAEでない通常のページテーブルエントリの構造を保ちながら4MBのページに限り36ビットの物理空間にアクセス可能な'''36ビットPSE'''とよばれる機能も提供している。
* {{Cite book| title = Intel 64 and IA-32 Architectures Software Developer's Manual | publisher = [[インテル|Intel]] |month = May | year = 2007 | location = [[デンバー|Denver, Colorado]] | url = http://www.intel.com/products/processor/manuals/index.htm |ref={{SfnRef|Intel|2007}} }}
* {{Cite book| title = Intel 80286 Programmer's Reference Manual 1987 | format = Manual | accessdate = July 2007 | year = 1987 | publisher = Intel | location = Santa Clara, CA |ref={{SfnRef|Intel|1987}} }}


== 関連項目 ==
これにより、セグメンテーションを意識すること無くページングベースのOSを実装することが可能になっている。
* [[アセンブリ言語]]
* [[インテル]]
* [[リングプロテクション]]


== 外部リンク ==
また、[[仮想86モード]]はIA-32のプロテクトモードの特殊なタスクの一つである。
* [http://www.rcollins.org/articles/pmbasics/tspec_a1_doc.html Protected Mode Basics]
* [http://www.internals.com/articles/protmode/introduction.htm Introduction to Protected-Mode]
* [http://www.intel.com/design/intarch/papers/exc_ia.htm Overview of the Protected Mode Operations of the Intel Architecture]
* [http://www.intel.com/products/processor/manuals/index.htm Intel 64 and IA-32 Architectures Software Developer's Manuals]
* [http://www.turboirc.com/asm TurboIRC.COM tutorial to enter protected mode from DOS]
* [http://www.codeproject.com/KB/system/asm.aspx Code Project Protected Mode Tutorial]
* [http://code.google.com/p/akernelloader/ Akernelloader switching from real mode to protected mode]


{{オペレーティングシステム}}
{{オペレーティングシステム}}
48行目: 266行目:
[[fr:Mode protégé]]
[[fr:Mode protégé]]
[[ga:Mód cosanta]]
[[ga:Mód cosanta]]
[[id:Mode terproteksi]]
[[it:Modalità protetta]]
[[it:Modalità protetta]]
[[kk:Қорғалған режім]]
[[kk:Қорғалған режім]]

2012年10月28日 (日) 23:20時点における版

プロテクトモードとは、80286以降のx86アーキテクチャのCPUの動作モードの一つ。正式名称は Protected Virtual Address Mode(保護仮想アドレスモード)である[1]。メモリやI/Oの保護を行うと共に、アドレス空間の拡張を行ったモードである。このモードでは仮想記憶ページング、安全なマルチタスクといった機能をシステムソフトウェアが使えるようになり、アプリケーションソフトウェアへのオペレーティングシステム (OS) の制御能力が向上するよう設計されている[2][3]

概要

プロテクトモードとは80286以降のCPUの命令セットアーキテクチャの動作モードの一つであり、これらのCPUの本来の動作モードといえる物である。特徴づけるものは、その名前の通り、階層的な特権管理(リングプロテクション)や、タスク間のメモリ保護(プロテクト)を行う事が可能な事である。

プロテクトモードをサポートしているx86系プロセッサを起動したとき、それ以前のx86系プロセッサとの後方互換を保つためリアルモードで命令を実行する[4]。プロテクトモードに移行するには、システムソフトウェアがいくつかのディスクリプタテーブルを設定してから、コントロールレジスタ0 (CR0) のPE (Protection Enable) ビットをセットしなければならない[5]

プロテクトモードは1982年、インテル80286 (286) プロセッサのリリースと共にx86アーキテクチャに追加され[6]、1985年の 80386 (386) で拡張された[7]。プロテクトモードの追加による機能向上によって広く採用され、同時にそれがその後のx86アーキテクチャの全ての強化の基礎となった[8]

プロテクトモードにおいては、メモリ上のグローバルディスクリプタテーブル (GDT) およびローカルディスクリプタテーブル (LDT) という構造体の配列をそれぞれ最大8192個管理する。この構造体はそれぞれ、リニアアドレスのポインタおよび大きさおよび保護情報を持つセグメントディスクリプタや、タスクセグメントへのポインタとサイズ、保護情報を持つタスクディスクリプタローカルディスクリプタテーブルへのポインタを保持するもの、そして特権等を変更するための呼び先である、ゲートディスクリプタ等を持つ。セグメントレジスタはセレクタと呼ばれGDTまたはLDTのオフセットでセグメントディスクリプタを指すものとなる。無効なディスクリプタをセレクタにロードしたりすると例外を発生するようになった。タスクセグメントは、LDTRを含むレジスタ等の実行環境を保持する。

また、割り込み/例外ベクタも、最低位アドレスに固定される事無く、割り込みディスクリプタテーブル (IDT) にあるゲートディスクリプタの配列により設定されることになった。

80286以降で物理メモリの拡張も行われたが、100000h以降(1MB以降)のアドレスの物理メモリは、HMAを除けばプロテクトモードを使用しない限り、CPUからはアクセスできない領域であった。そのため、この実質的にプロテクトモード専用の1MB以降の物理メモリ領域は通称プロテクトメモリと呼ばれた。 プロテクトモードでは、コンベンショナルメモリ以外にプロテクトメモリも利用できるので、利用可能な物理メモリも増大した。この利用可能なメモリの増大もプロテクトモードを使用する利点の一つである。 プロテクトメモリを利用するためには、本来UNIXOS/2等のマルチタスクOSが必要であるが、MS-DOS上でもEMSXMSドライバ、DOSエクステンダ等を使用すれば利用可能であった。

歴史

286に先立つ Intel 8086 での本来の設計では、メモリアクセス用アドレスバスは20ビット幅だった[9]。これにより 220 バイト、すなわち1メガバイトのメモリにアクセス可能である[9]。当時は1メガバイトといえばかなり大容量のメモリという感覚だったので[10]IBM PC の設計者らは先頭640キロバイトをアプリケーションとオペレーティングシステムで使用し、残る384キロバイトBIOS (Basic Input/Output System) や周辺機器で使用する設計にした[11]

元々、8086においては、セグメント方式仮想記憶を意識したセグメントレジスタがあり、コード、データおよびスタックの量がそれぞれ64キロバイト以内であれば、ロードされた物理アドレスを意識すること無く、タスクの実行が可能であったが、論理アドレスから物理アドレスへの変換は単純にセグメントレジスタを4ビットシフトして足すと言うもので、タスク間の保護もなかった。

メモリ価格が低下し、メモリ使用量が増えてくると、1MBという制約が大きな問題となってきた。インテルはこの制限に対処するためもあって 286 をリリースした[11]

286

最初に導入された80286においては24ビットの物理アドレス空間へのアクセス、そして1セグメントあたり最大64キロバイトの空間を提供していた。これまでに述べた機能を使ってセグメントレジスタを意識したセグメント方式の仮想記憶を使ったOS環境を作成することが可能になった。しかし286リリース当時、プロテクトモードはすぐに広く使われたわけではない[11]。プロセッサをリセットする以外にリアルモードに戻ることができないため、BIOSまたはDOSコールにアクセスすることができないなどの欠点があり、幅広い採用が妨げられた[12]。幅広い採用が見送られた他の要因として、286 では4本のセグメントレジスタでそれぞれ16ビットのセグメントしかアクセスできなかった。すなわち一度にアクセスできるメモリの範囲は 4*216 バイト(256キロバイト)に限られていた[11]

286 は 8086 との互換性を保つため、起動時にはリアルモードで動作を開始するようになっていた[4]。リアルモードでは 8086 と全く同じ動作をするので、古いソフトウェアも 286 で修正せずに動作することができる。286 の拡張機能にアクセスするには、オペレーティングシステムがプロセッサをプロテクトモードに移行させる必要がある。それによって24ビット・アドレッシングが可能になり、224 バイト(16メガバイト)のメモリにアクセス可能となる[9]

保護された空間外へのメモリアクセスなどを行うと、たちどころに例外割り込みが発生して処理が停止する。80286の16ビット PVAMにおいて全ての保護違反例外はただひとつの割り込みベクタ…悪名高き「一般保護例外 (General Protection Fault)」INT#13 に割り当てられており、一旦これが起きてしまうとそのプロセス(あるいはタスクまたはスレッド)の処理を復帰させる方法がない。すなわち外部記憶装置を持つ仮想記憶システムにおいてページ違反を例外処理として検出し、ページスワップを行ってからプロセスを再開させることができない(セグメントディスクリプタには「不在ビット」の属性があり、これを用いた仮想記憶管理を行うことは可能なのだが、メモリアクセス違反を流用した仮想記憶管理ができない)。これはそもそもインテルが80286を80186の上位機種であり「最高の信頼性を持つ制御用プロセッサ」として位置づけており、外部仮想記憶を持つような高度な処理はiAPX432 32ビットプロセッサによって実現する構想を抱いていたことに起因する。80286は、工業用ミニコンピュータのアーキテクチャにならったもので、間違った前提のまま動き続けるよりは間違いを検出して止まったほうが被害が少ない、という思想に基づくものであった。

しかし、インテルの思惑とは裏腹に、80286は汎用コンピュータである IBM PC/ATおよびIBM PS/2に搭載されてしまい、その上で汎用OSであるOS/2を動かす必要に迫られ、80286は、本来の設計思想とは異なる領域で、アーキテクチャを無理にねじ曲げた使い方を強いられることになってしまい、「石頭」「こんだけ苦労してたった16MB」「しかも相変わらずセグメントあたり64KBの制限つき」「Brain Damaged CPU」などの悪名を高めてしまうことになる。

386

Intel 80386 マイクロプロセッサ

1985年[7]にリリースされた 386 では、プロテクトモードの採用を妨げていた様々な問題への対処が行われている[11]。386のアドレスバスは32ビット幅で、232 バイト(4ギガバイト)のメモリにアクセス可能である[13]。セグメントも32ビットに拡大され、複数のセグメントを切り換えることなく4ギガバイトのアドレス空間にアクセス可能となった[13]。アドレスバスとセグメントレジスタの拡大に加えて、セキュリティと安定性を向上させるための様々な機能が追加されている[14]

プロテクトモードはその後、Microsoft WindowsLinuxなどほぼ全てのx86アーキテクチャ(IA-32)上のオペレーティングシステムで使われるようになった[15]

386のプロテクトモードで追加された機能

386のリリースに際し、以下の機能がプロテクトモードに追加された[2]

プロテクトモードへの(からの)移行

386がリリースされる以前は、プロテクトモードにいったん入った後、リアルモードに戻る直接的方法が提供されていなかった。IBMはその対処として、キーボードコントローラからCPUをリセットする技法を考案し、その際にシステムレジスタ群、スタックポインタ、割り込みマスクをリアルタイムクロックのチップにあるRAMにセーブするようにした。これによりBIOSがCPUをほぼ同じ状態に復旧することが可能となり、リセット前のコードの実行を続行できる。その後、トリプルフォールトを発生させて286CPUをリセットするという手段がとられた。こちらの方がキーボードコントローラを使うよりも高速できれいだった。

プロテクトモードにおいては、メモリ上のグローバルディスクリプタテーブル (GDT) およびローカルディスクリプタテーブル (LDT) という構造体の配列をそれぞれ最大8192個管理する。この構造体はそれぞれ、リニアアドレスのポインタおよび大きさおよび保護情報を持つセグメントディスクリプタや、タスクセグメントへのポインタとサイズ、保護情報を持つタスクディスクリプタローカルディスクリプタテーブルへのポインタを保持するもの、そして特権等を変更するための呼び先である、ゲートディスクリプタ等を持つ。セグメントレジスタはセレクタと呼ばれGDTまたはLDTのオフセットでセグメントディスクリプタを指すものとなる。無効なディスクリプタをセレクタにロードしたりすると例外を発生するようになった。タスクセグメントは、LDTRを含むレジスタ等の実行環境を保持する。

プロテクトモードに入るには、少なくとも3エントリ(ヌルディスクリプタ、コードセグメントディスクリプタ、データセグメントディスクリプタ)を持つGDTを作る必要がある。そして、アドレスバスのA20線(21番目のアドレス線)をイネーブルにし、1メガバイトを越えるメモリにアクセスできるようにする必要がある(電源投入直後は、古いソフトウェアの互換性を保証するため、20番目までのアドレス線しか使わない設定になっている)。この2段階を実行後、CR0レジスタのPEビットをセットして、far jump 命令を実行することで命令プリフェッチキューをクリアしなければならない。

; set PE bit
mov eax, cr0
or eax, 1
mov cr0, eax

; far jump (cs = selector of code segment)
jmp cs:@pm

@pm:
; Now we are in PM.

386以降でプロテクトモードからリアルモードに移行するには、セグメントレジスタをリアルモードの値にし、A20 線をディセーブルし、CR0レジスタのPEビットをクリアすればよく、286で必要だった初期設定が不要になった。

機能と特徴

プロテクトモードには、セキュリティとシステム安定性を向上させるべくOSのアプリケーションに対する制御を強化するよう設計された機能がいくつかある[3]。それら追加機能により、適切なハードウェアサポートなしではかなり難しいか不可能なOS機能の実装が可能になった[17]

特権レベル

特権リングの使用例。この例ではOSが全リングを使用している。

特権は数字が低い程高い特権で0,1,2,3の4段階の特権リングがある。リングの使用により、システムソフトウェアがタスクのデータやコールゲートへのアクセスまたは特権命令実行を制限できるようになった[18]。大抵の環境では、OSと一部のデバイスドライバがリング0で、アプリケーションがリング3で動作する[18]。高い特権のコードへの呼出はゲートディスクリプタや例外を通す必要がある。

リアルモードのアプリケーションの互換性

Intel 80286 Programmer's Reference Manual には以下のような記述がある[19]

80286は 8086および80186のほとんどのアプリケーションプログラムに対して上方互換を保っている。8086のほとんどのアプリケーションプログラムは、80286上で再コンパイルまたは再アセンブルすることでプロテクトモードで実行可能である。

リアルモードのコードとのバイナリ互換性の観点で、アプリケーションプログラマにとって最も明白な変化は、物理メモリが最大16MBまでアクセス可能になった点と1GBの仮想記憶であった[19]。これには制限がなかったわけではなく、以下のような技法を使っていたアプリケーションはプロテクトモードでは動作しなかった[20]

  • セグメント計算
  • 特権命令を使用
  • ハードウェアへの直接アクセス
  • コードセグメントの書き換え
  • データの実行
  • セグメントのオーバーラップ
  • インテルによって確保されているBIOS割り込みのためにBIOS関数を使用[21]

実際にはほぼ全てのDOSアプリケーションプログラムがこれらのルールのいずれかに反していた[22]。そのため、386では仮想86モードが導入された。そういった潜在的問題はあったが、Windows 3.0 とその後継では Windows 2.x でのリアルモードの各種アプリケーションをプロテクトモードで動作させるのに互換性を利用している[23]

仮想86モード

386のプロテクトモードでは、インテルが仮想8086モード (virtual 8086 mode) と呼ぶものを提供している。仮想86モードは8086向けのコードを修正することなく、プロテクトモードのOS上のタスクの1つとして安全に動作させることができる[24]。ただし完全な後方互換性があるわけではない。セグメント操作や特権命令、ハードウェアへの直接アクセス、自己書き換えコードなどを使っているプログラムの場合、例外が発生するのでOSがそれに対処しなければならない[25]。さらに仮想86モードで動作するアプリケーションが入出力 (I/O) 関連命令を使用するとトラップ処理が行われるので、性能が低下する[26]。そういった制約があるため、8086上のプログラムの一部は仮想86モードでは動作できない。結果としてシステムソフトウェアは、古いソフトウェアを扱う際にセキュリティか互換性のいずれかを犠牲にすることになった。例えば Windows NT では互換性を犠牲にし、行儀の悪いDOSアプリケーションをサポートしなくなった[27]

セグメント方式

80286の仮想セグメント

リアルモードでは、論理アドレスは2つの16ビットの部分で構成されており、論理アドレスが直接物理的メモリ位置に対応している。論理アドレスのセグメント部は16バイトでセグメントのベースアドレスを指しており、セグメントは物理アドレス 0, 16, 32, ..., 220-16 から始まる。論理アドレスのオフセット部はセグメント内のオフセットであり、物理アドレスは physical_address : = segment_part × 16 + offset という式で計算できる(アドレスバスのA20線がイネーブル状態の場合[28])。各セグメントのサイズは 216 バイトである。

プロテクトモード

プロテクトモードでは、セグメント部が16ビットの「セレクタ」で置き換えられ、セレクタの上位13ビット(ビット 3 から ビット15)がディスクリプタテーブル内のエントリのインデックスとなっている。下位2ビット(ビット 0 とビット 1)は要求の特権レベルを定義しており、0から3までの値をとり、0が最も特権が高く、3が最も特権が低い。残るビット(ビット 2)はGDTかLDTの指定に使われる。

ディスクリプタテーブルのエントリには以下の情報が含まれる。

  • セグメントの「リニア」アドレス
  • セグメントの大きさを示すリミット値
  • いくつかの属性ビット群(フラグ)

286

ディスクリプタテーブルのエントリ内のセグメントアドレスは24ビットであり、リアルモードとは異なり任意のアドレスからセグメントを開始できるようになった。リミット値は16ビット幅であり、セグメントの大きさは1バイトから 216 バイトまで指定可能である。これに基づいて計算したリニアアドレスは物理メモリアドレスとなる。

386

ディスクリプタテーブルのエントリ内のセグメントアドレスは32ビットに拡張されている。リミット値は20ビット幅に拡張され、しかもG-ビットで倍率を指定できる。

  • G-ビットがゼロなら、リミット値の倍率は1であり、セグメントの大きさは1バイトから 220 バイトまでとなる。
  • G-ビットが1なら、リミット値の倍率は4096倍であり、セグメントの大きさは 4096 の倍数で4096バイトから4ギガバイトまでとなる。

ページングを使わない場合、リニアアドレスはそのまま物理メモリアドレスとなるが、ページングを使う場合はリニアアドレスはページング機構への入力となる。

386プロセッサではアドレスオフセットとしても32ビットの値を使用する。

286のプロテクトモードとの互換性を維持するため、D-ビットが追加されている。D-ビットがオフとなっているコードセグメントは16ビット・セグメントと解釈され、その中の命令は16ビット命令として実行される。

セグメントディスクリプタのエントリの構造

B ビット 80286 80386 B
0 00..07,0..7 リミット値 リミット値のビット0..15 0
1 08..15,0..7 1
2 16..23,0..7 セグメントベースアドレス ベースアドレスのビット 0..23 2
3 24..31,0..7 3
4 32..39,0..7 4
5 40..47,0..7 属性フラグ #1 5
6 48..51,0..3 未使用 リミット値のビット 16..19 6
52..55,4..7 属性フラグ #2
7 56..63,0..7 ベースアドレスのビット 24..31 7
  • カラム B: エントリ内のバイトオフセット
  • カラム ビット の前半部: エントリ内のビットオフセット
  • カラム ビット の後半部: バイト内のビットオフセット
属性フラグ #2
52 4 未使用でありOSで使用可能
53 5 予約済み。常に0
54 6 D-ビット(0:16ビット・セグメント、1:32ビットセグメント)
55 7 G-bit(リミット値の倍率、1なら4096倍)

ページング方式

ページングによる仮想記憶の概念図
386における4Kページでのページテーブル構成

386では仮想86モードだけでなく、ページング方式がプロテクトモードに追加された[29]。ページングを使うことでシステムソフトウェアはページと呼ばれるメモリ単位毎にタスクのアクセスを制限し制御することができる。多くのOSでページングを使ってタスク毎の仮想アドレス空間を作成している。それによって、あるタスクが他のタスクのメモリを操作することを防ぐ。また、ページ単位で主記憶装置からより低速だが大容量の補助記憶装置ハードディスクなど)へ移すこともできる[30]。それにより、主記憶装置の物理メモリ量以上のメモリを使用可能となる[30]。x86アーキテクチャではページの制御をページディレクトリとページテーブルという2段階の配列で行う。1ページは基本的には4キロバイトであり、ページテーブルはプロセッサによって直接読まれるため構造が決まっている。元々、ページディレクトリの大きさは1ページ、すなわち4キロバイトで、1,024個のページ・ディレクトリ・エントリ (PDE) がそこに格納されていた。PDEにはページテーブルへのポインタが含まれている。ページテーブルも本来は4キロバイトの大きさで、1,024個のページ・テーブル・エントリ (PTE) で構成されている。PTEには実際の物理ページのアドレス(ポインタ)が含まれており、その場合の各ページは4キロバイトである。これで1024×1024×4096バイト、すなわち4GBの論理空間を全て指すことが可能になる。

Pentium Pro以降に導入された物理アドレス拡張(PAE)が有効である場合は、一エントリあたりが8バイトとなり、もう一段4つのエントリを持つ32バイトのテーブルが追加される。これにより、64ビットの物理アドレス空間の任意のアドレスを4×512×512×4096バイトの32ビットの空間に配置することが可能になるが、実際の物理アドレス空間はもっと少ない。[31] このページエントリの構造は段数を増やしてAMD64でも継承されている。また、Pentiumからはページサイズ拡張 (PSE) という拡張により、一部のページを一段へらして4メガバイト(PAEの時は2メガバイト)の大きなページとしてマップすることが可能になっている。Pentium II以降においては、PAEでない通常のページテーブルエントリの構造を保ちながら4MBのページに限り36ビットの物理空間にアクセス可能な36ビットPSEとよばれる機能も提供している。

マルチタスク

286で導入されたリング、特権コールゲートタスク・ステート・セグメント英語版 (TSS) により、x86アーキテクチャでプリエンプティブマルチタスクが可能となった。TSSにより、他のタスクに影響を及ぼすことなく汎用レジスタ群、セグメントセレクタフィールド群、スタック群を書き換え可能となった。TSSはまた、タスク毎に特権レベルやI/Oポート許可マップを設定できる。

多くのOSはTSSの全機能を使ってはいない[32]。これは移植性を考慮したためでもあるし、ハードウェアによるタスク切り替えが性能問題を抱えているためでもある[32]。結果として多くのOSはハードウェアとソフトウェアを共に活用してマルチタスクを実現している[33]

OS

OS/2 1.x では、プロテクトモードとリアルモードの切り替えを試みている。しかしその技法は低速であり、リアルモードではコンピュータが容易にクラッシュするため、安全ではなかった。OS/2 1.x ではプログラミングに制約を課して、両方のモードで動作可能なプログラムを書ける方法を定義していた。初期のUNIXOS/2 1.x、Windows でこのようなモードの使い方が見られた。Windows 3.0 ではリアルモードのプログラムを16ビット・プロテクトモードで動作させることができた。Windows 3.0 でプロテクトモードに切り換えたとき、リアルモードと同じ単一特権レベルのモデルを保持したため、Windows ではアプリケーションやDLLが割り込みにフックを仕掛けることができ、ハードウェアに直接アクセス可能になっていた。この方式は Windows 9x系でもそのまま維持されている。Windows 1.x や 2.x のプログラムが行儀よくプログラミングされていて、セグメントアドレスを計算で求めたりしていない場合、リアルモードでもプロテクトモードでも同じように動作可能だった。Windowsではソフトウェアによる仮想記憶を実装しており、プログラムが動作していないときにそのコードやデータのセグメントを移動させることがあったため、絶対アドレスを操作することは危険であり、一般に Windows プログラムはセグメント計算を避けていた。動作していないプログラムが保持できるのはメモリブロックのハンドルだけだった。プロテクトモードで動作中の Windows 3.0 で古いプログラムを起動すると、Windowsをリアルモードで動作させるかアプリケーションの新しいバージョンを取得することを推奨する警告ダイアログが表示されていた。Windows 3.1 ではリアルモードが廃止されている。

16ビットのプロテクトモードは今も一部アプリケーションで使われている。例えばDPMI互換のDOSエクステンダプログラム(仮想DOSマシン経由)、Windows 3.x 用アプリケーション(Windows on Windows英語版 サブシステム経由)、OS/2 2.0 以降での一部のデバイスドライバ(たとえばBIOS機能を使ってディスプレイの解像度を変更するもの)などであり、いずれも32ビットカーネルの制御下で動作する。

脚注

  1. ^ Memory access control method and system for realizing the same” (Patent). US Patent 5483646 (1995年5月23日). 2007年7月14日閲覧。 “The memory access control system according to claim 4, wherein said first address mode is a real address mode, and said second address mode is a protected virtual address mode.”
  2. ^ a b Intel 2007, "2.1.3 The Intel 386 Processor (1985)" p.35
  3. ^ a b Guide: What does protected mode mean?” (Guide). Delorie software (2007年7月14日). 2007年7月14日閲覧。 “The purpose of protected mode is not to protect your program. The purpose is to protect everyone else (including the operating system) from your program.”
  4. ^ a b Intel 2007, "3.2 Modes of Operation" p.59
  5. ^ Collins, Robert (2007年). “Protected Mode Basics” (PDF). ftp.utcluj.ro. 2009年7月31日閲覧。
  6. ^ Intel 2007, "2.1.2 The Intel 286 Processor (1982)" p.34
  7. ^ a b Intel Global Citizenship Report 2003” (Timeline). 2008年3月22日時点のオリジナルよりアーカイブ。2007年7月14日閲覧。 “1985 Intel launches Intel386 processor”
  8. ^ Intel 2007, "2.1 Brief History of the IA-32 Architecture" p.31
  9. ^ a b c A+ - Hardware” (Tutorial/Guide). PC Microprocessor Developments and Features Tutorials. BrainBell.com. 2007年7月24日閲覧。
  10. ^ Risley, David (2001年3月23日). “A CPU History” (Article). PCMechanic. 2008年1月15日時点のオリジナルよりアーカイブ。2007年7月24日閲覧。 “What is interesting is that the designers of the time never suspected anyone would ever need more than 1 MB of RAM.”
  11. ^ a b c d e Kaplan, Yariv (1997年). “Introduction to Protected-Mode” (Article). Internals.com. 2007年7月24日閲覧。
  12. ^ Mueller, Scott (March 24, 2006). “P2 (286) Second-Generation Processors” (Book). Upgrading and Repairing PCs, 17th Edition (17 ed.). Que. ISBN 0-7897-3404-4. http://www.informit.com/articles/article.aspx?p=481859&seqNum=13 2007年7月閲覧。 
  13. ^ a b “2.1 Memory Organization and Segmentation” (Manual). Intel 80386 Programmer's Reference Manual 1986. Santa Clara, CA: Intel. (1986) 
  14. ^ Intel 2007, "3.1 Modes of Operation" p.55
  15. ^ Hyde, Randall (November 2004). “12.10. Protected Mode Operation and Device Drivers”. Write Great Code. O'Reilly. ISBN 1-59327-003-8 
  16. ^ Shvets, Gennadiy (2007年6月3日). “Intel 80386 processor family” (Article). 2007年7月24日閲覧。 “80386SX — low cost version of the 80386. This processor had 16 bit external data bus and 24-bit external address bus.”
  17. ^ “7 Multitasking” (Manual). Intel 80386 Programmer's Reference Manual 1986. Santa Clara, CA: Intel. (1986) 
  18. ^ a b Intel 2007, "6.3.5 Calls to Other Privilege Levels" p.162
  19. ^ a b Intel 1987, 1.2 Modes of Operation 引用エラー: 無効な <ref> タグ; name "286 compatibility"が異なる内容で複数回定義されています
  20. ^ Intel 1987, Appendix C 8086/8088 Compatibility Considerations
  21. ^ Memory access control method and system for realizing the same” (Patent). US Patent 5483646 (1998年5月6日). 2007年7月25日閲覧。 “This has been impossible to-date and has forced BIOS development teams to add support into the BIOS for 32 bit function calls from 32 bit applications.”
  22. ^ Robinson, Tim (2002年8月26日). “Virtual 8086 Mode” (Guide). berliOS. 2007年7月25日閲覧。 “...secondly, protected mode was also incompatible with the vast amount of real-mode code around at the time.”
  23. ^ Robinson, Tim (2002年8月26日). “Virtual 8086 Mode” (Guide). berliOS. 2007年7月25日閲覧。
  24. ^ Intel 2007, "15.2 Virtual 8086 Mode" p.560
  25. ^ Intel 2007, "15.2.7 Sensitive Instructions" p.568
  26. ^ Robinson, Tim (2002年8月26日). “Virtual 8086 Mode” (Guide). berliOS. 2007年7月25日閲覧。 “A downside to using V86 mode is speed: every IOPL-sensitive instruction will cause the CPU to trap to kernel mode, as will I/O to ports which are masked out in the TSS.”
  27. ^ Dabak, Prasad; Millind Borate (October 1999) (Book). Undocumented Windows NT. Hungry Minds. ISBN 0-7645-4569-8. Memory Management 
  28. ^ A20線がディセーブル状態なら (segment_part × 16 + offset) mod 220 となる
  29. ^ ProtectedMode overview [deinmeister.de]” (Website). 2007年7月29日閲覧。
  30. ^ a b What Is PAE X86?” (Article). Microsoft TechNet (2003年5月28日). 2007年7月29日閲覧。 “The paging process allows the operating system to overcome the real physical memory limits. However, it also has a direct impact on performance because of the time necessary to write or retrieve data from disk.”
  31. ^ 当初の上限は36ビット、x64命令セットをサポートしている場合は52ビット。x64命令セットではページテーブルの最上位ビットをNXビットに利用しているため、将来の拡張で残りを全部物理アドレスにしたとしても63ビットである
  32. ^ a b news: Multitasking for x86 explained #1” (Article). NewOrer. NewOrder (2004年5月2日). 2007年2月12日時点のオリジナルよりアーカイブ。2007年7月29日閲覧。 “The reason why software task switching is so popular is that it can be faster than hardware task switching. Intel never actually developed the hardware task switching, they implemented it, saw that it worked, and just left it there. Advances in multitasking using software have made this form of task switching faster (some say up to 3 times faster) than the hardware method. Another reason is that the Intel way of switching tasks isn't portable at all”
  33. ^ news: Multitasking for x86 explained #1” (Article). NewOrer. NewOrder (2004年5月2日). 2007年2月12日時点のオリジナルよりアーカイブ。2007年7月29日閲覧。 “...both rely on the Intel processors ability to switch tasks, they rely on it in different ways.”

参考文献

関連項目

外部リンク