1/* 2 * Copyright (C) 2012,2013 - ARM Ltd 3 * Author: Marc Zyngier <marc.zyngier@arm.com> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18#include <linux/linkage.h> 19#include <linux/irqchip/arm-gic.h> 20 21#include <asm/assembler.h> 22#include <asm/memory.h> 23#include <asm/asm-offsets.h> 24#include <asm/kvm.h> 25#include <asm/kvm_asm.h> 26#include <asm/kvm_arm.h> 27#include <asm/kvm_mmu.h> 28 29 .text 30 .pushsection .hyp.text, "ax" 31 32/* 33 * Save the VGIC CPU state into memory 34 * x0: Register pointing to VCPU struct 35 * Do not corrupt x1!!! 36 */ 37ENTRY(__save_vgic_v2_state) 38__save_vgic_v2_state: 39 /* Get VGIC VCTRL base into x2 */ 40 ldr x2, [x0, #VCPU_KVM] 41 kern_hyp_va x2 42 ldr x2, [x2, #KVM_VGIC_VCTRL] 43 kern_hyp_va x2 44 cbz x2, 2f // disabled 45 46 /* Compute the address of struct vgic_cpu */ 47 add x3, x0, #VCPU_VGIC_CPU 48 49 /* Save all interesting registers */ 50 ldr w5, [x2, #GICH_VMCR] 51 ldr w6, [x2, #GICH_MISR] 52 ldr w7, [x2, #GICH_EISR0] 53 ldr w8, [x2, #GICH_EISR1] 54 ldr w9, [x2, #GICH_ELRSR0] 55 ldr w10, [x2, #GICH_ELRSR1] 56 ldr w11, [x2, #GICH_APR] 57CPU_BE( rev w5, w5 ) 58CPU_BE( rev w6, w6 ) 59CPU_BE( rev w7, w7 ) 60CPU_BE( rev w8, w8 ) 61CPU_BE( rev w9, w9 ) 62CPU_BE( rev w10, w10 ) 63CPU_BE( rev w11, w11 ) 64 65 str w5, [x3, #VGIC_V2_CPU_VMCR] 66 str w6, [x3, #VGIC_V2_CPU_MISR] 67CPU_LE( str w7, [x3, #VGIC_V2_CPU_EISR] ) 68CPU_LE( str w8, [x3, #(VGIC_V2_CPU_EISR + 4)] ) 69CPU_LE( str w9, [x3, #VGIC_V2_CPU_ELRSR] ) 70CPU_LE( str w10, [x3, #(VGIC_V2_CPU_ELRSR + 4)] ) 71CPU_BE( str w7, [x3, #(VGIC_V2_CPU_EISR + 4)] ) 72CPU_BE( str w8, [x3, #VGIC_V2_CPU_EISR] ) 73CPU_BE( str w9, [x3, #(VGIC_V2_CPU_ELRSR + 4)] ) 74CPU_BE( str w10, [x3, #VGIC_V2_CPU_ELRSR] ) 75 str w11, [x3, #VGIC_V2_CPU_APR] 76 77 /* Clear GICH_HCR */ 78 str wzr, [x2, #GICH_HCR] 79 80 /* Save list registers */ 81 add x2, x2, #GICH_LR0 82 ldr w4, [x3, #VGIC_CPU_NR_LR] 83 add x3, x3, #VGIC_V2_CPU_LR 841: ldr w5, [x2], #4 85CPU_BE( rev w5, w5 ) 86 str w5, [x3], #4 87 sub w4, w4, #1 88 cbnz w4, 1b 892: 90 ret 91ENDPROC(__save_vgic_v2_state) 92 93/* 94 * Restore the VGIC CPU state from memory 95 * x0: Register pointing to VCPU struct 96 */ 97ENTRY(__restore_vgic_v2_state) 98__restore_vgic_v2_state: 99 /* Get VGIC VCTRL base into x2 */ 100 ldr x2, [x0, #VCPU_KVM] 101 kern_hyp_va x2 102 ldr x2, [x2, #KVM_VGIC_VCTRL] 103 kern_hyp_va x2 104 cbz x2, 2f // disabled 105 106 /* Compute the address of struct vgic_cpu */ 107 add x3, x0, #VCPU_VGIC_CPU 108 109 /* We only restore a minimal set of registers */ 110 ldr w4, [x3, #VGIC_V2_CPU_HCR] 111 ldr w5, [x3, #VGIC_V2_CPU_VMCR] 112 ldr w6, [x3, #VGIC_V2_CPU_APR] 113CPU_BE( rev w4, w4 ) 114CPU_BE( rev w5, w5 ) 115CPU_BE( rev w6, w6 ) 116 117 str w4, [x2, #GICH_HCR] 118 str w5, [x2, #GICH_VMCR] 119 str w6, [x2, #GICH_APR] 120 121 /* Restore list registers */ 122 add x2, x2, #GICH_LR0 123 ldr w4, [x3, #VGIC_CPU_NR_LR] 124 add x3, x3, #VGIC_V2_CPU_LR 1251: ldr w5, [x3], #4 126CPU_BE( rev w5, w5 ) 127 str w5, [x2], #4 128 sub w4, w4, #1 129 cbnz w4, 1b 1302: 131 ret 132ENDPROC(__restore_vgic_v2_state) 133 134 .popsection 135