Skip to content

Commit 33280b4

Browse files
author
Marc Zyngier
committed
ARM: KVM: Add banked registers save/restore
Banked registers are one of the many perks of the 32bit architecture, and the world switch needs to cope with it. This requires some "special" accessors, as these are not accessed using a standard coprocessor instruction. Reviewed-by: Christoffer Dall <[email protected]> Signed-off-by: Marc Zyngier <[email protected]>
1 parent 59cbcdb commit 33280b4

File tree

3 files changed

+89
-0
lines changed

3 files changed

+89
-0
lines changed

arch/arm/kvm/hyp/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ obj-$(CONFIG_KVM_ARM_HOST) += cp15-sr.o
77
obj-$(CONFIG_KVM_ARM_HOST) += timer-sr.o
88
obj-$(CONFIG_KVM_ARM_HOST) += vgic-v2-sr.o
99
obj-$(CONFIG_KVM_ARM_HOST) += vfp.o
10+
obj-$(CONFIG_KVM_ARM_HOST) += banked-sr.o

arch/arm/kvm/hyp/banked-sr.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Original code:
3+
* Copyright (C) 2012 - Virtual Open Systems and Columbia University
4+
* Author: Christoffer Dall <[email protected]>
5+
*
6+
* Mostly rewritten in C by Marc Zyngier <[email protected]>
7+
*
8+
* This program is free software; you can redistribute it and/or modify
9+
* it under the terms of the GNU General Public License version 2 as
10+
* published by the Free Software Foundation.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
*/
20+
21+
#include "hyp.h"
22+
23+
__asm__(".arch_extension virt");
24+
25+
void __hyp_text __banked_save_state(struct kvm_cpu_context *ctxt)
26+
{
27+
ctxt->gp_regs.usr_regs.ARM_sp = read_special(SP_usr);
28+
ctxt->gp_regs.usr_regs.ARM_pc = read_special(ELR_hyp);
29+
ctxt->gp_regs.usr_regs.ARM_cpsr = read_special(SPSR);
30+
ctxt->gp_regs.KVM_ARM_SVC_sp = read_special(SP_svc);
31+
ctxt->gp_regs.KVM_ARM_SVC_lr = read_special(LR_svc);
32+
ctxt->gp_regs.KVM_ARM_SVC_spsr = read_special(SPSR_svc);
33+
ctxt->gp_regs.KVM_ARM_ABT_sp = read_special(SP_abt);
34+
ctxt->gp_regs.KVM_ARM_ABT_lr = read_special(LR_abt);
35+
ctxt->gp_regs.KVM_ARM_ABT_spsr = read_special(SPSR_abt);
36+
ctxt->gp_regs.KVM_ARM_UND_sp = read_special(SP_und);
37+
ctxt->gp_regs.KVM_ARM_UND_lr = read_special(LR_und);
38+
ctxt->gp_regs.KVM_ARM_UND_spsr = read_special(SPSR_und);
39+
ctxt->gp_regs.KVM_ARM_IRQ_sp = read_special(SP_irq);
40+
ctxt->gp_regs.KVM_ARM_IRQ_lr = read_special(LR_irq);
41+
ctxt->gp_regs.KVM_ARM_IRQ_spsr = read_special(SPSR_irq);
42+
ctxt->gp_regs.KVM_ARM_FIQ_r8 = read_special(R8_fiq);
43+
ctxt->gp_regs.KVM_ARM_FIQ_r9 = read_special(R9_fiq);
44+
ctxt->gp_regs.KVM_ARM_FIQ_r10 = read_special(R10_fiq);
45+
ctxt->gp_regs.KVM_ARM_FIQ_fp = read_special(R11_fiq);
46+
ctxt->gp_regs.KVM_ARM_FIQ_ip = read_special(R12_fiq);
47+
ctxt->gp_regs.KVM_ARM_FIQ_sp = read_special(SP_fiq);
48+
ctxt->gp_regs.KVM_ARM_FIQ_lr = read_special(LR_fiq);
49+
ctxt->gp_regs.KVM_ARM_FIQ_spsr = read_special(SPSR_fiq);
50+
}
51+
52+
void __hyp_text __banked_restore_state(struct kvm_cpu_context *ctxt)
53+
{
54+
write_special(ctxt->gp_regs.usr_regs.ARM_sp, SP_usr);
55+
write_special(ctxt->gp_regs.usr_regs.ARM_pc, ELR_hyp);
56+
write_special(ctxt->gp_regs.usr_regs.ARM_cpsr, SPSR_cxsf);
57+
write_special(ctxt->gp_regs.KVM_ARM_SVC_sp, SP_svc);
58+
write_special(ctxt->gp_regs.KVM_ARM_SVC_lr, LR_svc);
59+
write_special(ctxt->gp_regs.KVM_ARM_SVC_spsr, SPSR_svc);
60+
write_special(ctxt->gp_regs.KVM_ARM_ABT_sp, SP_abt);
61+
write_special(ctxt->gp_regs.KVM_ARM_ABT_lr, LR_abt);
62+
write_special(ctxt->gp_regs.KVM_ARM_ABT_spsr, SPSR_abt);
63+
write_special(ctxt->gp_regs.KVM_ARM_UND_sp, SP_und);
64+
write_special(ctxt->gp_regs.KVM_ARM_UND_lr, LR_und);
65+
write_special(ctxt->gp_regs.KVM_ARM_UND_spsr, SPSR_und);
66+
write_special(ctxt->gp_regs.KVM_ARM_IRQ_sp, SP_irq);
67+
write_special(ctxt->gp_regs.KVM_ARM_IRQ_lr, LR_irq);
68+
write_special(ctxt->gp_regs.KVM_ARM_IRQ_spsr, SPSR_irq);
69+
write_special(ctxt->gp_regs.KVM_ARM_FIQ_r8, R8_fiq);
70+
write_special(ctxt->gp_regs.KVM_ARM_FIQ_r9, R9_fiq);
71+
write_special(ctxt->gp_regs.KVM_ARM_FIQ_r10, R10_fiq);
72+
write_special(ctxt->gp_regs.KVM_ARM_FIQ_fp, R11_fiq);
73+
write_special(ctxt->gp_regs.KVM_ARM_FIQ_ip, R12_fiq);
74+
write_special(ctxt->gp_regs.KVM_ARM_FIQ_sp, SP_fiq);
75+
write_special(ctxt->gp_regs.KVM_ARM_FIQ_lr, LR_fiq);
76+
write_special(ctxt->gp_regs.KVM_ARM_FIQ_spsr, SPSR_fiq);
77+
}

arch/arm/kvm/hyp/hyp.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@
4545
})
4646
#define read_sysreg(...) __read_sysreg(__VA_ARGS__)
4747

48+
#define write_special(v, r) \
49+
asm volatile("msr " __stringify(r) ", %0" : : "r" (v))
50+
#define read_special(r) ({ \
51+
u32 __val; \
52+
asm volatile("mrs %0, " __stringify(r) : "=r" (__val)); \
53+
__val; \
54+
})
55+
4856
#define TTBR0 __ACCESS_CP15_64(0, c2)
4957
#define TTBR1 __ACCESS_CP15_64(1, c2)
5058
#define VTTBR __ACCESS_CP15_64(6, c2)
@@ -99,4 +107,7 @@ static inline bool __vfp_enabled(void)
99107
return !(read_sysreg(HCPTR) & (HCPTR_TCP(11) | HCPTR_TCP(10)));
100108
}
101109

110+
void __hyp_text __banked_save_state(struct kvm_cpu_context *ctxt);
111+
void __hyp_text __banked_restore_state(struct kvm_cpu_context *ctxt);
112+
102113
#endif /* __ARM_KVM_HYP_H__ */

0 commit comments

Comments
 (0)