page0058
の編集
http://osecpu.osask.jp/wiki/?page0058
[
トップ
] [
編集
|
差分
|
バックアップ
|
添付
|
リロード
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
-- 雛形とするページ --
BracketName
FormattingRules
FrontPage
Fulyn
Fulyn-v2
Fulyn_Samples
Help
InterWiki
InterWikiName
InterWikiSandBox
K
KOR_PIT8254
KWVM.NET
Liva
MANA
MenuBar
OSECPU_FPGA
PG_MANA
PHP
PukiWiki
PukiWiki/1.4
PukiWiki/1.4/Manual
PukiWiki/1.4/Manual/Plugin
PukiWiki/1.4/Manual/Plugin/A-D
PukiWiki/1.4/Manual/Plugin/E-G
PukiWiki/1.4/Manual/Plugin/H-K
PukiWiki/1.4/Manual/Plugin/L-N
PukiWiki/1.4/Manual/Plugin/O-R
PukiWiki/1.4/Manual/Plugin/S-U
PukiWiki/1.4/Manual/Plugin/V-Z
RecentDeleted
SandBox
WikiEngines
WikiName
WikiWikiWeb
YukiWiki
hikalium
hikarupsp
hikarupsp_ELCHNOS
hikarupsp_ELCHNOS_IDE
hikarupsp_FrontEndCode
hikarupsp_WebCPU-VM
hikarupsp_WebCPU-VM_internal
hikarupsp_study_hh4
impressions
impressions0000
jpag0000
jpag0001
jpag0002
jpag0003
jpag0004
jpag0005
lambdalice
mandel59
members
memo0000
memo0001
memo0002
memo0003
memo0004
memo0005
memo0006
memo0007
memo0008
memo0009
memo0010
osask
osecpu4android
page0000
page0001
page0002
page0003
page0004
page0005
page0006
page0007
page0008
page0009
page0010
page0011
page0012
page0013
page0014
page0015
page0016
page0017
page0018
page0019
page0020
page0021
page0022
page0023
page0024
page0025
page0026
page0027
page0028
page0029
page0030
page0031
page0032
page0033
page0034
page0035
page0036
page0037
page0038
page0039
page0040
page0041
page0042
page0043
page0044
page0045
page0046
page0047
page0048
page0049
page0050
page0051
page0052
page0053
page0054
page0055
page0056
page0057
page0058
page0059
page0060
page0061
page0062
page0063
page0064
page0065
page0066
page0067
page0068
page0069
page0070
page0071
page0072
page0073
page0074
page0075
page0076
page0077
page0078
page0079
page0080
page0081
page0082
page0083
page0084
page0085
page0086
page0087
page0088
page0089
page0090
page0091
page0092
page0093
page0094
page0095
page0096
page0097
page0098
page0099
page0100
page0101
page0102
page0103
page0104
page0105
page0106
page0107
page0108
page0109
pagenames
populars
seccamp2013
seccamp2014
seccamp2017
ttwilb
ttwilb-asmi
yao
* セキュリティを考えなくてもOSECPUの設計に至る -(by [[K]], 2013.08.02) ** (0) はじめに -OSECPUのバイトコードは、「第三世代OSASK」として[[K]]が数年前から設計していたものでした。これがOSECPUになる際に、実は大きな仕様変更をすることなく、そのまま流用できています。つまり[[K]]は知らないうちにセキュアな設計をしていたのです。 -ではどうやってこの仕様に決めていたのか、その話を書きたいと思います。 ** (1) 仕様の理由(セキュアに関係ある部分) -なぜJITコンパイル方式? --CPUに依存しない互換性を提供したかったから。Javaがうらやましかったから真似してみた。 --(セキュアなOSを考えると、アプリを実行する前に、悪い命令が混ざっていないかをチェックすることは重要である。JITコンパイルはすべての命令を実行前にチェックできるので、これはとても理にかなっていた。) -なぜ整数レジスタとポインタレジスタを分離したのか? --ページングもセグメンテーションもない環境下で、(多少時間がかかってもいいから)メモリ上のある構造体を移動することを考えよう。幅広いCPUに対応するのならこのような可能性も検討しておくべきだ。・・・この時、この構造体を指していたポインタはすべて修正されなければいけない。だからメモリ内のデータのうち、どれがポインタであるかはOSが完全に把握することにした(だからmalloc時に型を明示する)。 --ではレジスタはどうか。もし汎用レジスタ方式を採用していたら、その値は整数値なのかポインタなのかをどうにかして判断できなければいけない。そのために各レジスタがポインタを扱っているのかどうかを反映するフラグレジスタを作り、それを制御する命令を付けたモデルを検討したが、結局のところ、汎用レジスタ方式をやめるほうが単純化できると分かった。 --汎用レジスタ方式をやめれば、整数レジスタとポインタレジスタのビット幅も独立に決められる。さらにポインタレジスタの値を直接設定させなければ、ポインタレジスタのビット数に依存しないでプログラムが書けることもわかった。これはアドレス幅に無関係にアプリが書けるということなので、互換性の面で非常に良い。 --(ポインタレジスタを分離していたからこそ、ポインタレジスタ側にたくさんの属性情報を追加することができた。型情報やアクセスリミット、死活情報などである。命令セットをほとんど変えることなく、これらをサポートできた。) -なぜメモリアクセス時に型チェックをするのか? --エンディアンが違うシステムでも同一の動作結果を保証するにはこれがいいと思ったから。 --またポインタレジスタの値をメモリに書いて、それを整数レジスタで読み取ることを許せば、結局は整数レジスタでのポインタ操作を許していることと同じになり、構造体移動の際には整数値まで補正しなければいけなくなる危険性がある。 -なぜラベル命令で無限ループ対策という仕組みを導入するのか? --これは[[page0055]]の(3)の事を指している。 --最初はこうだ。まずJITコンパイラでは、バイトコードの1命令が複数の実CPUの命令に翻訳されるということがよく起こる。これで普通に割り込みを許せば、命令が中途半端にしか実行されない状態で割り込まれるかもしれないということを意味する。これは気持ち悪いし、もしかしたら深刻なバグの原因になるかもしれない。 --じゃあどうするか。とりあえず、そんなものはすべてCLI/STIでサンドイッチにして、途中で割り込みが生じないようにしておくしかない(x86の場合)。・・・しかしこの方法だとIOPLによっては実行できないし、翻訳コードはCLIとSTIばかりになって、実行速度が下がってしまう。これはよくない。 --というか、「割り込めない期間がたまにある」ではなくて「割り込みできるタイミングがたまにある」のなら、アプリにとって都合のよいタイミングで割り込み要求がきていないかを自発的にチェックすればいいではないか。しかもこの方法ならCPUに割り込み機能がなくても割り込みが実現できる。 --しかし何からのミスで割り込みチェックを忘れてしまうと割り込みに対応できなくなってしまう。割り込みチェックがあまりにも長い間隔なのもダメだ。ということで、アプリがちゃんと適正な間隔で割り込みチェックしていることを確認するために、分岐回数カウンタというアイデアが生まれた。無限ループ対策はそれを利用しているだけに過ぎない。 -なぜセキュリティをOFFにできる、という設計なのか? --このページの説明からも明らかなように、セキュリティは全くの後付けである。だからOFFにしてもいいものであって、それゆえにOFFにできなければならない。 --これはOFFにしなければいけないという意味ではない。選択できなければいけないという意味である。OFFにしたらアプリにばれて好き放題されるので、事実上できない、なんていうことは許されない。 ** (2) 仕様の理由(セキュアに関係ない部分) -なぜレジスタ数がこんなに多いのか? --x86が8本しか汎用レジスタがなく、しかもそのうちの一つはESPで、実質7本しかない。これで長い間プログラミングをしていたら、いつの間にかレジスタがたくさんほしいと熱望するようになった。一時は256本にしようとさえ思ったほどだ。 --64にした最大の動機は、hh4エンコードで1バイトで表現できる本数が64だったから、というだけに過ぎない。でも今でも64本というのはなかなか程よい本数だと思っている。 -なぜ「reg0=reg1+reg2;」のような三項演算形式にしたのか? --ARMの影響。x86で計算値を生成するたびに、元の値が必ず破壊されていくのが嫌だった。そのたびに破壊前の値をPUSHしたり別のレジスタにMOVしたりしていた。ARMがうらやましかった。 -なぜフラグレジスタがないのか? --MIPSの仕様がかっこいいと思ったから。 -なぜスタックがないのか? --レジスタが十分に豊富なら、スタックがなくても困らないはずだと直感的に思った。スタックを扱わなくてよければ、それだけ命令セットは単純になる。 --スタックには、整数値もポインタ値も積んだりおろしたりするだろう。ということは、「メモリ内データの型管理情報」を頻繁に更新する必要が出てくる。これは遅そうだ。こんなことになるくらいなら、スタックなんかなくてもいいじゃないか。それとも整数専用スタックとポインタ専用スタックを作るのか?またそうやって命令の種類が増えて、命令セットが複雑になるのか?それでいいのか? -なぜスタックマシンにしなかったのか?Javaのまねで出発したのに。 --レジスタマシンが好きだから。スタックマシンはレジスタマシンよりも機能密度が高いという説があるらしいが、それと対決してやろうと思った。 --レジスタマシンならJITコンパイラがレジスタ割り付けに悩まなくて済む。 ** (3) 考察 -セキュリティを考えなくても既にセキュアな仕様になっていたとは、どういうことなのでしょうか。それはこの設計が予想以上に汎用的だったということではないでしょうか。・・・つまり設計がよかったのです。 -よい設計は十分にシンプルで、多くの問題を同時に解決するものです。複雑にすれば複数の問題を解決できるのは当然であって、それはもはやよい設計ではありません。また複雑なのにひとつの問題すら満足に解決できないものもありますが、そんなのは論外です。 * こめんと欄 #comment
タイムスタンプを変更しない
* セキュリティを考えなくてもOSECPUの設計に至る -(by [[K]], 2013.08.02) ** (0) はじめに -OSECPUのバイトコードは、「第三世代OSASK」として[[K]]が数年前から設計していたものでした。これがOSECPUになる際に、実は大きな仕様変更をすることなく、そのまま流用できています。つまり[[K]]は知らないうちにセキュアな設計をしていたのです。 -ではどうやってこの仕様に決めていたのか、その話を書きたいと思います。 ** (1) 仕様の理由(セキュアに関係ある部分) -なぜJITコンパイル方式? --CPUに依存しない互換性を提供したかったから。Javaがうらやましかったから真似してみた。 --(セキュアなOSを考えると、アプリを実行する前に、悪い命令が混ざっていないかをチェックすることは重要である。JITコンパイルはすべての命令を実行前にチェックできるので、これはとても理にかなっていた。) -なぜ整数レジスタとポインタレジスタを分離したのか? --ページングもセグメンテーションもない環境下で、(多少時間がかかってもいいから)メモリ上のある構造体を移動することを考えよう。幅広いCPUに対応するのならこのような可能性も検討しておくべきだ。・・・この時、この構造体を指していたポインタはすべて修正されなければいけない。だからメモリ内のデータのうち、どれがポインタであるかはOSが完全に把握することにした(だからmalloc時に型を明示する)。 --ではレジスタはどうか。もし汎用レジスタ方式を採用していたら、その値は整数値なのかポインタなのかをどうにかして判断できなければいけない。そのために各レジスタがポインタを扱っているのかどうかを反映するフラグレジスタを作り、それを制御する命令を付けたモデルを検討したが、結局のところ、汎用レジスタ方式をやめるほうが単純化できると分かった。 --汎用レジスタ方式をやめれば、整数レジスタとポインタレジスタのビット幅も独立に決められる。さらにポインタレジスタの値を直接設定させなければ、ポインタレジスタのビット数に依存しないでプログラムが書けることもわかった。これはアドレス幅に無関係にアプリが書けるということなので、互換性の面で非常に良い。 --(ポインタレジスタを分離していたからこそ、ポインタレジスタ側にたくさんの属性情報を追加することができた。型情報やアクセスリミット、死活情報などである。命令セットをほとんど変えることなく、これらをサポートできた。) -なぜメモリアクセス時に型チェックをするのか? --エンディアンが違うシステムでも同一の動作結果を保証するにはこれがいいと思ったから。 --またポインタレジスタの値をメモリに書いて、それを整数レジスタで読み取ることを許せば、結局は整数レジスタでのポインタ操作を許していることと同じになり、構造体移動の際には整数値まで補正しなければいけなくなる危険性がある。 -なぜラベル命令で無限ループ対策という仕組みを導入するのか? --これは[[page0055]]の(3)の事を指している。 --最初はこうだ。まずJITコンパイラでは、バイトコードの1命令が複数の実CPUの命令に翻訳されるということがよく起こる。これで普通に割り込みを許せば、命令が中途半端にしか実行されない状態で割り込まれるかもしれないということを意味する。これは気持ち悪いし、もしかしたら深刻なバグの原因になるかもしれない。 --じゃあどうするか。とりあえず、そんなものはすべてCLI/STIでサンドイッチにして、途中で割り込みが生じないようにしておくしかない(x86の場合)。・・・しかしこの方法だとIOPLによっては実行できないし、翻訳コードはCLIとSTIばかりになって、実行速度が下がってしまう。これはよくない。 --というか、「割り込めない期間がたまにある」ではなくて「割り込みできるタイミングがたまにある」のなら、アプリにとって都合のよいタイミングで割り込み要求がきていないかを自発的にチェックすればいいではないか。しかもこの方法ならCPUに割り込み機能がなくても割り込みが実現できる。 --しかし何からのミスで割り込みチェックを忘れてしまうと割り込みに対応できなくなってしまう。割り込みチェックがあまりにも長い間隔なのもダメだ。ということで、アプリがちゃんと適正な間隔で割り込みチェックしていることを確認するために、分岐回数カウンタというアイデアが生まれた。無限ループ対策はそれを利用しているだけに過ぎない。 -なぜセキュリティをOFFにできる、という設計なのか? --このページの説明からも明らかなように、セキュリティは全くの後付けである。だからOFFにしてもいいものであって、それゆえにOFFにできなければならない。 --これはOFFにしなければいけないという意味ではない。選択できなければいけないという意味である。OFFにしたらアプリにばれて好き放題されるので、事実上できない、なんていうことは許されない。 ** (2) 仕様の理由(セキュアに関係ない部分) -なぜレジスタ数がこんなに多いのか? --x86が8本しか汎用レジスタがなく、しかもそのうちの一つはESPで、実質7本しかない。これで長い間プログラミングをしていたら、いつの間にかレジスタがたくさんほしいと熱望するようになった。一時は256本にしようとさえ思ったほどだ。 --64にした最大の動機は、hh4エンコードで1バイトで表現できる本数が64だったから、というだけに過ぎない。でも今でも64本というのはなかなか程よい本数だと思っている。 -なぜ「reg0=reg1+reg2;」のような三項演算形式にしたのか? --ARMの影響。x86で計算値を生成するたびに、元の値が必ず破壊されていくのが嫌だった。そのたびに破壊前の値をPUSHしたり別のレジスタにMOVしたりしていた。ARMがうらやましかった。 -なぜフラグレジスタがないのか? --MIPSの仕様がかっこいいと思ったから。 -なぜスタックがないのか? --レジスタが十分に豊富なら、スタックがなくても困らないはずだと直感的に思った。スタックを扱わなくてよければ、それだけ命令セットは単純になる。 --スタックには、整数値もポインタ値も積んだりおろしたりするだろう。ということは、「メモリ内データの型管理情報」を頻繁に更新する必要が出てくる。これは遅そうだ。こんなことになるくらいなら、スタックなんかなくてもいいじゃないか。それとも整数専用スタックとポインタ専用スタックを作るのか?またそうやって命令の種類が増えて、命令セットが複雑になるのか?それでいいのか? -なぜスタックマシンにしなかったのか?Javaのまねで出発したのに。 --レジスタマシンが好きだから。スタックマシンはレジスタマシンよりも機能密度が高いという説があるらしいが、それと対決してやろうと思った。 --レジスタマシンならJITコンパイラがレジスタ割り付けに悩まなくて済む。 ** (3) 考察 -セキュリティを考えなくても既にセキュアな仕様になっていたとは、どういうことなのでしょうか。それはこの設計が予想以上に汎用的だったということではないでしょうか。・・・つまり設計がよかったのです。 -よい設計は十分にシンプルで、多くの問題を同時に解決するものです。複雑にすれば複数の問題を解決できるのは当然であって、それはもはやよい設計ではありません。また複雑なのにひとつの問題すら満足に解決できないものもありますが、そんなのは論外です。 * こめんと欄 #comment
テキスト整形のルールを表示する