1############################################################################### 2# 3# switch_to.S: context switch operation 4# 5# Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. 6# Written by David Howells (dhowells@redhat.com) 7# 8# This program is free software; you can redistribute it and/or 9# modify it under the terms of the GNU General Public License 10# as published by the Free Software Foundation; either version 11# 2 of the License, or (at your option) any later version. 12# 13############################################################################### 14 15#include <linux/linkage.h> 16#include <asm/thread_info.h> 17#include <asm/processor.h> 18#include <asm/registers.h> 19#include <asm/spr-regs.h> 20 21.macro LEDS val 22 setlos #~\val,gr27 23 st gr27,@(gr30,gr0) 24 membar 25 dcf @(gr30,gr0) 26.endm 27 28 .section .sdata 29 .balign 8 30 31 # address of frame 0 (userspace) on current kernel stack 32 .globl __kernel_frame0_ptr 33__kernel_frame0_ptr: 34 .long init_thread_union + THREAD_SIZE - FRV_FRAME0_SIZE 35 36 # address of current task 37 .globl __kernel_current_task 38__kernel_current_task: 39 .long init_task 40 41 .section .text 42 .balign 4 43 44############################################################################### 45# 46# struct task_struct *__switch_to(struct thread_struct *prev_thread, 47# struct thread_struct *next_thread, 48# struct task_struct *prev) 49# 50############################################################################### 51 .globl __switch_to 52__switch_to: 53 # save outgoing process's context 54 sethi.p %hi(__switch_back),gr13 55 setlo %lo(__switch_back),gr13 56 movsg lr,gr12 57 58 stdi gr28,@(gr8,#__THREAD_FRAME) 59 sti sp ,@(gr8,#__THREAD_SP) 60 sti fp ,@(gr8,#__THREAD_FP) 61 stdi gr12,@(gr8,#__THREAD_LR) 62 stdi gr16,@(gr8,#__THREAD_GR(16)) 63 stdi gr18,@(gr8,#__THREAD_GR(18)) 64 stdi gr20,@(gr8,#__THREAD_GR(20)) 65 stdi gr22,@(gr8,#__THREAD_GR(22)) 66 stdi gr24,@(gr8,#__THREAD_GR(24)) 67 stdi.p gr26,@(gr8,#__THREAD_GR(26)) 68 69 or gr8,gr8,gr22 70 ldi.p @(gr8,#__THREAD_USER),gr8 71 call save_user_regs 72 or gr22,gr22,gr8 73 74 # retrieve the new context 75 sethi.p %hi(__kernel_frame0_ptr),gr6 76 setlo %lo(__kernel_frame0_ptr),gr6 77 movsg psr,gr4 78 79 lddi.p @(gr9,#__THREAD_FRAME),gr10 80 or gr10,gr10,gr27 ; save prev for the return value 81 82 ldi @(gr11,#4),gr19 ; get new_current->thread_info 83 84 lddi @(gr9,#__THREAD_SP),gr12 85 ldi @(gr9,#__THREAD_LR),gr14 86 ldi @(gr9,#__THREAD_PC),gr18 87 ldi.p @(gr9,#__THREAD_FRAME0),gr7 88 89 # actually switch kernel contexts with ordinary exceptions disabled 90 andi gr4,#~PSR_ET,gr5 91 movgs gr5,psr 92 93 or.p gr10,gr0,gr28 ; set __frame 94 or gr11,gr0,gr29 ; set __current 95 or.p gr12,gr0,sp 96 or gr13,gr0,fp 97 or gr19,gr0,gr15 ; set __current_thread_info 98 99 sti gr7,@(gr6,#0) ; set __kernel_frame0_ptr 100 sti gr29,@(gr6,#4) ; set __kernel_current_task 101 102 movgs gr14,lr 103 bar 104 105 # jump to __switch_back or ret_from_fork as appropriate 106 # - move prev to GR8 107 movgs gr4,psr 108 jmpl.p @(gr18,gr0) 109 or gr27,gr27,gr8 110 111############################################################################### 112# 113# restore incoming process's context 114# - on entry: 115# - SP, FP, LR, GR15, GR28 and GR29 will have been set up appropriately 116# - GR8 will point to the outgoing task_struct 117# - GR9 will point to the incoming thread_struct 118# 119############################################################################### 120__switch_back: 121 lddi @(gr9,#__THREAD_GR(16)),gr16 122 lddi @(gr9,#__THREAD_GR(18)),gr18 123 lddi @(gr9,#__THREAD_GR(20)),gr20 124 lddi @(gr9,#__THREAD_GR(22)),gr22 125 lddi @(gr9,#__THREAD_GR(24)),gr24 126 lddi @(gr9,#__THREAD_GR(26)),gr26 127 128 # fall through into restore_user_regs() 129 ldi.p @(gr9,#__THREAD_USER),gr8 130 or gr8,gr8,gr9 131 132############################################################################### 133# 134# restore extra general regs and FP/Media regs 135# - void *restore_user_regs(const struct user_context *target, void *retval) 136# - on entry: 137# - GR8 will point to the user context to swap in 138# - GR9 will contain the value to be returned in GR8 (prev task on context switch) 139# 140############################################################################### 141 .globl restore_user_regs 142restore_user_regs: 143 movsg hsr0,gr6 144 ori gr6,#HSR0_GRHE|HSR0_FRLE|HSR0_FRHE,gr6 145 movgs gr6,hsr0 146 movsg hsr0,gr6 147 148 movsg psr,gr7 149 ori gr7,#PSR_EF|PSR_EM,gr7 150 movgs gr7,psr 151 movsg psr,gr7 152 srli gr7,#24,gr7 153 bar 154 155 lddi @(gr8,#__FPMEDIA_MSR(0)),gr4 156 157 movgs gr4,msr0 158 movgs gr5,msr1 159 160 lddfi @(gr8,#__FPMEDIA_ACC(0)),fr16 161 lddfi @(gr8,#__FPMEDIA_ACC(2)),fr18 162 ldbfi @(gr8,#__FPMEDIA_ACCG(0)),fr20 163 ldbfi @(gr8,#__FPMEDIA_ACCG(1)),fr21 164 ldbfi @(gr8,#__FPMEDIA_ACCG(2)),fr22 165 ldbfi @(gr8,#__FPMEDIA_ACCG(3)),fr23 166 167 mwtacc fr16,acc0 168 mwtacc fr17,acc1 169 mwtacc fr18,acc2 170 mwtacc fr19,acc3 171 mwtaccg fr20,accg0 172 mwtaccg fr21,accg1 173 mwtaccg fr22,accg2 174 mwtaccg fr23,accg3 175 176 # some CPUs have extra ACCx and ACCGx regs and maybe FSRx regs 177 subicc.p gr7,#0x50,gr0,icc0 178 subicc gr7,#0x31,gr0,icc1 179 beq icc0,#0,__restore_acc_fr451 180 beq icc1,#0,__restore_acc_fr555 181__restore_acc_cont: 182 183 # some CPU's have GR32-GR63 184 setlos #HSR0_FRHE,gr4 185 andcc gr6,gr4,gr0,icc0 186 beq icc0,#1,__restore_skip_gr32_gr63 187 188 lddi @(gr8,#__INT_GR(32)),gr32 189 lddi @(gr8,#__INT_GR(34)),gr34 190 lddi @(gr8,#__INT_GR(36)),gr36 191 lddi @(gr8,#__INT_GR(38)),gr38 192 lddi @(gr8,#__INT_GR(40)),gr40 193 lddi @(gr8,#__INT_GR(42)),gr42 194 lddi @(gr8,#__INT_GR(44)),gr44 195 lddi @(gr8,#__INT_GR(46)),gr46 196 lddi @(gr8,#__INT_GR(48)),gr48 197 lddi @(gr8,#__INT_GR(50)),gr50 198 lddi @(gr8,#__INT_GR(52)),gr52 199 lddi @(gr8,#__INT_GR(54)),gr54 200 lddi @(gr8,#__INT_GR(56)),gr56 201 lddi @(gr8,#__INT_GR(58)),gr58 202 lddi @(gr8,#__INT_GR(60)),gr60 203 lddi @(gr8,#__INT_GR(62)),gr62 204__restore_skip_gr32_gr63: 205 206 # all CPU's have FR0-FR31 207 lddfi @(gr8,#__FPMEDIA_FR( 0)),fr0 208 lddfi @(gr8,#__FPMEDIA_FR( 2)),fr2 209 lddfi @(gr8,#__FPMEDIA_FR( 4)),fr4 210 lddfi @(gr8,#__FPMEDIA_FR( 6)),fr6 211 lddfi @(gr8,#__FPMEDIA_FR( 8)),fr8 212 lddfi @(gr8,#__FPMEDIA_FR(10)),fr10 213 lddfi @(gr8,#__FPMEDIA_FR(12)),fr12 214 lddfi @(gr8,#__FPMEDIA_FR(14)),fr14 215 lddfi @(gr8,#__FPMEDIA_FR(16)),fr16 216 lddfi @(gr8,#__FPMEDIA_FR(18)),fr18 217 lddfi @(gr8,#__FPMEDIA_FR(20)),fr20 218 lddfi @(gr8,#__FPMEDIA_FR(22)),fr22 219 lddfi @(gr8,#__FPMEDIA_FR(24)),fr24 220 lddfi @(gr8,#__FPMEDIA_FR(26)),fr26 221 lddfi @(gr8,#__FPMEDIA_FR(28)),fr28 222 lddfi.p @(gr8,#__FPMEDIA_FR(30)),fr30 223 224 # some CPU's have FR32-FR63 225 setlos #HSR0_FRHE,gr4 226 andcc gr6,gr4,gr0,icc0 227 beq icc0,#1,__restore_skip_fr32_fr63 228 229 lddfi @(gr8,#__FPMEDIA_FR(32)),fr32 230 lddfi @(gr8,#__FPMEDIA_FR(34)),fr34 231 lddfi @(gr8,#__FPMEDIA_FR(36)),fr36 232 lddfi @(gr8,#__FPMEDIA_FR(38)),fr38 233 lddfi @(gr8,#__FPMEDIA_FR(40)),fr40 234 lddfi @(gr8,#__FPMEDIA_FR(42)),fr42 235 lddfi @(gr8,#__FPMEDIA_FR(44)),fr44 236 lddfi @(gr8,#__FPMEDIA_FR(46)),fr46 237 lddfi @(gr8,#__FPMEDIA_FR(48)),fr48 238 lddfi @(gr8,#__FPMEDIA_FR(50)),fr50 239 lddfi @(gr8,#__FPMEDIA_FR(52)),fr52 240 lddfi @(gr8,#__FPMEDIA_FR(54)),fr54 241 lddfi @(gr8,#__FPMEDIA_FR(56)),fr56 242 lddfi @(gr8,#__FPMEDIA_FR(58)),fr58 243 lddfi @(gr8,#__FPMEDIA_FR(60)),fr60 244 lddfi @(gr8,#__FPMEDIA_FR(62)),fr62 245__restore_skip_fr32_fr63: 246 247 lddi @(gr8,#__FPMEDIA_FNER(0)),gr4 248 movsg fner0,gr4 249 movsg fner1,gr5 250 or.p gr9,gr9,gr8 251 bralr 252 253 # the FR451 also has ACC8-11/ACCG8-11 regs (but not 4-7...) 254__restore_acc_fr451: 255 lddfi @(gr8,#__FPMEDIA_ACC(4)),fr16 256 lddfi @(gr8,#__FPMEDIA_ACC(6)),fr18 257 ldbfi @(gr8,#__FPMEDIA_ACCG(4)),fr20 258 ldbfi @(gr8,#__FPMEDIA_ACCG(5)),fr21 259 ldbfi @(gr8,#__FPMEDIA_ACCG(6)),fr22 260 ldbfi @(gr8,#__FPMEDIA_ACCG(7)),fr23 261 262 mwtacc fr16,acc8 263 mwtacc fr17,acc9 264 mwtacc fr18,acc10 265 mwtacc fr19,acc11 266 mwtaccg fr20,accg8 267 mwtaccg fr21,accg9 268 mwtaccg fr22,accg10 269 mwtaccg fr23,accg11 270 bra __restore_acc_cont 271 272 # the FR555 also has ACC4-7/ACCG4-7 regs and an FSR0 reg 273__restore_acc_fr555: 274 lddfi @(gr8,#__FPMEDIA_ACC(4)),fr16 275 lddfi @(gr8,#__FPMEDIA_ACC(6)),fr18 276 ldbfi @(gr8,#__FPMEDIA_ACCG(4)),fr20 277 ldbfi @(gr8,#__FPMEDIA_ACCG(5)),fr21 278 ldbfi @(gr8,#__FPMEDIA_ACCG(6)),fr22 279 ldbfi @(gr8,#__FPMEDIA_ACCG(7)),fr23 280 281 mnop.p 282 mwtacc fr16,acc4 283 mnop.p 284 mwtacc fr17,acc5 285 mnop.p 286 mwtacc fr18,acc6 287 mnop.p 288 mwtacc fr19,acc7 289 mnop.p 290 mwtaccg fr20,accg4 291 mnop.p 292 mwtaccg fr21,accg5 293 mnop.p 294 mwtaccg fr22,accg6 295 mnop.p 296 mwtaccg fr23,accg7 297 298 ldi @(gr8,#__FPMEDIA_FSR(0)),gr4 299 movgs gr4,fsr0 300 301 bra __restore_acc_cont 302 303 304############################################################################### 305# 306# save extra general regs and FP/Media regs 307# - void save_user_regs(struct user_context *target) 308# 309############################################################################### 310 .globl save_user_regs 311save_user_regs: 312 movsg hsr0,gr6 313 ori gr6,#HSR0_GRHE|HSR0_FRLE|HSR0_FRHE,gr6 314 movgs gr6,hsr0 315 movsg hsr0,gr6 316 317 movsg psr,gr7 318 ori gr7,#PSR_EF|PSR_EM,gr7 319 movgs gr7,psr 320 movsg psr,gr7 321 srli gr7,#24,gr7 322 bar 323 324 movsg fner0,gr4 325 movsg fner1,gr5 326 stdi.p gr4,@(gr8,#__FPMEDIA_FNER(0)) 327 328 # some CPU's have GR32-GR63 329 setlos #HSR0_GRHE,gr4 330 andcc gr6,gr4,gr0,icc0 331 beq icc0,#1,__save_skip_gr32_gr63 332 333 stdi gr32,@(gr8,#__INT_GR(32)) 334 stdi gr34,@(gr8,#__INT_GR(34)) 335 stdi gr36,@(gr8,#__INT_GR(36)) 336 stdi gr38,@(gr8,#__INT_GR(38)) 337 stdi gr40,@(gr8,#__INT_GR(40)) 338 stdi gr42,@(gr8,#__INT_GR(42)) 339 stdi gr44,@(gr8,#__INT_GR(44)) 340 stdi gr46,@(gr8,#__INT_GR(46)) 341 stdi gr48,@(gr8,#__INT_GR(48)) 342 stdi gr50,@(gr8,#__INT_GR(50)) 343 stdi gr52,@(gr8,#__INT_GR(52)) 344 stdi gr54,@(gr8,#__INT_GR(54)) 345 stdi gr56,@(gr8,#__INT_GR(56)) 346 stdi gr58,@(gr8,#__INT_GR(58)) 347 stdi gr60,@(gr8,#__INT_GR(60)) 348 stdi gr62,@(gr8,#__INT_GR(62)) 349__save_skip_gr32_gr63: 350 351 # all CPU's have FR0-FR31 352 stdfi fr0 ,@(gr8,#__FPMEDIA_FR( 0)) 353 stdfi fr2 ,@(gr8,#__FPMEDIA_FR( 2)) 354 stdfi fr4 ,@(gr8,#__FPMEDIA_FR( 4)) 355 stdfi fr6 ,@(gr8,#__FPMEDIA_FR( 6)) 356 stdfi fr8 ,@(gr8,#__FPMEDIA_FR( 8)) 357 stdfi fr10,@(gr8,#__FPMEDIA_FR(10)) 358 stdfi fr12,@(gr8,#__FPMEDIA_FR(12)) 359 stdfi fr14,@(gr8,#__FPMEDIA_FR(14)) 360 stdfi fr16,@(gr8,#__FPMEDIA_FR(16)) 361 stdfi fr18,@(gr8,#__FPMEDIA_FR(18)) 362 stdfi fr20,@(gr8,#__FPMEDIA_FR(20)) 363 stdfi fr22,@(gr8,#__FPMEDIA_FR(22)) 364 stdfi fr24,@(gr8,#__FPMEDIA_FR(24)) 365 stdfi fr26,@(gr8,#__FPMEDIA_FR(26)) 366 stdfi fr28,@(gr8,#__FPMEDIA_FR(28)) 367 stdfi.p fr30,@(gr8,#__FPMEDIA_FR(30)) 368 369 # some CPU's have FR32-FR63 370 setlos #HSR0_FRHE,gr4 371 andcc gr6,gr4,gr0,icc0 372 beq icc0,#1,__save_skip_fr32_fr63 373 374 stdfi fr32,@(gr8,#__FPMEDIA_FR(32)) 375 stdfi fr34,@(gr8,#__FPMEDIA_FR(34)) 376 stdfi fr36,@(gr8,#__FPMEDIA_FR(36)) 377 stdfi fr38,@(gr8,#__FPMEDIA_FR(38)) 378 stdfi fr40,@(gr8,#__FPMEDIA_FR(40)) 379 stdfi fr42,@(gr8,#__FPMEDIA_FR(42)) 380 stdfi fr44,@(gr8,#__FPMEDIA_FR(44)) 381 stdfi fr46,@(gr8,#__FPMEDIA_FR(46)) 382 stdfi fr48,@(gr8,#__FPMEDIA_FR(48)) 383 stdfi fr50,@(gr8,#__FPMEDIA_FR(50)) 384 stdfi fr52,@(gr8,#__FPMEDIA_FR(52)) 385 stdfi fr54,@(gr8,#__FPMEDIA_FR(54)) 386 stdfi fr56,@(gr8,#__FPMEDIA_FR(56)) 387 stdfi fr58,@(gr8,#__FPMEDIA_FR(58)) 388 stdfi fr60,@(gr8,#__FPMEDIA_FR(60)) 389 stdfi fr62,@(gr8,#__FPMEDIA_FR(62)) 390__save_skip_fr32_fr63: 391 392 mrdacc acc0 ,fr4 393 mrdacc acc1 ,fr5 394 395 stdfi.p fr4 ,@(gr8,#__FPMEDIA_ACC(0)) 396 397 mrdacc acc2 ,fr6 398 mrdacc acc3 ,fr7 399 400 stdfi.p fr6 ,@(gr8,#__FPMEDIA_ACC(2)) 401 402 mrdaccg accg0,fr4 403 stbfi.p fr4 ,@(gr8,#__FPMEDIA_ACCG(0)) 404 405 mrdaccg accg1,fr5 406 stbfi.p fr5 ,@(gr8,#__FPMEDIA_ACCG(1)) 407 408 mrdaccg accg2,fr6 409 stbfi.p fr6 ,@(gr8,#__FPMEDIA_ACCG(2)) 410 411 mrdaccg accg3,fr7 412 stbfi fr7 ,@(gr8,#__FPMEDIA_ACCG(3)) 413 414 movsg msr0 ,gr4 415 movsg msr1 ,gr5 416 417 stdi gr4 ,@(gr8,#__FPMEDIA_MSR(0)) 418 419 # some CPUs have extra ACCx and ACCGx regs and maybe FSRx regs 420 subicc.p gr7,#0x50,gr0,icc0 421 subicc gr7,#0x31,gr0,icc1 422 beq icc0,#0,__save_acc_fr451 423 beq icc1,#0,__save_acc_fr555 424__save_acc_cont: 425 426 lddfi @(gr8,#__FPMEDIA_FR(4)),fr4 427 lddfi.p @(gr8,#__FPMEDIA_FR(6)),fr6 428 bralr 429 430 # the FR451 also has ACC8-11/ACCG8-11 regs (but not 4-7...) 431__save_acc_fr451: 432 mrdacc acc8 ,fr4 433 mrdacc acc9 ,fr5 434 435 stdfi.p fr4 ,@(gr8,#__FPMEDIA_ACC(4)) 436 437 mrdacc acc10,fr6 438 mrdacc acc11,fr7 439 440 stdfi.p fr6 ,@(gr8,#__FPMEDIA_ACC(6)) 441 442 mrdaccg accg8,fr4 443 stbfi.p fr4 ,@(gr8,#__FPMEDIA_ACCG(4)) 444 445 mrdaccg accg9,fr5 446 stbfi.p fr5 ,@(gr8,#__FPMEDIA_ACCG(5)) 447 448 mrdaccg accg10,fr6 449 stbfi.p fr6 ,@(gr8,#__FPMEDIA_ACCG(6)) 450 451 mrdaccg accg11,fr7 452 stbfi fr7 ,@(gr8,#__FPMEDIA_ACCG(7)) 453 bra __save_acc_cont 454 455 # the FR555 also has ACC4-7/ACCG4-7 regs and an FSR0 reg 456__save_acc_fr555: 457 mnop.p 458 mrdacc acc4 ,fr4 459 mnop.p 460 mrdacc acc5 ,fr5 461 462 stdfi fr4 ,@(gr8,#__FPMEDIA_ACC(4)) 463 464 mnop.p 465 mrdacc acc6 ,fr6 466 mnop.p 467 mrdacc acc7 ,fr7 468 469 stdfi fr6 ,@(gr8,#__FPMEDIA_ACC(6)) 470 471 mnop.p 472 mrdaccg accg4,fr4 473 stbfi fr4 ,@(gr8,#__FPMEDIA_ACCG(4)) 474 475 mnop.p 476 mrdaccg accg5,fr5 477 stbfi fr5 ,@(gr8,#__FPMEDIA_ACCG(5)) 478 479 mnop.p 480 mrdaccg accg6,fr6 481 stbfi fr6 ,@(gr8,#__FPMEDIA_ACCG(6)) 482 483 mnop.p 484 mrdaccg accg7,fr7 485 stbfi fr7 ,@(gr8,#__FPMEDIA_ACCG(7)) 486 487 movsg fsr0 ,gr4 488 sti gr4 ,@(gr8,#__FPMEDIA_FSR(0)) 489 bra __save_acc_cont 490