123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- /*
- * Copyright (C) 2012,2013 - ARM Ltd
- * Author: Marc Zyngier <marc.zyngier@arm.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- #include <linux/linkage.h>
- #include <linux/irqchip/arm-gic.h>
- #include <asm/assembler.h>
- #include <asm/memory.h>
- #include <asm/asm-offsets.h>
- #include <asm/kvm.h>
- #include <asm/kvm_asm.h>
- #include <asm/kvm_arm.h>
- #include <asm/kvm_mmu.h>
- .text
- .pushsection .hyp.text, "ax"
- /*
- * Save the VGIC CPU state into memory
- * x0: Register pointing to VCPU struct
- * Do not corrupt x1!!!
- */
- ENTRY(__save_vgic_v2_state)
- __save_vgic_v2_state:
- /* Get VGIC VCTRL base into x2 */
- ldr x2, [x0, #VCPU_KVM]
- kern_hyp_va x2
- ldr x2, [x2, #KVM_VGIC_VCTRL]
- kern_hyp_va x2
- cbz x2, 2f // disabled
- /* Compute the address of struct vgic_cpu */
- add x3, x0, #VCPU_VGIC_CPU
- /* Save all interesting registers */
- ldr w5, [x2, #GICH_VMCR]
- ldr w6, [x2, #GICH_MISR]
- ldr w7, [x2, #GICH_EISR0]
- ldr w8, [x2, #GICH_EISR1]
- ldr w9, [x2, #GICH_ELRSR0]
- ldr w10, [x2, #GICH_ELRSR1]
- ldr w11, [x2, #GICH_APR]
- CPU_BE( rev w5, w5 )
- CPU_BE( rev w6, w6 )
- CPU_BE( rev w7, w7 )
- CPU_BE( rev w8, w8 )
- CPU_BE( rev w9, w9 )
- CPU_BE( rev w10, w10 )
- CPU_BE( rev w11, w11 )
- str w5, [x3, #VGIC_V2_CPU_VMCR]
- str w6, [x3, #VGIC_V2_CPU_MISR]
- CPU_LE( str w7, [x3, #VGIC_V2_CPU_EISR] )
- CPU_LE( str w8, [x3, #(VGIC_V2_CPU_EISR + 4)] )
- CPU_LE( str w9, [x3, #VGIC_V2_CPU_ELRSR] )
- CPU_LE( str w10, [x3, #(VGIC_V2_CPU_ELRSR + 4)] )
- CPU_BE( str w7, [x3, #(VGIC_V2_CPU_EISR + 4)] )
- CPU_BE( str w8, [x3, #VGIC_V2_CPU_EISR] )
- CPU_BE( str w9, [x3, #(VGIC_V2_CPU_ELRSR + 4)] )
- CPU_BE( str w10, [x3, #VGIC_V2_CPU_ELRSR] )
- str w11, [x3, #VGIC_V2_CPU_APR]
- /* Clear GICH_HCR */
- str wzr, [x2, #GICH_HCR]
- /* Save list registers */
- add x2, x2, #GICH_LR0
- ldr w4, [x3, #VGIC_CPU_NR_LR]
- add x3, x3, #VGIC_V2_CPU_LR
- 1: ldr w5, [x2], #4
- CPU_BE( rev w5, w5 )
- str w5, [x3], #4
- sub w4, w4, #1
- cbnz w4, 1b
- 2:
- ret
- ENDPROC(__save_vgic_v2_state)
- /*
- * Restore the VGIC CPU state from memory
- * x0: Register pointing to VCPU struct
- */
- ENTRY(__restore_vgic_v2_state)
- __restore_vgic_v2_state:
- /* Get VGIC VCTRL base into x2 */
- ldr x2, [x0, #VCPU_KVM]
- kern_hyp_va x2
- ldr x2, [x2, #KVM_VGIC_VCTRL]
- kern_hyp_va x2
- cbz x2, 2f // disabled
- /* Compute the address of struct vgic_cpu */
- add x3, x0, #VCPU_VGIC_CPU
- /* We only restore a minimal set of registers */
- ldr w4, [x3, #VGIC_V2_CPU_HCR]
- ldr w5, [x3, #VGIC_V2_CPU_VMCR]
- ldr w6, [x3, #VGIC_V2_CPU_APR]
- CPU_BE( rev w4, w4 )
- CPU_BE( rev w5, w5 )
- CPU_BE( rev w6, w6 )
- str w4, [x2, #GICH_HCR]
- str w5, [x2, #GICH_VMCR]
- str w6, [x2, #GICH_APR]
- /* Restore list registers */
- add x2, x2, #GICH_LR0
- ldr w4, [x3, #VGIC_CPU_NR_LR]
- add x3, x3, #VGIC_V2_CPU_LR
- 1: ldr w5, [x3], #4
- CPU_BE( rev w5, w5 )
- str w5, [x2], #4
- sub w4, w4, #1
- cbnz w4, 1b
- 2:
- ret
- ENDPROC(__restore_vgic_v2_state)
- .popsection
|