1 /******************************************************************************/
2 /* src/kernel/ProcMng/ProcMngTask.c */
4 /* Copyright (C) 2017 Mochi. */
5 /******************************************************************************/
6 /******************************************************************************/
8 /******************************************************************************/
13 #include <hardware/IA32/IA32Instruction.h>
22 #include "ProcMngSched.h"
23 #include "ProcMngTask.h"
24 #include "ProcMngTss.h"
27 /******************************************************************************/
29 /******************************************************************************/
31 #ifdef DEBUG_LOG_ENABLE
32 #define DEBUG_LOG( ... ) \
33 DebugLogOutput( CMN_MODULE_PROCMNG_TASK, \
37 #define DEBUG_LOG( ... )
41 #define TASK_ID_UNUSED ( 0 ) /** 未使用 */
42 #define TASK_ID_USED ( 1 ) /** 使用済 */
45 #define TASK_KERNEL_STACK_SIZE ( 1024000 ) /**< カーネルスタックサイズ */
46 #define TASK_STACK_SIZE ( 1024000 ) /**< スタックサイズ */
50 void *pTopAddr; /**< 先頭アドレス */
51 void *pBottomAddr; /**< 後尾アドレス */
52 size_t size; /**< サイズ */
57 uint8_t used; /**< 使用フラグ */
58 uint8_t type; /**< タスクタイプ */
59 uint8_t state; /**< タスク状態 */
60 uint8_t reserved; /**< パディング */
61 ProcMngTaskContext_t context; /**< コンテキスト */
62 uint32_t pageDirId; /**< ページディレクトリID */
63 void *pEntryPoint; /**< エントリポイント */
64 taskStackInfo_t kernelStackInfo; /**< カーネルスタックアドレス */
65 taskStackInfo_t stackInfo; /**< スタックアドレス */
69 /******************************************************************************/
71 /******************************************************************************/
73 static taskTbl_t gTaskTbl[ PROCMNG_TASK_ID_NUM ];
76 /******************************************************************************/
78 /******************************************************************************/
79 /******************************************************************************/
84 * @param[in] taskType タスクタイプ
85 * - PROCMNG_TASK_TYPE_DRIVER ドライバ
86 * - PROCMNG_TASK_TYPE_SERVER サーバ
87 * - PROCMNG_TASK_TYPE_USER ユーザ
88 * @param[in] *pEntryPoint エントリポイント
90 * @retval PROCMNG_TASK_ID_NULL 失敗
91 * @retval PROCMNG_TASK_ID_MIN タスクID最小値
92 * @retval PROCMNG_TASK_ID_MAX タスクID最大値
94 /******************************************************************************/
95 uint32_t ProcMngTaskAdd( uint8_t taskType,
98 void *pKernelStack; /* カーネルスタック */
99 void *pStack; /* スタック */
100 int32_t ret; /* 関数戻り値 */
101 uint32_t taskId; /* タスクID */
102 uint32_t pageDirId; /* ページディレクトリID */
103 taskStackInfo_t *pStackInfo; /* スタック情報 */
109 taskId = PROCMNG_TASK_ID_MIN;
110 pageDirId = MEMMNG_PAGE_DIR_FULL;
114 DEBUG_LOG( "%s() start. taskType=%u, pEntryPoint=%010p",
120 for ( ; taskId < PROCMNG_TASK_ID_MAX; taskId++ ) {
122 if ( gTaskTbl[ taskId ].used == TASK_ID_UNUSED ) {
126 pageDirId = MemMngPageAllocDir();
128 /* ページディレクトリ割当結果判定 */
129 if ( pageDirId == MEMMNG_PAGE_DIR_FULL ) {
133 /* 設定したタスクを初期化する処理。異常処理はちょっと後回し */
135 return PROCMNG_TASK_ID_NULL;
139 pKernelStack = MemMngAreaAlloc( TASK_KERNEL_STACK_SIZE );
142 pStack = MemMngAreaAlloc( TASK_STACK_SIZE );
145 if ( ( pKernelStack == NULL ) ||
146 ( pStack == NULL ) ) {
150 /* 設定したタスクを初期化する処理。異常処理はちょっと後回し */
152 return PROCMNG_TASK_ID_NULL;
156 MemMngPageMap( pageDirId,
159 TASK_KERNEL_STACK_SIZE,
163 MemMngPageMap( pageDirId,
172 gTaskTbl[ taskId ].used = TASK_ID_USED;
173 gTaskTbl[ taskId ].type = taskType;
174 gTaskTbl[ taskId ].state = 0;
175 gTaskTbl[ taskId ].context.eip = ( uint32_t ) ProcMngTaskStart;
176 gTaskTbl[ taskId ].context.esp = ( uint32_t ) pKernelStack +
177 TASK_KERNEL_STACK_SIZE;
178 gTaskTbl[ taskId ].pEntryPoint = pEntryPoint;
179 gTaskTbl[ taskId ].pageDirId = pageDirId;
182 pStackInfo = &( gTaskTbl[ taskId ].kernelStackInfo );
183 pStackInfo->pTopAddr = pKernelStack;
184 pStackInfo->pBottomAddr = pKernelStack + TASK_KERNEL_STACK_SIZE;
185 pStackInfo->size = TASK_KERNEL_STACK_SIZE;
188 pStackInfo = &( gTaskTbl[ taskId ].stackInfo );
189 pStackInfo->pTopAddr = pStack;
190 pStackInfo->pBottomAddr = pStack + TASK_STACK_SIZE;
191 pStackInfo->size = TASK_STACK_SIZE;
194 ret = ProcMngSchedAdd( taskId );
197 if ( ret == CMN_FAILURE ) {
201 /* 設定したタスクを初期化する処理。異常処理はちょっと後回し */
203 return PROCMNG_TASK_ID_NULL;
207 DEBUG_LOG( "%s() end. ret=%u", __func__, taskId );
214 DEBUG_LOG( "%s() end. ret=%u", __func__, PROCMNG_TASK_ID_NULL );
216 return PROCMNG_TASK_ID_NULL;
220 /******************************************************************************/
223 * @details 指定したタスクIDのコンテキストを取得する。
225 * @param[in] taskId タスクID
226 * - PROCMNG_TASK_ID_MIN タスクID最小値
227 * - PROCMNG_TASK_ID_MAX タスクID最大値
231 /******************************************************************************/
232 ProcMngTaskContext_t ProcMngTaskGetContext( uint32_t taskId )
235 return gTaskTbl[ taskId ].context;
239 /******************************************************************************/
241 * @brief カーネルスタックアドレス取得
242 * @details 指定したタスクIDのカーネルスタックアドレスを取得する。
244 * @param[in] taskId タスクID
245 * - PROCMNG_TASK_ID_MIN タスクID最小値
246 * - PROCMNG_TASK_ID_MAX タスクID最大値
248 * @return カーネルスタックアドレス
250 /******************************************************************************/
251 void *ProcMngTaskGetKernelStack( uint32_t taskId )
254 return gTaskTbl[ taskId ].kernelStackInfo.pBottomAddr;
258 /******************************************************************************/
260 * @brief ページディレクトリID取得
261 * @details 指定したタスクIDのページディレクトリIDを取得する。
263 * @param[in] taskId タスクID
264 * - PROCMNG_TASK_ID_MIN タスクID最小値
265 * - PROCMNG_TASK_ID_MAX タスクID最大値
267 * @return ページディレクトリID
269 /******************************************************************************/
270 uint32_t ProcMngTaskGetPageDirId( uint32_t taskId )
273 return gTaskTbl[ taskId ].pageDirId;
277 /******************************************************************************/
280 * @details 指定したタスクIDのタスクタイプを取得する。
282 * @param[in] taskId タスクID
283 * - PROCMNG_TASK_ID_MIN タスクID最小値
284 * - PROCMNG_TASK_ID_MAX タスクID最大値
286 * @retval PROCMNG_TASK_TYPE_DRIVER ドライバ
287 * @retval PROCMNG_TASK_TYPE_SERVER サーバ
288 * @retval PROCMNG_TASK_TYPE_USER ユーザ
290 /******************************************************************************/
291 uint8_t ProcMngTaskGetType( uint32_t taskId )
294 return gTaskTbl[ taskId ].type;
298 /******************************************************************************/
301 * @details タスク管理サブモジュールの初期化を行う。
303 /******************************************************************************/
304 void ProcMngTaskInit( void )
307 DEBUG_LOG( "%s() start.", __func__ );
310 memset( gTaskTbl, 0, sizeof ( gTaskTbl ) );
313 gTaskTbl[ PROCMNG_TASK_ID_IDLE ].used = TASK_ID_USED;
314 gTaskTbl[ PROCMNG_TASK_ID_IDLE ].pageDirId = MEMMNG_PAGE_DIR_ID_IDLE;
317 DEBUG_LOG( "%s() end.", __func__ );
323 /******************************************************************************/
326 * @details 指定したタスクIDのコンテキストを設定する。
328 * @param[in] taskId 設定先タスクID
329 * - PROCMNG_TASK_ID_MIN タスクID最小値
330 * - PROCMNG_TASK_ID_MAX タスクID最大値
331 * @param[in] *pContext コンテキスト
333 /******************************************************************************/
334 void ProcMngTaskSetContext( uint32_t taskId,
335 ProcMngTaskContext_t *pContext )
338 gTaskTbl[ taskId ].context = *pContext;
344 /******************************************************************************/
347 * @details タスクの起動を開始する。
349 /******************************************************************************/
350 void ProcMngTaskStart( void )
352 void *pEntryPoint; /* エントリポイント */
353 void *pStack; /* スタックアドレス */
354 uint8_t taskType; /* タスクタイプ */
355 uint32_t taskId; /* タスクID */
356 uint32_t codeSegSel; /* コードセグメントセレクタ */
357 uint32_t dataSegSel; /* データセグメントセレクタ */
358 taskTbl_t *pTask; /* タスク管理情報 */
361 DEBUG_LOG( "%s() start.", __func__ );
364 taskId = ProcMngSchedGetTaskId(); /* タスクID */
365 pTask = &( gTaskTbl[ taskId ] ); /* タスク管理情報 */
366 pEntryPoint = pTask->pEntryPoint; /* エントリポイント */
367 pStack = pTask->stackInfo.pBottomAddr; /* スタックアドレス */
368 taskType = pTask->type; /* タスクタイプ */
371 DEBUG_LOG( "taskId=%d, pEntryPoint=%p, pStack=%p",
377 if ( taskType == PROCMNG_TASK_TYPE_DRIVER ) {
381 codeSegSel = MEMMNG_SEGSEL_DRIVER_CODE; /* コード */
382 dataSegSel = MEMMNG_SEGSEL_DRIVER_DATA; /* データ */
384 } else if ( taskType == PROCMNG_TASK_TYPE_SERVER ) {
387 codeSegSel = MEMMNG_SEGSEL_SERVER_CODE; /* コード */
388 dataSegSel = MEMMNG_SEGSEL_SERVER_DATA; /* データ */
393 codeSegSel = MEMMNG_SEGSEL_USER_CODE; /* コード */
394 dataSegSel = MEMMNG_SEGSEL_USER_DATA; /* データ */
398 IA32InstructionPush( dataSegSel ); /* ss */
399 IA32InstructionPush( ( uint32_t ) pStack ); /* esp */
400 IA32InstructionPush( 0x00003202 ); /* eflags */
401 IA32InstructionPush( codeSegSel ); /* cs */
402 IA32InstructionPush( ( uint32_t ) pEntryPoint );/* eip */
404 /* セグメントレジスタ設定用スタック設定 */
405 IA32InstructionPush( dataSegSel ); /* gs */
406 IA32InstructionPush( dataSegSel ); /* fs */
407 IA32InstructionPush( dataSegSel ); /* es */
408 IA32InstructionPush( dataSegSel ); /* ds */
410 /* 汎用レジスタ設定用スタック設定 */
411 IA32InstructionPush( 0 ); /* eax */
412 IA32InstructionPush( 0 ); /* ecx */
413 IA32InstructionPush( 0 ); /* edx */
414 IA32InstructionPush( 0 ); /* ebx */
415 IA32InstructionPush( 0 ); /* esp( 未使用 ) */
416 IA32InstructionPush( 0 ); /* ebp */
417 IA32InstructionPush( 0 ); /* esi */
418 IA32InstructionPush( 0 ); /* edi */
421 IA32InstructionPopad();
424 IA32InstructionPopDs();
425 IA32InstructionPopEs();
426 IA32InstructionPopFs();
427 IA32InstructionPopGs();
430 IA32InstructionIretd();
436 /******************************************************************************/