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 void *pEntryPoint; /**< エントリポイント */
63 taskStackInfo_t kernelStackInfo; /**< カーネルスタックアドレス */
64 taskStackInfo_t stackInfo; /**< スタックアドレス */
68 /******************************************************************************/
70 /******************************************************************************/
72 static taskTbl_t gTaskTbl[ PROCMNG_TASK_ID_NUM ];
75 /******************************************************************************/
77 /******************************************************************************/
78 /******************************************************************************/
83 * @param[in] taskType タスクタイプ
84 * - PROCMNG_TASK_TYPE_DRIVER ドライバ
85 * - PROCMNG_TASK_TYPE_SERVER サーバ
86 * - PROCMNG_TASK_TYPE_USER ユーザ
87 * @param[in] *pEntryPoint エントリポイント
89 * @retval PROCMNG_TASK_ID_NULL 失敗
90 * @retval PROCMNG_TASK_ID_MIN タスクID最小値
91 * @retval PROCMNG_TASK_ID_MAX タスクID最大値
93 /******************************************************************************/
94 uint32_t ProcMngTaskAdd( uint8_t taskType,
97 void *pKernelStack; /* カーネルスタック */
98 void *pStack; /* スタック */
99 int32_t ret; /* 関数戻り値 */
100 uint32_t taskId; /* タスクID */
101 taskStackInfo_t *pStackInfo; /* スタック情報 */
107 taskId = PROCMNG_TASK_ID_MIN;
111 DEBUG_LOG( "%s() start. taskType=%u, pEntryPoint=%010p",
117 for ( ; taskId < PROCMNG_TASK_ID_MAX; taskId++ ) {
119 if ( gTaskTbl[ taskId ].used == TASK_ID_UNUSED ) {
123 pKernelStack = MemMngAreaAlloc( TASK_KERNEL_STACK_SIZE );
126 pStack = MemMngAreaAlloc( TASK_STACK_SIZE );
129 if ( ( pKernelStack == NULL ) ||
130 ( pStack == NULL ) ) {
134 /* 設定したタスクを初期化する処理。異常処理はちょっと後回し */
136 return PROCMNG_TASK_ID_NULL;
140 gTaskTbl[ taskId ].used = TASK_ID_USED;
141 gTaskTbl[ taskId ].type = taskType;
142 gTaskTbl[ taskId ].state = 0;
143 gTaskTbl[ taskId ].context.eip = ( uint32_t ) ProcMngTaskStart;
144 gTaskTbl[ taskId ].context.esp = ( uint32_t ) pKernelStack + TASK_KERNEL_STACK_SIZE;
145 gTaskTbl[ taskId ].pEntryPoint = pEntryPoint;
148 pStackInfo = &( gTaskTbl[ taskId ].kernelStackInfo );
149 pStackInfo->pTopAddr = pKernelStack;
150 pStackInfo->pBottomAddr = pKernelStack + TASK_KERNEL_STACK_SIZE;
151 pStackInfo->size = TASK_KERNEL_STACK_SIZE;
154 pStackInfo = &( gTaskTbl[ taskId ].stackInfo );
155 pStackInfo->pTopAddr = pStack;
156 pStackInfo->pBottomAddr = pStack + TASK_STACK_SIZE;
157 pStackInfo->size = TASK_STACK_SIZE;
160 ret = ProcMngSchedAdd( taskId );
163 if ( ret == CMN_FAILURE ) {
167 /* 設定したタスクを初期化する処理。異常処理はちょっと後回し */
169 return PROCMNG_TASK_ID_NULL;
173 DEBUG_LOG( "%s() end. ret=%u", __func__, taskId );
180 DEBUG_LOG( "%s() end. ret=%u", __func__, PROCMNG_TASK_ID_NULL );
182 return PROCMNG_TASK_ID_NULL;
186 /******************************************************************************/
189 * @details 指定したタスクIDのコンテキストを取得する。
191 * @param[in] taskId タスクID
192 * - PROCMNG_TASK_ID_MIN タスクID最小値
193 * - PROCMNG_TASK_ID_MAX タスクID最大値
197 /******************************************************************************/
198 ProcMngTaskContext_t ProcMngTaskGetContext( uint32_t taskId )
201 return gTaskTbl[ taskId ].context;
205 /******************************************************************************/
207 * @brief カーネルスタックアドレス取得
208 * @details 指定したタスクIDのカーネルスタックアドレスを取得する。
210 * @param[in] taskId タスクID
211 * - PROCMNG_TASK_ID_MIN タスクID最小値
212 * - PROCMNG_TASK_ID_MAX タスクID最大値
214 * @return カーネルスタックアドレス
216 /******************************************************************************/
217 void *ProcMngTaskGetKernelStack( uint32_t taskId )
220 return gTaskTbl[ taskId ].kernelStackInfo.pBottomAddr;
224 /******************************************************************************/
227 * @details 指定したタスクIDのタスクタイプを取得する。
229 * @param[in] taskId タスクID
230 * - PROCMNG_TASK_ID_MIN タスクID最小値
231 * - PROCMNG_TASK_ID_MAX タスクID最大値
233 * @retval PROCMNG_TASK_TYPE_DRIVER ドライバ
234 * @retval PROCMNG_TASK_TYPE_SERVER サーバ
235 * @retval PROCMNG_TASK_TYPE_USER ユーザ
237 /******************************************************************************/
238 uint8_t ProcMngTaskGetType( uint32_t taskId )
241 return gTaskTbl[ taskId ].type;
245 /******************************************************************************/
248 * @details タスク管理サブモジュールの初期化を行う。
250 /******************************************************************************/
251 void ProcMngTaskInit( void )
254 DEBUG_LOG( "%s() start.", __func__ );
257 memset( gTaskTbl, 0, sizeof ( gTaskTbl ) );
260 gTaskTbl[ PROCMNG_TASK_ID_IDLE ].used = TASK_ID_USED; /* 使用フラグ */
263 DEBUG_LOG( "%s() end.", __func__ );
269 /******************************************************************************/
272 * @details 指定したタスクIDのコンテキストを設定する。
274 * @param[in] taskId 設定先タスクID
275 * - PROCMNG_TASK_ID_MIN タスクID最小値
276 * - PROCMNG_TASK_ID_MAX タスクID最大値
277 * @param[in] *pContext コンテキスト
279 /******************************************************************************/
280 void ProcMngTaskSetContext( uint32_t taskId,
281 ProcMngTaskContext_t *pContext )
284 gTaskTbl[ taskId ].context = *pContext;
290 /******************************************************************************/
293 * @details タスクの起動を開始する。
295 /******************************************************************************/
296 void ProcMngTaskStart( void )
298 void *pEntryPoint; /* エントリポイント */
299 void *pStack; /* スタックアドレス */
300 uint8_t taskType; /* タスクタイプ */
301 uint32_t taskId; /* タスクID */
302 uint32_t codeSegSel; /* コードセグメントセレクタ */
303 uint32_t dataSegSel; /* データセグメントセレクタ */
304 taskTbl_t *pTask; /* タスク管理情報 */
307 DEBUG_LOG( "%s() start.", __func__ );
310 taskId = ProcMngSchedGetTaskId(); /* タスクID */
311 pTask = &( gTaskTbl[ taskId ] ); /* タスク管理情報 */
312 pEntryPoint = pTask->pEntryPoint; /* エントリポイント */
313 pStack = pTask->stackInfo.pBottomAddr; /* スタックアドレス */
314 taskType = pTask->type; /* タスクタイプ */
317 DEBUG_LOG( "taskId=%d, pEntryPoint=%p, pStack=%p",
323 if ( taskType == PROCMNG_TASK_TYPE_DRIVER ) {
327 codeSegSel = MEMMNG_SEGSEL_DRIVER_CODE; /* コード */
328 dataSegSel = MEMMNG_SEGSEL_DRIVER_DATA; /* データ */
330 } else if ( taskType == PROCMNG_TASK_TYPE_SERVER ) {
333 codeSegSel = MEMMNG_SEGSEL_SERVER_CODE; /* コード */
334 dataSegSel = MEMMNG_SEGSEL_SERVER_DATA; /* データ */
339 codeSegSel = MEMMNG_SEGSEL_USER_CODE; /* コード */
340 dataSegSel = MEMMNG_SEGSEL_USER_DATA; /* データ */
344 IA32InstructionPush( dataSegSel ); /* ss */
345 IA32InstructionPush( ( uint32_t ) pStack ); /* esp */
346 IA32InstructionPush( 0x00003202 ); /* eflags */
347 IA32InstructionPush( codeSegSel ); /* cs */
348 IA32InstructionPush( ( uint32_t ) pEntryPoint );/* eip */
350 /* セグメントレジスタ設定用スタック設定 */
351 IA32InstructionPush( dataSegSel ); /* gs */
352 IA32InstructionPush( dataSegSel ); /* fs */
353 IA32InstructionPush( dataSegSel ); /* es */
354 IA32InstructionPush( dataSegSel ); /* ds */
356 /* 汎用レジスタ設定用スタック設定 */
357 IA32InstructionPush( 0 ); /* eax */
358 IA32InstructionPush( 0 ); /* ecx */
359 IA32InstructionPush( 0 ); /* edx */
360 IA32InstructionPush( 0 ); /* ebx */
361 IA32InstructionPush( 0 ); /* esp( 未使用 ) */
362 IA32InstructionPush( 0 ); /* ebp */
363 IA32InstructionPush( 0 ); /* esi */
364 IA32InstructionPush( 0 ); /* edi */
367 IA32InstructionPopad();
370 IA32InstructionPopDs();
371 IA32InstructionPopEs();
372 IA32InstructionPopFs();
373 IA32InstructionPopGs();
376 IA32InstructionIretd();
382 /******************************************************************************/