| /* 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 |