| 1 | /* SPDX-License-Identifier: GPL-2.0-only */
|
| 2 | /*
|
| 3 | * Context switch support for Hexagon
|
| 4 | *
|
| 5 | * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
|
| 6 | */
|
| 7 |
|
| 8 | |
| 9 |
|
| 10 | .text
|
| 11 |
|
| 12 | /*
|
| 13 | * The register used as a fast-path thread information pointer
|
| 14 | * is determined as a kernel configuration option. If it happens
|
| 15 | * to be a callee-save register, we're going to be saving and
|
| 16 | * restoring it twice here.
|
| 17 | *
|
| 18 | * This code anticipates a revised ABI where R20-23 are added
|
| 19 | * to the set of callee-save registers, but this should be
|
| 20 | * backward compatible to legacy tools.
|
| 21 | */
|
| 22 |
|
| 23 |
|
| 24 | /*
|
| 25 | * void switch_to(struct task_struct *prev,
|
| 26 | * struct task_struct *next, struct task_struct *last);
|
| 27 | */
|
| 28 | .p2align 2
|
| 29 | .globl __switch_to
|
| 30 | .type __switch_to, @function
|
| 31 |
|
| 32 | /*
|
| 33 | * When we exit the wormhole, we need to store the previous task
|
| 34 | * in the new R0's pointer. Technically it should be R2, but they should
|
| 35 | * be the same; seems like a legacy thing. In short, don't butcher
|
| 36 | * R0, let it go back out unmolested.
|
| 37 | */
|
| 38 |
|
| 39 | __switch_to:
|
| 40 | /*
|
| 41 | * Push callee-saves onto "prev" stack.
|
| 42 | * Here, we're sneaky because the LR and FP
|
| 43 | * storage of the thread_stack structure
|
| 44 | * is automagically allocated by allocframe,
|
| 45 | * so we pass struct size less 8.
|
| 46 | */
|
| 47 | allocframe( |
| 48 | memd(R29+ |
| 49 | memd(R29+ |
| 50 | memd(R29+ |
| 51 | memd(R29+ |
| 52 | memd(R29+ |
| 53 | memd(R29+ |
| 54 | /* Stash thread_info pointer in task_struct */
|
| 55 | memw(R0+ |
| 56 | memw(R0 + |
| 57 | /* Switch to "next" stack and restore callee saves from there */
|
| 58 | R29 = memw(R1 + |
| 59 | {
|
| 60 | R27:26 = memd(R29+ |
| 61 | R25:24 = memd(R29+ |
| 62 | }
|
| 63 | {
|
| 64 | R23:22 = memd(R29+ |
| 65 | R21:20 = memd(R29+ |
| 66 | }
|
| 67 | {
|
| 68 | R19:18 = memd(R29+ |
| 69 | R17:16 = memd(R29+ |
| 70 | }
|
| 71 | {
|
| 72 | /* THREADINFO_REG is currently one of the callee-saved regs
|
| 73 | * above, and so be sure to re-load it last.
|
| 74 | */
|
| 75 | THREADINFO_REG = memw(R1 + |
| 76 | R31:30 = memd(R29+ |
| 77 | }
|
| 78 | {
|
| 79 | R29 = add(R29, |
| 80 | jumpr R31;
|
| 81 | }
|
| 82 | .size __switch_to, .-__switch_to
|