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 srli gr15,#28,gr5 106 subicc gr5,#0xc,gr0,icc0 107 beq icc0,#0,111f 108 break 109 nop 110111: 111 112 # jump to __switch_back or ret_from_fork as appropriate 113 # - move prev to GR8 114 movgs gr4,psr 115 jmpl.p @(gr18,gr0) 116 or gr27,gr27,gr8 117 118############################################################################### 119# 120# restore incoming process's context 121# - on entry: 122# - SP, FP, LR, GR15, GR28 and GR29 will have been set up appropriately 123# - GR8 will point to the outgoing task_struct 124# - GR9 will point to the incoming thread_struct 125# 126############################################################################### 127__switch_back: 128 lddi @(gr9,#__THREAD_GR(16)),gr16 129 lddi @(gr9,#__THREAD_GR(18)),gr18 130 lddi @(gr9,#__THREAD_GR(20)),gr20 131 lddi @(gr9,#__THREAD_GR(22)),gr22 132 lddi @(gr9,#__THREAD_GR(24)),gr24 133 lddi @(gr9,#__THREAD_GR(26)),gr26 134 135 # fall through into restore_user_regs() 136 ldi.p @(gr9,#__THREAD_USER),gr8 137 or gr8,gr8,gr9 138 139############################################################################### 140# 141# restore extra general regs and FP/Media regs 142# - void *restore_user_regs(const struct user_context *target, void *retval) 143# - on entry: 144# - GR8 will point to the user context to swap in 145# - GR9 will contain the value to be returned in GR8 (prev task on context switch) 146# 147############################################################################### 148 .globl restore_user_regs 149restore_user_regs: 150 movsg hsr0,gr6 151 ori gr6,#HSR0_GRHE|HSR0_FRLE|HSR0_FRHE,gr6 152 movgs gr6,hsr0 153 movsg hsr0,gr6 154 155 movsg psr,gr7 156 ori gr7,#PSR_EF|PSR_EM,gr7 157 movgs gr7,psr 158 movsg psr,gr7 159 srli gr7,#24,gr7 160 bar 161 162 lddi @(gr8,#__FPMEDIA_MSR(0)),gr4 163 164 movgs gr4,msr0 165 movgs gr5,msr1 166 167 lddfi @(gr8,#__FPMEDIA_ACC(0)),fr16 168 lddfi @(gr8,#__FPMEDIA_ACC(2)),fr18 169 ldbfi @(gr8,#__FPMEDIA_ACCG(0)),fr20 170 ldbfi @(gr8,#__FPMEDIA_ACCG(1)),fr21 171 ldbfi @(gr8,#__FPMEDIA_ACCG(2)),fr22 172 ldbfi @(gr8,#__FPMEDIA_ACCG(3)),fr23 173 174 mwtacc fr16,acc0 175 mwtacc fr17,acc1 176 mwtacc fr18,acc2 177 mwtacc fr19,acc3 178 mwtaccg fr20,accg0 179 mwtaccg fr21,accg1 180 mwtaccg fr22,accg2 181 mwtaccg fr23,accg3 182 183 # some CPUs have extra ACCx and ACCGx regs and maybe FSRx regs 184 subicc.p gr7,#0x50,gr0,icc0 185 subicc gr7,#0x31,gr0,icc1 186 beq icc0,#0,__restore_acc_fr451 187 beq icc1,#0,__restore_acc_fr555 188__restore_acc_cont: 189 190 # some CPU's have GR32-GR63 191 setlos #HSR0_FRHE,gr4 192 andcc gr6,gr4,gr0,icc0 193 beq icc0,#1,__restore_skip_gr32_gr63 194 195 lddi @(gr8,#__INT_GR(32)),gr32 196 lddi @(gr8,#__INT_GR(34)),gr34 197 lddi @(gr8,#__INT_GR(36)),gr36 198 lddi @(gr8,#__INT_GR(38)),gr38 199 lddi @(gr8,#__INT_GR(40)),gr40 200 lddi @(gr8,#__INT_GR(42)),gr42 201 lddi @(gr8,#__INT_GR(44)),gr44 202 lddi @(gr8,#__INT_GR(46)),gr46 203 lddi @(gr8,#__INT_GR(48)),gr48 204 lddi @(gr8,#__INT_GR(50)),gr50 205 lddi @(gr8,#__INT_GR(52)),gr52 206 lddi @(gr8,#__INT_GR(54)),gr54 207 lddi @(gr8,#__INT_GR(56)),gr56 208 lddi @(gr8,#__INT_GR(58)),gr58 209 lddi @(gr8,#__INT_GR(60)),gr60 210 lddi @(gr8,#__INT_GR(62)),gr62 211__restore_skip_gr32_gr63: 212 213 # all CPU's have FR0-FR31 214 lddfi @(gr8,#__FPMEDIA_FR( 0)),fr0 215 lddfi @(gr8,#__FPMEDIA_FR( 2)),fr2 216 lddfi @(gr8,#__FPMEDIA_FR( 4)),fr4 217 lddfi @(gr8,#__FPMEDIA_FR( 6)),fr6 218 lddfi @(gr8,#__FPMEDIA_FR( 8)),fr8 219 lddfi @(gr8,#__FPMEDIA_FR(10)),fr10 220 lddfi @(gr8,#__FPMEDIA_FR(12)),fr12 221 lddfi @(gr8,#__FPMEDIA_FR(14)),fr14 222 lddfi @(gr8,#__FPMEDIA_FR(16)),fr16 223 lddfi @(gr8,#__FPMEDIA_FR(18)),fr18 224 lddfi @(gr8,#__FPMEDIA_FR(20)),fr20 225 lddfi @(gr8,#__FPMEDIA_FR(22)),fr22 226 lddfi @(gr8,#__FPMEDIA_FR(24)),fr24 227 lddfi @(gr8,#__FPMEDIA_FR(26)),fr26 228 lddfi @(gr8,#__FPMEDIA_FR(28)),fr28 229 lddfi.p @(gr8,#__FPMEDIA_FR(30)),fr30 230 231 # some CPU's have FR32-FR63 232 setlos #HSR0_FRHE,gr4 233 andcc gr6,gr4,gr0,icc0 234 beq icc0,#1,__restore_skip_fr32_fr63 235 236 lddfi @(gr8,#__FPMEDIA_FR(32)),fr32 237 lddfi @(gr8,#__FPMEDIA_FR(34)),fr34 238 lddfi @(gr8,#__FPMEDIA_FR(36)),fr36 239 lddfi @(gr8,#__FPMEDIA_FR(38)),fr38 240 lddfi @(gr8,#__FPMEDIA_FR(40)),fr40 241 lddfi @(gr8,#__FPMEDIA_FR(42)),fr42 242 lddfi @(gr8,#__FPMEDIA_FR(44)),fr44 243 lddfi @(gr8,#__FPMEDIA_FR(46)),fr46 244 lddfi @(gr8,#__FPMEDIA_FR(48)),fr48 245 lddfi @(gr8,#__FPMEDIA_FR(50)),fr50 246 lddfi @(gr8,#__FPMEDIA_FR(52)),fr52 247 lddfi @(gr8,#__FPMEDIA_FR(54)),fr54 248 lddfi @(gr8,#__FPMEDIA_FR(56)),fr56 249 lddfi @(gr8,#__FPMEDIA_FR(58)),fr58 250 lddfi @(gr8,#__FPMEDIA_FR(60)),fr60 251 lddfi @(gr8,#__FPMEDIA_FR(62)),fr62 252__restore_skip_fr32_fr63: 253 254 lddi @(gr8,#__FPMEDIA_FNER(0)),gr4 255 movsg fner0,gr4 256 movsg fner1,gr5 257 or.p gr9,gr9,gr8 258 bralr 259 260 # the FR451 also has ACC8-11/ACCG8-11 regs (but not 4-7...) 261__restore_acc_fr451: 262 lddfi @(gr8,#__FPMEDIA_ACC(4)),fr16 263 lddfi @(gr8,#__FPMEDIA_ACC(6)),fr18 264 ldbfi @(gr8,#__FPMEDIA_ACCG(4)),fr20 265 ldbfi @(gr8,#__FPMEDIA_ACCG(5)),fr21 266 ldbfi @(gr8,#__FPMEDIA_ACCG(6)),fr22 267 ldbfi @(gr8,#__FPMEDIA_ACCG(7)),fr23 268 269 mwtacc fr16,acc8 270 mwtacc fr17,acc9 271 mwtacc fr18,acc10 272 mwtacc fr19,acc11 273 mwtaccg fr20,accg8 274 mwtaccg fr21,accg9 275 mwtaccg fr22,accg10 276 mwtaccg fr23,accg11 277 bra __restore_acc_cont 278 279 # the FR555 also has ACC4-7/ACCG4-7 regs and an FSR0 reg 280__restore_acc_fr555: 281 lddfi @(gr8,#__FPMEDIA_ACC(4)),fr16 282 lddfi @(gr8,#__FPMEDIA_ACC(6)),fr18 283 ldbfi @(gr8,#__FPMEDIA_ACCG(4)),fr20 284 ldbfi @(gr8,#__FPMEDIA_ACCG(5)),fr21 285 ldbfi @(gr8,#__FPMEDIA_ACCG(6)),fr22 286 ldbfi @(gr8,#__FPMEDIA_ACCG(7)),fr23 287 288 mnop.p 289 mwtacc fr16,acc4 290 mnop.p 291 mwtacc fr17,acc5 292 mnop.p 293 mwtacc fr18,acc6 294 mnop.p 295 mwtacc fr19,acc7 296 mnop.p 297 mwtaccg fr20,accg4 298 mnop.p 299 mwtaccg fr21,accg5 300 mnop.p 301 mwtaccg fr22,accg6 302 mnop.p 303 mwtaccg fr23,accg7 304 305 ldi @(gr8,#__FPMEDIA_FSR(0)),gr4 306 movgs gr4,fsr0 307 308 bra __restore_acc_cont 309 310 311############################################################################### 312# 313# save extra general regs and FP/Media regs 314# - void save_user_regs(struct user_context *target) 315# 316############################################################################### 317 .globl save_user_regs 318save_user_regs: 319 movsg hsr0,gr6 320 ori gr6,#HSR0_GRHE|HSR0_FRLE|HSR0_FRHE,gr6 321 movgs gr6,hsr0 322 movsg hsr0,gr6 323 324 movsg psr,gr7 325 ori gr7,#PSR_EF|PSR_EM,gr7 326 movgs gr7,psr 327 movsg psr,gr7 328 srli gr7,#24,gr7 329 bar 330 331 movsg fner0,gr4 332 movsg fner1,gr5 333 stdi.p gr4,@(gr8,#__FPMEDIA_FNER(0)) 334 335 # some CPU's have GR32-GR63 336 setlos #HSR0_GRHE,gr4 337 andcc gr6,gr4,gr0,icc0 338 beq icc0,#1,__save_skip_gr32_gr63 339 340 stdi gr32,@(gr8,#__INT_GR(32)) 341 stdi gr34,@(gr8,#__INT_GR(34)) 342 stdi gr36,@(gr8,#__INT_GR(36)) 343 stdi gr38,@(gr8,#__INT_GR(38)) 344 stdi gr40,@(gr8,#__INT_GR(40)) 345 stdi gr42,@(gr8,#__INT_GR(42)) 346 stdi gr44,@(gr8,#__INT_GR(44)) 347 stdi gr46,@(gr8,#__INT_GR(46)) 348 stdi gr48,@(gr8,#__INT_GR(48)) 349 stdi gr50,@(gr8,#__INT_GR(50)) 350 stdi gr52,@(gr8,#__INT_GR(52)) 351 stdi gr54,@(gr8,#__INT_GR(54)) 352 stdi gr56,@(gr8,#__INT_GR(56)) 353 stdi gr58,@(gr8,#__INT_GR(58)) 354 stdi gr60,@(gr8,#__INT_GR(60)) 355 stdi gr62,@(gr8,#__INT_GR(62)) 356__save_skip_gr32_gr63: 357 358 # all CPU's have FR0-FR31 359 stdfi fr0 ,@(gr8,#__FPMEDIA_FR( 0)) 360 stdfi fr2 ,@(gr8,#__FPMEDIA_FR( 2)) 361 stdfi fr4 ,@(gr8,#__FPMEDIA_FR( 4)) 362 stdfi fr6 ,@(gr8,#__FPMEDIA_FR( 6)) 363 stdfi fr8 ,@(gr8,#__FPMEDIA_FR( 8)) 364 stdfi fr10,@(gr8,#__FPMEDIA_FR(10)) 365 stdfi fr12,@(gr8,#__FPMEDIA_FR(12)) 366 stdfi fr14,@(gr8,#__FPMEDIA_FR(14)) 367 stdfi fr16,@(gr8,#__FPMEDIA_FR(16)) 368 stdfi fr18,@(gr8,#__FPMEDIA_FR(18)) 369 stdfi fr20,@(gr8,#__FPMEDIA_FR(20)) 370 stdfi fr22,@(gr8,#__FPMEDIA_FR(22)) 371 stdfi fr24,@(gr8,#__FPMEDIA_FR(24)) 372 stdfi fr26,@(gr8,#__FPMEDIA_FR(26)) 373 stdfi fr28,@(gr8,#__FPMEDIA_FR(28)) 374 stdfi.p fr30,@(gr8,#__FPMEDIA_FR(30)) 375 376 # some CPU's have FR32-FR63 377 setlos #HSR0_FRHE,gr4 378 andcc gr6,gr4,gr0,icc0 379 beq icc0,#1,__save_skip_fr32_fr63 380 381 stdfi fr32,@(gr8,#__FPMEDIA_FR(32)) 382 stdfi fr34,@(gr8,#__FPMEDIA_FR(34)) 383 stdfi fr36,@(gr8,#__FPMEDIA_FR(36)) 384 stdfi fr38,@(gr8,#__FPMEDIA_FR(38)) 385 stdfi fr40,@(gr8,#__FPMEDIA_FR(40)) 386 stdfi fr42,@(gr8,#__FPMEDIA_FR(42)) 387 stdfi fr44,@(gr8,#__FPMEDIA_FR(44)) 388 stdfi fr46,@(gr8,#__FPMEDIA_FR(46)) 389 stdfi fr48,@(gr8,#__FPMEDIA_FR(48)) 390 stdfi fr50,@(gr8,#__FPMEDIA_FR(50)) 391 stdfi fr52,@(gr8,#__FPMEDIA_FR(52)) 392 stdfi fr54,@(gr8,#__FPMEDIA_FR(54)) 393 stdfi fr56,@(gr8,#__FPMEDIA_FR(56)) 394 stdfi fr58,@(gr8,#__FPMEDIA_FR(58)) 395 stdfi fr60,@(gr8,#__FPMEDIA_FR(60)) 396 stdfi fr62,@(gr8,#__FPMEDIA_FR(62)) 397__save_skip_fr32_fr63: 398 399 mrdacc acc0 ,fr4 400 mrdacc acc1 ,fr5 401 402 stdfi.p fr4 ,@(gr8,#__FPMEDIA_ACC(0)) 403 404 mrdacc acc2 ,fr6 405 mrdacc acc3 ,fr7 406 407 stdfi.p fr6 ,@(gr8,#__FPMEDIA_ACC(2)) 408 409 mrdaccg accg0,fr4 410 stbfi.p fr4 ,@(gr8,#__FPMEDIA_ACCG(0)) 411 412 mrdaccg accg1,fr5 413 stbfi.p fr5 ,@(gr8,#__FPMEDIA_ACCG(1)) 414 415 mrdaccg accg2,fr6 416 stbfi.p fr6 ,@(gr8,#__FPMEDIA_ACCG(2)) 417 418 mrdaccg accg3,fr7 419 stbfi fr7 ,@(gr8,#__FPMEDIA_ACCG(3)) 420 421 movsg msr0 ,gr4 422 movsg msr1 ,gr5 423 424 stdi gr4 ,@(gr8,#__FPMEDIA_MSR(0)) 425 426 # some CPUs have extra ACCx and ACCGx regs and maybe FSRx regs 427 subicc.p gr7,#0x50,gr0,icc0 428 subicc gr7,#0x31,gr0,icc1 429 beq icc0,#0,__save_acc_fr451 430 beq icc1,#0,__save_acc_fr555 431__save_acc_cont: 432 433 lddfi @(gr8,#__FPMEDIA_FR(4)),fr4 434 lddfi.p @(gr8,#__FPMEDIA_FR(6)),fr6 435 bralr 436 437 # the FR451 also has ACC8-11/ACCG8-11 regs (but not 4-7...) 438__save_acc_fr451: 439 mrdacc acc8 ,fr4 440 mrdacc acc9 ,fr5 441 442 stdfi.p fr4 ,@(gr8,#__FPMEDIA_ACC(4)) 443 444 mrdacc acc10,fr6 445 mrdacc acc11,fr7 446 447 stdfi.p fr6 ,@(gr8,#__FPMEDIA_ACC(6)) 448 449 mrdaccg accg8,fr4 450 stbfi.p fr4 ,@(gr8,#__FPMEDIA_ACCG(4)) 451 452 mrdaccg accg9,fr5 453 stbfi.p fr5 ,@(gr8,#__FPMEDIA_ACCG(5)) 454 455 mrdaccg accg10,fr6 456 stbfi.p fr6 ,@(gr8,#__FPMEDIA_ACCG(6)) 457 458 mrdaccg accg11,fr7 459 stbfi fr7 ,@(gr8,#__FPMEDIA_ACCG(7)) 460 bra __save_acc_cont 461 462 # the FR555 also has ACC4-7/ACCG4-7 regs and an FSR0 reg 463__save_acc_fr555: 464 mnop.p 465 mrdacc acc4 ,fr4 466 mnop.p 467 mrdacc acc5 ,fr5 468 469 stdfi fr4 ,@(gr8,#__FPMEDIA_ACC(4)) 470 471 mnop.p 472 mrdacc acc6 ,fr6 473 mnop.p 474 mrdacc acc7 ,fr7 475 476 stdfi fr6 ,@(gr8,#__FPMEDIA_ACC(6)) 477 478 mnop.p 479 mrdaccg accg4,fr4 480 stbfi fr4 ,@(gr8,#__FPMEDIA_ACCG(4)) 481 482 mnop.p 483 mrdaccg accg5,fr5 484 stbfi fr5 ,@(gr8,#__FPMEDIA_ACCG(5)) 485 486 mnop.p 487 mrdaccg accg6,fr6 488 stbfi fr6 ,@(gr8,#__FPMEDIA_ACCG(6)) 489 490 mnop.p 491 mrdaccg accg7,fr7 492 stbfi fr7 ,@(gr8,#__FPMEDIA_ACCG(7)) 493 494 movsg fsr0 ,gr4 495 sti gr4 ,@(gr8,#__FPMEDIA_FSR(0)) 496 bra __save_acc_cont 497