comparison driver/interrupt.c @ 0:42f240cc4bc6

From: 太田 篤志 <atoc@namikilab.tuat.ac.jp>
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Tue, 08 Sep 2009 13:44:18 +0900
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:42f240cc4bc6
1 /**
2 * interrupt.c
3 * SPE プロセスマネージャ spe_manager
4 * 割り込みハンドラ
5 */
6
7 #include <linux/module.h> // カーネルモジュール全般
8 #include <linux/kernel.h> // printk
9 #include <linux/slab.h> // kmalloc, kfree
10 #include <linux/interrupt.h> // request_irq, free_irq
11 #include <asm/ps3.h> // ps3_irq_plug_setup, ps3_irq_plug_destroy
12 #include <asm/io.h> // ioremap, iounmap, in_xx, out_xx
13
14 #include <asm/pgtable-ppc64.h> // 暫定
15 #include <asm/mmu-hash64.h> // 暫定
16
17 #include "../include/hvcalls/spe.h"
18 #include "interrupt.h"
19 #include "lspe.h"
20 #include "main.h"
21 #include "critical.h"
22 #include "process_list.h"
23
24
25
26
27
28
29
30
31 //================================================================================================== interrupt_handler()
32 /**
33 * interrupt_handler
34 * 割り込みハンドラ
35 *
36 * @param int irq
37 * @param void * dev_id
38 * @return irqreturn_t
39 */
40 irqreturn_t interrupt_handler(int irq, void *dev_id)
41 {
42 int i, lspe_count = get_lspe_count();
43 unsigned long int_stat;
44
45
46 for (i = 0; i < lspe_count; i++)
47 {
48 lspe_data_t *lspe = get_lspe_data(i);
49 if (lspe == NULL) continue;
50
51 if (lspe->virq[0] == (unsigned int)irq)
52 {
53 /**
54 * クラス 0 割り込み
55 * (エラー)
56 */
57
58 // 割り込みステータスを取得
59 hvc_get_spe_int_stat(lspe->spe_id, 0, &int_stat);
60 int_stat &= spe_int_mask[0];
61 printk(KERN_INFO "[%s] INT_Stat_class0 = 0x%016lx\n", SPE_MANAGER_MODULE_NAME, int_stat);
62
63
64 /*
65 * とりあえず今はやることなし
66 */
67
68
69 // 割り込みステータスをクリア
70 hvc_clear_spe_int_stat(lspe->spe_id, 0, int_stat);
71 break;
72 }
73
74 if (lspe->virq[1] == (unsigned int)irq)
75 {
76 /**
77 * クラス 1 割り込み
78 * (変換)
79 */
80 unsigned long mfc_dsisr, mfc_dar;
81
82 // 割り込みステータスを取得
83 hvc_get_spe_int_stat(lspe->spe_id, 1, &int_stat);
84 int_stat &= spe_int_mask[1];
85 // printk(KERN_INFO "[%s] INT_Stat_class1 = 0x%016lx\n", SPE_MANAGER_MODULE_NAME, int_stat);
86
87
88 // MFC データ・ストレージ割り込みステータス・レジスタおよび
89 // MFC データ・アドレス・レジスタの値を取得
90 mfc_dsisr = in_be64(lspe->shadow + 0x0610 /*MFC_DSISR*/);
91 mfc_dar = in_be64(lspe->shadow + 0x0620 /*MFC_DAR*/);
92 // printk(KERN_INFO " MFC_DSISR = 0x%016lx\n", mfc_dsisr);
93 // printk(KERN_INFO " MFC_DAR = 0x%016lx\n", mfc_dar);
94
95
96
97
98
99
100 if (int_stat & 1) // MFC データ・セグメントエラー
101 {
102 unsigned long esid = (mfc_dar & 0xFFFFFFFFF0000000UL) | 0x8000000UL /*[V]*/;
103
104 if (REGION_ID(mfc_dar) == USER_REGION_ID)
105 {
106 unsigned long vsid = get_vsid(lspe->mm->context.id, mfc_dar, MMU_SEGSIZE_256M);
107
108 // vsid を SLB エントリに登録
109 out_be64(lspe->priv2 + 0x01108 /*SLB_Index*/, lspe->slb_index);
110 out_be64(lspe->priv2 + 0x01118 /*SLB_VSID*/, vsid << 12 | 0xc00 /*Ks|Kp*/ | 0x80 /*C*/ | 0x000 /*L|LP*/);
111 out_be64(lspe->priv2 + 0x01110 /*SLB_ESID*/, esid);
112
113 lspe->slb_index++;
114 if (lspe->slb_index >= 8) lspe->slb_index = 2;
115
116 // MFC コマンドの再始動
117 out_be64(lspe->priv2 + 0x03000 /*MFC_Cntl*/, 1UL<<32 /*[R]*/);
118 }
119 }
120
121
122
123
124
125
126
127
128
129 #if 0
130 // 割り込みステータスをクリア
131 if (int_stat & 2)
132 {
133 lv1_set_spe_privilege_state_area_1_register(lspe->spe_id, 0x0610UL /*MFC_DSISR*/, 0UL);
134 }
135 hvc_clear_spe_int_stat(lspe->spe_id, 1, int_stat);
136
137
138 if (int_stat & 2) // MFC データ・ストレージエラー
139 {
140 if (mfc_dsisr & 0x40000000 /*MFC_DSISR[M]*/)
141 {
142 if (REGION_ID(mfc_dar) != USER_REGION_ID)
143 {
144 int ret = hash_page(mfc_dar, _PAGE_PRESENT, 0x300);
145 // printk(KERN_INFO "hash_page() [kernel side] = %d\n", ret);
146 if (!ret)
147 {
148 // MFC コマンドの再始動
149 out_be64(lspe->priv2 + 0x03000 /*MFC_Cntl*/, 1UL<<32 /*[R]*/);
150 }
151 }
152 }
153 }
154 #endif
155
156
157
158
159
160
161
162
163 // 割り込みステータスをクリア
164 if (int_stat & 2)
165 lv1_set_spe_privilege_state_area_1_register(lspe->spe_id, 0x0610UL /*MFC_DSISR*/, 0UL);
166 hvc_clear_spe_int_stat(lspe->spe_id, 1, int_stat);
167 break;
168 }
169
170 if (lspe->virq[2] == (unsigned int)irq)
171 {
172 /**
173 * クラス 2 割り込み
174 * (アプリケーション)
175 */
176 unsigned int spu_status, spu_npc, spu_stop_code;
177
178 // 割り込みステータスを取得
179 hvc_get_spe_int_stat(lspe->spe_id, 2, &int_stat);
180 int_stat &= spe_int_mask[2];
181 // printk(KERN_INFO "[%s] INT_Stat_class2 = 0x%016lx\n", SPE_MANAGER_MODULE_NAME, int_stat);
182
183
184 // SPU ステータスおよびネクスト・プログラム・カウンタを取得
185 asm volatile("eieio"); // cf. Cell Broadband Engine アーキテクチャ version 1.01 (p.93)
186 spu_status = in_be32(lspe->problem + 0x04024UL /*SPU_Status*/);
187 spu_stop_code = spu_status >> 16;
188 spu_npc = in_be32(lspe->problem + 0x04034UL /*SPU_NPC*/);
189 // printk(KERN_INFO " SPU_Status = 0x%08x\n", spu_status);
190 // printk(KERN_INFO " StopCode = 0x%04x\n", spu_stop_code);
191 // printk(KERN_INFO " SPU_NPC = 0x%08x\n", spu_npc);
192
193
194 if (spu_status & 1<<1 /*[P]*/)
195 {
196 switch (spu_stop_code)
197 {
198 case SPE_PROCESS_STOP_CODE_FINISH:
199 {
200 spe_process_context_list_t *this_process = get_running_process(i), *next_process = NULL;
201 spinlock_t *spinlock_for_process_list = get_spinlock_for_process_list();
202
203
204 // Critical Section (spinlock) >>>
205 spin_lock(spinlock_for_process_list);
206 {
207 next_process = get_next_waiting_process();
208
209 /*
210 unsigned long addr;
211 for (addr = 0x0; addr < 0x0 + 0x60; addr+= 0x10)
212 {
213 printk(KERN_INFO "0x%04lx | %016lx %016lx\n", addr, in_be64(lspe->ls + addr), in_be64(lspe->ls + addr + 8));
214 }
215 */
216
217 // 実行プロセスコンテキストをクリア
218 clear_running_process(i);
219
220 // このプロセスのコンテキストを更新
221 this_process->context.read.status = SPE_PROCESS_CONTEXT_STATUS_NOT_RELEASED;
222 increment_not_released();
223
224 // 実行待ちプロセスがあるか
225 if (next_process != NULL)
226 {
227 // このプロセスを実行中にする
228 remove_process_from_waiting(next_process);
229 // next_process->context.read.spe_no = i;
230 next_process->context.read.status = SPE_PROCESS_CONTEXT_STATUS_RUNNING;
231
232 set_running_process(i, next_process);
233 }
234 }
235 spin_unlock(spinlock_for_process_list);
236 // <<< Critical Section (spinlock)
237
238
239 // SPE プロセス開始
240 if (next_process != NULL) start_spe_process(i, next_process);
241 }
242 }
243 }
244
245 // 割り込みステータスをクリア
246 hvc_clear_spe_int_stat(lspe->spe_id, 2, int_stat);
247 break;
248 }
249 }
250
251 return IRQ_HANDLED;
252 // return int_stat ? IRQ_HANDLED : IRQ_NONE;
253 }