アドレス空間管理機能

アドレス空間管理機能は、論理アドレス空間に対して各種の操作や管理を行うための機能である。本機能は、主としてMMUやページテーブルを操作することによって実現され、タスク固有空間の設定を行うアドレス空間設定、アクセス権のチェックを行うアドレス空間チェック、メモリ領域のロック(常駐化)、論理アドレスと物理アドレスの変換やマッピングなどの機能を提供する。

本機能は、デバイスドライバやサブシステム等のシステムプログラムを実装するために利用されるほか、デマンドページングに関する処理を行うサブシステムを併用することにより、仮想記憶システムを実現するためにも利用される。

なお、MMUを使用しないシステムであっても、アドレス空間管理機能のAPIは提供される。移植性や拡張性への配慮から、MMUを使用しないシステム上でも、アプリケーションがこれらのAPIを適切に使用することが望ましい。

T-Kernelでは、実行時の保護レベルとして0~3の4段階(特権モード/ユーザモードなどに相当)、アクセス対象となるメモリの保護レベルとしても0~3の4段階がそれぞれ定義されており、現在実行中の保護レベルと同じか、それより低い保護レベルのメモリにのみアクセスができる。実行時のメモリアクセス権のチェックはMMUが行う。この機能は、プログラムの不正なアクセスから、OSなどのシステムを保護するために役立つ。メモリアクセス権のチェック機能を実現するために、T-Kernelは、MMU等の設定を適切に行う。

メモリの呼出元アクセス権情報は、基本的に拡張SVCを呼び出す直前の保護レベルでアクセスできる権利を示す情報であり、タスクごとに保持される。拡張SVCを呼び出す直前の保護レベルを示す情報であるため、一般には現在の保護レベルと一致しない。例えば、保護レベル3で実行中のタスクが拡張SVCを呼び出した場合、拡張SVCの実行中の保護レベルは0となるが、タスクがアクセスできる権利としては保護レベル3である。拡張SVC(a)からさらにネストして拡張SVC(b)を呼び出した場合、ネストして呼び出した拡張SVC(b)での呼出元アクセス権情報は、拡張SVC(b)を呼び出す直前の保護レベル、すなわち拡張SVC(a)を実行中の保護レベル0である。

メモリの呼出元アクセス権情報は次のように設定される。

メモリの呼出元アクセス権情報は、拡張SVCから呼び出し元の保護レベルに基づく処理を行うことを想定して保持される。一例としてアドレス空間チェック機能(ChkSpaceXXX)では、現在の実行時の保護レベルの代わりに呼出元アクセス権情報を利用することで、拡張SVCの呼び出し元の権限でのメモリアクセス権の検査が実現されている。

アドレス空間設定

T-Kernelのアドレス空間の扱いに関しては、「アドレス空間T-Kernelの概念」で説明している。アドレス空間設定の機能では、タスクのアドレス空間と呼出元アクセス権情報を設定するAPIを提供する。

SetTaskSpace - タスクのアドレス空間設定

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = SetTaskSpace (ID tskid );

パラメータ

ID tskid Task ID設定元のアドレス空間を持つタスクのタスクID

リターンパラメータ

ER ercd Error Codeエラーコード

エラーコード

E_OK 正常終了
E_ID tskid が不正
E_NOEXS オブジェクトが存在していない(tskid のタスクが存在しない)
E_OBJ TSK_SELF 以外で自タスクを指定した

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

自タスクのタスク固有空間と呼出元アクセス権情報を、tskid で指定したタスクの情報に基づいて設定する。これにより、このAPIを実行したタスクは、tskid のタスクと同じアドレス空間と、指定されたタスクがその時点で拡張SVCを呼び出す直前に実行していた実行時の保護レベルを示す呼出元アクセス権情報を持つことになる。ネストして拡張SVCが呼び出されている場合には、最後に呼ばれた拡張SVCを呼び出す直前の保護レベルが自タスクの呼出元アクセス権情報として設定される。なお、tskid で指定したタスクがタスク部を実行中の場合には、指定したタスクの生成時に指定された実行時の保護レベルが、自タスクの呼出元アクセス権情報として設定される。

なお、本APIの実行後に、tskid のタスク(対象タスク)のアドレス空間や呼出元アクセス権情報が変わった場合でも、自タスクのアドレス空間や呼出元アクセス権情報は影響を受けない。すなわち、本APIを実行する時点における対象タスクの状態が自タスクに反映されるだけで、その後の対象タスクの状態に自タスクが追従するわけではない。

拡張SVCの実行中に本APIを実行した場合、拡張SVCから戻ると、呼出元アクセス権情報については拡張SVCの呼出前の状態に戻る。一方、タスク固有空間は拡張SVCの呼出前の状態には戻らない。本APIで設定されたタスク固有空間が、拡張SVCから戻った後もそのまま有効である。

tskid に自タスクのタスクIDを指定することはできない。ただし、TSK_SELF により自タスクを指定した場合は、現在実行中の保護レベルの呼出元アクセス権情報が設定される。このとき、タスク固有空間は切り替わらない。

なお、呼出元アクセス権情報の設定により、実行時の保護レベルが変更されるわけではないことに注意が必要である。

補足事項

SetTaskSpace() は、デバイスドライバやサブシステムの処理を行うために、処理の依頼元のタスクA(デバイス管理やサブシステムの拡張SVCを呼んだタスク)とは別の処理用タスクBが動作しているような状況において、処理用タスクBのタスク固有空間および呼出元アクセス権情報を、依頼元のタスクAと同じ設定にするために使用する。

たとえば、デバイスドライバの処理用タスクBが、デバイスから入力データを読み込み、依頼元のタスクAが指定したバッファXにそのデータを格納するケースを考える。ここで、バッファXのアドレスがタスクAのタスク固有空間の中にあり、かつ処理用タスクBと依頼元タスクAのタスク固有空間が異なっていた場合には、処理用タスクBからバッファXにアクセスできず、入力データを格納することもできない。

このようなケースでは、処理用タスクBがあらかじめ SetTaskSpace() を実行し、自タスクのタスク固有空間を依頼元タスクAと同じ設定にしておくことにより、バッファXへのアクセスが可能となる。また、処理用タスクBの呼出元アクセス権情報が依頼元タスクAと同じになるので、バッファXに入力データを格納する際のアクセス権のチェックも適切に行われる。

呼出元アクセス権情報の設定を行わず、タスク固有空間の設定のみを行う場合には、tk_set_tsp を利用する。

アドレス空間チェック

現在の呼出元アクセス権情報にしたがって、指定されたメモリ領域へのアクセスが許可されているか検査する。

検査のために、ChkSpaceXXX()のAPIを提供する。APIの名称の最後の文字の意味は次の通りである。

現在の呼出元アクセス権情報にて対象となるメモリ領域へのアクセスが許可されていない場合や、対象となるメモリ領域にメモリが存在しない場合には、E_MACV のエラーを返す。対象となるメモリ領域の一部のアクセスが許可されていない場合や、一部のメモリが存在しない場合も、同様に E_MACV のエラーを返す。

なお、検査対象のメモリ領域がタスク固有空間の場合には、現在設定されているタスク固有空間がそのまま使用される。

注意補足事項
 

低い保護レベルで動作している一般のアプリケーションタスクAが、高い保護レベルで動作するデバイスドライバやサブシステムに処理を依頼するようなケースにおいて、処理のパラメータやリターンパラメータをメモリ領域Xに置いた場合には、依頼元のタスクAがメモリ領域Xに対してアクセス可能かどうかをデバイスドライバやサブシステムの側でチェックする必要がある。このチェックを行わないと、たとえば、タスクAからアクセス権のないメモリ領域を、デバイスドライバやサブシステム経由で不正にアクセスできてしまうからである。アドレス空間チェックのAPIは、このような場面でのチェックを行うために利用することを想定した機能である。

ChkSpaceR - メモリ読込みアクセス権の検査

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = ChkSpaceR (void *addr , INT len );

パラメータ

void* addr Memory Start Address検査対象メモリの開始アドレス
INT len Length検査対象メモリのサイズ(バイト数)

リターンパラメータ

ER ercd Error Codeエラーコード

エラーコード

E_OK 正常終了
E_MACV メモリアクセス不能

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

addr が示すアドレスから len バイトの領域に対して、現在の呼出元アクセス権情報により読込みアクセスが可能かどうかを検査する。アクセス可能であれば E_OK を返し、アクセス不能であれば E_MACV を返す。

ChkSpaceRW - メモリ読込み書込みアクセス権の検査

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = ChkSpaceRW (void *addr , INT len );

パラメータ

void* addr Memory Start Address検査対象メモリの開始アドレス
INT len Length検査対象メモリのサイズ(バイト数)

リターンパラメータ

ER ercd Error Codeエラーコード

エラーコード

E_OK 正常終了
E_MACV メモリアクセス不能

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

addr が示すアドレスから len バイトの領域に対して、現在の呼出元アクセス権情報により読込みアクセスと書込みアクセスの両方が可能かどうかを検査する。両方のアクセス可能であれば E_OK を返し、少なくとも一方のアクセスが不能であれば E_MACV を返す。

ChkSpaceRE - メモリ読込みアクセス権および実行権の検査

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = ChkSpaceRE (void *addr , INT len );

パラメータ

void* addr Memory Start Address検査対象メモリの開始アドレス
INT len Length検査対象メモリのサイズ(バイト数)

リターンパラメータ

ER ercd Error Codeエラーコード

エラーコード

E_OK 正常終了
E_MACV メモリアクセス不能

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

addr が示すアドレスから len バイトの領域に対して、現在の呼出元アクセス権情報により読込みアクセスが可能で、かつプログラムとして実行が可能かどうかを検査する。両方とも可能であれば E_OK を返し、少なくとも一方が不能であれば E_MACV を返す。

ChkSpaceBstrR - 文字列読込みアクセス権の検査

C言語インタフェース

#include <tk/tkernel.h>

INT rlen = ChkSpaceBstrR (CONST UB *str , INT max );

パラメータ

CONST UB* str String検査対象の文字列の開始アドレス
INT max Max Length検査対象の文字列の長さの最大値

リターンパラメータ

INT rlen Result Lengthアクセス可能な文字列の長さ

エラーコード

E_MACV メモリアクセス不能

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

str から文字列の終端('\0')に達するか max 文字目(バイト数)に達するまでのメモリ領域に対して、現在の呼出元アクセス権情報により読込みアクセスが可能かどうかを検査する。max=0の場合は、文字列終端まで検査する。

アクセス可能であれば、その文字列の長さ(バイト数)を返す。max 文字目までに文字列の終端があった場合は'\0'の直前までの長さ、文字列の終端より先に max 文字に達した場合は max を返す。

アクセス不能であれば、E_MACV のエラーを返す。

ChkSpaceBstrRW - 文字列読込み書込みアクセス権の検査

C言語インタフェース

#include <tk/tkernel.h>

INT rlen = ChkSpaceBstrRW (CONST UB *str , INT max );

パラメータ

CONST UB* str String検査対象の文字列の開始アドレス
INT max Max Length検査対象の文字列の長さの最大値

リターンパラメータ

INT rlen Result Lengthアクセス可能な文字列の長さ

エラーコード

E_MACV メモリアクセス不能

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

str から文字列の終端('\0')に達するか max 文字目(バイト数)に達するまでのメモリ領域に対して、現在の呼出元アクセス権情報により読込みアクセスおよび書込みアクセスが可能かどうかを検査する。max=0の場合は、文字列終端まで検査する。

読込み、書込みともアクセス可能であれば、その文字列の長さ(バイト数)を返す。max 文字目までに文字列の終端があった場合は'\0'の直前までの長さ、文字列の終端より先に max 文字に達した場合は max を返す。

読込み、書込みの少なくとも一方がアクセス不能であれば、E_MACV のエラーを返す。

ChkSpaceTstrR - TRONコード文字列読込みアクセス権の検査

C言語インタフェース

#include <tk/tkernel.h>

INT rlen = ChkSpaceTstrR (CONST TC *str , INT max );

パラメータ

CONST TC* str String検査対象の文字列の開始アドレス
INT max Max Length検査対象の文字列の長さの最大値

リターンパラメータ

INT rlen Result Lengthアクセス可能な文字列の長さ

エラーコード

E_MACV メモリアクセス不能

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

str からTRONコード文字列の終端(TNULL=0x0000)に達するか max 文字目(TRONコード文字数)に達するまでのメモリ領域に対して、現在の呼出元アクセス権情報により読込みアクセスが可能かどうかを検査する。max=0の場合は、文字列終端まで検査する。

アクセス可能であれば、その文字列の長さ(TRONコード文字数)を返す。max 文字目までに文字列の終端があった場合は TNULL の直前までの長さ、文字列の終端より先に max 文字に達した場合は max を返す。

アクセス不能であれば、E_MACV のエラーを返す。

str は、偶数アドレスでなければならない。

ChkSpaceTstrRW - TRONコード文字列読込み書込みアクセス権の検査

C言語インタフェース

#include <tk/tkernel.h>

INT rlen = ChkSpaceTstrRW (CONST TC *str , INT max );

パラメータ

CONST TC* str String検査対象の文字列の開始アドレス
INT max Max Length検査対象の文字列の長さの最大値

リターンパラメータ

INT rlen Result Lengthアクセス可能な文字列の長さ

エラーコード

E_MACV メモリアクセス不能

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

str からTRONコード文字列の終端(TNULL=0x0000)に達するか max 文字目(TRONコード文字数)に達するまでのメモリ領域に対して、現在の呼出元アクセス権情報により読込みアクセスおよび書込みアクセスが可能かどうかを検査する。max=0の場合は、文字列終端まで検査する。

読込み、書込みともアクセス可能であれば、その文字列の長さ(TRONコード文字数)を返す。max 文字目までに文字列の終端があった場合は TNULL の直前までの長さ、文字列の終端より先に max 文字に達した場合は max を返す。

読込み、書込みの少なくとも一方がアクセス不能であれば、E_MACV のエラーを返す。

str は、偶数アドレスでなければならない。

論理アドレス空間管理

論理アドレス空間管理の機能では、アドレス変換(論理アドレスから物理アドレスへの変換)、メモリの常駐化、メモリアクセス権の設定に関連したAPIを提供する。

T-Kernelでは、メモリに対するアクセス権の管理やタスク固有空間の実現、メモリの効率的な利用などを行うために、MMUを利用したアドレス変換(論理アドレスから物理アドレスへの変換)を行っている。通常のプログラムは論理アドレス空間の中で動作しており、物理アドレスを扱う必要はないが、DMA転送を行うデバイスドライバなど、ハードウェアを直接操作する一部のシステムプログラムでは物理アドレスを扱う場合がある。この時、論理アドレスと物理アドレスとの対応関係の取得や設定を行う必要があるので、そのためのAPIとして CnvPhysicalAddr()MapMemory()UnmapMemory() が提供される。

また、T-Kernel上に仮想記憶システムを実現した場合には、プログラムAからアクセスされるメモリが物理的に存在しない状態(ページアウトされた状態)が発生する。ページアウトされたメモリへのアクセスがあった場合、CPUによっては、MMUがそれを検出してページフォルトのCPU例外を発生し、その例外を処理する仮想記憶システムがページアウトされていたメモリの内容をディスク(二次記憶装置)からメモリに戻す(ページイン)。このような処理を行うことによって、プログラムAから見ると、アクセス対象メモリがページアウトされているかどうかを気にすることなく、処理を進めることができる。これは、仮想記憶システムの一般的な実装方法である。

しかし、タスク独立部実行中、ディスパッチ禁止中、割込み禁止中のプログラムでは、ページフォルト発生時にも、上記のようなページインの処理を行うことができない。このため、プログラムの実行中にページフォルトが発生しないように、あらかじめアクセス対象となるすべてのメモリをページインして常駐化しておく必要がある。また、DMA転送を行う場合や、時間制約の強いプログラムを実行する場合にも、同様の処置が必要になる。このような場合に使用するAPIとして、メモリ領域をロック(常駐化)する LockSpace() や、それを解除する UnlockSpace() が提供される。

このほか、アドレス空間の各種情報を取得する GetSpaceInfo()、メモリアクセス権の設定を行う SetMemoryAccess() といったAPIが提供される。

上記のうち、DMA転送に関連した処理を行うAPIでは、DMA転送に合わせたメモリキャッシュ制御も行う、具体的には、CnvPhysicalAddr() によって論理アドレスから物理アドレスへの変換を行う際、対象となった領域は、DMA転送ができるようにメモリキャッシュがオフになる。DMA転送の終了後、UnlockSpace() を実行してメモリの常駐解除を行うと、キャッシュオン状態に戻る。

注意補足事項
 

T-Kernel/SMでは、論理アドレス空間と物理アドレス空間の対応関係(マッピング)、メモリのアクセス権、ページ不在や常駐化などの管理を行うために、MMUやページテーブルの設定や操作を行う。しかし、T-Kernel本体だけで仮想記憶システムを実現するわけではない。実際に仮想記憶を実現するためには、物理メモリとディスク(二次記憶装置)との間でページインやページアウトの処理を行うなど、他にもいろいろな処理が必要である。これらの処理は、T-Kernel本体ではなく、仮想記憶を実現するためのサブシステム(T-Kernel Extensionの一部など)によって行われる。

LockSpace - メモリ領域のロック

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = LockSpace (CONST void *addr , INT len );

パラメータ

CONST void* addr Memory Start Addressロックするメモリの開始アドレス
INT len Lengthロックするメモリのサイズ(バイト数)

リターンパラメータ

ER ercd Error Codeエラーコード

エラーコード

E_OK 正常終了
E_PAR パラメータエラー(len≦0)
E_MACV メモリ領域ではない部分を指定した
E_NOMEM メモリ不足(常駐化に伴うページインのためのメモリが確保できない)
E_LIMIT ロック回数の上限を超えてロックした

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

論理アドレス addr から len バイトのメモリ領域(ロック対象領域)をロック(常駐化)する。本APIによる常駐化の後、ロック対象領域はページアウトされなくなり、常に物理アドレス空間にマッピングされるとともに、実メモリ(物理的なメモリ)も割り当てられた状態となる。

ロック対象領域の一部がページアウトされていた場合には、その領域に対してページインの処理を行ってから常駐化する。ページインの際に実メモリの確保ができなかった場合には、E_NOMEM のエラーを返す。

同じメモリ領域に対して複数回の LockSpace() を実行することができる。このとき、LockSpace() の回数はカウントされ、同じ回数の UnlockSpace() の実行によって常駐化が解除される。すなわち、LockSpace() により常駐化した状態をネストすることができる。ただし、この場合のネストの多重度(LockSpace()UnlockSpace() の実行回数の差)には実装依存の上限値があり、その上限値を越えて LockSpace() を実行した場合には、E_LIMIT のエラーを返す。

len に0以下の値を指定した場合には、E_PAR のエラーを返す。また、メモリ領域ではない部分(メモリの割当てを想定していない論理アドレス)がロック対象領域に含まれていた場合には、E_MACV のエラーを返す。

本APIによるロック(常駐化)の処理は、MMUの機能を使ってページ単位で行われる。このため、addr がページの先頭アドレスでない場合や、len がページサイズの整数倍でない場合は、addrlen で指定した範囲を含むページ全体がロック対象領域となる。たとえば、len に1を指定しても、1ページ分の領域がロックされることになる。

MMUを使用しないシステムにおいては、すべてのメモリを常駐メモリとみなすことができる。そのため、LockSpace() において具体的な処理をする必要はないが、MMUを使用するシステムとの互換性を考慮し、エラーとはせずに E_OK を返す。MMUを使用しないシステムにおいて、E_PAR などエラーをチェックするかどうかは実装依存である。

補足事項

LockSpace() によるメモリ常駐化の処理のうち、ページインなどの処理は、仮想記憶を実現するサブシステムを呼び出すことによって行われる。呼出のインタフェースは実装依存である。

MapMemory() によって割り当てられた論理アドレス空間を、LockSpace() のロック対象領域に含めてはいけない。この場合の動作は保証されない。

UnlockSpace - メモリ領域のアンロック

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = UnlockSpace (CONST void *addr , INT len );

パラメータ

CONST void* addr Memory Start Addressアンロックするメモリの開始アドレス
INT len Lengthアンロックするメモリのサイズ(バイト数)

リターンパラメータ

ER ercd Error Codeエラーコード

エラーコード

E_OK 正常終了
E_PAR パラメータエラー(len≦0)
E_MACV メモリ領域ではない部分を指定した
E_LIMIT ロックされていない領域を指定した

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

論理アドレス addr から len バイトの領域(アンロック対象領域)をアンロック(常駐解除)する。本APIによる常駐解除の後、アンロック対象領域はページアウトの対象になる。

また、アンロック対象領域のメモリキャッシュモードがオフになっていた場合は、オンの設定に変更する。

アンロック対象領域としては、必ず LockSpace() の発行時に指定したロック対象領域と同じ領域を指定する必要がある。ロックした領域の一部のみをアンロックすることはできない。ただし、このような使い方をした場合でも、T-Kernelではエラーを検出できない。呼出側の責任で、必ず同じ領域を指定しなければならない。

同じメモリ領域に対して複数回の LockSpace() が実行されていた場合、同じ回数の UnlockSpace() の実行によって常駐解除される。UnlockSpace() の回数が LockSpace() の回数に満たず、常駐解除されない場合でも、UnlockSpace() はエラーとはならずに E_OK を返す。一方、まだロックされていない領域をアンロック対象領域として指定した場合には、ロックカウントのエラーとして E_LIMIT を返す。

len に0以下の値を指定した場合には、E_PAR のエラーを返す。また、メモリ領域ではない部分(メモリの割当てを想定していない論理アドレス)がアンロック対象領域に含まれていた場合には、E_MACV のエラーを返す。

本APIによるアンロック(常駐解除)の処理は、MMUの機能を使ってページ単位で行われる。このため、addr がページの先頭アドレスでない場合や、len がページサイズの整数倍でない場合は、addrlen で指定した範囲を含むページ全体がアンロック対象領域となる。たとえば、len に1を指定しても、1ページ分の領域がアンロックされることになる。

MMUを使用しないシステムにおいては、すべてのメモリを常駐メモリとみなすことができる。そのため、UnlockSpace() においても、LockSpace() と同様に具体的な処理をする必要はないが、MMUを使用するシステムとの互換性を考慮し、エラーとはせずに E_OK を返す。MMUを使用しないシステムにおいて、E_PAR などエラーをチェックするかどうかは実装依存である。

補足事項

MapMemory() によって割り当てられた論理アドレス空間を、UnlockSpace() のアンロック対象領域に含めてはいけない。この場合の動作は保証されない。

DMA転送を行う際には、バッファとなるメモリ領域を常駐化し、メモリキャッシュモード設定をオフにした上で、バッファの物理アドレスをDMAコントローラに設定する必要がある。この場合の通常の手順は次のようになる。

  1. LockSpace() によってバッファの常駐化を行う。

  2. CnvPhysicalAddr() によってバッファの物理アドレスを取得するとともに、バッファのメモリキャッシュモード設定をオフにする。

  3. バッファと入出力デバイスとの間でDMA転送を行う。

  4. UnlockSpace() によって、バッファの常駐解除を行うとともに、バッファのメモリキャッシュモード設定をオンに戻す。

ただし、UnlockSpace() では、上記のようなAPIの発行履歴とは無関係にメモリキャッシュモードをオンに設定する。UnlockSpace() の実行によりメモリキャッシュモード設定が変更される可能性について、注意が必要である。

CnvPhysicalAddr - 物理アドレスの取得

C言語インタフェース

#include <tk/tkernel.h>

INT rlen = CnvPhysicalAddr (CONST void *vaddr , INT len , void **paddr );

パラメータ

CONST void* vaddr Vitrual Address変換元の論理アドレス
INT len Length領域サイズ(バイト数)
void** paddr Pointer to Physical Address論理アドレスに対応する物理アドレスを返す領域へのポインタ

リターンパラメータ

INT rlen Result Length連続物理アドレス空間のサイズ(バイト数)
またはError Codeエラーコード
void* paddr Physical Address論理アドレスに対応する物理アドレス

エラーコード

E_OK 正常終了
E_PAR パラメータエラー(対象領域のキャッシュ制御ができない)
E_MACV メモリ領域ではない部分を指定した

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

論理アドレス vaddr のメモリ領域に対応する物理アドレスを求め、paddr へ返す。また、vaddr から len バイトのメモリ領域のうち、対応する物理アドレスが連続しているサイズ(バイト数)を戻値 rlen に返す。すなわち、論理アドレスと物理アドレスの対応関係が連続するのは、rlen のサイズまでであり、rlenlen である。論理アドレス空間の vaddr から rlen のサイズの連続領域が、物理アドレス空間の paddr から rlen のサイズの連続領域に対応するということになる。

また、物理アドレス空間の paddr から rlen のサイズの領域(対象領域)に対して、メモリキャッシュモードをオフに設定する。これは、CnvPhysicalAddr() の実行後にDMA転送を行うことを想定しているためである。ただし、ハードウェアの制限から、部分的なメモリのキャッシュのオフができない場合には、キャッシュのフラッシュ(ライトバックして無効化)を行うものとする。

CnvPhysicalAddr() では、対象領域の常駐化の処理は行わない。DMA転送を行う場合には、バッファとして使用する領域に対して別途 LockSpace() を発行し、バッファ領域を常駐化(ロック)しておかなければならない。

len に0以下の値を指定した場合には、E_PAR のエラーを返す。また、vaddr から len バイトの領域の中に、メモリ領域ではない部分(メモリの割当てを想定していない論理アドレス)が含まれていた場合には、E_MACV のエラーを返す。

補足事項

CnvPhysicalAddr() は、DMA転送の準備のために使用することを想定したAPIである。DMA転送の際の具体的な使い方については、UnlockSpace() の補足事項を参照のこと。

CnvPhysicalAddr() の対象領域に対しては、キャッシュモードをオフに設定するだけでなく、メモリアクセスの完了を保証するメモリ属性に設定することが望ましい。

MapMemory - メモリのマップ

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = MapMemory (CONST void *paddr , INT len , UINT attr , void **laddr );

パラメータ

CONST void* paddr Physical Addressマップする物理アドレス
INT len Lengthマップするメモリのサイズ(バイト数)
UINT attr Attributeマップする際のメモリ属性
void** laddr Pointer to Logical Addressマップ先の論理アドレスを返す領域へのポインタ

リターンパラメータ

ER ercd Error Codeエラーコード
void* laddr Logical Addressマップ先の論理アドレス

エラーコード

E_OK 正常終了
E_PAR パラメータエラー(len≦0)
E_LIMIT マップ先の論理アドレス空間が不足
E_NOMEM 割り当てる実メモリが不足、論理アドレス空間の管理用メモリが不足

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

物理アドレス paddr から len バイトの連続領域を論理アドレス空間にマップし、マップ先の先頭の論理アドレスを laddr に返す。マップされたメモリ領域は、常駐化(ロック)された状態となる。また、マップされたメモリ領域に、attr で指定した属性を設定する。

attr では、次の属性を指定する。

attr := (MM_USER || MM_SYSTEM) | [MM_READ] | [MM_WRITE] | [MM_EXECUTE] | [MM_CDIS]

MM_USER ユーザレベルアクセス可
MM_SYSTEM システムレベルアクセス可
MM_READ 読込みアクセス可
MM_WRITE 書込みアクセス可
MM_EXECUTE プログラム実行可
MM_CDIS キャッシュ禁止

ハードウェアや実装によっては、上記の以外の属性を指定できる場合もある。

paddrNULL を指定した場合には、物理アドレスの連続した len バイトの実メモリを確保して割当てを行い、その実メモリの物理アドレス空間を論理アドレス空間にマップする。

len に0以下の値を指定した場合には、E_PAR のエラーを返す。また、マップ先の論理アドレス空間が不足していて割当てに失敗した場合には、E_LIMIT のエラーを返す。論理アドレス空間を管理するために必要なメモリが確保できなかった場合や、paddrNULL を指定したケースで実メモリの確保ができなかった場合には、E_NOMEM のエラーを返す。

補足事項

MapMemory() は、物理アドレス空間に置かれた入出力デバイス(Video RAMなど)の領域を、デバイスドライバなどのプログラムから直接アクセス可能な論理アドレス空間にマッピングするための機能である。

マップ先の論理アドレス laddr は、本APIの実行時に自動的に割り当てられる。マップ先の論理アドレスを指定することはできない。

T-Kernelが管理するシステムメモリに含まれるアドレスを paddr に指定してはならない。MapMemory() によってシステムメモリの確保を行いたい場合には、paddrNULL を指定し、T-Kernelによって自動的に割り当てられたシステムメモリを使用する。

attr で指定する属性のシンボル(ニーモニック)に対応する値は、実装によって異なっている場合がある。そのため、互換性への配慮から、attr の指定には必ず上記のシンボルを使用すべきである。

既に MapMemory() の対象となっている物理アドレス領域に対して、重複して MapMemory() を実行してはいけない。また、MapMemory() によって割り当てたメモリは常駐メモリであるが、この常駐は解除できず、常駐解除のために UnlockSpace()を呼び出してはならない。このような使い方をしないことは、呼出側で保証する必要がある。

MapMemory() を実行した後、何らかの方法にて、laddr として割り当てられた論理アドレスを経由せず、paddr 以降の物理アドレスに直接アクセスした場合、キャッシュ等の不整合が生じる可能性がある。このような使い方をする場合は、呼出側の責任において、データの整合性などに十分注意する必要がある。

attrMM_CDIS を指定した場合のメモリ属性は、キャッシュを使用しない属性であるだけでなく、メモリアクセスの完了を保証する属性であることが望ましい。

UnmapMemory - メモリのアンマップ

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = UnmapMemory (CONST void *laddr );

パラメータ

CONST void* laddr Logical Addressアンマップする論理アドレス

リターンパラメータ

ER ercd Error Codeエラーコード

エラーコード

E_OK 正常終了
E_PAR パラメータエラー(laddr が不正)

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

MapMemory() で割り当てられた論理アドレス空間をアンマップ(解放)する。laddr にはアンマップの対象となる領域の論理アドレスを指定するが、この値は、MapMemory() の戻値 laddr で得た値でなければならない。

MapMemory() の実行時に paddrNULL を指定し、実メモリの割当ても行っていた場合には、UnmapMemory() の実行によりそのメモリも解放される。

GetSpaceInfo - アドレス空間の各種情報の取得

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = GetSpaceInfo (CONST void *addr , INT len , T_SPINFO *pk_spinfo );

パラメータ

CONST void* addr Start Address情報を取得する先頭論理アドレス
INT len Length情報を取得する領域サイズ(バイト数)
T_SPINFO* pk_spinfo Packet to Refer Space Infoアドレス空間情報を返す領域へのポインタ

リターンパラメータ

ER ercd Error Codeエラーコード

pk_spinfo の内容

void* paddr Physical Address addr に対応する物理アドレス
void* page Page Start Address addr が属するページの先頭物理アドレス
INT pagesz Page Sizeページサイズ(バイト数)
INT cachesz Cache Line Sizeキャッシュラインサイズ(バイト数)
INT cont Continuous Length物理アドレスが連続している領域のサイズ(バイト数)
──(以下に実装独自に他の情報を追加してもよい)──

エラーコード

E_OK 正常終了
E_PAR パラメータエラー(addr, len, pk_spinfo が不正あるいは利用できない)
E_MACV メモリアクセス不能、メモリアクセス権違反

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

論理アドレス addr から len の領域のアドレス空間情報を取得して、リターンパラメータ pk_spinfo に返す。paddr には addr に対応する物理アドレスを返す。page には addr が属するページの先頭の物理アドレスを返す。

pagesz にはページサイズを返す。ページサイズは、MMUで定義されるページサイズであり、SetMemoryAccess() でメモリアクセス権を設定したり、SetCacheMode() でキャッシュモードを設定したりする際の単位となるページサイズと同じ値である。

cachesz にはキャッシュラインサイズを返す。キャッシュラインサイズは、ControlCache() でキャッシュを制御する際の単位となるキャッシュラインサイズと同じ値である。

cont には addr から len バイトの領域のうち、対応する物理アドレスが連続しているサイズ(バイト数)を返す。すなわち、論理アドレスと物理アドレスの対応関係が連続するのは、cont のサイズまでであり、contlen である。論理アドレス空間の addr から cont のサイズの連続領域が、物理アドレス空間の paddr から cont のサイズの連続領域に対応するということになる。

途中にページアウトされている領域が存在した場合は、その領域の直前までの物理アドレスが連続しているものとみなす。特に、addr の属するページがページアウトされていた場合は、cont=0を返す。このとき、戻値 ercdE_OK を返すが、pk_spinfo に返されるリターンパラメータのうち、cont 以外の内容は不定となる。

len に0以下の値を指定した場合には、E_PAR のエラーを返す。エラーが発生した場合に pk_spinfo に設定される内容は不定である。

T-Kernel 1.0との差異

T-Kernel 2.0で追加されたAPIである。

SetMemoryAccess - メモリアクセス権の設定

C言語インタフェース

#include <tk/tkernel.h>

INT rlen = SetMemoryAccess (CONST void *addr , INT len , UINT mode );

パラメータ

CONST void* addr Start Addressアクセス権を設定するメモリ領域の先頭アドレス
INT len Lengthアクセス権を設定するメモリ領域のサイズ(バイト数)
UINT mode Memory Access Mode設定するメモリアクセス権を示すモード

リターンパラメータ

INT rlen Result Lengthメモリアクセス権を設定できた領域のサイズ(バイト数)
またはError Codeエラーコード

エラーコード

E_OK 正常終了
E_PAR パラメータエラー(addr, len, mode が不正あるいは利用できない)
E_NOSPT 未サポート機能(mode で指定した機能が未サポート)

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

論理アドレス addr から len バイトのメモリ領域に対して、mode で指定したメモリアクセス権を設定する。また、実際にメモリアクセス権を設定できた領域のサイズ(バイト数)を戻値 rlen に返す。

mode では、次のメモリアクセス権を指定する。

mode := ( MM_EXECUTE | MM_READ | MM_WRITE )
                MM_EXECUTE      プログラム実行アクセス可能
                MM_READ         読み出しアクセス可能
                MM_WRITE        書き込みアクセス可能
                    ...
                /* 実装独自のモードを追加してもよい */

本APIによるメモリアクセス権の設定は、MMUの機能を使ってページ単位で行われる。このため、addr がページの先頭アドレスでない場合や、len がページサイズの整数倍でない場合は、addrlen で指定した範囲を含むページ全体がメモリアクセス権設定の対象領域となる。たとえば、len に1を指定しても、1ページ分のメモリアクセス権が設定されることになる。

ハードウェアや実装によっては、上記の以外のメモリアクセス権を指定できる場合もある。また、ハードウェアや実装によっては、上記のメモリアクセス権の一部または全部の設定ができない場合がある。設定できないメモリアクセス権を mode で指定した場合には、E_NOSPT のエラーを返す。

補足事項

通常のアプリケーションなどで使用するメモリ領域に対しては、T-Kernelがあらかじめ適切なメモリアクセス権の設定を行っている。このため、通常のアプリケーションが SetMemoryAccess() を使う必要はない。SetMemoryAccess() を使用するのは、システムのメモリ割当てやセキュリティを動的に管理するプログラム、デバッグ用のプログラムなど、通常のアプリケーションとは異なる特別な目的を持ったプログラムである。

mode で指定するメモリアクセス権は、MapMemoryattr で指定する属性の一部と共通である。

T-Kernel 1.0との差異

T-Kernel 2.0で追加されたAPIである。