Skip to content

Commit 9da5ac2

Browse files
Russell KingChristoffer Dall
authored andcommitted
ARM: soft-reboot into same mode that we entered the kernel
When we soft-reboot (eg, kexec) from one kernel into the next, we need to ensure that we enter the new kernel in the same processor mode as when we were entered, so that (eg) the new kernel can install its own hypervisor - the old kernel's hypervisor will have been overwritten. In order to do this, we need to pass a flag to cpu_reset() so it knows what to do, and we need to modify the kernel's own hypervisor stub to allow it to handle a soft-reboot. As we are always guaranteed to install our own hypervisor if we're entered in HYP32 mode, and KVM will have moved itself out of the way on kexec/normal reboot, we can assume that our hypervisor is in place when we want to kexec, so changing our hypervisor API should not be a problem. Tested-by: Keerthy <[email protected]> Acked-by: Catalin Marinas <[email protected]> Signed-off-by: Russell King <[email protected]> Signed-off-by: Marc Zyngier <[email protected]> Signed-off-by: Christoffer Dall <[email protected]>
1 parent 1342337 commit 9da5ac2

File tree

4 files changed

+28
-8
lines changed

4 files changed

+28
-8
lines changed

arch/arm/include/asm/proc-fns.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ extern struct processor {
4343
/*
4444
* Special stuff for a reset
4545
*/
46-
void (*reset)(unsigned long addr) __attribute__((noreturn));
46+
void (*reset)(unsigned long addr, bool hvc) __attribute__((noreturn));
4747
/*
4848
* Idle the processor
4949
*/
@@ -88,7 +88,7 @@ extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte);
8888
#else
8989
extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext);
9090
#endif
91-
extern void cpu_reset(unsigned long addr) __attribute__((noreturn));
91+
extern void cpu_reset(unsigned long addr, bool hvc) __attribute__((noreturn));
9292

9393
/* These three are private to arch/arm/kernel/suspend.c */
9494
extern void cpu_do_suspend(void *);

arch/arm/kernel/hyp-stub.S

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#define HVC_GET_VECTORS 0
2626
#define HVC_SET_VECTORS 1
27+
#define HVC_SOFT_RESTART 2
2728

2829
#ifndef ZIMAGE
2930
/*
@@ -215,6 +216,10 @@ __hyp_stub_do_trap:
215216
mcr p15, 4, r1, c12, c0, 0 @ set HVBAR
216217
b __hyp_stub_exit
217218

219+
1: teq r0, #HVC_SOFT_RESTART
220+
bne 1f
221+
bx r3
222+
218223
1: mov r0, #-1
219224

220225
__hyp_stub_exit:
@@ -256,6 +261,14 @@ ENTRY(__hyp_set_vectors)
256261
ret lr
257262
ENDPROC(__hyp_set_vectors)
258263

264+
ENTRY(__hyp_soft_restart)
265+
mov r3, r0
266+
mov r0, #HVC_SOFT_RESTART
267+
__HVC(0)
268+
mov r0, r3
269+
ret lr
270+
ENDPROC(__hyp_soft_restart)
271+
259272
#ifndef ZIMAGE
260273
.align 2
261274
.L__boot_cpu_mode_offset:

arch/arm/kernel/reboot.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@
1212

1313
#include <asm/cacheflush.h>
1414
#include <asm/idmap.h>
15+
#include <asm/virt.h>
1516

1617
#include "reboot.h"
1718

18-
typedef void (*phys_reset_t)(unsigned long);
19+
typedef void (*phys_reset_t)(unsigned long, bool);
1920

2021
/*
2122
* Function pointers to optional machine specific functions
@@ -51,7 +52,9 @@ static void __soft_restart(void *addr)
5152

5253
/* Switch to the identity mapping. */
5354
phys_reset = (phys_reset_t)virt_to_idmap(cpu_reset);
54-
phys_reset((unsigned long)addr);
55+
56+
/* original stub should be restored by kvm */
57+
phys_reset((unsigned long)addr, is_hyp_mode_available());
5558

5659
/* Should never get here. */
5760
BUG();

arch/arm/mm/proc-v7.S

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,15 @@ ENDPROC(cpu_v7_proc_fin)
5353
.align 5
5454
.pushsection .idmap.text, "ax"
5555
ENTRY(cpu_v7_reset)
56-
mrc p15, 0, r1, c1, c0, 0 @ ctrl register
57-
bic r1, r1, #0x1 @ ...............m
58-
THUMB( bic r1, r1, #1 << 30 ) @ SCTLR.TE (Thumb exceptions)
59-
mcr p15, 0, r1, c1, c0, 0 @ disable MMU
56+
mrc p15, 0, r2, c1, c0, 0 @ ctrl register
57+
bic r2, r2, #0x1 @ ...............m
58+
THUMB( bic r2, r2, #1 << 30 ) @ SCTLR.TE (Thumb exceptions)
59+
mcr p15, 0, r2, c1, c0, 0 @ disable MMU
6060
isb
61+
#ifdef CONFIG_ARM_VIRT_EXT
62+
teq r1, #0
63+
bne __hyp_soft_restart
64+
#endif
6165
bx r0
6266
ENDPROC(cpu_v7_reset)
6367
.popsection

0 commit comments

Comments
 (0)