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 w4, [x2, #GICH_HCR] 51 ldr w5, [x2, #GICH_VMCR] 52 ldr w6, [x2, #GICH_MISR] 53 ldr w7, [x2, #GICH_EISR0] 54 ldr w8, [x2, #GICH_EISR1] 55 ldr w9, [x2, #GICH_ELRSR0] 56 ldr w10, [x2, #GICH_ELRSR1] 57 ldr w11, [x2, #GICH_APR] 58CPU_BE( rev w4, w4 ) 59CPU_BE( rev w5, w5 ) 60CPU_BE( rev w6, w6 ) 61CPU_BE( rev w7, w7 ) 62CPU_BE( rev w8, w8 ) 63CPU_BE( rev w9, w9 ) 64CPU_BE( rev w10, w10 ) 65CPU_BE( rev w11, w11 ) 66 67 str w4, [x3, #VGIC_V2_CPU_HCR] 68 str w5, [x3, #VGIC_V2_CPU_VMCR] 69 str w6, [x3, #VGIC_V2_CPU_MISR] 70CPU_LE( str w7, [x3, #VGIC_V2_CPU_EISR] ) 71CPU_LE( str w8, [x3, #(VGIC_V2_CPU_EISR + 4)] ) 72CPU_LE( str w9, [x3, #VGIC_V2_CPU_ELRSR] ) 73CPU_LE( str w10, [x3, #(VGIC_V2_CPU_ELRSR + 4)] ) 74CPU_BE( str w7, [x3, #(VGIC_V2_CPU_EISR + 4)] ) 75CPU_BE( str w8, [x3, #VGIC_V2_CPU_EISR] ) 76CPU_BE( str w9, [x3, #(VGIC_V2_CPU_ELRSR + 4)] ) 77CPU_BE( str w10, [x3, #VGIC_V2_CPU_ELRSR] ) 78 str w11, [x3, #VGIC_V2_CPU_APR] 79 80 /* Clear GICH_HCR */ 81 str wzr, [x2, #GICH_HCR] 82 83 /* Save list registers */ 84 add x2, x2, #GICH_LR0 85 ldr w4, [x3, #VGIC_CPU_NR_LR] 86 add x3, x3, #VGIC_V2_CPU_LR 871: ldr w5, [x2], #4 88CPU_BE( rev w5, w5 ) 89 str w5, [x3], #4 90 sub w4, w4, #1 91 cbnz w4, 1b 922: 93 ret 94ENDPROC(__save_vgic_v2_state) 95 96/* 97 * Restore the VGIC CPU state from memory 98 * x0: Register pointing to VCPU struct 99 */ 100ENTRY(__restore_vgic_v2_state) 101__restore_vgic_v2_state: 102 /* Get VGIC VCTRL base into x2 */ 103 ldr x2, [x0, #VCPU_KVM] 104 kern_hyp_va x2 105 ldr x2, [x2, #KVM_VGIC_VCTRL] 106 kern_hyp_va x2 107 cbz x2, 2f // disabled 108 109 /* Compute the address of struct vgic_cpu */ 110 add x3, x0, #VCPU_VGIC_CPU 111 112 /* We only restore a minimal set of registers */ 113 ldr w4, [x3, #VGIC_V2_CPU_HCR] 114 ldr w5, [x3, #VGIC_V2_CPU_VMCR] 115 ldr w6, [x3, #VGIC_V2_CPU_APR] 116CPU_BE( rev w4, w4 ) 117CPU_BE( rev w5, w5 ) 118CPU_BE( rev w6, w6 ) 119 120 str w4, [x2, #GICH_HCR] 121 str w5, [x2, #GICH_VMCR] 122 str w6, [x2, #GICH_APR] 123 124 /* Restore list registers */ 125 add x2, x2, #GICH_LR0 126 ldr w4, [x3, #VGIC_CPU_NR_LR] 127 add x3, x3, #VGIC_V2_CPU_LR 1281: ldr w5, [x3], #4 129CPU_BE( rev w5, w5 ) 130 str w5, [x2], #4 131 sub w4, w4, #1 132 cbnz w4, 1b 1332: 134 ret 135ENDPROC(__restore_vgic_v2_state) 136 137 .popsection 138