OSDN Git Service

e5b7e36cf28e65e43edf408911c7f35ecf536499
[mochi/master.git] / src / kernel / ProcMng / ProcMngTask.c
1 /******************************************************************************/
2 /* src/kernel/ProcMng/ProcMngTask.c                                           */
3 /*                                                                 2017/04/16 */
4 /* Copyright (C) 2017 Mochi.                                                  */
5 /******************************************************************************/
6 /******************************************************************************/
7 /* インクルード                                                               */
8 /******************************************************************************/
9 /* 共通ヘッダ */
10 #include <stdarg.h>
11 #include <stdint.h>
12 #include <string.h>
13 #include <hardware/IA32/IA32Instruction.h>
14
15 /* 外部モジュールヘッダ */
16 #include <Cmn.h>
17 #include <Debug.h>
18 #include <MemMng.h>
19 #include <ProcMng.h>
20
21 /* 内部モジュールヘッダ */
22 #include "ProcMngSched.h"
23 #include "ProcMngTask.h"
24 #include "ProcMngTss.h"
25
26
27 /******************************************************************************/
28 /* 定義                                                                       */
29 /******************************************************************************/
30 /* デバッグトレースログ出力マクロ */
31 #ifdef DEBUG_LOG_ENABLE
32 #define DEBUG_LOG( ... )                        \
33     DebugLogOutput( CMN_MODULE_PROCMNG_TASK,    \
34                     __LINE__,                   \
35                     __VA_ARGS__ )
36 #else
37 #define DEBUG_LOG( ... )
38 #endif
39
40 /* タスクID使用フラグ */
41 #define TASK_ID_UNUSED ( 0 )    /** 未使用 */
42 #define TASK_ID_USED   ( 1 )    /** 使用済 */
43
44 /* スタックサイズ */
45 #define TASK_KERNEL_STACK_SIZE ( 1024000 )  /**< カーネルスタックサイズ */
46 #define TASK_STACK_SIZE        ( 1024000 )  /**< スタックサイズ         */
47
48 /** タスクスタック情報 */
49 typedef struct {
50     void   *pTopAddr;       /**< 先頭アドレス */
51     void   *pBottomAddr;    /**< 後尾アドレス */
52     size_t size;            /**< サイズ       */
53 } taskStackInfo_t;
54
55 /** タスク管理テーブル構造体 */
56 typedef struct {
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;         /**< スタックアドレス         */
66 } taskTbl_t;
67
68
69 /******************************************************************************/
70 /* 変数定義                                                                   */
71 /******************************************************************************/
72 /** タスク管理テーブル */
73 static taskTbl_t gTaskTbl[ PROCMNG_TASK_ID_NUM ];
74
75
76 /******************************************************************************/
77 /* グローバル関数定義                                                         */
78 /******************************************************************************/
79 /******************************************************************************/
80 /**
81  * @brief       タスク追加
82  * @details     タスク追加を行う。
83  * 
84  * @param[in]   taskType     タスクタイプ
85  *                  - PROCMNG_TASK_TYPE_DRIVER ドライバ
86  *                  - PROCMNG_TASK_TYPE_SERVER サーバ
87  *                  - PROCMNG_TASK_TYPE_USER   ユーザ
88  * @param[in]   *pEntryPoint エントリポイント
89  * 
90  * @retval      PROCMNG_TASK_ID_NULL 失敗
91  * @retval      PROCMNG_TASK_ID_MIN  タスクID最小値
92  * @retval      PROCMNG_TASK_ID_MAX  タスクID最大値
93  */
94 /******************************************************************************/
95 uint32_t ProcMngTaskAdd( uint8_t taskType,
96                          void    *pEntryPoint )
97 {
98     void            *pKernelStack;  /* カーネルスタック     */
99     void            *pStack;        /* スタック             */
100     int32_t         ret;            /* 関数戻り値           */
101     uint32_t        taskId;         /* タスクID             */
102     uint32_t        pageDirId;      /* ページディレクトリID */
103     taskStackInfo_t *pStackInfo;    /* スタック情報         */
104     
105     /* 初期化 */
106     pKernelStack = NULL;
107     pStack       = NULL;
108     ret          = CMN_FAILURE;
109     taskId       = PROCMNG_TASK_ID_MIN;
110     pageDirId    = MEMMNG_PAGE_DIR_FULL;
111     pStackInfo   = NULL;
112     
113     /* デバッグトレースログ出力 */
114     DEBUG_LOG( "%s() start. taskType=%u, pEntryPoint=%010p",
115                __func__,
116                taskType,
117                pEntryPoint );
118     
119     /* 空タスク検索 */
120     for ( ; taskId < PROCMNG_TASK_ID_MAX; taskId++ ) {
121         /* 使用フラグ判定 */
122         if ( gTaskTbl[ taskId ].used == TASK_ID_UNUSED ) {
123             /* 未使用 */
124             
125             /* ページディレクトリ割当 */
126             pageDirId = MemMngPageAllocDir();
127             
128             /* ページディレクトリ割当結果判定 */
129             if ( pageDirId == MEMMNG_PAGE_DIR_FULL ) {
130                 /* 失敗 */
131                 
132                 /* [TODO] */
133                 /* 設定したタスクを初期化する処理。異常処理はちょっと後回し */
134                 
135                 return PROCMNG_TASK_ID_NULL;
136             }
137             
138             /* カーネルスタック領域割り当て */
139             pKernelStack = MemMngAreaAlloc( TASK_KERNEL_STACK_SIZE );
140             
141             /* スタック領域割り当て */
142             pStack = MemMngAreaAlloc( TASK_STACK_SIZE );
143             
144             /* 割り当て結果判定 */
145             if ( ( pKernelStack == NULL ) ||
146                  ( pStack       == NULL )    ) {
147                 /* 失敗 */
148                 
149                 /* [TODO] */
150                 /* 設定したタスクを初期化する処理。異常処理はちょっと後回し */
151                 
152                 return PROCMNG_TASK_ID_NULL;
153             }
154             
155             /* ページマッピング(仮) */
156             MemMngPageMap( pageDirId,
157                            pKernelStack,
158                            pKernelStack,
159                            TASK_KERNEL_STACK_SIZE,
160                            IA32_PAGING_G_NO,
161                            IA32_PAGING_US_SV,
162                            IA32_PAGING_RW_RW       );
163             MemMngPageMap( pageDirId,
164                            pStack,
165                            pStack,
166                            TASK_STACK_SIZE,
167                            IA32_PAGING_G_NO,
168                            IA32_PAGING_US_USER,
169                            IA32_PAGING_RW_RW    );
170             
171             /* タスク基本設定 */
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;
180             
181             /* カーネルスタック情報設定 */
182             pStackInfo              = &( gTaskTbl[ taskId ].kernelStackInfo );
183             pStackInfo->pTopAddr    = pKernelStack;
184             pStackInfo->pBottomAddr = pKernelStack + TASK_KERNEL_STACK_SIZE;
185             pStackInfo->size        = TASK_KERNEL_STACK_SIZE;
186             
187             /* スタック情報設定 */
188             pStackInfo              = &( gTaskTbl[ taskId ].stackInfo );
189             pStackInfo->pTopAddr    = pStack;
190             pStackInfo->pBottomAddr = pStack + TASK_STACK_SIZE;
191             pStackInfo->size        = TASK_STACK_SIZE;
192             
193             /* スケジューラ追加 */
194             ret = ProcMngSchedAdd( taskId );
195             
196             /* 追加結果判定 */
197             if ( ret == CMN_FAILURE ) {
198                 /* 失敗 */
199                 
200                 /* [TODO] */
201                 /* 設定したタスクを初期化する処理。異常処理はちょっと後回し */
202                 
203                 return PROCMNG_TASK_ID_NULL;
204             }
205             
206             /* デバッグトレースログ出力 */
207             DEBUG_LOG( "%s() end. ret=%u", __func__, taskId );
208             
209             return taskId;
210         }
211     }
212     
213     /* デバッグトレースログ出力 */
214     DEBUG_LOG( "%s() end. ret=%u", __func__, PROCMNG_TASK_ID_NULL );
215     
216     return PROCMNG_TASK_ID_NULL;
217 }
218
219
220 /******************************************************************************/
221 /**
222  * @brief       コンテキスト取得
223  * @details     指定したタスクIDのコンテキストを取得する。
224  * 
225  * @param[in]   taskId タスクID
226  *                  - PROCMNG_TASK_ID_MIN タスクID最小値
227  *                  - PROCMNG_TASK_ID_MAX タスクID最大値
228  * 
229  * @return      コンテキスト
230  */
231 /******************************************************************************/
232 ProcMngTaskContext_t ProcMngTaskGetContext( uint32_t taskId )
233 {
234     /* コンテキスト返却 */
235     return gTaskTbl[ taskId ].context;
236 }
237
238
239 /******************************************************************************/
240 /**
241  * @brief       カーネルスタックアドレス取得
242  * @details     指定したタスクIDのカーネルスタックアドレスを取得する。
243  * 
244  * @param[in]   taskId タスクID
245  *                  - PROCMNG_TASK_ID_MIN タスクID最小値
246  *                  - PROCMNG_TASK_ID_MAX タスクID最大値
247  * 
248  * @return      カーネルスタックアドレス
249  */
250 /******************************************************************************/
251 void *ProcMngTaskGetKernelStack( uint32_t taskId )
252 {
253     /* カーネルスタックアドレス返却 */
254     return gTaskTbl[ taskId ].kernelStackInfo.pBottomAddr;
255 }
256
257
258 /******************************************************************************/
259 /**
260  * @brief       ページディレクトリID取得
261  * @details     指定したタスクIDのページディレクトリIDを取得する。
262  * 
263  * @param[in]   taskId タスクID
264  *                  - PROCMNG_TASK_ID_MIN タスクID最小値
265  *                  - PROCMNG_TASK_ID_MAX タスクID最大値
266  * 
267  * @return      ページディレクトリID
268  */
269 /******************************************************************************/
270 uint32_t ProcMngTaskGetPageDirId( uint32_t taskId )
271 {
272     /* ページディレクトリID返却 */
273     return gTaskTbl[ taskId ].pageDirId;
274 }
275
276
277 /******************************************************************************/
278 /**
279  * @brief       タスクタイプ取得
280  * @details     指定したタスクIDのタスクタイプを取得する。
281  * 
282  * @param[in]   taskId タスクID
283  *                  - PROCMNG_TASK_ID_MIN タスクID最小値
284  *                  - PROCMNG_TASK_ID_MAX タスクID最大値
285  * 
286  * @retval      PROCMNG_TASK_TYPE_DRIVER ドライバ
287  * @retval      PROCMNG_TASK_TYPE_SERVER サーバ
288  * @retval      PROCMNG_TASK_TYPE_USER   ユーザ
289  */
290 /******************************************************************************/
291 uint8_t ProcMngTaskGetType( uint32_t taskId )
292 {
293     /* タスクタイプ返却 */
294     return gTaskTbl[ taskId ].type;
295 }
296
297
298 /******************************************************************************/
299 /**
300  * @brief       タスク管理初期化
301  * @details     タスク管理サブモジュールの初期化を行う。
302  */
303 /******************************************************************************/
304 void ProcMngTaskInit( void )
305 {
306     /* デバッグトレースログ出力 */
307     DEBUG_LOG( "%s() start.", __func__ );
308     
309     /* タスク管理テーブル初期化 */
310     memset( gTaskTbl, 0, sizeof ( gTaskTbl ) );
311     
312     /* アイドルタスク設定 */
313     gTaskTbl[ PROCMNG_TASK_ID_IDLE ].used      = TASK_ID_USED;
314     gTaskTbl[ PROCMNG_TASK_ID_IDLE ].pageDirId = MEMMNG_PAGE_DIR_ID_IDLE;
315     
316     /* デバッグトレースログ出力 */
317     DEBUG_LOG( "%s() end.", __func__ );
318     
319     return;
320 }
321
322
323 /******************************************************************************/
324 /**
325  * @brief       コンテキスト設定
326  * @details     指定したタスクIDのコンテキストを設定する。
327  * 
328  * @param[in]   taskId    設定先タスクID
329  *                  - PROCMNG_TASK_ID_MIN タスクID最小値
330  *                  - PROCMNG_TASK_ID_MAX タスクID最大値
331  * @param[in]   *pContext コンテキスト
332  */
333 /******************************************************************************/
334 void ProcMngTaskSetContext( uint32_t             taskId,
335                             ProcMngTaskContext_t *pContext )
336 {
337     /* コンテキスト設定 */
338     gTaskTbl[ taskId ].context = *pContext;
339     
340     return;
341 }
342
343
344 /******************************************************************************/
345 /**
346  * @brief       タスク起動開始
347  * @details     タスクの起動を開始する。
348  */
349 /******************************************************************************/
350 void ProcMngTaskStart( void )
351 {
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;       /* タスク管理情報           */
359     
360     /* デバッグトレースログ出力 */
361     DEBUG_LOG( "%s() start.", __func__ );
362     
363     /* 初期化 */
364     taskId      = ProcMngSchedGetTaskId();      /* タスクID         */
365     pTask       = &( gTaskTbl[ taskId ] );      /* タスク管理情報   */
366     pEntryPoint = pTask->pEntryPoint;           /* エントリポイント */
367     pStack      = pTask->stackInfo.pBottomAddr; /* スタックアドレス */
368     taskType    = pTask->type;                  /* タスクタイプ     */
369     
370     /* デバッグトレースログ出力 */
371     DEBUG_LOG( "taskId=%d, pEntryPoint=%p, pStack=%p",
372                taskId,
373                pEntryPoint,
374                pStack );
375     
376     /* タスクタイプ判定 */
377     if ( taskType == PROCMNG_TASK_TYPE_DRIVER ) {
378         /* ドライバ */
379         
380         /* セグメントセレクタ設定 */
381         codeSegSel = MEMMNG_SEGSEL_DRIVER_CODE;     /* コード */
382         dataSegSel = MEMMNG_SEGSEL_DRIVER_DATA;     /* データ */
383         
384     } else if ( taskType == PROCMNG_TASK_TYPE_SERVER ) {
385         /* サーバ */
386         
387         codeSegSel = MEMMNG_SEGSEL_SERVER_CODE;     /* コード */
388         dataSegSel = MEMMNG_SEGSEL_SERVER_DATA;     /* データ */
389         
390     } else {
391         /* ユーザ */
392         
393         codeSegSel = MEMMNG_SEGSEL_USER_CODE;       /* コード */
394         dataSegSel = MEMMNG_SEGSEL_USER_DATA;       /* データ */
395     }
396     
397     /* iretd命令用スタック設定 */
398     IA32InstructionPush( dataSegSel );              /* ss     */
399     IA32InstructionPush( ( uint32_t ) pStack );     /* esp    */
400     IA32InstructionPush( 0x00003202 );              /* eflags */
401     IA32InstructionPush( codeSegSel );              /* cs     */
402     IA32InstructionPush( ( uint32_t ) pEntryPoint );/* eip    */
403     
404     /* セグメントレジスタ設定用スタック設定 */
405     IA32InstructionPush( dataSegSel );              /* gs */
406     IA32InstructionPush( dataSegSel );              /* fs */
407     IA32InstructionPush( dataSegSel );              /* es */
408     IA32InstructionPush( dataSegSel );              /* ds */
409     
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           */
419     
420     /* 汎用レジスタ設定 */
421     IA32InstructionPopad();
422     
423     /* セグメントレジスタ設定 */
424     IA32InstructionPopDs();
425     IA32InstructionPopEs();
426     IA32InstructionPopFs();
427     IA32InstructionPopGs();
428     
429     /* タスクエントリポイントへ移行 */
430     IA32InstructionIretd();
431     
432     /* not return */
433 }
434
435
436 /******************************************************************************/