146 строки
3.1 KiB
ArmAsm
146 строки
3.1 KiB
ArmAsm
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
*
|
|
* Copyright SUSE Linux Products GmbH 2009
|
|
*
|
|
* Authors: Alexander Graf <agraf@suse.de>
|
|
*/
|
|
|
|
#include <asm/asm-compat.h>
|
|
#include <asm/feature-fixups.h>
|
|
|
|
#define SHADOW_SLB_ENTRY_LEN 0x10
|
|
#define OFFSET_ESID(x) (SHADOW_SLB_ENTRY_LEN * x)
|
|
#define OFFSET_VSID(x) ((SHADOW_SLB_ENTRY_LEN * x) + 8)
|
|
|
|
/******************************************************************************
|
|
* *
|
|
* Entry code *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
.macro LOAD_GUEST_SEGMENTS
|
|
|
|
/* Required state:
|
|
*
|
|
* MSR = ~IR|DR
|
|
* R13 = PACA
|
|
* 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
|
|
*/
|
|
|
|
BEGIN_FW_FTR_SECTION
|
|
|
|
/* Declare SLB shadow as 0 entries big */
|
|
|
|
ld r11, PACA_SLBSHADOWPTR(r13)
|
|
li r8, 0
|
|
stb r8, 3(r11)
|
|
|
|
END_FW_FTR_SECTION_IFSET(FW_FEATURE_LPAR)
|
|
|
|
/* Flush SLB */
|
|
|
|
li r10, 0
|
|
slbmte r10, r10
|
|
slbia
|
|
|
|
/* Fill SLB with our shadow */
|
|
|
|
lbz r12, SVCPU_SLB_MAX(r3)
|
|
mulli r12, r12, 16
|
|
addi r12, r12, SVCPU_SLB
|
|
add r12, r12, r3
|
|
|
|
/* for (r11 = kvm_slb; r11 < kvm_slb + kvm_slb_size; r11+=slb_entry) */
|
|
li r11, SVCPU_SLB
|
|
add r11, r11, r3
|
|
|
|
slb_loop_enter:
|
|
|
|
ld r10, 0(r11)
|
|
|
|
andis. r9, r10, SLB_ESID_V@h
|
|
beq slb_loop_enter_skip
|
|
|
|
ld r9, 8(r11)
|
|
slbmte r9, r10
|
|
|
|
slb_loop_enter_skip:
|
|
addi r11, r11, 16
|
|
cmpd cr0, r11, r12
|
|
blt slb_loop_enter
|
|
|
|
slb_do_enter:
|
|
|
|
.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 [=PACA on PPC64]
|
|
* SVCPU.* = guest *
|
|
* SVCPU[CR] = guest CR
|
|
* SVCPU[XER] = guest XER
|
|
* SVCPU[CTR] = guest CTR
|
|
* SVCPU[LR] = guest LR
|
|
*
|
|
*/
|
|
|
|
/* Remove all SLB entries that are in use. */
|
|
|
|
li r0, 0
|
|
slbmte r0, r0
|
|
slbia
|
|
|
|
/* Restore bolted entries from the shadow */
|
|
|
|
ld r11, PACA_SLBSHADOWPTR(r13)
|
|
|
|
BEGIN_FW_FTR_SECTION
|
|
|
|
/* Declare SLB shadow as SLB_NUM_BOLTED entries big */
|
|
|
|
li r8, SLB_NUM_BOLTED
|
|
stb r8, 3(r11)
|
|
|
|
END_FW_FTR_SECTION_IFSET(FW_FEATURE_LPAR)
|
|
|
|
/* Manually load all entries from shadow SLB */
|
|
|
|
li r8, SLBSHADOW_SAVEAREA
|
|
li r7, SLBSHADOW_SAVEAREA + 8
|
|
|
|
.rept SLB_NUM_BOLTED
|
|
LDX_BE r10, r11, r8
|
|
cmpdi r10, 0
|
|
beq 1f
|
|
LDX_BE r9, r11, r7
|
|
slbmte r9, r10
|
|
1: addi r7, r7, SHADOW_SLB_ENTRY_LEN
|
|
addi r8, r8, SHADOW_SLB_ENTRY_LEN
|
|
.endr
|
|
|
|
isync
|
|
sync
|
|
|
|
slb_do_exit:
|
|
|
|
.endm
|