Skip to content

Commit c0c2cdb

Browse files
author
Marc Zyngier
committed
ARM: KVM: Add vgic v2 save/restore
This patch shouldn't exist, as we should be able to reuse the arm64 version for free. I'll get there eventually, but in the meantime I need an interrupt controller. Reviewed-by: Christoffer Dall <[email protected]> Signed-off-by: Marc Zyngier <[email protected]>
1 parent e59bff9 commit c0c2cdb

File tree

3 files changed

+88
-0
lines changed

3 files changed

+88
-0
lines changed

arch/arm/kvm/hyp/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@
55
obj-$(CONFIG_KVM_ARM_HOST) += tlb.o
66
obj-$(CONFIG_KVM_ARM_HOST) += cp15-sr.o
77
obj-$(CONFIG_KVM_ARM_HOST) += timer-sr.o
8+
obj-$(CONFIG_KVM_ARM_HOST) += vgic-v2-sr.o

arch/arm/kvm/hyp/hyp.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@
8080
void __timer_save_state(struct kvm_vcpu *vcpu);
8181
void __timer_restore_state(struct kvm_vcpu *vcpu);
8282

83+
void __vgic_v2_save_state(struct kvm_vcpu *vcpu);
84+
void __vgic_v2_restore_state(struct kvm_vcpu *vcpu);
85+
8386
void __sysreg_save_state(struct kvm_cpu_context *ctxt);
8487
void __sysreg_restore_state(struct kvm_cpu_context *ctxt);
8588

arch/arm/kvm/hyp/vgic-v2-sr.c

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Copyright (C) 2012-2015 - ARM Ltd
3+
* Author: Marc Zyngier <[email protected]>
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/compiler.h>
19+
#include <linux/irqchip/arm-gic.h>
20+
#include <linux/kvm_host.h>
21+
22+
#include <asm/kvm_mmu.h>
23+
24+
#include "hyp.h"
25+
26+
/* vcpu is already in the HYP VA space */
27+
void __hyp_text __vgic_v2_save_state(struct kvm_vcpu *vcpu)
28+
{
29+
struct kvm *kvm = kern_hyp_va(vcpu->kvm);
30+
struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
31+
struct vgic_dist *vgic = &kvm->arch.vgic;
32+
void __iomem *base = kern_hyp_va(vgic->vctrl_base);
33+
u32 eisr0, eisr1, elrsr0, elrsr1;
34+
int i, nr_lr;
35+
36+
if (!base)
37+
return;
38+
39+
nr_lr = vcpu->arch.vgic_cpu.nr_lr;
40+
cpu_if->vgic_vmcr = readl_relaxed(base + GICH_VMCR);
41+
cpu_if->vgic_misr = readl_relaxed(base + GICH_MISR);
42+
eisr0 = readl_relaxed(base + GICH_EISR0);
43+
elrsr0 = readl_relaxed(base + GICH_ELRSR0);
44+
if (unlikely(nr_lr > 32)) {
45+
eisr1 = readl_relaxed(base + GICH_EISR1);
46+
elrsr1 = readl_relaxed(base + GICH_ELRSR1);
47+
} else {
48+
eisr1 = elrsr1 = 0;
49+
}
50+
#ifdef CONFIG_CPU_BIG_ENDIAN
51+
cpu_if->vgic_eisr = ((u64)eisr0 << 32) | eisr1;
52+
cpu_if->vgic_elrsr = ((u64)elrsr0 << 32) | elrsr1;
53+
#else
54+
cpu_if->vgic_eisr = ((u64)eisr1 << 32) | eisr0;
55+
cpu_if->vgic_elrsr = ((u64)elrsr1 << 32) | elrsr0;
56+
#endif
57+
cpu_if->vgic_apr = readl_relaxed(base + GICH_APR);
58+
59+
writel_relaxed(0, base + GICH_HCR);
60+
61+
for (i = 0; i < nr_lr; i++)
62+
cpu_if->vgic_lr[i] = readl_relaxed(base + GICH_LR0 + (i * 4));
63+
}
64+
65+
/* vcpu is already in the HYP VA space */
66+
void __hyp_text __vgic_v2_restore_state(struct kvm_vcpu *vcpu)
67+
{
68+
struct kvm *kvm = kern_hyp_va(vcpu->kvm);
69+
struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
70+
struct vgic_dist *vgic = &kvm->arch.vgic;
71+
void __iomem *base = kern_hyp_va(vgic->vctrl_base);
72+
int i, nr_lr;
73+
74+
if (!base)
75+
return;
76+
77+
writel_relaxed(cpu_if->vgic_hcr, base + GICH_HCR);
78+
writel_relaxed(cpu_if->vgic_vmcr, base + GICH_VMCR);
79+
writel_relaxed(cpu_if->vgic_apr, base + GICH_APR);
80+
81+
nr_lr = vcpu->arch.vgic_cpu.nr_lr;
82+
for (i = 0; i < nr_lr; i++)
83+
writel_relaxed(cpu_if->vgic_lr[i], base + GICH_LR0 + (i * 4));
84+
}

0 commit comments

Comments
 (0)