~ubuntu-branches/debian/wheezy/linux-2.6/wheezy

« back to all changes in this revision

Viewing changes to arch/microblaze/kernel/entry.S

  • Committer: Bazaar Package Importer
  • Author(s): Ben Hutchings, Ben Hutchings, Aurelien Jarno, Martin Michlmayr
  • Date: 2011-04-06 13:53:30 UTC
  • mfrom: (43.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20110406135330-wjufxhd0tvn3zx4z
Tags: 2.6.38-3
[ Ben Hutchings ]
* [ppc64] Add to linux-tools package architectures (Closes: #620124)
* [amd64] Save cr4 to mmu_cr4_features at boot time (Closes: #620284)
* appletalk: Fix bugs introduced when removing use of BKL
* ALSA: Fix yet another race in disconnection
* cciss: Fix lost command issue
* ath9k: Fix kernel panic in AR2427
* ses: Avoid kernel panic when lun 0 is not mapped
* PCI/ACPI: Report ASPM support to BIOS if not disabled from command line

[ Aurelien Jarno ]
* rtlwifi: fix build when PCI is not enabled.

[ Martin Michlmayr ]
* rtlwifi: Eliminate udelay calls with too large values (Closes: #620204)

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
#include <linux/errno.h>
32
32
#include <asm/signal.h>
33
33
 
 
34
#undef DEBUG
 
35
 
34
36
/* The size of a state save frame. */
35
37
#define STATE_SAVE_SIZE         (PT_SIZE + STATE_SAVE_ARG_SPACE)
36
38
 
46
48
 */
47
49
#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
48
50
        .macro  clear_bip
49
 
        msrclr  r11, MSR_BIP
50
 
        nop
 
51
        msrclr  r0, MSR_BIP
51
52
        .endm
52
53
 
53
54
        .macro  set_bip
54
 
        msrset  r11, MSR_BIP
55
 
        nop
 
55
        msrset  r0, MSR_BIP
56
56
        .endm
57
57
 
58
58
        .macro  clear_eip
59
 
        msrclr  r11, MSR_EIP
60
 
        nop
 
59
        msrclr  r0, MSR_EIP
61
60
        .endm
62
61
 
63
62
        .macro  set_ee
64
 
        msrset  r11, MSR_EE
65
 
        nop
 
63
        msrset  r0, MSR_EE
66
64
        .endm
67
65
 
68
66
        .macro  disable_irq
69
 
        msrclr  r11, MSR_IE
70
 
        nop
 
67
        msrclr  r0, MSR_IE
71
68
        .endm
72
69
 
73
70
        .macro  enable_irq
74
 
        msrset  r11, MSR_IE
75
 
        nop
 
71
        msrset  r0, MSR_IE
76
72
        .endm
77
73
 
78
74
        .macro  set_ums
79
 
        msrset  r11, MSR_UMS
80
 
        nop
81
 
        msrclr  r11, MSR_VMS
82
 
        nop
 
75
        msrset  r0, MSR_UMS
 
76
        msrclr  r0, MSR_VMS
83
77
        .endm
84
78
 
85
79
        .macro  set_vms
86
 
        msrclr  r11, MSR_UMS
87
 
        nop
88
 
        msrset  r11, MSR_VMS
89
 
        nop
 
80
        msrclr  r0, MSR_UMS
 
81
        msrset  r0, MSR_VMS
 
82
        .endm
 
83
 
 
84
        .macro  clear_ums
 
85
        msrclr  r0, MSR_UMS
90
86
        .endm
91
87
 
92
88
        .macro  clear_vms_ums
93
 
        msrclr  r11, MSR_VMS
94
 
        nop
95
 
        msrclr  r11, MSR_UMS
96
 
        nop
 
89
        msrclr  r0, MSR_VMS | MSR_UMS
97
90
        .endm
98
91
#else
99
92
        .macro  clear_bip
100
93
        mfs     r11, rmsr
101
 
        nop
102
94
        andi    r11, r11, ~MSR_BIP
103
95
        mts     rmsr, r11
104
 
        nop
105
96
        .endm
106
97
 
107
98
        .macro  set_bip
108
99
        mfs     r11, rmsr
109
 
        nop
110
100
        ori     r11, r11, MSR_BIP
111
101
        mts     rmsr, r11
112
 
        nop
113
102
        .endm
114
103
 
115
104
        .macro  clear_eip
116
105
        mfs     r11, rmsr
117
 
        nop
118
106
        andi    r11, r11, ~MSR_EIP
119
107
        mts     rmsr, r11
120
 
        nop
121
108
        .endm
122
109
 
123
110
        .macro  set_ee
124
111
        mfs     r11, rmsr
125
 
        nop
126
112
        ori     r11, r11, MSR_EE
127
113
        mts     rmsr, r11
128
 
        nop
129
114
        .endm
130
115
 
131
116
        .macro  disable_irq
132
117
        mfs     r11, rmsr
133
 
        nop
134
118
        andi    r11, r11, ~MSR_IE
135
119
        mts     rmsr, r11
136
 
        nop
137
120
        .endm
138
121
 
139
122
        .macro  enable_irq
140
123
        mfs     r11, rmsr
141
 
        nop
142
124
        ori     r11, r11, MSR_IE
143
125
        mts     rmsr, r11
144
 
        nop
145
126
        .endm
146
127
 
147
128
        .macro set_ums
148
129
        mfs     r11, rmsr
149
 
        nop
150
130
        ori     r11, r11, MSR_VMS
151
131
        andni   r11, r11, MSR_UMS
152
132
        mts     rmsr, r11
153
 
        nop
154
133
        .endm
155
134
 
156
135
        .macro  set_vms
157
136
        mfs     r11, rmsr
158
 
        nop
159
137
        ori     r11, r11, MSR_VMS
160
138
        andni   r11, r11, MSR_UMS
161
139
        mts     rmsr, r11
162
 
        nop
 
140
        .endm
 
141
 
 
142
        .macro  clear_ums
 
143
        mfs     r11, rmsr
 
144
        andni   r11, r11, MSR_UMS
 
145
        mts     rmsr,r11
163
146
        .endm
164
147
 
165
148
        .macro  clear_vms_ums
166
149
        mfs     r11, rmsr
167
 
        nop
168
150
        andni   r11, r11, (MSR_VMS|MSR_UMS)
169
151
        mts     rmsr,r11
170
 
        nop
171
152
        .endm
172
153
#endif
173
154
 
178
159
 
179
160
/* turn on virtual protected mode save */
180
161
#define VM_ON           \
181
 
        set_ums;                \
 
162
        set_ums;        \
182
163
        rted    r0, 2f; \
183
 
2: nop;
 
164
        nop; \
 
165
2:
184
166
 
185
167
/* turn off virtual protected mode save and user mode save*/
186
168
#define VM_OFF                  \
187
 
        clear_vms_ums;                  \
 
169
        clear_vms_ums;          \
188
170
        rted    r0, TOPHYS(1f); \
189
 
1: nop;
 
171
        nop; \
 
172
1:
190
173
 
191
174
#define SAVE_REGS \
192
175
        swi     r2, r1, PTO+PT_R2;      /* Save SDA */                  \
 
176
        swi     r3, r1, PTO+PT_R3;                                      \
 
177
        swi     r4, r1, PTO+PT_R4;                                      \
193
178
        swi     r5, r1, PTO+PT_R5;                                      \
194
179
        swi     r6, r1, PTO+PT_R6;                                      \
195
180
        swi     r7, r1, PTO+PT_R7;                                      \
201
186
        swi     r13, r1, PTO+PT_R13;    /* Save SDA2 */                 \
202
187
        swi     r14, r1, PTO+PT_PC;     /* PC, before IRQ/trap */       \
203
188
        swi     r15, r1, PTO+PT_R15;    /* Save LP */                   \
 
189
        swi     r16, r1, PTO+PT_R16;                                    \
 
190
        swi     r17, r1, PTO+PT_R17;                                    \
204
191
        swi     r18, r1, PTO+PT_R18;    /* Save asm scratch reg */      \
205
192
        swi     r19, r1, PTO+PT_R19;                                    \
206
193
        swi     r20, r1, PTO+PT_R20;                                    \
216
203
        swi     r30, r1, PTO+PT_R30;                                    \
217
204
        swi     r31, r1, PTO+PT_R31;    /* Save current task reg */     \
218
205
        mfs     r11, rmsr;              /* save MSR */                  \
219
 
        nop;                                                            \
220
206
        swi     r11, r1, PTO+PT_MSR;
221
207
 
222
208
#define RESTORE_REGS \
223
209
        lwi     r11, r1, PTO+PT_MSR;                                    \
224
210
        mts     rmsr , r11;                                             \
225
 
        nop;                                                            \
226
211
        lwi     r2, r1, PTO+PT_R2;      /* restore SDA */               \
 
212
        lwi     r3, r1, PTO+PT_R3;                                      \
 
213
        lwi     r4, r1, PTO+PT_R4;                                      \
227
214
        lwi     r5, r1, PTO+PT_R5;                                      \
228
215
        lwi     r6, r1, PTO+PT_R6;                                      \
229
216
        lwi     r7, r1, PTO+PT_R7;                                      \
235
222
        lwi     r13, r1, PTO+PT_R13;    /* restore SDA2 */              \
236
223
        lwi     r14, r1, PTO+PT_PC;     /* RESTORE_LINK PC, before IRQ/trap */\
237
224
        lwi     r15, r1, PTO+PT_R15;    /* restore LP */                \
 
225
        lwi     r16, r1, PTO+PT_R16;                                    \
 
226
        lwi     r17, r1, PTO+PT_R17;                                    \
238
227
        lwi     r18, r1, PTO+PT_R18;    /* restore asm scratch reg */   \
239
228
        lwi     r19, r1, PTO+PT_R19;                                    \
240
229
        lwi     r20, r1, PTO+PT_R20;                                    \
250
239
        lwi     r30, r1, PTO+PT_R30;                                    \
251
240
        lwi     r31, r1, PTO+PT_R31;    /* Restore cur task reg */
252
241
 
 
242
#define SAVE_STATE      \
 
243
        swi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* save stack */     \
 
244
        /* See if already in kernel mode.*/                             \
 
245
        mfs     r1, rmsr;                                               \
 
246
        andi    r1, r1, MSR_UMS;                                        \
 
247
        bnei    r1, 1f;                                         \
 
248
        /* Kernel-mode state save.  */                                  \
 
249
        /* Reload kernel stack-ptr. */                                  \
 
250
        lwi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP));                      \
 
251
        /* FIXME: I can add these two lines to one */                   \
 
252
        /* tophys(r1,r1); */                                            \
 
253
        /* addik        r1, r1, -STATE_SAVE_SIZE; */                    \
 
254
        addik   r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE; \
 
255
        SAVE_REGS                                                       \
 
256
        brid    2f;                                                     \
 
257
        swi     r1, r1, PTO+PT_MODE;                                    \
 
258
1:      /* User-mode state save.  */                                    \
 
259
        lwi     r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */\
 
260
        tophys(r1,r1);                                                  \
 
261
        lwi     r1, r1, TS_THREAD_INFO; /* get the thread info */       \
 
262
        /* MS these three instructions can be added to one */           \
 
263
        /* addik        r1, r1, THREAD_SIZE; */                         \
 
264
        /* tophys(r1,r1); */                                            \
 
265
        /* addik        r1, r1, -STATE_SAVE_SIZE; */                    \
 
266
        addik r1, r1, THREAD_SIZE + CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE; \
 
267
        SAVE_REGS                                                       \
 
268
        lwi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP));                     \
 
269
        swi     r11, r1, PTO+PT_R1; /* Store user SP.  */               \
 
270
        swi     r0, r1, PTO + PT_MODE; /* Was in user-mode.  */         \
 
271
        /* MS: I am clearing UMS even in case when I come from kernel space */ \
 
272
        clear_ums;                                                      \
 
273
2:      lwi     CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
 
274
 
253
275
.text
254
276
 
255
277
/*
267
289
C_ENTRY(_user_exception):
268
290
        swi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */
269
291
        addi    r14, r14, 4     /* return address is 4 byte after call */
270
 
        swi     r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* Save r11 */
271
 
 
272
 
        lwi     r11, r0, TOPHYS(PER_CPU(KM));/* See if already in kernel mode.*/
273
 
        beqi    r11, 1f;                /* Jump ahead if coming from user */
274
 
/* Kernel-mode state save. */
275
 
        lwi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/
276
 
        tophys(r1,r11);
277
 
        swi     r11, r1, (PT_R1-PT_SIZE); /* Save original SP. */
278
 
        lwi     r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* restore r11 */
 
292
 
 
293
        mfs     r1, rmsr
 
294
        nop
 
295
        andi    r1, r1, MSR_UMS
 
296
        bnei    r1, 1f
 
297
 
 
298
/* Kernel-mode state save - kernel execve */
 
299
        lwi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/
 
300
        tophys(r1,r1);
279
301
 
280
302
        addik   r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */
281
303
        SAVE_REGS
282
304
 
283
 
        addi    r11, r0, 1;             /* Was in kernel-mode. */
284
 
        swi     r11, r1, PTO+PT_MODE; /* pt_regs -> kernel mode */
 
305
        swi     r1, r1, PTO + PT_MODE; /* pt_regs -> kernel mode */
285
306
        brid    2f;
286
307
        nop;                            /* Fill delay slot */
287
308
 
288
309
/* User-mode state save.  */
289
310
1:
290
 
        lwi     r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* restore r11 */
291
311
        lwi     r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */
292
312
        tophys(r1,r1);
293
313
        lwi     r1, r1, TS_THREAD_INFO; /* get stack from task_struct */
297
317
 
298
318
        addik   r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack.  */
299
319
        SAVE_REGS
 
320
        swi     r0, r1, PTO + PT_R3
 
321
        swi     r0, r1, PTO + PT_R4
300
322
 
301
 
        swi     r0, r1, PTO+PT_MODE;                    /* Was in user-mode. */
 
323
        swi     r0, r1, PTO + PT_MODE;                  /* Was in user-mode. */
302
324
        lwi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
303
325
        swi     r11, r1, PTO+PT_R1;             /* Store user SP.  */
304
 
        addi    r11, r0, 1;
305
 
        swi     r11, r0, TOPHYS(PER_CPU(KM));   /* Now we're in kernel-mode.  */
306
 
2:      lwi     r31, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */
 
326
        clear_ums;
 
327
2:      lwi     CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
307
328
        /* Save away the syscall number.  */
308
329
        swi     r12, r1, PTO+PT_R0;
309
330
        tovirt(r1,r1)
314
335
 * register should point to the location where
315
336
 * the called function should return.  [note that MAKE_SYS_CALL uses label 1] */
316
337
 
317
 
        # Step into virtual mode.
318
 
        set_vms;
319
 
        addik   r11, r0, 3f
320
 
        rtid    r11, 0
 
338
        /* Step into virtual mode */
 
339
        rtbd    r0, 3f
321
340
        nop
322
341
3:
323
 
        add     r11, r0, CURRENT_TASK    /* Get current task ptr into r11 */
324
 
        lwi     r11, r11, TS_THREAD_INFO /* get thread info */
 
342
        lwi     r11, CURRENT_TASK, TS_THREAD_INFO /* get thread info */
325
343
        lwi     r11, r11, TI_FLAGS       /* get flags in thread info */
326
344
        andi    r11, r11, _TIF_WORK_SYSCALL_MASK
327
345
        beqi    r11, 4f
352
370
        add     r12, r12, r12;                  /* convert num -> ptr */
353
371
        add     r12, r12, r12;
354
372
 
 
373
#ifdef DEBUG
355
374
        /* Trac syscalls and stored them to r0_ram */
356
375
        lwi     r3, r12, 0x400 + r0_ram
357
376
        addi    r3, r3, 1
358
377
        swi     r3, r12, 0x400 + r0_ram
 
378
#endif
359
379
 
360
380
        # Find and jump into the syscall handler.
361
381
        lwi     r12, r12, sys_call_table
362
382
        /* where the trap should return need -8 to adjust for rtsd r15, 8 */
363
 
        la      r15, r0, ret_from_trap-8
 
383
        addi    r15, r0, ret_from_trap-8
364
384
        bra     r12
365
385
 
366
386
        /* The syscall number is invalid, return an error.  */
367
387
5:
 
388
        rtsd    r15, 8;         /* looks like a normal subroutine return */
368
389
        addi    r3, r0, -ENOSYS;
369
 
        rtsd    r15,8;          /* looks like a normal subroutine return */
370
 
        or      r0, r0, r0
371
 
 
372
390
 
373
391
/* Entry point used to return from a syscall/trap */
374
392
/* We re-enable BIP bit before state restore */
375
393
C_ENTRY(ret_from_trap):
376
 
        set_bip;                        /*  Ints masked for state restore*/
377
 
        lwi     r11, r1, PTO+PT_MODE;
 
394
        swi     r3, r1, PTO + PT_R3
 
395
        swi     r4, r1, PTO + PT_R4
 
396
 
 
397
        lwi     r11, r1, PTO + PT_MODE;
378
398
/* See if returning to kernel mode, if so, skip resched &c.  */
379
399
        bnei    r11, 2f;
380
 
 
381
400
        /* We're returning to user mode, so check for various conditions that
382
401
         * trigger rescheduling. */
383
 
        # FIXME: Restructure all these flag checks.
384
 
        add     r11, r0, CURRENT_TASK;  /* Get current task ptr into r11 */
385
 
        lwi     r11, r11, TS_THREAD_INFO;       /* get thread info */
 
402
        /* FIXME: Restructure all these flag checks. */
 
403
        lwi     r11, CURRENT_TASK, TS_THREAD_INFO;      /* get thread info */
386
404
        lwi     r11, r11, TI_FLAGS;             /* get flags in thread info */
387
405
        andi    r11, r11, _TIF_WORK_SYSCALL_MASK
388
406
        beqi    r11, 1f
389
407
 
390
 
        swi     r3, r1, PTO + PT_R3
391
 
        swi     r4, r1, PTO + PT_R4
392
408
        brlid   r15, do_syscall_trace_leave
393
409
        addik   r5, r1, PTO + PT_R0
394
 
        lwi     r3, r1, PTO + PT_R3
395
 
        lwi     r4, r1, PTO + PT_R4
396
410
1:
397
 
 
398
411
        /* We're returning to user mode, so check for various conditions that
399
412
         * trigger rescheduling. */
400
 
        /* Get current task ptr into r11 */
401
 
        add     r11, r0, CURRENT_TASK;  /* Get current task ptr into r11 */
402
 
        lwi     r11, r11, TS_THREAD_INFO;       /* get thread info */
 
413
        /* get thread info from current task */
 
414
        lwi     r11, CURRENT_TASK, TS_THREAD_INFO;
403
415
        lwi     r11, r11, TI_FLAGS;             /* get flags in thread info */
404
416
        andi    r11, r11, _TIF_NEED_RESCHED;
405
417
        beqi    r11, 5f;
406
418
 
407
 
        swi     r3, r1, PTO + PT_R3; /* store syscall result */
408
 
        swi     r4, r1, PTO + PT_R4;
409
419
        bralid  r15, schedule;  /* Call scheduler */
410
420
        nop;                            /* delay slot */
411
 
        lwi     r3, r1, PTO + PT_R3; /* restore syscall result */
412
 
        lwi     r4, r1, PTO + PT_R4;
413
421
 
414
422
        /* Maybe handle a signal */
415
 
5:      add     r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */
416
 
        lwi     r11, r11, TS_THREAD_INFO;       /* get thread info */
 
423
5:      /* get thread info from current task*/
 
424
        lwi     r11, CURRENT_TASK, TS_THREAD_INFO;
417
425
        lwi     r11, r11, TI_FLAGS;     /* get flags in thread info */
418
426
        andi    r11, r11, _TIF_SIGPENDING;
419
427
        beqi    r11, 1f;                /* Signals to handle, handle them */
420
428
 
421
 
        swi     r3, r1, PTO + PT_R3; /* store syscall result */
422
 
        swi     r4, r1, PTO + PT_R4;
423
 
        la      r5, r1, PTO;            /* Arg 1: struct pt_regs *regs */
424
 
        add     r6, r0, r0;             /* Arg 2: sigset_t *oldset */
 
429
        addik   r5, r1, PTO;            /* Arg 1: struct pt_regs *regs */
425
430
        addi    r7, r0, 1;              /* Arg 3: int in_syscall */
426
431
        bralid  r15, do_signal; /* Handle any signals */
427
 
        nop;
428
 
        lwi     r3, r1, PTO + PT_R3; /* restore syscall result */
429
 
        lwi     r4, r1, PTO + PT_R4;
 
432
        add     r6, r0, r0;             /* Arg 2: sigset_t *oldset */
430
433
 
431
434
/* Finally, return to user state.  */
432
 
1:      swi     r0, r0, PER_CPU(KM);    /* Now officially in user state. */
433
 
        add     r11, r0, CURRENT_TASK;  /* Get current task ptr into r11 */
434
 
        swi     r11, r0, PER_CPU(CURRENT_SAVE); /* save current */
 
435
1:      set_bip;                        /*  Ints masked for state restore */
 
436
        swi     CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
435
437
        VM_OFF;
436
438
        tophys(r1,r1);
437
439
        RESTORE_REGS;
440
442
        bri     6f;
441
443
 
442
444
/* Return to kernel state.  */
443
 
2:      VM_OFF;
 
445
2:      set_bip;                        /*  Ints masked for state restore */
 
446
        VM_OFF;
444
447
        tophys(r1,r1);
445
448
        RESTORE_REGS;
446
449
        addik   r1, r1, STATE_SAVE_SIZE         /* Clean up stack space.  */
457
460
C_ENTRY(sys_fork_wrapper):
458
461
        addi    r5, r0, SIGCHLD                 /* Arg 0: flags */
459
462
        lwi     r6, r1, PTO+PT_R1       /* Arg 1: child SP (use parent's) */
460
 
        la      r7, r1, PTO                     /* Arg 2: parent context */
 
463
        addik   r7, r1, PTO                     /* Arg 2: parent context */
461
464
        add     r8. r0, r0                      /* Arg 3: (unused) */
462
465
        add     r9, r0, r0;                     /* Arg 4: (unused) */
 
466
        brid    do_fork         /* Do real work (tail-call) */
463
467
        add     r10, r0, r0;                    /* Arg 5: (unused) */
464
 
        brid    do_fork         /* Do real work (tail-call) */
465
 
        nop;
466
468
 
467
469
/* This the initial entry point for a new child thread, with an appropriate
468
470
   stack in place that makes it look the the child is in the middle of an
473
475
        bralid  r15, schedule_tail; /* ...which is schedule_tail's arg */
474
476
        add     r3, r5, r0;     /* switch_thread returns the prev task */
475
477
                                /* ( in the delay slot ) */
 
478
        brid    ret_from_trap;  /* Do normal trap return */
476
479
        add     r3, r0, r0;     /* Child's fork call should return 0. */
477
 
        brid    ret_from_trap;  /* Do normal trap return */
478
 
        nop;
479
480
 
480
481
C_ENTRY(sys_vfork):
481
482
        brid    microblaze_vfork        /* Do real work (tail-call) */
482
 
        la      r5, r1, PTO
 
483
        addik   r5, r1, PTO
483
484
 
484
485
C_ENTRY(sys_clone):
485
486
        bnei    r6, 1f;                 /* See if child SP arg (arg 1) is 0. */
486
 
        lwi     r6, r1, PTO+PT_R1;      /* If so, use paret's stack ptr */
487
 
1:      la      r7, r1, PTO;                    /* Arg 2: parent context */
 
487
        lwi     r6, r1, PTO + PT_R1;    /* If so, use paret's stack ptr */
 
488
1:      addik   r7, r1, PTO;                    /* Arg 2: parent context */
488
489
        add     r8, r0, r0;                     /* Arg 3: (unused) */
489
490
        add     r9, r0, r0;                     /* Arg 4: (unused) */
 
491
        brid    do_fork         /* Do real work (tail-call) */
490
492
        add     r10, r0, r0;                    /* Arg 5: (unused) */
491
 
        brid    do_fork         /* Do real work (tail-call) */
492
 
        nop;
493
493
 
494
494
C_ENTRY(sys_execve):
495
 
        la      r8, r1, PTO;            /* add user context as 4th arg */
496
495
        brid    microblaze_execve;      /* Do real work (tail-call).*/
497
 
        nop;
498
 
 
499
 
C_ENTRY(sys_rt_sigsuspend_wrapper):
500
 
        swi     r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
501
 
        swi     r4, r1, PTO+PT_R4;
502
 
        la      r7, r1, PTO;            /* add user context as 3rd arg */
503
 
        brlid   r15, sys_rt_sigsuspend; /* Do real work.*/
504
 
        nop;
505
 
        lwi     r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
506
 
        lwi     r4, r1, PTO+PT_R4;
507
 
        bri ret_from_trap /* fall through will not work here due to align */
508
 
        nop;
 
496
        addik   r8, r1, PTO;            /* add user context as 4th arg */
509
497
 
510
498
C_ENTRY(sys_rt_sigreturn_wrapper):
511
 
        swi     r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
512
 
        swi     r4, r1, PTO+PT_R4;
513
 
        la      r5, r1, PTO;            /* add user context as 1st arg */
514
 
        brlid   r15, sys_rt_sigreturn   /* Do real work */
515
 
        nop;
516
 
        lwi     r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
517
 
        lwi     r4, r1, PTO+PT_R4;
518
 
        bri ret_from_trap /* fall through will not work here due to align */
519
 
        nop;
 
499
        brid    sys_rt_sigreturn        /* Do real work */
 
500
        addik   r5, r1, PTO;            /* add user context as 1st arg */
520
501
 
521
502
/*
522
503
 * HW EXCEPTION rutine start
523
504
 */
524
 
 
525
 
#define SAVE_STATE      \
526
 
        swi     r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* Save r11 */  \
527
 
        set_bip;        /*equalize initial state for all possible entries*/\
528
 
        clear_eip;                                                      \
529
 
        enable_irq;                                                     \
530
 
        set_ee;                                                         \
531
 
        /* See if already in kernel mode.*/                             \
532
 
        lwi     r11, r0, TOPHYS(PER_CPU(KM));                           \
533
 
        beqi    r11, 1f;                /* Jump ahead if coming from user */\
534
 
        /* Kernel-mode state save.  */                                  \
535
 
        /* Reload kernel stack-ptr. */                                  \
536
 
        lwi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP));                     \
537
 
        tophys(r1,r11);                                                 \
538
 
        swi     r11, r1, (PT_R1-PT_SIZE); /* Save original SP. */       \
539
 
        lwi     r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* restore r11 */\
540
 
        addik   r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack.  */\
541
 
        /* store return registers separately because                    \
542
 
         * this macros is use for others exceptions */                  \
543
 
        swi     r3, r1, PTO + PT_R3;                                    \
544
 
        swi     r4, r1, PTO + PT_R4;                                    \
545
 
        SAVE_REGS                                                       \
546
 
        /* PC, before IRQ/trap - this is one instruction above */       \
547
 
        swi     r17, r1, PTO+PT_PC;                                     \
548
 
                                                                        \
549
 
        addi    r11, r0, 1;             /* Was in kernel-mode.  */      \
550
 
        swi     r11, r1, PTO+PT_MODE;                                   \
551
 
        brid    2f;                                                     \
552
 
        nop;                            /* Fill delay slot */           \
553
 
1:      /* User-mode state save.  */                                    \
554
 
        lwi     r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* restore r11 */\
555
 
        lwi     r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */\
556
 
        tophys(r1,r1);                                                  \
557
 
        lwi     r1, r1, TS_THREAD_INFO; /* get the thread info */       \
558
 
        addik   r1, r1, THREAD_SIZE;    /* calculate kernel stack pointer */\
559
 
        tophys(r1,r1);                                                  \
560
 
                                                                        \
561
 
        addik   r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack.  */\
562
 
        /* store return registers separately because this macros        \
563
 
         * is use for others exceptions */                              \
564
 
        swi     r3, r1, PTO + PT_R3;                                    \
565
 
        swi     r4, r1, PTO + PT_R4;                                    \
566
 
        SAVE_REGS                                                       \
567
 
        /* PC, before IRQ/trap - this is one instruction above FIXME*/  \
568
 
        swi     r17, r1, PTO+PT_PC;                                     \
569
 
                                                                        \
570
 
        swi     r0, r1, PTO+PT_MODE; /* Was in user-mode.  */           \
571
 
        lwi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP));                     \
572
 
        swi     r11, r1, PTO+PT_R1; /* Store user SP.  */               \
573
 
        addi    r11, r0, 1;                                             \
574
 
        swi     r11, r0, TOPHYS(PER_CPU(KM)); /* Now we're in kernel-mode.*/\
575
 
2:      lwi     r31, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */\
576
 
        /* Save away the syscall number.  */                            \
577
 
        swi     r0, r1, PTO+PT_R0;                                      \
578
 
        tovirt(r1,r1)
579
 
 
580
505
C_ENTRY(full_exception_trap):
581
 
        swi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */
582
506
        /* adjust exception address for privileged instruction
583
507
         * for finding where is it */
584
508
        addik   r17, r17, -4
585
509
        SAVE_STATE /* Save registers */
 
510
        /* PC, before IRQ/trap - this is one instruction above */
 
511
        swi     r17, r1, PTO+PT_PC;
 
512
        tovirt(r1,r1)
586
513
        /* FIXME this can be store directly in PT_ESR reg.
587
514
         * I tested it but there is a fault */
588
515
        /* where the trap should return need -8 to adjust for rtsd r15, 8 */
589
 
        la      r15, r0, ret_from_exc - 8
590
 
        la      r5, r1, PTO              /* parameter struct pt_regs * regs */
 
516
        addik   r15, r0, ret_from_exc - 8
591
517
        mfs     r6, resr
592
 
        nop
593
518
        mfs     r7, rfsr;               /* save FSR */
594
 
        nop
595
519
        mts     rfsr, r0;       /* Clear sticky fsr */
596
 
        nop
597
 
        la      r12, r0, full_exception
598
 
        set_vms;
599
 
        rtbd    r12, 0;
600
 
        nop;
 
520
        rted    r0, full_exception
 
521
        addik   r5, r1, PTO              /* parameter struct pt_regs * regs */
601
522
 
602
523
/*
603
524
 * Unaligned data trap.
610
531
 * The assembler routine is in "arch/microblaze/kernel/hw_exception_handler.S"
611
532
 */
612
533
C_ENTRY(unaligned_data_trap):
613
 
        swi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */
 
534
        /* MS: I have to save r11 value and then restore it because
 
535
         * set_bit, clear_eip, set_ee use r11 as temp register if MSR
 
536
         * instructions are not used. We don't need to do if MSR instructions
 
537
         * are used and they use r0 instead of r11.
 
538
         * I am using ENTRY_SP which should be primary used only for stack
 
539
         * pointer saving. */
 
540
        swi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
 
541
        set_bip;        /* equalize initial state for all possible entries */
 
542
        clear_eip;
 
543
        set_ee;
 
544
        lwi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
614
545
        SAVE_STATE              /* Save registers.*/
 
546
        /* PC, before IRQ/trap - this is one instruction above */
 
547
        swi     r17, r1, PTO+PT_PC;
 
548
        tovirt(r1,r1)
615
549
        /* where the trap should return need -8 to adjust for rtsd r15, 8 */
616
 
        la      r15, r0, ret_from_exc-8
 
550
        addik   r15, r0, ret_from_exc-8
617
551
        mfs     r3, resr                /* ESR */
618
 
        nop
619
552
        mfs     r4, rear                /* EAR */
620
 
        nop
621
 
        la      r7, r1, PTO             /* parameter struct pt_regs * regs */
622
 
        la      r12, r0, _unaligned_data_exception
623
 
        set_vms;
624
 
        rtbd    r12, 0; /* interrupts enabled */
625
 
        nop;
 
553
        rtbd    r0, _unaligned_data_exception
 
554
        addik   r7, r1, PTO             /* parameter struct pt_regs * regs */
626
555
 
627
556
/*
628
557
 * Page fault traps.
643
572
 */
644
573
/* data and intruction trap - which is choose is resolved int fault.c */
645
574
C_ENTRY(page_fault_data_trap):
646
 
        swi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */
647
575
        SAVE_STATE              /* Save registers.*/
 
576
        /* PC, before IRQ/trap - this is one instruction above */
 
577
        swi     r17, r1, PTO+PT_PC;
 
578
        tovirt(r1,r1)
648
579
        /* where the trap should return need -8 to adjust for rtsd r15, 8 */
649
 
        la      r15, r0, ret_from_exc-8
650
 
        la      r5, r1, PTO             /* parameter struct pt_regs * regs */
 
580
        addik   r15, r0, ret_from_exc-8
651
581
        mfs     r6, rear                /* parameter unsigned long address */
652
 
        nop
653
582
        mfs     r7, resr                /* parameter unsigned long error_code */
654
 
        nop
655
 
        la      r12, r0, do_page_fault
656
 
        set_vms;
657
 
        rtbd    r12, 0; /* interrupts enabled */
658
 
        nop;
 
583
        rted    r0, do_page_fault
 
584
        addik   r5, r1, PTO             /* parameter struct pt_regs * regs */
659
585
 
660
586
C_ENTRY(page_fault_instr_trap):
661
 
        swi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */
662
587
        SAVE_STATE              /* Save registers.*/
 
588
        /* PC, before IRQ/trap - this is one instruction above */
 
589
        swi     r17, r1, PTO+PT_PC;
 
590
        tovirt(r1,r1)
663
591
        /* where the trap should return need -8 to adjust for rtsd r15, 8 */
664
 
        la      r15, r0, ret_from_exc-8
665
 
        la      r5, r1, PTO             /* parameter struct pt_regs * regs */
 
592
        addik   r15, r0, ret_from_exc-8
666
593
        mfs     r6, rear                /* parameter unsigned long address */
667
 
        nop
668
594
        ori     r7, r0, 0               /* parameter unsigned long error_code */
669
 
        la      r12, r0, do_page_fault
670
 
        set_vms;
671
 
        rtbd    r12, 0; /* interrupts enabled */
672
 
        nop;
 
595
        rted    r0, do_page_fault
 
596
        addik   r5, r1, PTO             /* parameter struct pt_regs * regs */
673
597
 
674
598
/* Entry point used to return from an exception.  */
675
599
C_ENTRY(ret_from_exc):
676
 
        set_bip;                        /*  Ints masked for state restore*/
677
 
        lwi     r11, r1, PTO+PT_MODE;
 
600
        lwi     r11, r1, PTO + PT_MODE;
678
601
        bnei    r11, 2f;                /* See if returning to kernel mode, */
679
602
                                        /* ... if so, skip resched &c.  */
680
603
 
681
604
        /* We're returning to user mode, so check for various conditions that
682
605
           trigger rescheduling. */
683
 
        /* Get current task ptr into r11 */
684
 
        add     r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */
685
 
        lwi     r11, r11, TS_THREAD_INFO;       /* get thread info */
 
606
        lwi     r11, CURRENT_TASK, TS_THREAD_INFO;      /* get thread info */
686
607
        lwi     r11, r11, TI_FLAGS;     /* get flags in thread info */
687
608
        andi    r11, r11, _TIF_NEED_RESCHED;
688
609
        beqi    r11, 5f;
692
613
        nop;                            /* delay slot */
693
614
 
694
615
        /* Maybe handle a signal */
695
 
5:      add     r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */
696
 
        lwi     r11, r11, TS_THREAD_INFO;       /* get thread info */
 
616
5:      lwi     r11, CURRENT_TASK, TS_THREAD_INFO;      /* get thread info */
697
617
        lwi     r11, r11, TI_FLAGS;     /* get flags in thread info */
698
618
        andi    r11, r11, _TIF_SIGPENDING;
699
619
        beqi    r11, 1f;                /* Signals to handle, handle them */
708
628
         * traps), but signal handlers may want to examine or change the
709
629
         * complete register state.  Here we save anything not saved by
710
630
         * the normal entry sequence, so that it may be safely restored
711
 
         * (in a possibly modified form) after do_signal returns.
712
 
         * store return registers separately because this macros is use
713
 
         * for others exceptions */
714
 
        swi     r3, r1, PTO + PT_R3;
715
 
        swi     r4, r1, PTO + PT_R4;
716
 
        la      r5, r1, PTO;            /* Arg 1: struct pt_regs *regs */
717
 
        add     r6, r0, r0;             /* Arg 2: sigset_t *oldset */
 
631
         * (in a possibly modified form) after do_signal returns. */
 
632
        addik   r5, r1, PTO;            /* Arg 1: struct pt_regs *regs */
718
633
        addi    r7, r0, 0;              /* Arg 3: int in_syscall */
719
634
        bralid  r15, do_signal; /* Handle any signals */
720
 
        nop;
721
 
        lwi     r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
722
 
        lwi     r4, r1, PTO+PT_R4;
 
635
        add     r6, r0, r0;             /* Arg 2: sigset_t *oldset */
723
636
 
724
637
/* Finally, return to user state.  */
725
 
1:      swi     r0, r0, PER_CPU(KM);    /* Now officially in user state. */
726
 
        add     r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */
727
 
        swi     r11, r0, PER_CPU(CURRENT_SAVE); /* save current */
 
638
1:      set_bip;                        /* Ints masked for state restore */
 
639
        swi     CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
728
640
        VM_OFF;
729
641
        tophys(r1,r1);
730
642
 
731
 
        lwi     r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
732
 
        lwi     r4, r1, PTO+PT_R4;
733
643
        RESTORE_REGS;
734
644
        addik   r1, r1, STATE_SAVE_SIZE         /* Clean up stack space.  */
735
645
 
736
646
        lwi     r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer. */
737
647
        bri     6f;
738
648
/* Return to kernel state.  */
739
 
2:      VM_OFF;
 
649
2:      set_bip;                        /* Ints masked for state restore */
 
650
        VM_OFF;
740
651
        tophys(r1,r1);
741
 
        lwi     r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
742
 
        lwi     r4, r1, PTO+PT_R4;
743
652
        RESTORE_REGS;
744
653
        addik   r1, r1, STATE_SAVE_SIZE         /* Clean up stack space.  */
745
654
 
763
672
/* MS: we are in physical address */
764
673
/* Save registers, switch to proper stack, convert SP to virtual.*/
765
674
        swi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP))
766
 
        swi     r11, r0, TOPHYS(PER_CPU(R11_SAVE));
767
675
        /* MS: See if already in kernel mode. */
768
 
        lwi     r11, r0, TOPHYS(PER_CPU(KM));
769
 
        beqi    r11, 1f; /* MS: Jump ahead if coming from user */
 
676
        mfs     r1, rmsr
 
677
        nop
 
678
        andi    r1, r1, MSR_UMS
 
679
        bnei    r1, 1f
770
680
 
771
681
/* Kernel-mode state save. */
772
 
        or      r11, r1, r0
773
 
        tophys(r1,r11); /* MS: I have in r1 physical address where stack is */
774
 
/* MS: Save original SP - position PT_R1 to next stack frame 4 *1 - 152*/
775
 
        swi     r11, r1, (PT_R1 - PT_SIZE);
776
 
/* MS: restore r11 because of saving in SAVE_REGS */
777
 
        lwi     r11, r0, TOPHYS(PER_CPU(R11_SAVE));
 
682
        lwi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP))
 
683
        tophys(r1,r1); /* MS: I have in r1 physical address where stack is */
778
684
        /* save registers */
779
685
/* MS: Make room on the stack -> activation record */
780
686
        addik   r1, r1, -STATE_SAVE_SIZE;
781
 
/* MS: store return registers separately because
782
 
 * this macros is use for others exceptions */
783
 
        swi     r3, r1, PTO + PT_R3;
784
 
        swi     r4, r1, PTO + PT_R4;
785
687
        SAVE_REGS
786
 
        /* MS: store mode */
787
 
        addi    r11, r0, 1; /* MS: Was in kernel-mode. */
788
 
        swi     r11, r1, PTO + PT_MODE; /* MS: and save it */
789
688
        brid    2f;
790
 
        nop; /* MS: Fill delay slot */
791
 
 
 
689
        swi     r1, r1, PTO + PT_MODE; /* 0 - user mode, 1 - kernel mode */
792
690
1:
793
691
/* User-mode state save. */
794
 
/* MS: restore r11 -> FIXME move before SAVE_REG */
795
 
        lwi     r11, r0, TOPHYS(PER_CPU(R11_SAVE));
796
692
 /* MS: get the saved current */
797
693
        lwi     r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
798
694
        tophys(r1,r1);
801
697
        tophys(r1,r1);
802
698
        /* save registers */
803
699
        addik   r1, r1, -STATE_SAVE_SIZE;
804
 
        swi     r3, r1, PTO+PT_R3;
805
 
        swi     r4, r1, PTO+PT_R4;
806
700
        SAVE_REGS
807
701
        /* calculate mode */
808
702
        swi     r0, r1, PTO + PT_MODE;
809
703
        lwi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
810
704
        swi     r11, r1, PTO+PT_R1;
811
 
        /* setup kernel mode to KM */
812
 
        addi    r11, r0, 1;
813
 
        swi     r11, r0, TOPHYS(PER_CPU(KM));
814
 
 
 
705
        clear_ums;
815
706
2:
816
 
        lwi     r31, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
817
 
        swi     r0, r1, PTO + PT_R0;
 
707
        lwi     CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
818
708
        tovirt(r1,r1)
819
 
        la      r5, r1, PTO;
820
 
        set_vms;
821
 
        la      r11, r0, do_IRQ;
822
 
        la      r15, r0, irq_call;
823
 
irq_call:rtbd   r11, 0;
824
 
        nop;
 
709
        addik   r15, r0, irq_call;
 
710
irq_call:rtbd   r0, do_IRQ;
 
711
        addik   r5, r1, PTO;
825
712
 
826
713
/* MS: we are in virtual mode */
827
714
ret_from_irq:
828
715
        lwi     r11, r1, PTO + PT_MODE;
829
716
        bnei    r11, 2f;
830
717
 
831
 
        add     r11, r0, CURRENT_TASK;
832
 
        lwi     r11, r11, TS_THREAD_INFO;
 
718
        lwi     r11, CURRENT_TASK, TS_THREAD_INFO;
833
719
        lwi     r11, r11, TI_FLAGS; /* MS: get flags from thread info */
834
720
        andi    r11, r11, _TIF_NEED_RESCHED;
835
721
        beqi    r11, 5f
837
723
        nop; /* delay slot */
838
724
 
839
725
    /* Maybe handle a signal */
840
 
5:      add     r11, r0, CURRENT_TASK;
841
 
        lwi     r11, r11, TS_THREAD_INFO; /* MS: get thread info */
 
726
5:      lwi     r11, CURRENT_TASK, TS_THREAD_INFO; /* MS: get thread info */
842
727
        lwi     r11, r11, TI_FLAGS; /* get flags in thread info */
843
728
        andi    r11, r11, _TIF_SIGPENDING;
844
729
        beqid   r11, no_intr_resched
845
730
/* Handle a signal return; Pending signals should be in r18. */
846
731
        addi    r7, r0, 0; /* Arg 3: int in_syscall */
847
 
        la      r5, r1, PTO; /* Arg 1: struct pt_regs *regs */
 
732
        addik   r5, r1, PTO; /* Arg 1: struct pt_regs *regs */
848
733
        bralid  r15, do_signal; /* Handle any signals */
849
734
        add     r6, r0, r0; /* Arg 2: sigset_t *oldset */
850
735
 
852
737
no_intr_resched:
853
738
    /* Disable interrupts, we are now committed to the state restore */
854
739
        disable_irq
855
 
        swi     r0, r0, PER_CPU(KM); /* MS: Now officially in user state. */
856
 
        add     r11, r0, CURRENT_TASK;
857
 
        swi     r11, r0, PER_CPU(CURRENT_SAVE);
 
740
        swi     CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE);
858
741
        VM_OFF;
859
742
        tophys(r1,r1);
860
 
        lwi     r3, r1, PTO + PT_R3; /* MS: restore saved r3, r4 registers */
861
 
        lwi     r4, r1, PTO + PT_R4;
862
743
        RESTORE_REGS
863
744
        addik   r1, r1, STATE_SAVE_SIZE /* MS: Clean up stack space. */
864
745
        lwi     r1, r1, PT_R1 - PT_SIZE;
865
746
        bri     6f;
866
747
/* MS: Return to kernel state. */
867
 
2:      VM_OFF /* MS: turn off MMU */
 
748
2:
 
749
#ifdef CONFIG_PREEMPT
 
750
        lwi     r11, CURRENT_TASK, TS_THREAD_INFO;
 
751
        /* MS: get preempt_count from thread info */
 
752
        lwi     r5, r11, TI_PREEMPT_COUNT;
 
753
        bgti    r5, restore;
 
754
 
 
755
        lwi     r5, r11, TI_FLAGS;              /* get flags in thread info */
 
756
        andi    r5, r5, _TIF_NEED_RESCHED;
 
757
        beqi    r5, restore /* if zero jump over */
 
758
 
 
759
preempt:
 
760
        /* interrupts are off that's why I am calling preempt_chedule_irq */
 
761
        bralid  r15, preempt_schedule_irq
 
762
        nop
 
763
        lwi     r11, CURRENT_TASK, TS_THREAD_INFO;      /* get thread info */
 
764
        lwi     r5, r11, TI_FLAGS;              /* get flags in thread info */
 
765
        andi    r5, r5, _TIF_NEED_RESCHED;
 
766
        bnei    r5, preempt /* if non zero jump to resched */
 
767
restore:
 
768
#endif
 
769
        VM_OFF /* MS: turn off MMU */
868
770
        tophys(r1,r1)
869
 
        lwi     r3, r1, PTO + PT_R3; /* MS: restore saved r3, r4 registers */
870
 
        lwi     r4, r1, PTO + PT_R4;
871
771
        RESTORE_REGS
872
772
        addik   r1, r1, STATE_SAVE_SIZE /* MS: Clean up stack space. */
873
773
        tovirt(r1,r1);
877
777
        nop
878
778
 
879
779
/*
880
 
 * `Debug' trap
881
 
 *  We enter dbtrap in "BIP" (breakpoint) mode.
882
 
 *  So we exit the breakpoint mode with an 'rtbd' and proceed with the
883
 
 *  original dbtrap.
884
 
 *  however, wait to save state first
 
780
 * Debug trap for KGDB. Enter to _debug_exception by brki r16, 0x18
 
781
 * and call handling function with saved pt_regs
885
782
 */
886
783
C_ENTRY(_debug_exception):
887
784
        /* BIP bit is set on entry, no interrupts can occur */
888
785
        swi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP))
889
786
 
890
 
        swi     r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* Save r11 */
891
 
        set_bip;        /*equalize initial state for all possible entries*/
892
 
        clear_eip;
893
 
        enable_irq;
894
 
        lwi     r11, r0, TOPHYS(PER_CPU(KM));/* See if already in kernel mode.*/
895
 
        beqi    r11, 1f;                /* Jump ahead if coming from user */
896
 
        /* Kernel-mode state save.  */
897
 
        lwi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/
898
 
        tophys(r1,r11);
899
 
        swi     r11, r1, (PT_R1-PT_SIZE); /* Save original SP. */
900
 
        lwi     r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* restore r11 */
 
787
        mfs     r1, rmsr
 
788
        nop
 
789
        andi    r1, r1, MSR_UMS
 
790
        bnei    r1, 1f
 
791
/* MS: Kernel-mode state save - kgdb */
 
792
        lwi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/
901
793
 
902
 
        addik   r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack.  */
903
 
        swi     r3, r1, PTO + PT_R3;
904
 
        swi     r4, r1, PTO + PT_R4;
 
794
        /* BIP bit is set on entry, no interrupts can occur */
 
795
        addik   r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE;
905
796
        SAVE_REGS;
906
 
 
907
 
        addi    r11, r0, 1;             /* Was in kernel-mode.  */
908
 
        swi     r11, r1, PTO + PT_MODE;
909
 
        brid    2f;
910
 
        nop;                            /* Fill delay slot */
911
 
1:      /* User-mode state save.  */
912
 
        lwi     r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* restore r11 */
913
 
        lwi     r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */
 
797
        /* save all regs to pt_reg structure */
 
798
        swi     r0, r1, PTO+PT_R0;      /* R0 must be saved too */
 
799
        swi     r14, r1, PTO+PT_R14     /* rewrite saved R14 value */
 
800
        swi     r16, r1, PTO+PT_PC; /* PC and r16 are the same */
 
801
        /* save special purpose registers to pt_regs */
 
802
        mfs     r11, rear;
 
803
        swi     r11, r1, PTO+PT_EAR;
 
804
        mfs     r11, resr;
 
805
        swi     r11, r1, PTO+PT_ESR;
 
806
        mfs     r11, rfsr;
 
807
        swi     r11, r1, PTO+PT_FSR;
 
808
 
 
809
        /* stack pointer is in physical address at it is decrease
 
810
         * by STATE_SAVE_SIZE but we need to get correct R1 value */
 
811
        addik   r11, r1, CONFIG_KERNEL_START - CONFIG_KERNEL_BASE_ADDR + STATE_SAVE_SIZE;
 
812
        swi     r11, r1, PTO+PT_R1
 
813
        /* MS: r31 - current pointer isn't changed */
 
814
        tovirt(r1,r1)
 
815
#ifdef CONFIG_KGDB
 
816
        addi    r5, r1, PTO /* pass pt_reg address as the first arg */
 
817
        la      r15, r0, dbtrap_call; /* return address */
 
818
        rtbd    r0, microblaze_kgdb_break
 
819
        nop;
 
820
#endif
 
821
        /* MS: Place handler for brki from kernel space if KGDB is OFF.
 
822
         * It is very unlikely that another brki instruction is called. */
 
823
        bri 0
 
824
 
 
825
/* MS: User-mode state save - gdb */
 
826
1:      lwi     r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */
914
827
        tophys(r1,r1);
915
828
        lwi     r1, r1, TS_THREAD_INFO; /* get the thread info */
916
829
        addik   r1, r1, THREAD_SIZE;    /* calculate kernel stack pointer */
917
830
        tophys(r1,r1);
918
831
 
919
832
        addik   r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack.  */
920
 
        swi     r3, r1, PTO + PT_R3;
921
 
        swi     r4, r1, PTO + PT_R4;
922
833
        SAVE_REGS;
923
 
 
924
 
        swi     r0, r1, PTO+PT_MODE; /* Was in user-mode.  */
 
834
        swi     r16, r1, PTO+PT_PC;     /* Save LP */
 
835
        swi     r0, r1, PTO + PT_MODE; /* Was in user-mode.  */
925
836
        lwi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
926
837
        swi     r11, r1, PTO+PT_R1; /* Store user SP.  */
927
 
        addi    r11, r0, 1;
928
 
        swi     r11, r0, TOPHYS(PER_CPU(KM));   /* Now we're in kernel-mode.  */
929
 
2:      lwi     r31, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */
930
 
        /* Save away the syscall number.  */
931
 
        swi     r0, r1, PTO+PT_R0;
 
838
        lwi     CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
932
839
        tovirt(r1,r1)
933
 
 
934
 
        addi    r5, r0, SIGTRAP              /* send the trap signal */
935
 
        add     r6, r0, CURRENT_TASK; /* Get current task ptr into r11 */
936
 
        addk    r7, r0, r0                   /* 3rd param zero */
937
 
 
938
840
        set_vms;
939
 
        la      r11, r0, send_sig;
940
 
        la      r15, r0, dbtrap_call;
941
 
dbtrap_call:    rtbd    r11, 0;
942
 
        nop;
 
841
        addik   r5, r1, PTO;
 
842
        addik   r15, r0, dbtrap_call;
 
843
dbtrap_call: /* Return point for kernel/user entry + 8 because of rtsd r15, 8 */
 
844
        rtbd    r0, sw_exception
 
845
        nop
943
846
 
944
 
        set_bip;                        /*  Ints masked for state restore*/
945
 
        lwi     r11, r1, PTO+PT_MODE;
 
847
        /* MS: The first instruction for the second part of the gdb/kgdb */
 
848
        set_bip; /* Ints masked for state restore */
 
849
        lwi     r11, r1, PTO + PT_MODE;
946
850
        bnei    r11, 2f;
947
 
 
 
851
/* MS: Return to user space - gdb */
948
852
        /* Get current task ptr into r11 */
949
 
        add     r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */
950
 
        lwi     r11, r11, TS_THREAD_INFO;       /* get thread info */
 
853
        lwi     r11, CURRENT_TASK, TS_THREAD_INFO;      /* get thread info */
951
854
        lwi     r11, r11, TI_FLAGS;     /* get flags in thread info */
952
855
        andi    r11, r11, _TIF_NEED_RESCHED;
953
856
        beqi    r11, 5f;
954
857
 
955
 
/* Call the scheduler before returning from a syscall/trap. */
956
 
 
 
858
        /* Call the scheduler before returning from a syscall/trap. */
957
859
        bralid  r15, schedule;  /* Call scheduler */
958
860
        nop;                            /* delay slot */
959
 
        /* XXX Is PT_DTRACE handling needed here? */
960
 
        /* XXX m68knommu also checks TASK_STATE & TASK_COUNTER here.  */
961
861
 
962
862
        /* Maybe handle a signal */
963
 
5:      add     r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */
964
 
        lwi     r11, r11, TS_THREAD_INFO;       /* get thread info */
 
863
5:      lwi     r11, CURRENT_TASK, TS_THREAD_INFO;      /* get thread info */
965
864
        lwi     r11, r11, TI_FLAGS;     /* get flags in thread info */
966
865
        andi    r11, r11, _TIF_SIGPENDING;
967
866
        beqi    r11, 1f;                /* Signals to handle, handle them */
968
867
 
969
 
/* Handle a signal return; Pending signals should be in r18.  */
970
 
        /* Not all registers are saved by the normal trap/interrupt entry
971
 
           points (for instance, call-saved registers (because the normal
972
 
           C-compiler calling sequence in the kernel makes sure they're
973
 
           preserved), and call-clobbered registers in the case of
974
 
           traps), but signal handlers may want to examine or change the
975
 
           complete register state.  Here we save anything not saved by
976
 
           the normal entry sequence, so that it may be safely restored
977
 
           (in a possibly modified form) after do_signal returns.  */
978
 
 
979
 
        la      r5, r1, PTO;            /* Arg 1: struct pt_regs *regs */
980
 
        add     r6, r0, r0;             /* Arg 2: sigset_t *oldset */
 
868
        addik   r5, r1, PTO;            /* Arg 1: struct pt_regs *regs */
981
869
        addi  r7, r0, 0;        /* Arg 3: int in_syscall */
982
870
        bralid  r15, do_signal; /* Handle any signals */
983
 
        nop;
984
 
 
 
871
        add     r6, r0, r0;             /* Arg 2: sigset_t *oldset */
985
872
 
986
873
/* Finally, return to user state.  */
987
 
1:      swi     r0, r0, PER_CPU(KM);    /* Now officially in user state. */
988
 
        add     r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */
989
 
        swi     r11, r0, PER_CPU(CURRENT_SAVE); /* save current */
 
874
1:      swi     CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
990
875
        VM_OFF;
991
876
        tophys(r1,r1);
992
 
 
993
 
        lwi     r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
994
 
        lwi     r4, r1, PTO+PT_R4;
 
877
        /* MS: Restore all regs */
995
878
        RESTORE_REGS
996
 
        addik   r1, r1, STATE_SAVE_SIZE         /* Clean up stack space.  */
997
 
 
998
 
 
999
 
        lwi     r1, r1, PT_R1 - PT_SIZE;
1000
 
                                        /* Restore user stack pointer. */
1001
 
        bri     6f;
1002
 
 
1003
 
/* Return to kernel state.  */
 
879
        addik   r1, r1, STATE_SAVE_SIZE  /* Clean up stack space */
 
880
        lwi     r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer */
 
881
DBTRAP_return_user: /* MS: Make global symbol for debugging */
 
882
        rtbd    r16, 0; /* MS: Instructions to return from a debug trap */
 
883
        nop;
 
884
 
 
885
/* MS: Return to kernel state - kgdb */
1004
886
2:      VM_OFF;
1005
887
        tophys(r1,r1);
1006
 
        lwi     r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
1007
 
        lwi     r4, r1, PTO+PT_R4;
 
888
        /* MS: Restore all regs */
1008
889
        RESTORE_REGS
1009
 
        addik   r1, r1, STATE_SAVE_SIZE         /* Clean up stack space.  */
1010
 
 
 
890
        lwi     r14, r1, PTO+PT_R14;
 
891
        lwi     r16, r1, PTO+PT_PC;
 
892
        addik   r1, r1, STATE_SAVE_SIZE; /* MS: Clean up stack space */
1011
893
        tovirt(r1,r1);
1012
 
6:
1013
 
DBTRAP_return:          /* Make global symbol for debugging */
1014
 
        rtbd    r14, 0; /* Instructions to return from an IRQ */
 
894
DBTRAP_return_kernel: /* MS: Make global symbol for debugging */
 
895
        rtbd    r16, 0; /* MS: Instructions to return from a debug trap */
1015
896
        nop;
1016
897
 
1017
898
 
1018
 
 
1019
899
ENTRY(_switch_to)
1020
900
        /* prepare return value */
1021
 
        addk    r3, r0, r31
 
901
        addk    r3, r0, CURRENT_TASK
1022
902
 
1023
903
        /* save registers in cpu_context */
1024
904
        /* use r11 and r12, volatile registers, as temp register */
1050
930
        swi     r30, r11, CC_R30
1051
931
        /* special purpose registers */
1052
932
        mfs     r12, rmsr
1053
 
        nop
1054
933
        swi     r12, r11, CC_MSR
1055
934
        mfs     r12, rear
1056
 
        nop
1057
935
        swi     r12, r11, CC_EAR
1058
936
        mfs     r12, resr
1059
 
        nop
1060
937
        swi     r12, r11, CC_ESR
1061
938
        mfs     r12, rfsr
1062
 
        nop
1063
939
        swi     r12, r11, CC_FSR
1064
940
 
1065
 
        /* update r31, the current */
1066
 
        lwi     r31, r6, TI_TASK/* give me pointer to task which will be next */
 
941
        /* update r31, the current-give me pointer to task which will be next */
 
942
        lwi     CURRENT_TASK, r6, TI_TASK
1067
943
        /* stored it to current_save too */
1068
 
        swi     r31, r0, PER_CPU(CURRENT_SAVE)
 
944
        swi     CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE)
1069
945
 
1070
946
        /* get new process' cpu context and restore */
1071
947
        /* give me start where start context of next task */
1098
974
        /* special purpose registers */
1099
975
        lwi     r12, r11, CC_FSR
1100
976
        mts     rfsr, r12
1101
 
        nop
1102
977
        lwi     r12, r11, CC_MSR
1103
978
        mts     rmsr, r12
1104
 
        nop
1105
979
 
1106
980
        rtsd    r15, 8
1107
981
        nop
1109
983
ENTRY(_reset)
1110
984
        brai    0x70; /* Jump back to FS-boot */
1111
985
 
1112
 
ENTRY(_break)
1113
 
        mfs     r5, rmsr
1114
 
        nop
1115
 
        swi     r5, r0, 0x250 + TOPHYS(r0_ram)
1116
 
        mfs     r5, resr
1117
 
        nop
1118
 
        swi     r5, r0, 0x254 + TOPHYS(r0_ram)
1119
 
        bri     0
1120
 
 
1121
986
        /* These are compiled and loaded into high memory, then
1122
987
         * copied into place in mach_early_setup */
1123
988
        .section        .init.ivt, "ax"
1129
994
        nop
1130
995
        brai    TOPHYS(_user_exception); /* syscall handler */
1131
996
        brai    TOPHYS(_interrupt);     /* Interrupt handler */
1132
 
        brai    TOPHYS(_break);         /* nmi trap handler */
 
997
        brai    TOPHYS(_debug_exception);       /* debug trap handler */
1133
998
        brai    TOPHYS(_hw_exception_handler);  /* HW exception handler */
1134
999
 
1135
 
        .org    0x60
1136
 
        brai    TOPHYS(_debug_exception);       /* debug trap handler*/
1137
 
 
1138
1000
.section .rodata,"a"
1139
1001
#include "syscall_table.S"
1140
1002
 
1141
1003
syscall_table_size=(.-sys_call_table)
1142
1004
 
 
1005
type_SYSCALL:
 
1006
        .ascii "SYSCALL\0"
 
1007
type_IRQ:
 
1008
        .ascii "IRQ\0"
 
1009
type_IRQ_PREEMPT:
 
1010
        .ascii "IRQ (PREEMPTED)\0"
 
1011
type_SYSCALL_PREEMPT:
 
1012
        .ascii " SYSCALL (PREEMPTED)\0"
 
1013
 
 
1014
        /*
 
1015
         * Trap decoding for stack unwinder
 
1016
         * Tuples are (start addr, end addr, string)
 
1017
         * If return address lies on [start addr, end addr],
 
1018
         * unwinder displays 'string'
 
1019
         */
 
1020
 
 
1021
        .align 4
 
1022
.global microblaze_trap_handlers
 
1023
microblaze_trap_handlers:
 
1024
        /* Exact matches come first */
 
1025
        .word ret_from_trap; .word ret_from_trap   ; .word type_SYSCALL
 
1026
        .word ret_from_irq ; .word ret_from_irq    ; .word type_IRQ
 
1027
        /* Fuzzy matches go here */
 
1028
        .word ret_from_irq ; .word no_intr_resched ; .word type_IRQ_PREEMPT
 
1029
        .word ret_from_trap; .word TRAP_return     ; .word type_SYSCALL_PREEMPT
 
1030
        /* End of table */
 
1031
        .word 0               ; .word 0               ; .word 0