forked from Minki/linux
ee8348496c
Commit863771a28e
("powerpc/32s: Convert switch_mmu_context() to C") moved the switch_mmu_context() to C. While in principle a good idea, it meant that the function now uses the stack. The stack is not accessible from real mode though. So to keep calling the function, let's turn on MSR_DR while we call it. That way, all pointer references to the stack are handled virtually. In addition, make sure to save/restore r12 on the stack, as it may get clobbered by the C function. Fixes:863771a28e
("powerpc/32s: Convert switch_mmu_context() to C") Cc: stable@vger.kernel.org # v5.14+ Reported-by: Matt Evans <matt@ozlabs.org> Signed-off-by: Alexander Graf <graf@amazon.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20220510123717.24508-1-graf@amazon.com
149 lines
3.4 KiB
ArmAsm
149 lines
3.4 KiB
ArmAsm
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
*
|
|
* Copyright SUSE Linux Products GmbH 2009
|
|
*
|
|
* Authors: Alexander Graf <agraf@suse.de>
|
|
*/
|
|
|
|
/******************************************************************************
|
|
* *
|
|
* Entry code *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
.macro LOAD_GUEST_SEGMENTS
|
|
|
|
/* Required state:
|
|
*
|
|
* MSR = ~IR|DR
|
|
* R1 = host R1
|
|
* R2 = host R2
|
|
* R3 = shadow vcpu
|
|
* all other volatile GPRS = free except R4, R6
|
|
* SVCPU[CR] = guest CR
|
|
* SVCPU[XER] = guest XER
|
|
* SVCPU[CTR] = guest CTR
|
|
* SVCPU[LR] = guest LR
|
|
*/
|
|
|
|
#define XCHG_SR(n) lwz r9, (SVCPU_SR+(n*4))(r3); \
|
|
mtsr n, r9
|
|
|
|
XCHG_SR(0)
|
|
XCHG_SR(1)
|
|
XCHG_SR(2)
|
|
XCHG_SR(3)
|
|
XCHG_SR(4)
|
|
XCHG_SR(5)
|
|
XCHG_SR(6)
|
|
XCHG_SR(7)
|
|
XCHG_SR(8)
|
|
XCHG_SR(9)
|
|
XCHG_SR(10)
|
|
XCHG_SR(11)
|
|
XCHG_SR(12)
|
|
XCHG_SR(13)
|
|
XCHG_SR(14)
|
|
XCHG_SR(15)
|
|
|
|
/* Clear BATs. */
|
|
|
|
#define KVM_KILL_BAT(n, reg) \
|
|
mtspr SPRN_IBAT##n##U,reg; \
|
|
mtspr SPRN_IBAT##n##L,reg; \
|
|
mtspr SPRN_DBAT##n##U,reg; \
|
|
mtspr SPRN_DBAT##n##L,reg; \
|
|
|
|
li r9, 0
|
|
KVM_KILL_BAT(0, r9)
|
|
KVM_KILL_BAT(1, r9)
|
|
KVM_KILL_BAT(2, r9)
|
|
KVM_KILL_BAT(3, r9)
|
|
|
|
.endm
|
|
|
|
/******************************************************************************
|
|
* *
|
|
* Exit code *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
.macro LOAD_HOST_SEGMENTS
|
|
|
|
/* Register usage at this point:
|
|
*
|
|
* R1 = host R1
|
|
* R2 = host R2
|
|
* R12 = exit handler id
|
|
* R13 = shadow vcpu - SHADOW_VCPU_OFF
|
|
* SVCPU.* = guest *
|
|
* SVCPU[CR] = guest CR
|
|
* SVCPU[XER] = guest XER
|
|
* SVCPU[CTR] = guest CTR
|
|
* SVCPU[LR] = guest LR
|
|
*
|
|
*/
|
|
|
|
/* Restore BATs */
|
|
|
|
/* We only overwrite the upper part, so we only restoree
|
|
the upper part. */
|
|
#define KVM_LOAD_BAT(n, reg, RA, RB) \
|
|
lwz RA,(n*16)+0(reg); \
|
|
lwz RB,(n*16)+4(reg); \
|
|
mtspr SPRN_IBAT##n##U,RA; \
|
|
mtspr SPRN_IBAT##n##L,RB; \
|
|
lwz RA,(n*16)+8(reg); \
|
|
lwz RB,(n*16)+12(reg); \
|
|
mtspr SPRN_DBAT##n##U,RA; \
|
|
mtspr SPRN_DBAT##n##L,RB; \
|
|
|
|
lis r9, BATS@ha
|
|
addi r9, r9, BATS@l
|
|
tophys(r9, r9)
|
|
KVM_LOAD_BAT(0, r9, r10, r11)
|
|
KVM_LOAD_BAT(1, r9, r10, r11)
|
|
KVM_LOAD_BAT(2, r9, r10, r11)
|
|
KVM_LOAD_BAT(3, r9, r10, r11)
|
|
|
|
/* Restore Segment Registers */
|
|
|
|
/* 0xc - 0xf */
|
|
|
|
li r0, 4
|
|
mtctr r0
|
|
LOAD_REG_IMMEDIATE(r3, 0x20000000 | (0x111 * 0xc))
|
|
lis r4, 0xc000
|
|
3: mtsrin r3, r4
|
|
addi r3, r3, 0x111 /* increment VSID */
|
|
addis r4, r4, 0x1000 /* address of next segment */
|
|
bdnz 3b
|
|
|
|
/* 0x0 - 0xb */
|
|
|
|
/* switch_mmu_context() needs paging, let's enable it */
|
|
mfmsr r9
|
|
ori r11, r9, MSR_DR
|
|
mtmsr r11
|
|
sync
|
|
|
|
/* switch_mmu_context() clobbers r12, rescue it */
|
|
SAVE_GPR(12, r1)
|
|
|
|
/* Calling switch_mmu_context(<inv>, current->mm, <inv>); */
|
|
lwz r4, MM(r2)
|
|
bl switch_mmu_context
|
|
|
|
/* restore r12 */
|
|
REST_GPR(12, r1)
|
|
|
|
/* Disable paging again */
|
|
mfmsr r9
|
|
li r6, MSR_DR
|
|
andc r9, r9, r6
|
|
mtmsr r9
|
|
sync
|
|
|
|
.endm
|