cregit-Linux how code gets into the kernel

Release 4.14 arch/powerpc/kvm/book3s_pr.c

Directory: arch/powerpc/kvm
/*
 * Copyright (C) 2009. SUSE Linux Products GmbH. All rights reserved.
 *
 * Authors:
 *    Alexander Graf <agraf@suse.de>
 *    Kevin Wolf <mail@kevin-wolf.de>
 *    Paul Mackerras <paulus@samba.org>
 *
 * Description:
 * Functions relating to running KVM on Book 3S processors where
 * we don't have access to hypervisor mode, and we run the guest
 * in problem state (user mode).
 *
 * This file is derived from arch/powerpc/kvm/44x.c,
 * by Hollis Blanchard <hollisb@us.ibm.com>.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License, version 2, as
 * published by the Free Software Foundation.
 */

#include <linux/kvm_host.h>
#include <linux/export.h>
#include <linux/err.h>
#include <linux/slab.h>

#include <asm/reg.h>
#include <asm/cputable.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
#include <linux/uaccess.h>
#include <asm/io.h>
#include <asm/kvm_ppc.h>
#include <asm/kvm_book3s.h>
#include <asm/mmu_context.h>
#include <asm/switch_to.h>
#include <asm/firmware.h>
#include <asm/setup.h>
#include <linux/gfp.h>
#include <linux/sched.h>
#include <linux/vmalloc.h>
#include <linux/highmem.h>
#include <linux/module.h>
#include <linux/miscdevice.h>

#include "book3s.h"


#define CREATE_TRACE_POINTS
#include "trace_pr.h"

/* #define EXIT_DEBUG */
/* #define DEBUG_EXT */

static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
			     ulong msr);
static void kvmppc_giveup_fac(struct kvm_vcpu *vcpu, ulong fac);

/* Some compatibility defines */
#ifdef CONFIG_PPC_BOOK3S_32

#define MSR_USER32 MSR_USER

#define MSR_USER64 MSR_USER

#define HW_PAGE_SIZE PAGE_SIZE
#endif


static bool kvmppc_is_split_real(struct kvm_vcpu *vcpu) { ulong msr = kvmppc_get_msr(vcpu); return (msr & (MSR_IR|MSR_DR)) == MSR_DR; }

Contributors

PersonTokensPropCommitsCommitProp
Alexander Graf32100.00%1100.00%
Total32100.00%1100.00%


static void kvmppc_fixup_split_real(struct kvm_vcpu *vcpu) { ulong msr = kvmppc_get_msr(vcpu); ulong pc = kvmppc_get_pc(vcpu); /* We are in DR only split real mode */ if ((msr & (MSR_IR|MSR_DR)) != MSR_DR) return; /* We have not fixed up the guest already */ if (vcpu->arch.hflags & BOOK3S_HFLAG_SPLIT_HACK) return; /* The code is in fixupable address space */ if (pc & SPLIT_HACK_MASK) return; vcpu->arch.hflags |= BOOK3S_HFLAG_SPLIT_HACK; kvmppc_set_pc(vcpu, pc | SPLIT_HACK_OFFS); }

Contributors

PersonTokensPropCommitsCommitProp
Alexander Graf80100.00%1100.00%
Total80100.00%1100.00%

void kvmppc_unfixup_split_real(struct kvm_vcpu *vcpu);
static void kvmppc_core_vcpu_load_pr(struct kvm_vcpu *vcpu, int cpu) { #ifdef CONFIG_PPC_BOOK3S_64 struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); memcpy(svcpu->slb, to_book3s(vcpu)->slb_shadow, sizeof(svcpu->slb)); svcpu->slb_max = to_book3s(vcpu)->slb_shadow_max; svcpu->in_use = 0; svcpu_put(svcpu); #endif /* Disable AIL if supported */ if (cpu_has_feature(CPU_FTR_HVMODE) && cpu_has_feature(CPU_FTR_ARCH_207S)) mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~LPCR_AIL); vcpu->cpu = smp_processor_id(); #ifdef CONFIG_PPC_BOOK3S_32 current->thread.kvm_shadow_vcpu = vcpu->arch.shadow_vcpu; #endif if (kvmppc_is_split_real(vcpu)) kvmppc_fixup_split_real(vcpu); }

Contributors

PersonTokensPropCommitsCommitProp
Paul Mackerras7152.99%337.50%
Alexander Graf6145.52%450.00%
Aneesh Kumar K.V21.49%112.50%
Total134100.00%8100.00%


static void kvmppc_core_vcpu_put_pr(struct kvm_vcpu *vcpu) { #ifdef CONFIG_PPC_BOOK3S_64 struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); if (svcpu->in_use) { kvmppc_copy_from_svcpu(vcpu, svcpu); } memcpy(to_book3s(vcpu)->slb_shadow, svcpu->slb, sizeof(svcpu->slb)); to_book3s(vcpu)->slb_shadow_max = svcpu->slb_max; svcpu_put(svcpu); #endif if (kvmppc_is_split_real(vcpu)) kvmppc_unfixup_split_real(vcpu); kvmppc_giveup_ext(vcpu, MSR_FP | MSR_VEC | MSR_VSX); kvmppc_giveup_fac(vcpu, FSCR_TAR_LG); /* Enable AIL if supported */ if (cpu_has_feature(CPU_FTR_HVMODE) && cpu_has_feature(CPU_FTR_ARCH_207S)) mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) | LPCR_AIL_3); vcpu->cpu = -1; }

Contributors

PersonTokensPropCommitsCommitProp
Alexander Graf7755.00%555.56%
Paul Mackerras6143.57%333.33%
Aneesh Kumar K.V21.43%111.11%
Total140100.00%9100.00%

/* Copy data needed by real-mode code from vcpu to shadow vcpu */
void kvmppc_copy_to_svcpu(struct kvmppc_book3s_shadow_vcpu *svcpu, struct kvm_vcpu *vcpu) { svcpu->gpr[0] = vcpu->arch.gpr[0]; svcpu->gpr[1] = vcpu->arch.gpr[1]; svcpu->gpr[2] = vcpu->arch.gpr[2]; svcpu->gpr[3] = vcpu->arch.gpr[3]; svcpu->gpr[4] = vcpu->arch.gpr[4]; svcpu->gpr[5] = vcpu->arch.gpr[5]; svcpu->gpr[6] = vcpu->arch.gpr[6]; svcpu->gpr[7] = vcpu->arch.gpr[7]; svcpu->gpr[8] = vcpu->arch.gpr[8]; svcpu->gpr[9] = vcpu->arch.gpr[9]; svcpu->gpr[10] = vcpu->arch.gpr[10]; svcpu->gpr[11] = vcpu->arch.gpr[11]; svcpu->gpr[12] = vcpu->arch.gpr[12]; svcpu->gpr[13] = vcpu->arch.gpr[13]; svcpu->cr = vcpu->arch.cr; svcpu->xer = vcpu->arch.xer; svcpu->ctr = vcpu->arch.ctr; svcpu->lr = vcpu->arch.lr; svcpu->pc = vcpu->arch.pc; #ifdef CONFIG_PPC_BOOK3S_64 svcpu->shadow_fscr = vcpu->arch.shadow_fscr; #endif /* * Now also save the current time base value. We use this * to find the guest purr and spurr value. */ vcpu->arch.entry_tb = get_tb(); vcpu->arch.entry_vtb = get_vtb(); if (cpu_has_feature(CPU_FTR_ARCH_207S)) vcpu->arch.entry_ic = mfspr(SPRN_IC); svcpu->in_use = true; }

Contributors

PersonTokensPropCommitsCommitProp
Paul Mackerras28481.84%225.00%
Aneesh Kumar K.V3710.66%337.50%
Alexander Graf267.49%337.50%
Total347100.00%8100.00%

/* Copy data touched by real-mode code from shadow vcpu back to vcpu */
void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu, struct kvmppc_book3s_shadow_vcpu *svcpu) { /* * vcpu_put would just call us again because in_use hasn't * been updated yet. */ preempt_disable(); /* * Maybe we were already preempted and synced the svcpu from * our preempt notifiers. Don't bother touching this svcpu then. */ if (!svcpu->in_use) goto out; vcpu->arch.gpr[0] = svcpu->gpr[0]; vcpu->arch.gpr[1] = svcpu->gpr[1]; vcpu->arch.gpr[2] = svcpu->gpr[2]; vcpu->arch.gpr[3] = svcpu->gpr[3]; vcpu->arch.gpr[4] = svcpu->gpr[4]; vcpu->arch.gpr[5] = svcpu->gpr[5]; vcpu->arch.gpr[6] = svcpu->gpr[6]; vcpu->arch.gpr[7] = svcpu->gpr[7]; vcpu->arch.gpr[8] = svcpu->gpr[8]; vcpu->arch.gpr[9] = svcpu->gpr[9]; vcpu->arch.gpr[10] = svcpu->gpr[10]; vcpu->arch.gpr[11] = svcpu->gpr[11]; vcpu->arch.gpr[12] = svcpu->gpr[12]; vcpu->arch.gpr[13] = svcpu->gpr[13]; vcpu->arch.cr = svcpu->cr; vcpu->arch.xer = svcpu->xer; vcpu->arch.ctr = svcpu->ctr; vcpu->arch.lr = svcpu->lr; vcpu->arch.pc = svcpu->pc; vcpu->arch.shadow_srr1 = svcpu->shadow_srr1; vcpu->arch.fault_dar = svcpu->fault_dar; vcpu->arch.fault_dsisr = svcpu->fault_dsisr; vcpu->arch.last_inst = svcpu->last_inst; #ifdef CONFIG_PPC_BOOK3S_64 vcpu->arch.shadow_fscr = svcpu->shadow_fscr; #endif /* * Update purr and spurr using time base on exit. */ vcpu->arch.purr += get_tb() - vcpu->arch.entry_tb; vcpu->arch.spurr += get_tb() - vcpu->arch.entry_tb; to_book3s(vcpu)->vtb += get_vtb() - vcpu->arch.entry_vtb; if (cpu_has_feature(CPU_FTR_ARCH_207S)) vcpu->arch.ic += mfspr(SPRN_IC) - vcpu->arch.entry_ic; svcpu->in_use = false; out: preempt_enable(); }

Contributors

PersonTokensPropCommitsCommitProp
Paul Mackerras32974.60%440.00%
Aneesh Kumar K.V6815.42%330.00%
Alexander Graf449.98%330.00%
Total441100.00%10100.00%


static int kvmppc_core_check_requests_pr(struct kvm_vcpu *vcpu) { int r = 1; /* Indicate we want to get back into the guest */ /* We misuse TLB_FLUSH to indicate that we want to clear all shadow cache entries */ if (kvm_check_request(KVM_REQ_TLB_FLUSH, vcpu)) kvmppc_mmu_pte_flush(vcpu, 0, 0); return r; }

Contributors

PersonTokensPropCommitsCommitProp
Alexander Graf3794.87%375.00%
Aneesh Kumar K.V25.13%125.00%
Total39100.00%4100.00%

/************* MMU Notifiers *************/
static void do_kvm_unmap_hva(struct kvm *kvm, unsigned long start, unsigned long end) { long i; struct kvm_vcpu *vcpu; struct kvm_memslots *slots; struct kvm_memory_slot *memslot; slots = kvm_memslots(kvm); kvm_for_each_memslot(memslot, slots) { unsigned long hva_start, hva_end; gfn_t gfn, gfn_end; hva_start = max(start, memslot->userspace_addr); hva_end = min(end, memslot->userspace_addr + (memslot->npages << PAGE_SHIFT)); if (hva_start >= hva_end) continue; /* * {gfn(page) | page intersects with [hva_start, hva_end)} = * {gfn, gfn+1, ..., gfn_end-1}. */ gfn = hva_to_gfn_memslot(hva_start, memslot); gfn_end = hva_to_gfn_memslot(hva_end + PAGE_SIZE - 1, memslot); kvm_for_each_vcpu(i, vcpu, kvm) kvmppc_mmu_pte_pflush(vcpu, gfn << PAGE_SHIFT, gfn_end << PAGE_SHIFT); } }

Contributors

PersonTokensPropCommitsCommitProp
Paul Mackerras144100.00%1100.00%
Total144100.00%1100.00%


static int kvm_unmap_hva_pr(struct kvm *kvm, unsigned long hva) { trace_kvm_unmap_hva(hva); do_kvm_unmap_hva(kvm, hva, hva + PAGE_SIZE); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Alexander Graf2573.53%133.33%
Paul Mackerras720.59%133.33%
Aneesh Kumar K.V25.88%133.33%
Total34100.00%3100.00%


static int kvm_unmap_hva_range_pr(struct kvm *kvm, unsigned long start, unsigned long end) { do_kvm_unmap_hva(kvm, start, end); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Alexander Graf2683.87%133.33%
Paul Mackerras39.68%133.33%
Aneesh Kumar K.V26.45%133.33%
Total31100.00%3100.00%


static int kvm_age_hva_pr(struct kvm *kvm, unsigned long start, unsigned long end) { /* XXX could be more clever ;) */ return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Alexander Graf1669.57%133.33%
Andres Lagar-Cavilla521.74%133.33%
Aneesh Kumar K.V28.70%133.33%
Total23100.00%3100.00%


static int kvm_test_age_hva_pr(struct kvm *kvm, unsigned long hva) { /* XXX could be more clever ;) */ return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Alexander Graf1789.47%150.00%
Aneesh Kumar K.V210.53%150.00%
Total19100.00%2100.00%


static void kvm_set_spte_hva_pr(struct kvm *kvm, unsigned long hva, pte_t pte) { /* The page will get remapped properly on its next fault */ do_kvm_unmap_hva(kvm, hva, hva + PAGE_SIZE); }

Contributors

PersonTokensPropCommitsCommitProp
Alexander Graf2376.67%133.33%
Paul Mackerras516.67%133.33%
Aneesh Kumar K.V26.67%133.33%
Total30100.00%3100.00%

/*****************************************/
static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu) { ulong guest_msr = kvmppc_get_msr(vcpu); ulong smsr = guest_msr; /* Guest MSR values */ smsr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE | MSR_BE | MSR_LE; /* Process MSR values */ smsr |= MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_PR | MSR_EE; /* External providers the guest reserved */ smsr |= (guest_msr & vcpu->arch.guest_owned_ext); /* 64-bit Process MSR values */ #ifdef CONFIG_PPC_BOOK3S_64 smsr |= MSR_ISF | MSR_HV; #endif vcpu->arch.shadow_msr = smsr; }

Contributors

PersonTokensPropCommitsCommitProp
Paul Mackerras7586.21%133.33%
Alexander Graf1011.49%133.33%
Aneesh Kumar K.V22.30%133.33%
Total87100.00%3100.00%


static void kvmppc_set_msr_pr(struct kvm_vcpu *vcpu, u64 msr) { ulong old_msr = kvmppc_get_msr(vcpu); #ifdef EXIT_DEBUG printk(KERN_INFO "KVM: Set MSR to 0x%llx\n", msr); #endif msr &= to_book3s(vcpu)->msr_mask; kvmppc_set_msr_fast(vcpu, msr); kvmppc_recalc_shadow_msr(vcpu); if (msr & MSR_POW) { if (!vcpu->arch.pending_exceptions) { kvm_vcpu_block(vcpu); kvm_clear_request(KVM_REQ_UNHALT, vcpu); vcpu->stat.halt_wakeup++; /* Unset POW bit after we woke up */ msr &= ~MSR_POW; kvmppc_set_msr_fast(vcpu, msr); } } if (kvmppc_is_split_real(vcpu)) kvmppc_fixup_split_real(vcpu); else kvmppc_unfixup_split_real(vcpu); if ((kvmppc_get_msr(vcpu) & (MSR_PR|MSR_IR|MSR_DR)) != (old_msr & (MSR_PR|MSR_IR|MSR_DR))) { kvmppc_mmu_flush_segments(vcpu); kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu)); /* Preload magic page segment when in kernel mode */ if (!(msr & MSR_PR) && vcpu->arch.magic_page_pa) { struct kvm_vcpu_arch *a = &vcpu->arch; if (msr & MSR_DR) kvmppc_mmu_map_segment(vcpu, a->magic_page_ea); else kvmppc_mmu_map_segment(vcpu, a->magic_page_pa); } } /* * When switching from 32 to 64-bit, we may have a stale 32-bit * magic page around, we need to flush it. Typically 32-bit magic * page will be instanciated when calling into RTAS. Note: We * assume that such transition only happens while in kernel mode, * ie, we never transition from user 32-bit to kernel 64-bit with * a 32-bit magic page around. */ if (vcpu->arch.magic_page_pa && !(old_msr & MSR_PR) && !(old_msr & MSR_SF) && (msr & MSR_SF)) { /* going from RTAS to normal kernel code */ kvmppc_mmu_pte_flush(vcpu, (uint32_t)vcpu->arch.magic_page_pa, ~0xFFFUL); } /* Preload FPU if it's enabled */ if (kvmppc_get_msr(vcpu) & MSR_FP) kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP); }

Contributors

PersonTokensPropCommitsCommitProp
Paul Mackerras19968.15%114.29%
Benjamin Herrenschmidt4916.78%114.29%
Alexander Graf4114.04%342.86%
Aneesh Kumar K.V20.68%114.29%
Radim Krčmář10.34%114.29%
Total292100.00%7100.00%


void kvmppc_set_pvr_pr(struct kvm_vcpu *vcpu, u32 pvr) { u32 host_pvr; vcpu->arch.hflags &= ~BOOK3S_HFLAG_SLB; vcpu->arch.pvr = pvr; #ifdef CONFIG_PPC_BOOK3S_64 if ((pvr >= 0x330000) && (pvr < 0x70330000)) { kvmppc_mmu_book3s_64_init(vcpu); if (!to_book3s(vcpu)->hior_explicit) to_book3s(vcpu)->hior = 0xfff00000; to_book3s(vcpu)->msr_mask = 0xffffffffffffffffULL; vcpu->arch.cpu_type = KVM_CPU_3S_64; } else #endif { kvmppc_mmu_book3s_32_init(vcpu); if (!to_book3s(vcpu)->hior_explicit) to_book3s(vcpu)->hior = 0; to_book3s(vcpu)->msr_mask = 0xffffffffULL; vcpu->arch.cpu_type = KVM_CPU_3S_32; } kvmppc_sanity_check(vcpu); /* If we are in hypervisor level on 970, we can tell the CPU to * treat DCBZ as 32 bytes store */ vcpu->arch.hflags &= ~BOOK3S_HFLAG_DCBZ32; if (vcpu->arch.mmu.is_dcbz32(vcpu) && (mfmsr() & MSR_HV) && !strcmp(cur_cpu_spec->platform, "ppc970")) vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32; /* Cell performs badly if MSR_FEx are set. So let's hope nobody really needs them in a VM on Cell and force disable them. */ if (!strcmp(cur_cpu_spec->platform, "ppc-cell-be")) to_book3s(vcpu)->msr_mask &= ~(MSR_FE0 | MSR_FE1); /* * If they're asking for POWER6 or later, set the flag * indicating that we can do multiple large page sizes * and 1TB segments. * Also set the flag that indicates that tlbie has the large * page bit in the RB operand instead of the instruction. */ switch (PVR_VER(pvr)) { case PVR_POWER6: case PVR_POWER7: case PVR_POWER7p: case PVR_POWER8: case PVR_POWER8E: case PVR_POWER8NVL: vcpu->arch.hflags |= BOOK3S_HFLAG_MULTI_PGSIZE | BOOK3S_HFLAG_NEW_TLBIE; break; } #ifdef CONFIG_PPC_BOOK3S_32 /* 32 bit Book3S always has 32 byte dcbz */ vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32; #endif /* On some CPUs we can execute paired single operations natively */ asm ( "mfpvr %0" : "=r"(host_pvr)); switch (host_pvr) { case 0x00080200: /* lonestar 2.0 */ case 0x00088202: /* lonestar 2.2 */ case 0x70000100: /* gekko 1.0 */ case 0x00080100: /* gekko 2.0 */ case 0x00083203: /* gekko 2.3a */ case 0x00083213: /* gekko 2.3b */ case 0x00083204: /* gekko 2.4 */ case 0x00083214: /* gekko 2.4e (8SE) - retail HW2 */ case 0x00087200: /* broadway */ vcpu->arch.hflags |= BOOK3S_HFLAG_NATIVE_PS; /* Enable HID2.PSE - in case we need it later */ mtspr(SPRN_HID2_GEKKO, mfspr(SPRN_HID2_GEKKO) | (1 << 29)); } }

Contributors

PersonTokensPropCommitsCommitProp
Paul Mackerras29385.92%233.33%
Alexander Graf4112.02%233.33%
Thomas Huth61.76%116.67%
Aneesh Kumar K.V10.29%116.67%
Total341100.00%6100.00%

/* Book3s_32 CPUs always have 32 bytes cache line size, which Linux assumes. To * make Book3s_32 Linux work on Book3s_64, we have to make sure we trap dcbz to * emulate 32 bytes dcbz length. * * The Book3s_64 inventors also realized this case and implemented a special bit * in the HID5 register, which is a hypervisor ressource. Thus we can't use it. * * My approach here is to patch the dcbz instruction on executing pages. */
static void kvmppc_patch_dcbz(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte) { struct page *hpage; u64 hpage_offset; u32 *page; int i; hpage = gfn_to_page(vcpu->kvm, pte->raddr >> PAGE_SHIFT); if (is_error_page(hpage)) return; hpage_offset = pte->raddr & ~PAGE_MASK; hpage_offset &= ~0xFFFULL; hpage_offset /= 4; get_page(hpage); page = kmap_atomic(hpage); /* patch dcbz into reserved instruction, so we trap */ for (i=hpage_offset; i < hpage_offset + (HW_PAGE_SIZE / 4); i++) if ((be32_to_cpu(page[i]) & 0xff0007ff) == INS_DCBZ) page[i] &= cpu_to_be32(0xfffffff7); kunmap_atomic(page); put_page(hpage); }

Contributors

PersonTokensPropCommitsCommitProp
Paul Mackerras13495.71%150.00%
Alexander Graf64.29%150.00%
Total140100.00%2100.00%


static bool kvmppc_visible_gpa(struct kvm_vcpu *vcpu, gpa_t gpa) { ulong mp_pa = vcpu->arch.magic_page_pa; if (!(kvmppc_get_msr(vcpu) & MSR_SF)) mp_pa = (uint32_t)mp_pa; gpa &= ~0xFFFULL; if (unlikely(mp_pa) && unlikely((mp_pa & KVM_PAM) == (gpa & KVM_PAM))) { return true; } return kvm_is_visible_gfn(vcpu->kvm, gpa >> PAGE_SHIFT); }

Contributors

PersonTokensPropCommitsCommitProp
Paul Mackerras4956.98%120.00%
Alexander Graf1922.09%240.00%
Benjamin Herrenschmidt1618.60%120.00%
Yaowei Bai22.33%120.00%
Total86100.00%5100.00%


int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu, ulong eaddr, int vec) { bool data = (vec == BOOK3S_INTERRUPT_DATA_STORAGE); bool iswrite = false; int r = RESUME_GUEST; int relocated; int page_found = 0; struct kvmppc_pte pte = { 0 }; bool dr = (kvmppc_get_msr(vcpu) & MSR_DR) ? true : false; bool ir = (kvmppc_get_msr(vcpu) & MSR_IR) ? true : false; u64 vsid; relocated = data ? dr : ir; if (data && (vcpu->arch.fault_dsisr & DSISR_ISSTORE)) iswrite = true; /* Resolve real address if translation turned on */ if (relocated) { page_found = vcpu->arch.mmu.xlate(vcpu, eaddr, &pte, data, iswrite); } else { pte.may_execute = true; pte.may_read = true; pte.may_write = true; pte.raddr = eaddr & KVM_PAM; pte.eaddr = eaddr; pte.vpage = eaddr >> 12; pte.page_size = MMU_PAGE_64K; } switch (kvmppc_get_msr(vcpu) & (MSR_DR|MSR_IR)) { case 0: pte.vpage |= ((u64)VSID_REAL << (SID_SHIFT - 12)); break; case MSR_DR: if (!data && (vcpu->arch.hflags & BOOK3S_HFLAG_SPLIT_HACK) && ((pte.raddr & SPLIT_HACK_MASK) == SPLIT_HACK_OFFS)) pte.raddr &= ~SPLIT_HACK_MASK; /* fall through */ case MSR_IR: vcpu->arch.mmu.esid_to_vsid(vcpu, eaddr >> SID_SHIFT, &vsid); if ((kvmppc_get_msr(vcpu) & (MSR_DR|MSR_IR)) == MSR_DR) pte.vpage |= ((u64)VSID_REAL_DR << (