18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright 2011 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com> 48c2ecf20Sopenharmony_ci * Copyright (C) 2009. SUSE Linux Products GmbH. All rights reserved. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Authors: 78c2ecf20Sopenharmony_ci * Paul Mackerras <paulus@au1.ibm.com> 88c2ecf20Sopenharmony_ci * Alexander Graf <agraf@suse.de> 98c2ecf20Sopenharmony_ci * Kevin Wolf <mail@kevin-wolf.de> 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * Description: KVM functions specific to running on Book 3S 128c2ecf20Sopenharmony_ci * processors in hypervisor mode (specifically POWER7 and later). 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * This file is derived from arch/powerpc/kvm/book3s.c, 158c2ecf20Sopenharmony_ci * by Alexander Graf <agraf@suse.de>. 168c2ecf20Sopenharmony_ci */ 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#include <linux/kvm_host.h> 198c2ecf20Sopenharmony_ci#include <linux/kernel.h> 208c2ecf20Sopenharmony_ci#include <linux/err.h> 218c2ecf20Sopenharmony_ci#include <linux/slab.h> 228c2ecf20Sopenharmony_ci#include <linux/preempt.h> 238c2ecf20Sopenharmony_ci#include <linux/sched/signal.h> 248c2ecf20Sopenharmony_ci#include <linux/sched/stat.h> 258c2ecf20Sopenharmony_ci#include <linux/delay.h> 268c2ecf20Sopenharmony_ci#include <linux/export.h> 278c2ecf20Sopenharmony_ci#include <linux/fs.h> 288c2ecf20Sopenharmony_ci#include <linux/anon_inodes.h> 298c2ecf20Sopenharmony_ci#include <linux/cpu.h> 308c2ecf20Sopenharmony_ci#include <linux/cpumask.h> 318c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 328c2ecf20Sopenharmony_ci#include <linux/page-flags.h> 338c2ecf20Sopenharmony_ci#include <linux/srcu.h> 348c2ecf20Sopenharmony_ci#include <linux/miscdevice.h> 358c2ecf20Sopenharmony_ci#include <linux/debugfs.h> 368c2ecf20Sopenharmony_ci#include <linux/gfp.h> 378c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 388c2ecf20Sopenharmony_ci#include <linux/highmem.h> 398c2ecf20Sopenharmony_ci#include <linux/hugetlb.h> 408c2ecf20Sopenharmony_ci#include <linux/kvm_irqfd.h> 418c2ecf20Sopenharmony_ci#include <linux/irqbypass.h> 428c2ecf20Sopenharmony_ci#include <linux/module.h> 438c2ecf20Sopenharmony_ci#include <linux/compiler.h> 448c2ecf20Sopenharmony_ci#include <linux/of.h> 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci#include <asm/ftrace.h> 478c2ecf20Sopenharmony_ci#include <asm/reg.h> 488c2ecf20Sopenharmony_ci#include <asm/ppc-opcode.h> 498c2ecf20Sopenharmony_ci#include <asm/asm-prototypes.h> 508c2ecf20Sopenharmony_ci#include <asm/archrandom.h> 518c2ecf20Sopenharmony_ci#include <asm/debug.h> 528c2ecf20Sopenharmony_ci#include <asm/disassemble.h> 538c2ecf20Sopenharmony_ci#include <asm/cputable.h> 548c2ecf20Sopenharmony_ci#include <asm/cacheflush.h> 558c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 568c2ecf20Sopenharmony_ci#include <asm/io.h> 578c2ecf20Sopenharmony_ci#include <asm/kvm_ppc.h> 588c2ecf20Sopenharmony_ci#include <asm/kvm_book3s.h> 598c2ecf20Sopenharmony_ci#include <asm/mmu_context.h> 608c2ecf20Sopenharmony_ci#include <asm/lppaca.h> 618c2ecf20Sopenharmony_ci#include <asm/pmc.h> 628c2ecf20Sopenharmony_ci#include <asm/processor.h> 638c2ecf20Sopenharmony_ci#include <asm/cputhreads.h> 648c2ecf20Sopenharmony_ci#include <asm/page.h> 658c2ecf20Sopenharmony_ci#include <asm/hvcall.h> 668c2ecf20Sopenharmony_ci#include <asm/switch_to.h> 678c2ecf20Sopenharmony_ci#include <asm/smp.h> 688c2ecf20Sopenharmony_ci#include <asm/dbell.h> 698c2ecf20Sopenharmony_ci#include <asm/hmi.h> 708c2ecf20Sopenharmony_ci#include <asm/pnv-pci.h> 718c2ecf20Sopenharmony_ci#include <asm/mmu.h> 728c2ecf20Sopenharmony_ci#include <asm/opal.h> 738c2ecf20Sopenharmony_ci#include <asm/xics.h> 748c2ecf20Sopenharmony_ci#include <asm/xive.h> 758c2ecf20Sopenharmony_ci#include <asm/hw_breakpoint.h> 768c2ecf20Sopenharmony_ci#include <asm/kvm_book3s_uvmem.h> 778c2ecf20Sopenharmony_ci#include <asm/ultravisor.h> 788c2ecf20Sopenharmony_ci#include <asm/dtl.h> 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci#include "book3s.h" 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci#define CREATE_TRACE_POINTS 838c2ecf20Sopenharmony_ci#include "trace_hv.h" 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci/* #define EXIT_DEBUG */ 868c2ecf20Sopenharmony_ci/* #define EXIT_DEBUG_SIMPLE */ 878c2ecf20Sopenharmony_ci/* #define EXIT_DEBUG_INT */ 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci/* Used to indicate that a guest page fault needs to be handled */ 908c2ecf20Sopenharmony_ci#define RESUME_PAGE_FAULT (RESUME_GUEST | RESUME_FLAG_ARCH1) 918c2ecf20Sopenharmony_ci/* Used to indicate that a guest passthrough interrupt needs to be handled */ 928c2ecf20Sopenharmony_ci#define RESUME_PASSTHROUGH (RESUME_GUEST | RESUME_FLAG_ARCH2) 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci/* Used as a "null" value for timebase values */ 958c2ecf20Sopenharmony_ci#define TB_NIL (~(u64)0) 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_cistatic DECLARE_BITMAP(default_enabled_hcalls, MAX_HCALL_OPCODE/4 + 1); 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_cistatic int dynamic_mt_modes = 6; 1008c2ecf20Sopenharmony_cimodule_param(dynamic_mt_modes, int, 0644); 1018c2ecf20Sopenharmony_ciMODULE_PARM_DESC(dynamic_mt_modes, "Set of allowed dynamic micro-threading modes: 0 (= none), 2, 4, or 6 (= 2 or 4)"); 1028c2ecf20Sopenharmony_cistatic int target_smt_mode; 1038c2ecf20Sopenharmony_cimodule_param(target_smt_mode, int, 0644); 1048c2ecf20Sopenharmony_ciMODULE_PARM_DESC(target_smt_mode, "Target threads per core (0 = max)"); 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_cistatic bool indep_threads_mode = true; 1078c2ecf20Sopenharmony_cimodule_param(indep_threads_mode, bool, S_IRUGO | S_IWUSR); 1088c2ecf20Sopenharmony_ciMODULE_PARM_DESC(indep_threads_mode, "Independent-threads mode (only on POWER9)"); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_cistatic bool one_vm_per_core; 1118c2ecf20Sopenharmony_cimodule_param(one_vm_per_core, bool, S_IRUGO | S_IWUSR); 1128c2ecf20Sopenharmony_ciMODULE_PARM_DESC(one_vm_per_core, "Only run vCPUs from the same VM on a core (requires indep_threads_mode=N)"); 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci#ifdef CONFIG_KVM_XICS 1158c2ecf20Sopenharmony_cistatic const struct kernel_param_ops module_param_ops = { 1168c2ecf20Sopenharmony_ci .set = param_set_int, 1178c2ecf20Sopenharmony_ci .get = param_get_int, 1188c2ecf20Sopenharmony_ci}; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_cimodule_param_cb(kvm_irq_bypass, &module_param_ops, &kvm_irq_bypass, 0644); 1218c2ecf20Sopenharmony_ciMODULE_PARM_DESC(kvm_irq_bypass, "Bypass passthrough interrupt optimization"); 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_cimodule_param_cb(h_ipi_redirect, &module_param_ops, &h_ipi_redirect, 0644); 1248c2ecf20Sopenharmony_ciMODULE_PARM_DESC(h_ipi_redirect, "Redirect H_IPI wakeup to a free host core"); 1258c2ecf20Sopenharmony_ci#endif 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci/* If set, guests are allowed to create and control nested guests */ 1288c2ecf20Sopenharmony_cistatic bool nested = true; 1298c2ecf20Sopenharmony_cimodule_param(nested, bool, S_IRUGO | S_IWUSR); 1308c2ecf20Sopenharmony_ciMODULE_PARM_DESC(nested, "Enable nested virtualization (only on POWER9)"); 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_cistatic inline bool nesting_enabled(struct kvm *kvm) 1338c2ecf20Sopenharmony_ci{ 1348c2ecf20Sopenharmony_ci return kvm->arch.nested_enable && kvm_is_radix(kvm); 1358c2ecf20Sopenharmony_ci} 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci/* If set, the threads on each CPU core have to be in the same MMU mode */ 1388c2ecf20Sopenharmony_cistatic bool no_mixing_hpt_and_radix; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_cistatic int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu); 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci/* 1438c2ecf20Sopenharmony_ci * RWMR values for POWER8. These control the rate at which PURR 1448c2ecf20Sopenharmony_ci * and SPURR count and should be set according to the number of 1458c2ecf20Sopenharmony_ci * online threads in the vcore being run. 1468c2ecf20Sopenharmony_ci */ 1478c2ecf20Sopenharmony_ci#define RWMR_RPA_P8_1THREAD 0x164520C62609AECAUL 1488c2ecf20Sopenharmony_ci#define RWMR_RPA_P8_2THREAD 0x7FFF2908450D8DA9UL 1498c2ecf20Sopenharmony_ci#define RWMR_RPA_P8_3THREAD 0x164520C62609AECAUL 1508c2ecf20Sopenharmony_ci#define RWMR_RPA_P8_4THREAD 0x199A421245058DA9UL 1518c2ecf20Sopenharmony_ci#define RWMR_RPA_P8_5THREAD 0x164520C62609AECAUL 1528c2ecf20Sopenharmony_ci#define RWMR_RPA_P8_6THREAD 0x164520C62609AECAUL 1538c2ecf20Sopenharmony_ci#define RWMR_RPA_P8_7THREAD 0x164520C62609AECAUL 1548c2ecf20Sopenharmony_ci#define RWMR_RPA_P8_8THREAD 0x164520C62609AECAUL 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_cistatic unsigned long p8_rwmr_values[MAX_SMT_THREADS + 1] = { 1578c2ecf20Sopenharmony_ci RWMR_RPA_P8_1THREAD, 1588c2ecf20Sopenharmony_ci RWMR_RPA_P8_1THREAD, 1598c2ecf20Sopenharmony_ci RWMR_RPA_P8_2THREAD, 1608c2ecf20Sopenharmony_ci RWMR_RPA_P8_3THREAD, 1618c2ecf20Sopenharmony_ci RWMR_RPA_P8_4THREAD, 1628c2ecf20Sopenharmony_ci RWMR_RPA_P8_5THREAD, 1638c2ecf20Sopenharmony_ci RWMR_RPA_P8_6THREAD, 1648c2ecf20Sopenharmony_ci RWMR_RPA_P8_7THREAD, 1658c2ecf20Sopenharmony_ci RWMR_RPA_P8_8THREAD, 1668c2ecf20Sopenharmony_ci}; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_cistatic inline struct kvm_vcpu *next_runnable_thread(struct kvmppc_vcore *vc, 1698c2ecf20Sopenharmony_ci int *ip) 1708c2ecf20Sopenharmony_ci{ 1718c2ecf20Sopenharmony_ci int i = *ip; 1728c2ecf20Sopenharmony_ci struct kvm_vcpu *vcpu; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci while (++i < MAX_SMT_THREADS) { 1758c2ecf20Sopenharmony_ci vcpu = READ_ONCE(vc->runnable_threads[i]); 1768c2ecf20Sopenharmony_ci if (vcpu) { 1778c2ecf20Sopenharmony_ci *ip = i; 1788c2ecf20Sopenharmony_ci return vcpu; 1798c2ecf20Sopenharmony_ci } 1808c2ecf20Sopenharmony_ci } 1818c2ecf20Sopenharmony_ci return NULL; 1828c2ecf20Sopenharmony_ci} 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci/* Used to traverse the list of runnable threads for a given vcore */ 1858c2ecf20Sopenharmony_ci#define for_each_runnable_thread(i, vcpu, vc) \ 1868c2ecf20Sopenharmony_ci for (i = -1; (vcpu = next_runnable_thread(vc, &i)); ) 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_cistatic bool kvmppc_ipi_thread(int cpu) 1898c2ecf20Sopenharmony_ci{ 1908c2ecf20Sopenharmony_ci unsigned long msg = PPC_DBELL_TYPE(PPC_DBELL_SERVER); 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci /* If we're a nested hypervisor, fall back to ordinary IPIs for now */ 1938c2ecf20Sopenharmony_ci if (kvmhv_on_pseries()) 1948c2ecf20Sopenharmony_ci return false; 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci /* On POWER9 we can use msgsnd to IPI any cpu */ 1978c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_300)) { 1988c2ecf20Sopenharmony_ci msg |= get_hard_smp_processor_id(cpu); 1998c2ecf20Sopenharmony_ci smp_mb(); 2008c2ecf20Sopenharmony_ci __asm__ __volatile__ (PPC_MSGSND(%0) : : "r" (msg)); 2018c2ecf20Sopenharmony_ci return true; 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci /* On POWER8 for IPIs to threads in the same core, use msgsnd */ 2058c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_207S)) { 2068c2ecf20Sopenharmony_ci preempt_disable(); 2078c2ecf20Sopenharmony_ci if (cpu_first_thread_sibling(cpu) == 2088c2ecf20Sopenharmony_ci cpu_first_thread_sibling(smp_processor_id())) { 2098c2ecf20Sopenharmony_ci msg |= cpu_thread_in_core(cpu); 2108c2ecf20Sopenharmony_ci smp_mb(); 2118c2ecf20Sopenharmony_ci __asm__ __volatile__ (PPC_MSGSND(%0) : : "r" (msg)); 2128c2ecf20Sopenharmony_ci preempt_enable(); 2138c2ecf20Sopenharmony_ci return true; 2148c2ecf20Sopenharmony_ci } 2158c2ecf20Sopenharmony_ci preempt_enable(); 2168c2ecf20Sopenharmony_ci } 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci#if defined(CONFIG_PPC_ICP_NATIVE) && defined(CONFIG_SMP) 2198c2ecf20Sopenharmony_ci if (cpu >= 0 && cpu < nr_cpu_ids) { 2208c2ecf20Sopenharmony_ci if (paca_ptrs[cpu]->kvm_hstate.xics_phys) { 2218c2ecf20Sopenharmony_ci xics_wake_cpu(cpu); 2228c2ecf20Sopenharmony_ci return true; 2238c2ecf20Sopenharmony_ci } 2248c2ecf20Sopenharmony_ci opal_int_set_mfrr(get_hard_smp_processor_id(cpu), IPI_PRIORITY); 2258c2ecf20Sopenharmony_ci return true; 2268c2ecf20Sopenharmony_ci } 2278c2ecf20Sopenharmony_ci#endif 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci return false; 2308c2ecf20Sopenharmony_ci} 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_cistatic void kvmppc_fast_vcpu_kick_hv(struct kvm_vcpu *vcpu) 2338c2ecf20Sopenharmony_ci{ 2348c2ecf20Sopenharmony_ci int cpu; 2358c2ecf20Sopenharmony_ci struct rcuwait *waitp; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci waitp = kvm_arch_vcpu_get_wait(vcpu); 2388c2ecf20Sopenharmony_ci if (rcuwait_wake_up(waitp)) 2398c2ecf20Sopenharmony_ci ++vcpu->stat.halt_wakeup; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci cpu = READ_ONCE(vcpu->arch.thread_cpu); 2428c2ecf20Sopenharmony_ci if (cpu >= 0 && kvmppc_ipi_thread(cpu)) 2438c2ecf20Sopenharmony_ci return; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci /* CPU points to the first thread of the core */ 2468c2ecf20Sopenharmony_ci cpu = vcpu->cpu; 2478c2ecf20Sopenharmony_ci if (cpu >= 0 && cpu < nr_cpu_ids && cpu_online(cpu)) 2488c2ecf20Sopenharmony_ci smp_send_reschedule(cpu); 2498c2ecf20Sopenharmony_ci} 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci/* 2528c2ecf20Sopenharmony_ci * We use the vcpu_load/put functions to measure stolen time. 2538c2ecf20Sopenharmony_ci * Stolen time is counted as time when either the vcpu is able to 2548c2ecf20Sopenharmony_ci * run as part of a virtual core, but the task running the vcore 2558c2ecf20Sopenharmony_ci * is preempted or sleeping, or when the vcpu needs something done 2568c2ecf20Sopenharmony_ci * in the kernel by the task running the vcpu, but that task is 2578c2ecf20Sopenharmony_ci * preempted or sleeping. Those two things have to be counted 2588c2ecf20Sopenharmony_ci * separately, since one of the vcpu tasks will take on the job 2598c2ecf20Sopenharmony_ci * of running the core, and the other vcpu tasks in the vcore will 2608c2ecf20Sopenharmony_ci * sleep waiting for it to do that, but that sleep shouldn't count 2618c2ecf20Sopenharmony_ci * as stolen time. 2628c2ecf20Sopenharmony_ci * 2638c2ecf20Sopenharmony_ci * Hence we accumulate stolen time when the vcpu can run as part of 2648c2ecf20Sopenharmony_ci * a vcore using vc->stolen_tb, and the stolen time when the vcpu 2658c2ecf20Sopenharmony_ci * needs its task to do other things in the kernel (for example, 2668c2ecf20Sopenharmony_ci * service a page fault) in busy_stolen. We don't accumulate 2678c2ecf20Sopenharmony_ci * stolen time for a vcore when it is inactive, or for a vcpu 2688c2ecf20Sopenharmony_ci * when it is in state RUNNING or NOTREADY. NOTREADY is a bit of 2698c2ecf20Sopenharmony_ci * a misnomer; it means that the vcpu task is not executing in 2708c2ecf20Sopenharmony_ci * the KVM_VCPU_RUN ioctl, i.e. it is in userspace or elsewhere in 2718c2ecf20Sopenharmony_ci * the kernel. We don't have any way of dividing up that time 2728c2ecf20Sopenharmony_ci * between time that the vcpu is genuinely stopped, time that 2738c2ecf20Sopenharmony_ci * the task is actively working on behalf of the vcpu, and time 2748c2ecf20Sopenharmony_ci * that the task is preempted, so we don't count any of it as 2758c2ecf20Sopenharmony_ci * stolen. 2768c2ecf20Sopenharmony_ci * 2778c2ecf20Sopenharmony_ci * Updates to busy_stolen are protected by arch.tbacct_lock; 2788c2ecf20Sopenharmony_ci * updates to vc->stolen_tb are protected by the vcore->stoltb_lock 2798c2ecf20Sopenharmony_ci * lock. The stolen times are measured in units of timebase ticks. 2808c2ecf20Sopenharmony_ci * (Note that the != TB_NIL checks below are purely defensive; 2818c2ecf20Sopenharmony_ci * they should never fail.) 2828c2ecf20Sopenharmony_ci */ 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_cistatic void kvmppc_core_start_stolen(struct kvmppc_vcore *vc) 2858c2ecf20Sopenharmony_ci{ 2868c2ecf20Sopenharmony_ci unsigned long flags; 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci spin_lock_irqsave(&vc->stoltb_lock, flags); 2898c2ecf20Sopenharmony_ci vc->preempt_tb = mftb(); 2908c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&vc->stoltb_lock, flags); 2918c2ecf20Sopenharmony_ci} 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_cistatic void kvmppc_core_end_stolen(struct kvmppc_vcore *vc) 2948c2ecf20Sopenharmony_ci{ 2958c2ecf20Sopenharmony_ci unsigned long flags; 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci spin_lock_irqsave(&vc->stoltb_lock, flags); 2988c2ecf20Sopenharmony_ci if (vc->preempt_tb != TB_NIL) { 2998c2ecf20Sopenharmony_ci vc->stolen_tb += mftb() - vc->preempt_tb; 3008c2ecf20Sopenharmony_ci vc->preempt_tb = TB_NIL; 3018c2ecf20Sopenharmony_ci } 3028c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&vc->stoltb_lock, flags); 3038c2ecf20Sopenharmony_ci} 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_cistatic void kvmppc_core_vcpu_load_hv(struct kvm_vcpu *vcpu, int cpu) 3068c2ecf20Sopenharmony_ci{ 3078c2ecf20Sopenharmony_ci struct kvmppc_vcore *vc = vcpu->arch.vcore; 3088c2ecf20Sopenharmony_ci unsigned long flags; 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci /* 3118c2ecf20Sopenharmony_ci * We can test vc->runner without taking the vcore lock, 3128c2ecf20Sopenharmony_ci * because only this task ever sets vc->runner to this 3138c2ecf20Sopenharmony_ci * vcpu, and once it is set to this vcpu, only this task 3148c2ecf20Sopenharmony_ci * ever sets it to NULL. 3158c2ecf20Sopenharmony_ci */ 3168c2ecf20Sopenharmony_ci if (vc->runner == vcpu && vc->vcore_state >= VCORE_SLEEPING) 3178c2ecf20Sopenharmony_ci kvmppc_core_end_stolen(vc); 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci spin_lock_irqsave(&vcpu->arch.tbacct_lock, flags); 3208c2ecf20Sopenharmony_ci if (vcpu->arch.state == KVMPPC_VCPU_BUSY_IN_HOST && 3218c2ecf20Sopenharmony_ci vcpu->arch.busy_preempt != TB_NIL) { 3228c2ecf20Sopenharmony_ci vcpu->arch.busy_stolen += mftb() - vcpu->arch.busy_preempt; 3238c2ecf20Sopenharmony_ci vcpu->arch.busy_preempt = TB_NIL; 3248c2ecf20Sopenharmony_ci } 3258c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&vcpu->arch.tbacct_lock, flags); 3268c2ecf20Sopenharmony_ci} 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_cistatic void kvmppc_core_vcpu_put_hv(struct kvm_vcpu *vcpu) 3298c2ecf20Sopenharmony_ci{ 3308c2ecf20Sopenharmony_ci struct kvmppc_vcore *vc = vcpu->arch.vcore; 3318c2ecf20Sopenharmony_ci unsigned long flags; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci if (vc->runner == vcpu && vc->vcore_state >= VCORE_SLEEPING) 3348c2ecf20Sopenharmony_ci kvmppc_core_start_stolen(vc); 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci spin_lock_irqsave(&vcpu->arch.tbacct_lock, flags); 3378c2ecf20Sopenharmony_ci if (vcpu->arch.state == KVMPPC_VCPU_BUSY_IN_HOST) 3388c2ecf20Sopenharmony_ci vcpu->arch.busy_preempt = mftb(); 3398c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&vcpu->arch.tbacct_lock, flags); 3408c2ecf20Sopenharmony_ci} 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_cistatic void kvmppc_set_pvr_hv(struct kvm_vcpu *vcpu, u32 pvr) 3438c2ecf20Sopenharmony_ci{ 3448c2ecf20Sopenharmony_ci vcpu->arch.pvr = pvr; 3458c2ecf20Sopenharmony_ci} 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci/* Dummy value used in computing PCR value below */ 3488c2ecf20Sopenharmony_ci#define PCR_ARCH_31 (PCR_ARCH_300 << 1) 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_cistatic int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat) 3518c2ecf20Sopenharmony_ci{ 3528c2ecf20Sopenharmony_ci unsigned long host_pcr_bit = 0, guest_pcr_bit = 0; 3538c2ecf20Sopenharmony_ci struct kvmppc_vcore *vc = vcpu->arch.vcore; 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci /* We can (emulate) our own architecture version and anything older */ 3568c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_31)) 3578c2ecf20Sopenharmony_ci host_pcr_bit = PCR_ARCH_31; 3588c2ecf20Sopenharmony_ci else if (cpu_has_feature(CPU_FTR_ARCH_300)) 3598c2ecf20Sopenharmony_ci host_pcr_bit = PCR_ARCH_300; 3608c2ecf20Sopenharmony_ci else if (cpu_has_feature(CPU_FTR_ARCH_207S)) 3618c2ecf20Sopenharmony_ci host_pcr_bit = PCR_ARCH_207; 3628c2ecf20Sopenharmony_ci else if (cpu_has_feature(CPU_FTR_ARCH_206)) 3638c2ecf20Sopenharmony_ci host_pcr_bit = PCR_ARCH_206; 3648c2ecf20Sopenharmony_ci else 3658c2ecf20Sopenharmony_ci host_pcr_bit = PCR_ARCH_205; 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci /* Determine lowest PCR bit needed to run guest in given PVR level */ 3688c2ecf20Sopenharmony_ci guest_pcr_bit = host_pcr_bit; 3698c2ecf20Sopenharmony_ci if (arch_compat) { 3708c2ecf20Sopenharmony_ci switch (arch_compat) { 3718c2ecf20Sopenharmony_ci case PVR_ARCH_205: 3728c2ecf20Sopenharmony_ci guest_pcr_bit = PCR_ARCH_205; 3738c2ecf20Sopenharmony_ci break; 3748c2ecf20Sopenharmony_ci case PVR_ARCH_206: 3758c2ecf20Sopenharmony_ci case PVR_ARCH_206p: 3768c2ecf20Sopenharmony_ci guest_pcr_bit = PCR_ARCH_206; 3778c2ecf20Sopenharmony_ci break; 3788c2ecf20Sopenharmony_ci case PVR_ARCH_207: 3798c2ecf20Sopenharmony_ci guest_pcr_bit = PCR_ARCH_207; 3808c2ecf20Sopenharmony_ci break; 3818c2ecf20Sopenharmony_ci case PVR_ARCH_300: 3828c2ecf20Sopenharmony_ci guest_pcr_bit = PCR_ARCH_300; 3838c2ecf20Sopenharmony_ci break; 3848c2ecf20Sopenharmony_ci case PVR_ARCH_31: 3858c2ecf20Sopenharmony_ci guest_pcr_bit = PCR_ARCH_31; 3868c2ecf20Sopenharmony_ci break; 3878c2ecf20Sopenharmony_ci default: 3888c2ecf20Sopenharmony_ci return -EINVAL; 3898c2ecf20Sopenharmony_ci } 3908c2ecf20Sopenharmony_ci } 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci /* Check requested PCR bits don't exceed our capabilities */ 3938c2ecf20Sopenharmony_ci if (guest_pcr_bit > host_pcr_bit) 3948c2ecf20Sopenharmony_ci return -EINVAL; 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci spin_lock(&vc->lock); 3978c2ecf20Sopenharmony_ci vc->arch_compat = arch_compat; 3988c2ecf20Sopenharmony_ci /* 3998c2ecf20Sopenharmony_ci * Set all PCR bits for which guest_pcr_bit <= bit < host_pcr_bit 4008c2ecf20Sopenharmony_ci * Also set all reserved PCR bits 4018c2ecf20Sopenharmony_ci */ 4028c2ecf20Sopenharmony_ci vc->pcr = (host_pcr_bit - guest_pcr_bit) | PCR_MASK; 4038c2ecf20Sopenharmony_ci spin_unlock(&vc->lock); 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci return 0; 4068c2ecf20Sopenharmony_ci} 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_cistatic void kvmppc_dump_regs(struct kvm_vcpu *vcpu) 4098c2ecf20Sopenharmony_ci{ 4108c2ecf20Sopenharmony_ci int r; 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci pr_err("vcpu %p (%d):\n", vcpu, vcpu->vcpu_id); 4138c2ecf20Sopenharmony_ci pr_err("pc = %.16lx msr = %.16llx trap = %x\n", 4148c2ecf20Sopenharmony_ci vcpu->arch.regs.nip, vcpu->arch.shregs.msr, vcpu->arch.trap); 4158c2ecf20Sopenharmony_ci for (r = 0; r < 16; ++r) 4168c2ecf20Sopenharmony_ci pr_err("r%2d = %.16lx r%d = %.16lx\n", 4178c2ecf20Sopenharmony_ci r, kvmppc_get_gpr(vcpu, r), 4188c2ecf20Sopenharmony_ci r+16, kvmppc_get_gpr(vcpu, r+16)); 4198c2ecf20Sopenharmony_ci pr_err("ctr = %.16lx lr = %.16lx\n", 4208c2ecf20Sopenharmony_ci vcpu->arch.regs.ctr, vcpu->arch.regs.link); 4218c2ecf20Sopenharmony_ci pr_err("srr0 = %.16llx srr1 = %.16llx\n", 4228c2ecf20Sopenharmony_ci vcpu->arch.shregs.srr0, vcpu->arch.shregs.srr1); 4238c2ecf20Sopenharmony_ci pr_err("sprg0 = %.16llx sprg1 = %.16llx\n", 4248c2ecf20Sopenharmony_ci vcpu->arch.shregs.sprg0, vcpu->arch.shregs.sprg1); 4258c2ecf20Sopenharmony_ci pr_err("sprg2 = %.16llx sprg3 = %.16llx\n", 4268c2ecf20Sopenharmony_ci vcpu->arch.shregs.sprg2, vcpu->arch.shregs.sprg3); 4278c2ecf20Sopenharmony_ci pr_err("cr = %.8lx xer = %.16lx dsisr = %.8x\n", 4288c2ecf20Sopenharmony_ci vcpu->arch.regs.ccr, vcpu->arch.regs.xer, vcpu->arch.shregs.dsisr); 4298c2ecf20Sopenharmony_ci pr_err("dar = %.16llx\n", vcpu->arch.shregs.dar); 4308c2ecf20Sopenharmony_ci pr_err("fault dar = %.16lx dsisr = %.8x\n", 4318c2ecf20Sopenharmony_ci vcpu->arch.fault_dar, vcpu->arch.fault_dsisr); 4328c2ecf20Sopenharmony_ci pr_err("SLB (%d entries):\n", vcpu->arch.slb_max); 4338c2ecf20Sopenharmony_ci for (r = 0; r < vcpu->arch.slb_max; ++r) 4348c2ecf20Sopenharmony_ci pr_err(" ESID = %.16llx VSID = %.16llx\n", 4358c2ecf20Sopenharmony_ci vcpu->arch.slb[r].orige, vcpu->arch.slb[r].origv); 4368c2ecf20Sopenharmony_ci pr_err("lpcr = %.16lx sdr1 = %.16lx last_inst = %.8x\n", 4378c2ecf20Sopenharmony_ci vcpu->arch.vcore->lpcr, vcpu->kvm->arch.sdr1, 4388c2ecf20Sopenharmony_ci vcpu->arch.last_inst); 4398c2ecf20Sopenharmony_ci} 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_cistatic struct kvm_vcpu *kvmppc_find_vcpu(struct kvm *kvm, int id) 4428c2ecf20Sopenharmony_ci{ 4438c2ecf20Sopenharmony_ci return kvm_get_vcpu_by_id(kvm, id); 4448c2ecf20Sopenharmony_ci} 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_cistatic void init_vpa(struct kvm_vcpu *vcpu, struct lppaca *vpa) 4478c2ecf20Sopenharmony_ci{ 4488c2ecf20Sopenharmony_ci vpa->__old_status |= LPPACA_OLD_SHARED_PROC; 4498c2ecf20Sopenharmony_ci vpa->yield_count = cpu_to_be32(1); 4508c2ecf20Sopenharmony_ci} 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_cistatic int set_vpa(struct kvm_vcpu *vcpu, struct kvmppc_vpa *v, 4538c2ecf20Sopenharmony_ci unsigned long addr, unsigned long len) 4548c2ecf20Sopenharmony_ci{ 4558c2ecf20Sopenharmony_ci /* check address is cacheline aligned */ 4568c2ecf20Sopenharmony_ci if (addr & (L1_CACHE_BYTES - 1)) 4578c2ecf20Sopenharmony_ci return -EINVAL; 4588c2ecf20Sopenharmony_ci spin_lock(&vcpu->arch.vpa_update_lock); 4598c2ecf20Sopenharmony_ci if (v->next_gpa != addr || v->len != len) { 4608c2ecf20Sopenharmony_ci v->next_gpa = addr; 4618c2ecf20Sopenharmony_ci v->len = addr ? len : 0; 4628c2ecf20Sopenharmony_ci v->update_pending = 1; 4638c2ecf20Sopenharmony_ci } 4648c2ecf20Sopenharmony_ci spin_unlock(&vcpu->arch.vpa_update_lock); 4658c2ecf20Sopenharmony_ci return 0; 4668c2ecf20Sopenharmony_ci} 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci/* Length for a per-processor buffer is passed in at offset 4 in the buffer */ 4698c2ecf20Sopenharmony_cistruct reg_vpa { 4708c2ecf20Sopenharmony_ci u32 dummy; 4718c2ecf20Sopenharmony_ci union { 4728c2ecf20Sopenharmony_ci __be16 hword; 4738c2ecf20Sopenharmony_ci __be32 word; 4748c2ecf20Sopenharmony_ci } length; 4758c2ecf20Sopenharmony_ci}; 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_cistatic int vpa_is_registered(struct kvmppc_vpa *vpap) 4788c2ecf20Sopenharmony_ci{ 4798c2ecf20Sopenharmony_ci if (vpap->update_pending) 4808c2ecf20Sopenharmony_ci return vpap->next_gpa != 0; 4818c2ecf20Sopenharmony_ci return vpap->pinned_addr != NULL; 4828c2ecf20Sopenharmony_ci} 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_cistatic unsigned long do_h_register_vpa(struct kvm_vcpu *vcpu, 4858c2ecf20Sopenharmony_ci unsigned long flags, 4868c2ecf20Sopenharmony_ci unsigned long vcpuid, unsigned long vpa) 4878c2ecf20Sopenharmony_ci{ 4888c2ecf20Sopenharmony_ci struct kvm *kvm = vcpu->kvm; 4898c2ecf20Sopenharmony_ci unsigned long len, nb; 4908c2ecf20Sopenharmony_ci void *va; 4918c2ecf20Sopenharmony_ci struct kvm_vcpu *tvcpu; 4928c2ecf20Sopenharmony_ci int err; 4938c2ecf20Sopenharmony_ci int subfunc; 4948c2ecf20Sopenharmony_ci struct kvmppc_vpa *vpap; 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci tvcpu = kvmppc_find_vcpu(kvm, vcpuid); 4978c2ecf20Sopenharmony_ci if (!tvcpu) 4988c2ecf20Sopenharmony_ci return H_PARAMETER; 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci subfunc = (flags >> H_VPA_FUNC_SHIFT) & H_VPA_FUNC_MASK; 5018c2ecf20Sopenharmony_ci if (subfunc == H_VPA_REG_VPA || subfunc == H_VPA_REG_DTL || 5028c2ecf20Sopenharmony_ci subfunc == H_VPA_REG_SLB) { 5038c2ecf20Sopenharmony_ci /* Registering new area - address must be cache-line aligned */ 5048c2ecf20Sopenharmony_ci if ((vpa & (L1_CACHE_BYTES - 1)) || !vpa) 5058c2ecf20Sopenharmony_ci return H_PARAMETER; 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci /* convert logical addr to kernel addr and read length */ 5088c2ecf20Sopenharmony_ci va = kvmppc_pin_guest_page(kvm, vpa, &nb); 5098c2ecf20Sopenharmony_ci if (va == NULL) 5108c2ecf20Sopenharmony_ci return H_PARAMETER; 5118c2ecf20Sopenharmony_ci if (subfunc == H_VPA_REG_VPA) 5128c2ecf20Sopenharmony_ci len = be16_to_cpu(((struct reg_vpa *)va)->length.hword); 5138c2ecf20Sopenharmony_ci else 5148c2ecf20Sopenharmony_ci len = be32_to_cpu(((struct reg_vpa *)va)->length.word); 5158c2ecf20Sopenharmony_ci kvmppc_unpin_guest_page(kvm, va, vpa, false); 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci /* Check length */ 5188c2ecf20Sopenharmony_ci if (len > nb || len < sizeof(struct reg_vpa)) 5198c2ecf20Sopenharmony_ci return H_PARAMETER; 5208c2ecf20Sopenharmony_ci } else { 5218c2ecf20Sopenharmony_ci vpa = 0; 5228c2ecf20Sopenharmony_ci len = 0; 5238c2ecf20Sopenharmony_ci } 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci err = H_PARAMETER; 5268c2ecf20Sopenharmony_ci vpap = NULL; 5278c2ecf20Sopenharmony_ci spin_lock(&tvcpu->arch.vpa_update_lock); 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci switch (subfunc) { 5308c2ecf20Sopenharmony_ci case H_VPA_REG_VPA: /* register VPA */ 5318c2ecf20Sopenharmony_ci /* 5328c2ecf20Sopenharmony_ci * The size of our lppaca is 1kB because of the way we align 5338c2ecf20Sopenharmony_ci * it for the guest to avoid crossing a 4kB boundary. We only 5348c2ecf20Sopenharmony_ci * use 640 bytes of the structure though, so we should accept 5358c2ecf20Sopenharmony_ci * clients that set a size of 640. 5368c2ecf20Sopenharmony_ci */ 5378c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct lppaca) != 640); 5388c2ecf20Sopenharmony_ci if (len < sizeof(struct lppaca)) 5398c2ecf20Sopenharmony_ci break; 5408c2ecf20Sopenharmony_ci vpap = &tvcpu->arch.vpa; 5418c2ecf20Sopenharmony_ci err = 0; 5428c2ecf20Sopenharmony_ci break; 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci case H_VPA_REG_DTL: /* register DTL */ 5458c2ecf20Sopenharmony_ci if (len < sizeof(struct dtl_entry)) 5468c2ecf20Sopenharmony_ci break; 5478c2ecf20Sopenharmony_ci len -= len % sizeof(struct dtl_entry); 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci /* Check that they have previously registered a VPA */ 5508c2ecf20Sopenharmony_ci err = H_RESOURCE; 5518c2ecf20Sopenharmony_ci if (!vpa_is_registered(&tvcpu->arch.vpa)) 5528c2ecf20Sopenharmony_ci break; 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci vpap = &tvcpu->arch.dtl; 5558c2ecf20Sopenharmony_ci err = 0; 5568c2ecf20Sopenharmony_ci break; 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci case H_VPA_REG_SLB: /* register SLB shadow buffer */ 5598c2ecf20Sopenharmony_ci /* Check that they have previously registered a VPA */ 5608c2ecf20Sopenharmony_ci err = H_RESOURCE; 5618c2ecf20Sopenharmony_ci if (!vpa_is_registered(&tvcpu->arch.vpa)) 5628c2ecf20Sopenharmony_ci break; 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci vpap = &tvcpu->arch.slb_shadow; 5658c2ecf20Sopenharmony_ci err = 0; 5668c2ecf20Sopenharmony_ci break; 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci case H_VPA_DEREG_VPA: /* deregister VPA */ 5698c2ecf20Sopenharmony_ci /* Check they don't still have a DTL or SLB buf registered */ 5708c2ecf20Sopenharmony_ci err = H_RESOURCE; 5718c2ecf20Sopenharmony_ci if (vpa_is_registered(&tvcpu->arch.dtl) || 5728c2ecf20Sopenharmony_ci vpa_is_registered(&tvcpu->arch.slb_shadow)) 5738c2ecf20Sopenharmony_ci break; 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci vpap = &tvcpu->arch.vpa; 5768c2ecf20Sopenharmony_ci err = 0; 5778c2ecf20Sopenharmony_ci break; 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci case H_VPA_DEREG_DTL: /* deregister DTL */ 5808c2ecf20Sopenharmony_ci vpap = &tvcpu->arch.dtl; 5818c2ecf20Sopenharmony_ci err = 0; 5828c2ecf20Sopenharmony_ci break; 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci case H_VPA_DEREG_SLB: /* deregister SLB shadow buffer */ 5858c2ecf20Sopenharmony_ci vpap = &tvcpu->arch.slb_shadow; 5868c2ecf20Sopenharmony_ci err = 0; 5878c2ecf20Sopenharmony_ci break; 5888c2ecf20Sopenharmony_ci } 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci if (vpap) { 5918c2ecf20Sopenharmony_ci vpap->next_gpa = vpa; 5928c2ecf20Sopenharmony_ci vpap->len = len; 5938c2ecf20Sopenharmony_ci vpap->update_pending = 1; 5948c2ecf20Sopenharmony_ci } 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci spin_unlock(&tvcpu->arch.vpa_update_lock); 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci return err; 5998c2ecf20Sopenharmony_ci} 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_cistatic void kvmppc_update_vpa(struct kvm_vcpu *vcpu, struct kvmppc_vpa *vpap) 6028c2ecf20Sopenharmony_ci{ 6038c2ecf20Sopenharmony_ci struct kvm *kvm = vcpu->kvm; 6048c2ecf20Sopenharmony_ci void *va; 6058c2ecf20Sopenharmony_ci unsigned long nb; 6068c2ecf20Sopenharmony_ci unsigned long gpa; 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci /* 6098c2ecf20Sopenharmony_ci * We need to pin the page pointed to by vpap->next_gpa, 6108c2ecf20Sopenharmony_ci * but we can't call kvmppc_pin_guest_page under the lock 6118c2ecf20Sopenharmony_ci * as it does get_user_pages() and down_read(). So we 6128c2ecf20Sopenharmony_ci * have to drop the lock, pin the page, then get the lock 6138c2ecf20Sopenharmony_ci * again and check that a new area didn't get registered 6148c2ecf20Sopenharmony_ci * in the meantime. 6158c2ecf20Sopenharmony_ci */ 6168c2ecf20Sopenharmony_ci for (;;) { 6178c2ecf20Sopenharmony_ci gpa = vpap->next_gpa; 6188c2ecf20Sopenharmony_ci spin_unlock(&vcpu->arch.vpa_update_lock); 6198c2ecf20Sopenharmony_ci va = NULL; 6208c2ecf20Sopenharmony_ci nb = 0; 6218c2ecf20Sopenharmony_ci if (gpa) 6228c2ecf20Sopenharmony_ci va = kvmppc_pin_guest_page(kvm, gpa, &nb); 6238c2ecf20Sopenharmony_ci spin_lock(&vcpu->arch.vpa_update_lock); 6248c2ecf20Sopenharmony_ci if (gpa == vpap->next_gpa) 6258c2ecf20Sopenharmony_ci break; 6268c2ecf20Sopenharmony_ci /* sigh... unpin that one and try again */ 6278c2ecf20Sopenharmony_ci if (va) 6288c2ecf20Sopenharmony_ci kvmppc_unpin_guest_page(kvm, va, gpa, false); 6298c2ecf20Sopenharmony_ci } 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci vpap->update_pending = 0; 6328c2ecf20Sopenharmony_ci if (va && nb < vpap->len) { 6338c2ecf20Sopenharmony_ci /* 6348c2ecf20Sopenharmony_ci * If it's now too short, it must be that userspace 6358c2ecf20Sopenharmony_ci * has changed the mappings underlying guest memory, 6368c2ecf20Sopenharmony_ci * so unregister the region. 6378c2ecf20Sopenharmony_ci */ 6388c2ecf20Sopenharmony_ci kvmppc_unpin_guest_page(kvm, va, gpa, false); 6398c2ecf20Sopenharmony_ci va = NULL; 6408c2ecf20Sopenharmony_ci } 6418c2ecf20Sopenharmony_ci if (vpap->pinned_addr) 6428c2ecf20Sopenharmony_ci kvmppc_unpin_guest_page(kvm, vpap->pinned_addr, vpap->gpa, 6438c2ecf20Sopenharmony_ci vpap->dirty); 6448c2ecf20Sopenharmony_ci vpap->gpa = gpa; 6458c2ecf20Sopenharmony_ci vpap->pinned_addr = va; 6468c2ecf20Sopenharmony_ci vpap->dirty = false; 6478c2ecf20Sopenharmony_ci if (va) 6488c2ecf20Sopenharmony_ci vpap->pinned_end = va + vpap->len; 6498c2ecf20Sopenharmony_ci} 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_cistatic void kvmppc_update_vpas(struct kvm_vcpu *vcpu) 6528c2ecf20Sopenharmony_ci{ 6538c2ecf20Sopenharmony_ci if (!(vcpu->arch.vpa.update_pending || 6548c2ecf20Sopenharmony_ci vcpu->arch.slb_shadow.update_pending || 6558c2ecf20Sopenharmony_ci vcpu->arch.dtl.update_pending)) 6568c2ecf20Sopenharmony_ci return; 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci spin_lock(&vcpu->arch.vpa_update_lock); 6598c2ecf20Sopenharmony_ci if (vcpu->arch.vpa.update_pending) { 6608c2ecf20Sopenharmony_ci kvmppc_update_vpa(vcpu, &vcpu->arch.vpa); 6618c2ecf20Sopenharmony_ci if (vcpu->arch.vpa.pinned_addr) 6628c2ecf20Sopenharmony_ci init_vpa(vcpu, vcpu->arch.vpa.pinned_addr); 6638c2ecf20Sopenharmony_ci } 6648c2ecf20Sopenharmony_ci if (vcpu->arch.dtl.update_pending) { 6658c2ecf20Sopenharmony_ci kvmppc_update_vpa(vcpu, &vcpu->arch.dtl); 6668c2ecf20Sopenharmony_ci vcpu->arch.dtl_ptr = vcpu->arch.dtl.pinned_addr; 6678c2ecf20Sopenharmony_ci vcpu->arch.dtl_index = 0; 6688c2ecf20Sopenharmony_ci } 6698c2ecf20Sopenharmony_ci if (vcpu->arch.slb_shadow.update_pending) 6708c2ecf20Sopenharmony_ci kvmppc_update_vpa(vcpu, &vcpu->arch.slb_shadow); 6718c2ecf20Sopenharmony_ci spin_unlock(&vcpu->arch.vpa_update_lock); 6728c2ecf20Sopenharmony_ci} 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci/* 6758c2ecf20Sopenharmony_ci * Return the accumulated stolen time for the vcore up until `now'. 6768c2ecf20Sopenharmony_ci * The caller should hold the vcore lock. 6778c2ecf20Sopenharmony_ci */ 6788c2ecf20Sopenharmony_cistatic u64 vcore_stolen_time(struct kvmppc_vcore *vc, u64 now) 6798c2ecf20Sopenharmony_ci{ 6808c2ecf20Sopenharmony_ci u64 p; 6818c2ecf20Sopenharmony_ci unsigned long flags; 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_ci spin_lock_irqsave(&vc->stoltb_lock, flags); 6848c2ecf20Sopenharmony_ci p = vc->stolen_tb; 6858c2ecf20Sopenharmony_ci if (vc->vcore_state != VCORE_INACTIVE && 6868c2ecf20Sopenharmony_ci vc->preempt_tb != TB_NIL) 6878c2ecf20Sopenharmony_ci p += now - vc->preempt_tb; 6888c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&vc->stoltb_lock, flags); 6898c2ecf20Sopenharmony_ci return p; 6908c2ecf20Sopenharmony_ci} 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_cistatic void kvmppc_create_dtl_entry(struct kvm_vcpu *vcpu, 6938c2ecf20Sopenharmony_ci struct kvmppc_vcore *vc) 6948c2ecf20Sopenharmony_ci{ 6958c2ecf20Sopenharmony_ci struct dtl_entry *dt; 6968c2ecf20Sopenharmony_ci struct lppaca *vpa; 6978c2ecf20Sopenharmony_ci unsigned long stolen; 6988c2ecf20Sopenharmony_ci unsigned long core_stolen; 6998c2ecf20Sopenharmony_ci u64 now; 7008c2ecf20Sopenharmony_ci unsigned long flags; 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci dt = vcpu->arch.dtl_ptr; 7038c2ecf20Sopenharmony_ci vpa = vcpu->arch.vpa.pinned_addr; 7048c2ecf20Sopenharmony_ci now = mftb(); 7058c2ecf20Sopenharmony_ci core_stolen = vcore_stolen_time(vc, now); 7068c2ecf20Sopenharmony_ci stolen = core_stolen - vcpu->arch.stolen_logged; 7078c2ecf20Sopenharmony_ci vcpu->arch.stolen_logged = core_stolen; 7088c2ecf20Sopenharmony_ci spin_lock_irqsave(&vcpu->arch.tbacct_lock, flags); 7098c2ecf20Sopenharmony_ci stolen += vcpu->arch.busy_stolen; 7108c2ecf20Sopenharmony_ci vcpu->arch.busy_stolen = 0; 7118c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&vcpu->arch.tbacct_lock, flags); 7128c2ecf20Sopenharmony_ci if (!dt || !vpa) 7138c2ecf20Sopenharmony_ci return; 7148c2ecf20Sopenharmony_ci memset(dt, 0, sizeof(struct dtl_entry)); 7158c2ecf20Sopenharmony_ci dt->dispatch_reason = 7; 7168c2ecf20Sopenharmony_ci dt->processor_id = cpu_to_be16(vc->pcpu + vcpu->arch.ptid); 7178c2ecf20Sopenharmony_ci dt->timebase = cpu_to_be64(now + vc->tb_offset); 7188c2ecf20Sopenharmony_ci dt->enqueue_to_dispatch_time = cpu_to_be32(stolen); 7198c2ecf20Sopenharmony_ci dt->srr0 = cpu_to_be64(kvmppc_get_pc(vcpu)); 7208c2ecf20Sopenharmony_ci dt->srr1 = cpu_to_be64(vcpu->arch.shregs.msr); 7218c2ecf20Sopenharmony_ci ++dt; 7228c2ecf20Sopenharmony_ci if (dt == vcpu->arch.dtl.pinned_end) 7238c2ecf20Sopenharmony_ci dt = vcpu->arch.dtl.pinned_addr; 7248c2ecf20Sopenharmony_ci vcpu->arch.dtl_ptr = dt; 7258c2ecf20Sopenharmony_ci /* order writing *dt vs. writing vpa->dtl_idx */ 7268c2ecf20Sopenharmony_ci smp_wmb(); 7278c2ecf20Sopenharmony_ci vpa->dtl_idx = cpu_to_be64(++vcpu->arch.dtl_index); 7288c2ecf20Sopenharmony_ci vcpu->arch.dtl.dirty = true; 7298c2ecf20Sopenharmony_ci} 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_ci/* See if there is a doorbell interrupt pending for a vcpu */ 7328c2ecf20Sopenharmony_cistatic bool kvmppc_doorbell_pending(struct kvm_vcpu *vcpu) 7338c2ecf20Sopenharmony_ci{ 7348c2ecf20Sopenharmony_ci int thr; 7358c2ecf20Sopenharmony_ci struct kvmppc_vcore *vc; 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci if (vcpu->arch.doorbell_request) 7388c2ecf20Sopenharmony_ci return true; 7398c2ecf20Sopenharmony_ci /* 7408c2ecf20Sopenharmony_ci * Ensure that the read of vcore->dpdes comes after the read 7418c2ecf20Sopenharmony_ci * of vcpu->doorbell_request. This barrier matches the 7428c2ecf20Sopenharmony_ci * smp_wmb() in kvmppc_guest_entry_inject(). 7438c2ecf20Sopenharmony_ci */ 7448c2ecf20Sopenharmony_ci smp_rmb(); 7458c2ecf20Sopenharmony_ci vc = vcpu->arch.vcore; 7468c2ecf20Sopenharmony_ci thr = vcpu->vcpu_id - vc->first_vcpuid; 7478c2ecf20Sopenharmony_ci return !!(vc->dpdes & (1 << thr)); 7488c2ecf20Sopenharmony_ci} 7498c2ecf20Sopenharmony_ci 7508c2ecf20Sopenharmony_cistatic bool kvmppc_power8_compatible(struct kvm_vcpu *vcpu) 7518c2ecf20Sopenharmony_ci{ 7528c2ecf20Sopenharmony_ci if (vcpu->arch.vcore->arch_compat >= PVR_ARCH_207) 7538c2ecf20Sopenharmony_ci return true; 7548c2ecf20Sopenharmony_ci if ((!vcpu->arch.vcore->arch_compat) && 7558c2ecf20Sopenharmony_ci cpu_has_feature(CPU_FTR_ARCH_207S)) 7568c2ecf20Sopenharmony_ci return true; 7578c2ecf20Sopenharmony_ci return false; 7588c2ecf20Sopenharmony_ci} 7598c2ecf20Sopenharmony_ci 7608c2ecf20Sopenharmony_cistatic int kvmppc_h_set_mode(struct kvm_vcpu *vcpu, unsigned long mflags, 7618c2ecf20Sopenharmony_ci unsigned long resource, unsigned long value1, 7628c2ecf20Sopenharmony_ci unsigned long value2) 7638c2ecf20Sopenharmony_ci{ 7648c2ecf20Sopenharmony_ci switch (resource) { 7658c2ecf20Sopenharmony_ci case H_SET_MODE_RESOURCE_SET_CIABR: 7668c2ecf20Sopenharmony_ci if (!kvmppc_power8_compatible(vcpu)) 7678c2ecf20Sopenharmony_ci return H_P2; 7688c2ecf20Sopenharmony_ci if (value2) 7698c2ecf20Sopenharmony_ci return H_P4; 7708c2ecf20Sopenharmony_ci if (mflags) 7718c2ecf20Sopenharmony_ci return H_UNSUPPORTED_FLAG_START; 7728c2ecf20Sopenharmony_ci /* Guests can't breakpoint the hypervisor */ 7738c2ecf20Sopenharmony_ci if ((value1 & CIABR_PRIV) == CIABR_PRIV_HYPER) 7748c2ecf20Sopenharmony_ci return H_P3; 7758c2ecf20Sopenharmony_ci vcpu->arch.ciabr = value1; 7768c2ecf20Sopenharmony_ci return H_SUCCESS; 7778c2ecf20Sopenharmony_ci case H_SET_MODE_RESOURCE_SET_DAWR0: 7788c2ecf20Sopenharmony_ci if (!kvmppc_power8_compatible(vcpu)) 7798c2ecf20Sopenharmony_ci return H_P2; 7808c2ecf20Sopenharmony_ci if (!ppc_breakpoint_available()) 7818c2ecf20Sopenharmony_ci return H_P2; 7828c2ecf20Sopenharmony_ci if (mflags) 7838c2ecf20Sopenharmony_ci return H_UNSUPPORTED_FLAG_START; 7848c2ecf20Sopenharmony_ci if (value2 & DABRX_HYP) 7858c2ecf20Sopenharmony_ci return H_P4; 7868c2ecf20Sopenharmony_ci vcpu->arch.dawr = value1; 7878c2ecf20Sopenharmony_ci vcpu->arch.dawrx = value2; 7888c2ecf20Sopenharmony_ci return H_SUCCESS; 7898c2ecf20Sopenharmony_ci case H_SET_MODE_RESOURCE_ADDR_TRANS_MODE: 7908c2ecf20Sopenharmony_ci /* KVM does not support mflags=2 (AIL=2) */ 7918c2ecf20Sopenharmony_ci if (mflags != 0 && mflags != 3) 7928c2ecf20Sopenharmony_ci return H_UNSUPPORTED_FLAG_START; 7938c2ecf20Sopenharmony_ci return H_TOO_HARD; 7948c2ecf20Sopenharmony_ci default: 7958c2ecf20Sopenharmony_ci return H_TOO_HARD; 7968c2ecf20Sopenharmony_ci } 7978c2ecf20Sopenharmony_ci} 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci/* Copy guest memory in place - must reside within a single memslot */ 8008c2ecf20Sopenharmony_cistatic int kvmppc_copy_guest(struct kvm *kvm, gpa_t to, gpa_t from, 8018c2ecf20Sopenharmony_ci unsigned long len) 8028c2ecf20Sopenharmony_ci{ 8038c2ecf20Sopenharmony_ci struct kvm_memory_slot *to_memslot = NULL; 8048c2ecf20Sopenharmony_ci struct kvm_memory_slot *from_memslot = NULL; 8058c2ecf20Sopenharmony_ci unsigned long to_addr, from_addr; 8068c2ecf20Sopenharmony_ci int r; 8078c2ecf20Sopenharmony_ci 8088c2ecf20Sopenharmony_ci /* Get HPA for from address */ 8098c2ecf20Sopenharmony_ci from_memslot = gfn_to_memslot(kvm, from >> PAGE_SHIFT); 8108c2ecf20Sopenharmony_ci if (!from_memslot) 8118c2ecf20Sopenharmony_ci return -EFAULT; 8128c2ecf20Sopenharmony_ci if ((from + len) >= ((from_memslot->base_gfn + from_memslot->npages) 8138c2ecf20Sopenharmony_ci << PAGE_SHIFT)) 8148c2ecf20Sopenharmony_ci return -EINVAL; 8158c2ecf20Sopenharmony_ci from_addr = gfn_to_hva_memslot(from_memslot, from >> PAGE_SHIFT); 8168c2ecf20Sopenharmony_ci if (kvm_is_error_hva(from_addr)) 8178c2ecf20Sopenharmony_ci return -EFAULT; 8188c2ecf20Sopenharmony_ci from_addr |= (from & (PAGE_SIZE - 1)); 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_ci /* Get HPA for to address */ 8218c2ecf20Sopenharmony_ci to_memslot = gfn_to_memslot(kvm, to >> PAGE_SHIFT); 8228c2ecf20Sopenharmony_ci if (!to_memslot) 8238c2ecf20Sopenharmony_ci return -EFAULT; 8248c2ecf20Sopenharmony_ci if ((to + len) >= ((to_memslot->base_gfn + to_memslot->npages) 8258c2ecf20Sopenharmony_ci << PAGE_SHIFT)) 8268c2ecf20Sopenharmony_ci return -EINVAL; 8278c2ecf20Sopenharmony_ci to_addr = gfn_to_hva_memslot(to_memslot, to >> PAGE_SHIFT); 8288c2ecf20Sopenharmony_ci if (kvm_is_error_hva(to_addr)) 8298c2ecf20Sopenharmony_ci return -EFAULT; 8308c2ecf20Sopenharmony_ci to_addr |= (to & (PAGE_SIZE - 1)); 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci /* Perform copy */ 8338c2ecf20Sopenharmony_ci r = raw_copy_in_user((void __user *)to_addr, (void __user *)from_addr, 8348c2ecf20Sopenharmony_ci len); 8358c2ecf20Sopenharmony_ci if (r) 8368c2ecf20Sopenharmony_ci return -EFAULT; 8378c2ecf20Sopenharmony_ci mark_page_dirty(kvm, to >> PAGE_SHIFT); 8388c2ecf20Sopenharmony_ci return 0; 8398c2ecf20Sopenharmony_ci} 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_cistatic long kvmppc_h_page_init(struct kvm_vcpu *vcpu, unsigned long flags, 8428c2ecf20Sopenharmony_ci unsigned long dest, unsigned long src) 8438c2ecf20Sopenharmony_ci{ 8448c2ecf20Sopenharmony_ci u64 pg_sz = SZ_4K; /* 4K page size */ 8458c2ecf20Sopenharmony_ci u64 pg_mask = SZ_4K - 1; 8468c2ecf20Sopenharmony_ci int ret; 8478c2ecf20Sopenharmony_ci 8488c2ecf20Sopenharmony_ci /* Check for invalid flags (H_PAGE_SET_LOANED covers all CMO flags) */ 8498c2ecf20Sopenharmony_ci if (flags & ~(H_ICACHE_INVALIDATE | H_ICACHE_SYNCHRONIZE | 8508c2ecf20Sopenharmony_ci H_ZERO_PAGE | H_COPY_PAGE | H_PAGE_SET_LOANED)) 8518c2ecf20Sopenharmony_ci return H_PARAMETER; 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_ci /* dest (and src if copy_page flag set) must be page aligned */ 8548c2ecf20Sopenharmony_ci if ((dest & pg_mask) || ((flags & H_COPY_PAGE) && (src & pg_mask))) 8558c2ecf20Sopenharmony_ci return H_PARAMETER; 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_ci /* zero and/or copy the page as determined by the flags */ 8588c2ecf20Sopenharmony_ci if (flags & H_COPY_PAGE) { 8598c2ecf20Sopenharmony_ci ret = kvmppc_copy_guest(vcpu->kvm, dest, src, pg_sz); 8608c2ecf20Sopenharmony_ci if (ret < 0) 8618c2ecf20Sopenharmony_ci return H_PARAMETER; 8628c2ecf20Sopenharmony_ci } else if (flags & H_ZERO_PAGE) { 8638c2ecf20Sopenharmony_ci ret = kvm_clear_guest(vcpu->kvm, dest, pg_sz); 8648c2ecf20Sopenharmony_ci if (ret < 0) 8658c2ecf20Sopenharmony_ci return H_PARAMETER; 8668c2ecf20Sopenharmony_ci } 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_ci /* We can ignore the remaining flags */ 8698c2ecf20Sopenharmony_ci 8708c2ecf20Sopenharmony_ci return H_SUCCESS; 8718c2ecf20Sopenharmony_ci} 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_cistatic int kvm_arch_vcpu_yield_to(struct kvm_vcpu *target) 8748c2ecf20Sopenharmony_ci{ 8758c2ecf20Sopenharmony_ci struct kvmppc_vcore *vcore = target->arch.vcore; 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci /* 8788c2ecf20Sopenharmony_ci * We expect to have been called by the real mode handler 8798c2ecf20Sopenharmony_ci * (kvmppc_rm_h_confer()) which would have directly returned 8808c2ecf20Sopenharmony_ci * H_SUCCESS if the source vcore wasn't idle (e.g. if it may 8818c2ecf20Sopenharmony_ci * have useful work to do and should not confer) so we don't 8828c2ecf20Sopenharmony_ci * recheck that here. 8838c2ecf20Sopenharmony_ci */ 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_ci spin_lock(&vcore->lock); 8868c2ecf20Sopenharmony_ci if (target->arch.state == KVMPPC_VCPU_RUNNABLE && 8878c2ecf20Sopenharmony_ci vcore->vcore_state != VCORE_INACTIVE && 8888c2ecf20Sopenharmony_ci vcore->runner) 8898c2ecf20Sopenharmony_ci target = vcore->runner; 8908c2ecf20Sopenharmony_ci spin_unlock(&vcore->lock); 8918c2ecf20Sopenharmony_ci 8928c2ecf20Sopenharmony_ci return kvm_vcpu_yield_to(target); 8938c2ecf20Sopenharmony_ci} 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_cistatic int kvmppc_get_yield_count(struct kvm_vcpu *vcpu) 8968c2ecf20Sopenharmony_ci{ 8978c2ecf20Sopenharmony_ci int yield_count = 0; 8988c2ecf20Sopenharmony_ci struct lppaca *lppaca; 8998c2ecf20Sopenharmony_ci 9008c2ecf20Sopenharmony_ci spin_lock(&vcpu->arch.vpa_update_lock); 9018c2ecf20Sopenharmony_ci lppaca = (struct lppaca *)vcpu->arch.vpa.pinned_addr; 9028c2ecf20Sopenharmony_ci if (lppaca) 9038c2ecf20Sopenharmony_ci yield_count = be32_to_cpu(lppaca->yield_count); 9048c2ecf20Sopenharmony_ci spin_unlock(&vcpu->arch.vpa_update_lock); 9058c2ecf20Sopenharmony_ci return yield_count; 9068c2ecf20Sopenharmony_ci} 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_ciint kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu) 9098c2ecf20Sopenharmony_ci{ 9108c2ecf20Sopenharmony_ci unsigned long req = kvmppc_get_gpr(vcpu, 3); 9118c2ecf20Sopenharmony_ci unsigned long target, ret = H_SUCCESS; 9128c2ecf20Sopenharmony_ci int yield_count; 9138c2ecf20Sopenharmony_ci struct kvm_vcpu *tvcpu; 9148c2ecf20Sopenharmony_ci int idx, rc; 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_ci if (req <= MAX_HCALL_OPCODE && 9178c2ecf20Sopenharmony_ci !test_bit(req/4, vcpu->kvm->arch.enabled_hcalls)) 9188c2ecf20Sopenharmony_ci return RESUME_HOST; 9198c2ecf20Sopenharmony_ci 9208c2ecf20Sopenharmony_ci switch (req) { 9218c2ecf20Sopenharmony_ci case H_CEDE: 9228c2ecf20Sopenharmony_ci break; 9238c2ecf20Sopenharmony_ci case H_PROD: 9248c2ecf20Sopenharmony_ci target = kvmppc_get_gpr(vcpu, 4); 9258c2ecf20Sopenharmony_ci tvcpu = kvmppc_find_vcpu(vcpu->kvm, target); 9268c2ecf20Sopenharmony_ci if (!tvcpu) { 9278c2ecf20Sopenharmony_ci ret = H_PARAMETER; 9288c2ecf20Sopenharmony_ci break; 9298c2ecf20Sopenharmony_ci } 9308c2ecf20Sopenharmony_ci tvcpu->arch.prodded = 1; 9318c2ecf20Sopenharmony_ci smp_mb(); 9328c2ecf20Sopenharmony_ci if (tvcpu->arch.ceded) 9338c2ecf20Sopenharmony_ci kvmppc_fast_vcpu_kick_hv(tvcpu); 9348c2ecf20Sopenharmony_ci break; 9358c2ecf20Sopenharmony_ci case H_CONFER: 9368c2ecf20Sopenharmony_ci target = kvmppc_get_gpr(vcpu, 4); 9378c2ecf20Sopenharmony_ci if (target == -1) 9388c2ecf20Sopenharmony_ci break; 9398c2ecf20Sopenharmony_ci tvcpu = kvmppc_find_vcpu(vcpu->kvm, target); 9408c2ecf20Sopenharmony_ci if (!tvcpu) { 9418c2ecf20Sopenharmony_ci ret = H_PARAMETER; 9428c2ecf20Sopenharmony_ci break; 9438c2ecf20Sopenharmony_ci } 9448c2ecf20Sopenharmony_ci yield_count = kvmppc_get_gpr(vcpu, 5); 9458c2ecf20Sopenharmony_ci if (kvmppc_get_yield_count(tvcpu) != yield_count) 9468c2ecf20Sopenharmony_ci break; 9478c2ecf20Sopenharmony_ci kvm_arch_vcpu_yield_to(tvcpu); 9488c2ecf20Sopenharmony_ci break; 9498c2ecf20Sopenharmony_ci case H_REGISTER_VPA: 9508c2ecf20Sopenharmony_ci ret = do_h_register_vpa(vcpu, kvmppc_get_gpr(vcpu, 4), 9518c2ecf20Sopenharmony_ci kvmppc_get_gpr(vcpu, 5), 9528c2ecf20Sopenharmony_ci kvmppc_get_gpr(vcpu, 6)); 9538c2ecf20Sopenharmony_ci break; 9548c2ecf20Sopenharmony_ci case H_RTAS: 9558c2ecf20Sopenharmony_ci if (list_empty(&vcpu->kvm->arch.rtas_tokens)) 9568c2ecf20Sopenharmony_ci return RESUME_HOST; 9578c2ecf20Sopenharmony_ci 9588c2ecf20Sopenharmony_ci idx = srcu_read_lock(&vcpu->kvm->srcu); 9598c2ecf20Sopenharmony_ci rc = kvmppc_rtas_hcall(vcpu); 9608c2ecf20Sopenharmony_ci srcu_read_unlock(&vcpu->kvm->srcu, idx); 9618c2ecf20Sopenharmony_ci 9628c2ecf20Sopenharmony_ci if (rc == -ENOENT) 9638c2ecf20Sopenharmony_ci return RESUME_HOST; 9648c2ecf20Sopenharmony_ci else if (rc == 0) 9658c2ecf20Sopenharmony_ci break; 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_ci /* Send the error out to userspace via KVM_RUN */ 9688c2ecf20Sopenharmony_ci return rc; 9698c2ecf20Sopenharmony_ci case H_LOGICAL_CI_LOAD: 9708c2ecf20Sopenharmony_ci ret = kvmppc_h_logical_ci_load(vcpu); 9718c2ecf20Sopenharmony_ci if (ret == H_TOO_HARD) 9728c2ecf20Sopenharmony_ci return RESUME_HOST; 9738c2ecf20Sopenharmony_ci break; 9748c2ecf20Sopenharmony_ci case H_LOGICAL_CI_STORE: 9758c2ecf20Sopenharmony_ci ret = kvmppc_h_logical_ci_store(vcpu); 9768c2ecf20Sopenharmony_ci if (ret == H_TOO_HARD) 9778c2ecf20Sopenharmony_ci return RESUME_HOST; 9788c2ecf20Sopenharmony_ci break; 9798c2ecf20Sopenharmony_ci case H_SET_MODE: 9808c2ecf20Sopenharmony_ci ret = kvmppc_h_set_mode(vcpu, kvmppc_get_gpr(vcpu, 4), 9818c2ecf20Sopenharmony_ci kvmppc_get_gpr(vcpu, 5), 9828c2ecf20Sopenharmony_ci kvmppc_get_gpr(vcpu, 6), 9838c2ecf20Sopenharmony_ci kvmppc_get_gpr(vcpu, 7)); 9848c2ecf20Sopenharmony_ci if (ret == H_TOO_HARD) 9858c2ecf20Sopenharmony_ci return RESUME_HOST; 9868c2ecf20Sopenharmony_ci break; 9878c2ecf20Sopenharmony_ci case H_XIRR: 9888c2ecf20Sopenharmony_ci case H_CPPR: 9898c2ecf20Sopenharmony_ci case H_EOI: 9908c2ecf20Sopenharmony_ci case H_IPI: 9918c2ecf20Sopenharmony_ci case H_IPOLL: 9928c2ecf20Sopenharmony_ci case H_XIRR_X: 9938c2ecf20Sopenharmony_ci if (kvmppc_xics_enabled(vcpu)) { 9948c2ecf20Sopenharmony_ci if (xics_on_xive()) { 9958c2ecf20Sopenharmony_ci ret = H_NOT_AVAILABLE; 9968c2ecf20Sopenharmony_ci return RESUME_GUEST; 9978c2ecf20Sopenharmony_ci } 9988c2ecf20Sopenharmony_ci ret = kvmppc_xics_hcall(vcpu, req); 9998c2ecf20Sopenharmony_ci break; 10008c2ecf20Sopenharmony_ci } 10018c2ecf20Sopenharmony_ci return RESUME_HOST; 10028c2ecf20Sopenharmony_ci case H_SET_DABR: 10038c2ecf20Sopenharmony_ci ret = kvmppc_h_set_dabr(vcpu, kvmppc_get_gpr(vcpu, 4)); 10048c2ecf20Sopenharmony_ci break; 10058c2ecf20Sopenharmony_ci case H_SET_XDABR: 10068c2ecf20Sopenharmony_ci ret = kvmppc_h_set_xdabr(vcpu, kvmppc_get_gpr(vcpu, 4), 10078c2ecf20Sopenharmony_ci kvmppc_get_gpr(vcpu, 5)); 10088c2ecf20Sopenharmony_ci break; 10098c2ecf20Sopenharmony_ci#ifdef CONFIG_SPAPR_TCE_IOMMU 10108c2ecf20Sopenharmony_ci case H_GET_TCE: 10118c2ecf20Sopenharmony_ci ret = kvmppc_h_get_tce(vcpu, kvmppc_get_gpr(vcpu, 4), 10128c2ecf20Sopenharmony_ci kvmppc_get_gpr(vcpu, 5)); 10138c2ecf20Sopenharmony_ci if (ret == H_TOO_HARD) 10148c2ecf20Sopenharmony_ci return RESUME_HOST; 10158c2ecf20Sopenharmony_ci break; 10168c2ecf20Sopenharmony_ci case H_PUT_TCE: 10178c2ecf20Sopenharmony_ci ret = kvmppc_h_put_tce(vcpu, kvmppc_get_gpr(vcpu, 4), 10188c2ecf20Sopenharmony_ci kvmppc_get_gpr(vcpu, 5), 10198c2ecf20Sopenharmony_ci kvmppc_get_gpr(vcpu, 6)); 10208c2ecf20Sopenharmony_ci if (ret == H_TOO_HARD) 10218c2ecf20Sopenharmony_ci return RESUME_HOST; 10228c2ecf20Sopenharmony_ci break; 10238c2ecf20Sopenharmony_ci case H_PUT_TCE_INDIRECT: 10248c2ecf20Sopenharmony_ci ret = kvmppc_h_put_tce_indirect(vcpu, kvmppc_get_gpr(vcpu, 4), 10258c2ecf20Sopenharmony_ci kvmppc_get_gpr(vcpu, 5), 10268c2ecf20Sopenharmony_ci kvmppc_get_gpr(vcpu, 6), 10278c2ecf20Sopenharmony_ci kvmppc_get_gpr(vcpu, 7)); 10288c2ecf20Sopenharmony_ci if (ret == H_TOO_HARD) 10298c2ecf20Sopenharmony_ci return RESUME_HOST; 10308c2ecf20Sopenharmony_ci break; 10318c2ecf20Sopenharmony_ci case H_STUFF_TCE: 10328c2ecf20Sopenharmony_ci ret = kvmppc_h_stuff_tce(vcpu, kvmppc_get_gpr(vcpu, 4), 10338c2ecf20Sopenharmony_ci kvmppc_get_gpr(vcpu, 5), 10348c2ecf20Sopenharmony_ci kvmppc_get_gpr(vcpu, 6), 10358c2ecf20Sopenharmony_ci kvmppc_get_gpr(vcpu, 7)); 10368c2ecf20Sopenharmony_ci if (ret == H_TOO_HARD) 10378c2ecf20Sopenharmony_ci return RESUME_HOST; 10388c2ecf20Sopenharmony_ci break; 10398c2ecf20Sopenharmony_ci#endif 10408c2ecf20Sopenharmony_ci case H_RANDOM: 10418c2ecf20Sopenharmony_ci if (!powernv_get_random_long(&vcpu->arch.regs.gpr[4])) 10428c2ecf20Sopenharmony_ci ret = H_HARDWARE; 10438c2ecf20Sopenharmony_ci break; 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_ci case H_SET_PARTITION_TABLE: 10468c2ecf20Sopenharmony_ci ret = H_FUNCTION; 10478c2ecf20Sopenharmony_ci if (nesting_enabled(vcpu->kvm)) 10488c2ecf20Sopenharmony_ci ret = kvmhv_set_partition_table(vcpu); 10498c2ecf20Sopenharmony_ci break; 10508c2ecf20Sopenharmony_ci case H_ENTER_NESTED: 10518c2ecf20Sopenharmony_ci ret = H_FUNCTION; 10528c2ecf20Sopenharmony_ci if (!nesting_enabled(vcpu->kvm)) 10538c2ecf20Sopenharmony_ci break; 10548c2ecf20Sopenharmony_ci ret = kvmhv_enter_nested_guest(vcpu); 10558c2ecf20Sopenharmony_ci if (ret == H_INTERRUPT) { 10568c2ecf20Sopenharmony_ci kvmppc_set_gpr(vcpu, 3, 0); 10578c2ecf20Sopenharmony_ci vcpu->arch.hcall_needed = 0; 10588c2ecf20Sopenharmony_ci return -EINTR; 10598c2ecf20Sopenharmony_ci } else if (ret == H_TOO_HARD) { 10608c2ecf20Sopenharmony_ci kvmppc_set_gpr(vcpu, 3, 0); 10618c2ecf20Sopenharmony_ci vcpu->arch.hcall_needed = 0; 10628c2ecf20Sopenharmony_ci return RESUME_HOST; 10638c2ecf20Sopenharmony_ci } 10648c2ecf20Sopenharmony_ci break; 10658c2ecf20Sopenharmony_ci case H_TLB_INVALIDATE: 10668c2ecf20Sopenharmony_ci ret = H_FUNCTION; 10678c2ecf20Sopenharmony_ci if (nesting_enabled(vcpu->kvm)) 10688c2ecf20Sopenharmony_ci ret = kvmhv_do_nested_tlbie(vcpu); 10698c2ecf20Sopenharmony_ci break; 10708c2ecf20Sopenharmony_ci case H_COPY_TOFROM_GUEST: 10718c2ecf20Sopenharmony_ci ret = H_FUNCTION; 10728c2ecf20Sopenharmony_ci if (nesting_enabled(vcpu->kvm)) 10738c2ecf20Sopenharmony_ci ret = kvmhv_copy_tofrom_guest_nested(vcpu); 10748c2ecf20Sopenharmony_ci break; 10758c2ecf20Sopenharmony_ci case H_PAGE_INIT: 10768c2ecf20Sopenharmony_ci ret = kvmppc_h_page_init(vcpu, kvmppc_get_gpr(vcpu, 4), 10778c2ecf20Sopenharmony_ci kvmppc_get_gpr(vcpu, 5), 10788c2ecf20Sopenharmony_ci kvmppc_get_gpr(vcpu, 6)); 10798c2ecf20Sopenharmony_ci break; 10808c2ecf20Sopenharmony_ci case H_SVM_PAGE_IN: 10818c2ecf20Sopenharmony_ci ret = H_UNSUPPORTED; 10828c2ecf20Sopenharmony_ci if (kvmppc_get_srr1(vcpu) & MSR_S) 10838c2ecf20Sopenharmony_ci ret = kvmppc_h_svm_page_in(vcpu->kvm, 10848c2ecf20Sopenharmony_ci kvmppc_get_gpr(vcpu, 4), 10858c2ecf20Sopenharmony_ci kvmppc_get_gpr(vcpu, 5), 10868c2ecf20Sopenharmony_ci kvmppc_get_gpr(vcpu, 6)); 10878c2ecf20Sopenharmony_ci break; 10888c2ecf20Sopenharmony_ci case H_SVM_PAGE_OUT: 10898c2ecf20Sopenharmony_ci ret = H_UNSUPPORTED; 10908c2ecf20Sopenharmony_ci if (kvmppc_get_srr1(vcpu) & MSR_S) 10918c2ecf20Sopenharmony_ci ret = kvmppc_h_svm_page_out(vcpu->kvm, 10928c2ecf20Sopenharmony_ci kvmppc_get_gpr(vcpu, 4), 10938c2ecf20Sopenharmony_ci kvmppc_get_gpr(vcpu, 5), 10948c2ecf20Sopenharmony_ci kvmppc_get_gpr(vcpu, 6)); 10958c2ecf20Sopenharmony_ci break; 10968c2ecf20Sopenharmony_ci case H_SVM_INIT_START: 10978c2ecf20Sopenharmony_ci ret = H_UNSUPPORTED; 10988c2ecf20Sopenharmony_ci if (kvmppc_get_srr1(vcpu) & MSR_S) 10998c2ecf20Sopenharmony_ci ret = kvmppc_h_svm_init_start(vcpu->kvm); 11008c2ecf20Sopenharmony_ci break; 11018c2ecf20Sopenharmony_ci case H_SVM_INIT_DONE: 11028c2ecf20Sopenharmony_ci ret = H_UNSUPPORTED; 11038c2ecf20Sopenharmony_ci if (kvmppc_get_srr1(vcpu) & MSR_S) 11048c2ecf20Sopenharmony_ci ret = kvmppc_h_svm_init_done(vcpu->kvm); 11058c2ecf20Sopenharmony_ci break; 11068c2ecf20Sopenharmony_ci case H_SVM_INIT_ABORT: 11078c2ecf20Sopenharmony_ci /* 11088c2ecf20Sopenharmony_ci * Even if that call is made by the Ultravisor, the SSR1 value 11098c2ecf20Sopenharmony_ci * is the guest context one, with the secure bit clear as it has 11108c2ecf20Sopenharmony_ci * not yet been secured. So we can't check it here. 11118c2ecf20Sopenharmony_ci * Instead the kvm->arch.secure_guest flag is checked inside 11128c2ecf20Sopenharmony_ci * kvmppc_h_svm_init_abort(). 11138c2ecf20Sopenharmony_ci */ 11148c2ecf20Sopenharmony_ci ret = kvmppc_h_svm_init_abort(vcpu->kvm); 11158c2ecf20Sopenharmony_ci break; 11168c2ecf20Sopenharmony_ci 11178c2ecf20Sopenharmony_ci default: 11188c2ecf20Sopenharmony_ci return RESUME_HOST; 11198c2ecf20Sopenharmony_ci } 11208c2ecf20Sopenharmony_ci kvmppc_set_gpr(vcpu, 3, ret); 11218c2ecf20Sopenharmony_ci vcpu->arch.hcall_needed = 0; 11228c2ecf20Sopenharmony_ci return RESUME_GUEST; 11238c2ecf20Sopenharmony_ci} 11248c2ecf20Sopenharmony_ci 11258c2ecf20Sopenharmony_ci/* 11268c2ecf20Sopenharmony_ci * Handle H_CEDE in the nested virtualization case where we haven't 11278c2ecf20Sopenharmony_ci * called the real-mode hcall handlers in book3s_hv_rmhandlers.S. 11288c2ecf20Sopenharmony_ci * This has to be done early, not in kvmppc_pseries_do_hcall(), so 11298c2ecf20Sopenharmony_ci * that the cede logic in kvmppc_run_single_vcpu() works properly. 11308c2ecf20Sopenharmony_ci */ 11318c2ecf20Sopenharmony_cistatic void kvmppc_nested_cede(struct kvm_vcpu *vcpu) 11328c2ecf20Sopenharmony_ci{ 11338c2ecf20Sopenharmony_ci vcpu->arch.shregs.msr |= MSR_EE; 11348c2ecf20Sopenharmony_ci vcpu->arch.ceded = 1; 11358c2ecf20Sopenharmony_ci smp_mb(); 11368c2ecf20Sopenharmony_ci if (vcpu->arch.prodded) { 11378c2ecf20Sopenharmony_ci vcpu->arch.prodded = 0; 11388c2ecf20Sopenharmony_ci smp_mb(); 11398c2ecf20Sopenharmony_ci vcpu->arch.ceded = 0; 11408c2ecf20Sopenharmony_ci } 11418c2ecf20Sopenharmony_ci} 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_cistatic int kvmppc_hcall_impl_hv(unsigned long cmd) 11448c2ecf20Sopenharmony_ci{ 11458c2ecf20Sopenharmony_ci switch (cmd) { 11468c2ecf20Sopenharmony_ci case H_CEDE: 11478c2ecf20Sopenharmony_ci case H_PROD: 11488c2ecf20Sopenharmony_ci case H_CONFER: 11498c2ecf20Sopenharmony_ci case H_REGISTER_VPA: 11508c2ecf20Sopenharmony_ci case H_SET_MODE: 11518c2ecf20Sopenharmony_ci case H_LOGICAL_CI_LOAD: 11528c2ecf20Sopenharmony_ci case H_LOGICAL_CI_STORE: 11538c2ecf20Sopenharmony_ci#ifdef CONFIG_KVM_XICS 11548c2ecf20Sopenharmony_ci case H_XIRR: 11558c2ecf20Sopenharmony_ci case H_CPPR: 11568c2ecf20Sopenharmony_ci case H_EOI: 11578c2ecf20Sopenharmony_ci case H_IPI: 11588c2ecf20Sopenharmony_ci case H_IPOLL: 11598c2ecf20Sopenharmony_ci case H_XIRR_X: 11608c2ecf20Sopenharmony_ci#endif 11618c2ecf20Sopenharmony_ci case H_PAGE_INIT: 11628c2ecf20Sopenharmony_ci return 1; 11638c2ecf20Sopenharmony_ci } 11648c2ecf20Sopenharmony_ci 11658c2ecf20Sopenharmony_ci /* See if it's in the real-mode table */ 11668c2ecf20Sopenharmony_ci return kvmppc_hcall_impl_hv_realmode(cmd); 11678c2ecf20Sopenharmony_ci} 11688c2ecf20Sopenharmony_ci 11698c2ecf20Sopenharmony_cistatic int kvmppc_emulate_debug_inst(struct kvm_vcpu *vcpu) 11708c2ecf20Sopenharmony_ci{ 11718c2ecf20Sopenharmony_ci u32 last_inst; 11728c2ecf20Sopenharmony_ci 11738c2ecf20Sopenharmony_ci if (kvmppc_get_last_inst(vcpu, INST_GENERIC, &last_inst) != 11748c2ecf20Sopenharmony_ci EMULATE_DONE) { 11758c2ecf20Sopenharmony_ci /* 11768c2ecf20Sopenharmony_ci * Fetch failed, so return to guest and 11778c2ecf20Sopenharmony_ci * try executing it again. 11788c2ecf20Sopenharmony_ci */ 11798c2ecf20Sopenharmony_ci return RESUME_GUEST; 11808c2ecf20Sopenharmony_ci } 11818c2ecf20Sopenharmony_ci 11828c2ecf20Sopenharmony_ci if (last_inst == KVMPPC_INST_SW_BREAKPOINT) { 11838c2ecf20Sopenharmony_ci vcpu->run->exit_reason = KVM_EXIT_DEBUG; 11848c2ecf20Sopenharmony_ci vcpu->run->debug.arch.address = kvmppc_get_pc(vcpu); 11858c2ecf20Sopenharmony_ci return RESUME_HOST; 11868c2ecf20Sopenharmony_ci } else { 11878c2ecf20Sopenharmony_ci kvmppc_core_queue_program(vcpu, SRR1_PROGILL); 11888c2ecf20Sopenharmony_ci return RESUME_GUEST; 11898c2ecf20Sopenharmony_ci } 11908c2ecf20Sopenharmony_ci} 11918c2ecf20Sopenharmony_ci 11928c2ecf20Sopenharmony_cistatic void do_nothing(void *x) 11938c2ecf20Sopenharmony_ci{ 11948c2ecf20Sopenharmony_ci} 11958c2ecf20Sopenharmony_ci 11968c2ecf20Sopenharmony_cistatic unsigned long kvmppc_read_dpdes(struct kvm_vcpu *vcpu) 11978c2ecf20Sopenharmony_ci{ 11988c2ecf20Sopenharmony_ci int thr, cpu, pcpu, nthreads; 11998c2ecf20Sopenharmony_ci struct kvm_vcpu *v; 12008c2ecf20Sopenharmony_ci unsigned long dpdes; 12018c2ecf20Sopenharmony_ci 12028c2ecf20Sopenharmony_ci nthreads = vcpu->kvm->arch.emul_smt_mode; 12038c2ecf20Sopenharmony_ci dpdes = 0; 12048c2ecf20Sopenharmony_ci cpu = vcpu->vcpu_id & ~(nthreads - 1); 12058c2ecf20Sopenharmony_ci for (thr = 0; thr < nthreads; ++thr, ++cpu) { 12068c2ecf20Sopenharmony_ci v = kvmppc_find_vcpu(vcpu->kvm, cpu); 12078c2ecf20Sopenharmony_ci if (!v) 12088c2ecf20Sopenharmony_ci continue; 12098c2ecf20Sopenharmony_ci /* 12108c2ecf20Sopenharmony_ci * If the vcpu is currently running on a physical cpu thread, 12118c2ecf20Sopenharmony_ci * interrupt it in order to pull it out of the guest briefly, 12128c2ecf20Sopenharmony_ci * which will update its vcore->dpdes value. 12138c2ecf20Sopenharmony_ci */ 12148c2ecf20Sopenharmony_ci pcpu = READ_ONCE(v->cpu); 12158c2ecf20Sopenharmony_ci if (pcpu >= 0) 12168c2ecf20Sopenharmony_ci smp_call_function_single(pcpu, do_nothing, NULL, 1); 12178c2ecf20Sopenharmony_ci if (kvmppc_doorbell_pending(v)) 12188c2ecf20Sopenharmony_ci dpdes |= 1 << thr; 12198c2ecf20Sopenharmony_ci } 12208c2ecf20Sopenharmony_ci return dpdes; 12218c2ecf20Sopenharmony_ci} 12228c2ecf20Sopenharmony_ci 12238c2ecf20Sopenharmony_ci/* 12248c2ecf20Sopenharmony_ci * On POWER9, emulate doorbell-related instructions in order to 12258c2ecf20Sopenharmony_ci * give the guest the illusion of running on a multi-threaded core. 12268c2ecf20Sopenharmony_ci * The instructions emulated are msgsndp, msgclrp, mfspr TIR, 12278c2ecf20Sopenharmony_ci * and mfspr DPDES. 12288c2ecf20Sopenharmony_ci */ 12298c2ecf20Sopenharmony_cistatic int kvmppc_emulate_doorbell_instr(struct kvm_vcpu *vcpu) 12308c2ecf20Sopenharmony_ci{ 12318c2ecf20Sopenharmony_ci u32 inst, rb, thr; 12328c2ecf20Sopenharmony_ci unsigned long arg; 12338c2ecf20Sopenharmony_ci struct kvm *kvm = vcpu->kvm; 12348c2ecf20Sopenharmony_ci struct kvm_vcpu *tvcpu; 12358c2ecf20Sopenharmony_ci 12368c2ecf20Sopenharmony_ci if (kvmppc_get_last_inst(vcpu, INST_GENERIC, &inst) != EMULATE_DONE) 12378c2ecf20Sopenharmony_ci return RESUME_GUEST; 12388c2ecf20Sopenharmony_ci if (get_op(inst) != 31) 12398c2ecf20Sopenharmony_ci return EMULATE_FAIL; 12408c2ecf20Sopenharmony_ci rb = get_rb(inst); 12418c2ecf20Sopenharmony_ci thr = vcpu->vcpu_id & (kvm->arch.emul_smt_mode - 1); 12428c2ecf20Sopenharmony_ci switch (get_xop(inst)) { 12438c2ecf20Sopenharmony_ci case OP_31_XOP_MSGSNDP: 12448c2ecf20Sopenharmony_ci arg = kvmppc_get_gpr(vcpu, rb); 12458c2ecf20Sopenharmony_ci if (((arg >> 27) & 0xf) != PPC_DBELL_SERVER) 12468c2ecf20Sopenharmony_ci break; 12478c2ecf20Sopenharmony_ci arg &= 0x3f; 12488c2ecf20Sopenharmony_ci if (arg >= kvm->arch.emul_smt_mode) 12498c2ecf20Sopenharmony_ci break; 12508c2ecf20Sopenharmony_ci tvcpu = kvmppc_find_vcpu(kvm, vcpu->vcpu_id - thr + arg); 12518c2ecf20Sopenharmony_ci if (!tvcpu) 12528c2ecf20Sopenharmony_ci break; 12538c2ecf20Sopenharmony_ci if (!tvcpu->arch.doorbell_request) { 12548c2ecf20Sopenharmony_ci tvcpu->arch.doorbell_request = 1; 12558c2ecf20Sopenharmony_ci kvmppc_fast_vcpu_kick_hv(tvcpu); 12568c2ecf20Sopenharmony_ci } 12578c2ecf20Sopenharmony_ci break; 12588c2ecf20Sopenharmony_ci case OP_31_XOP_MSGCLRP: 12598c2ecf20Sopenharmony_ci arg = kvmppc_get_gpr(vcpu, rb); 12608c2ecf20Sopenharmony_ci if (((arg >> 27) & 0xf) != PPC_DBELL_SERVER) 12618c2ecf20Sopenharmony_ci break; 12628c2ecf20Sopenharmony_ci vcpu->arch.vcore->dpdes = 0; 12638c2ecf20Sopenharmony_ci vcpu->arch.doorbell_request = 0; 12648c2ecf20Sopenharmony_ci break; 12658c2ecf20Sopenharmony_ci case OP_31_XOP_MFSPR: 12668c2ecf20Sopenharmony_ci switch (get_sprn(inst)) { 12678c2ecf20Sopenharmony_ci case SPRN_TIR: 12688c2ecf20Sopenharmony_ci arg = thr; 12698c2ecf20Sopenharmony_ci break; 12708c2ecf20Sopenharmony_ci case SPRN_DPDES: 12718c2ecf20Sopenharmony_ci arg = kvmppc_read_dpdes(vcpu); 12728c2ecf20Sopenharmony_ci break; 12738c2ecf20Sopenharmony_ci default: 12748c2ecf20Sopenharmony_ci return EMULATE_FAIL; 12758c2ecf20Sopenharmony_ci } 12768c2ecf20Sopenharmony_ci kvmppc_set_gpr(vcpu, get_rt(inst), arg); 12778c2ecf20Sopenharmony_ci break; 12788c2ecf20Sopenharmony_ci default: 12798c2ecf20Sopenharmony_ci return EMULATE_FAIL; 12808c2ecf20Sopenharmony_ci } 12818c2ecf20Sopenharmony_ci kvmppc_set_pc(vcpu, kvmppc_get_pc(vcpu) + 4); 12828c2ecf20Sopenharmony_ci return RESUME_GUEST; 12838c2ecf20Sopenharmony_ci} 12848c2ecf20Sopenharmony_ci 12858c2ecf20Sopenharmony_cistatic int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu, 12868c2ecf20Sopenharmony_ci struct task_struct *tsk) 12878c2ecf20Sopenharmony_ci{ 12888c2ecf20Sopenharmony_ci struct kvm_run *run = vcpu->run; 12898c2ecf20Sopenharmony_ci int r = RESUME_HOST; 12908c2ecf20Sopenharmony_ci 12918c2ecf20Sopenharmony_ci vcpu->stat.sum_exits++; 12928c2ecf20Sopenharmony_ci 12938c2ecf20Sopenharmony_ci /* 12948c2ecf20Sopenharmony_ci * This can happen if an interrupt occurs in the last stages 12958c2ecf20Sopenharmony_ci * of guest entry or the first stages of guest exit (i.e. after 12968c2ecf20Sopenharmony_ci * setting paca->kvm_hstate.in_guest to KVM_GUEST_MODE_GUEST_HV 12978c2ecf20Sopenharmony_ci * and before setting it to KVM_GUEST_MODE_HOST_HV). 12988c2ecf20Sopenharmony_ci * That can happen due to a bug, or due to a machine check 12998c2ecf20Sopenharmony_ci * occurring at just the wrong time. 13008c2ecf20Sopenharmony_ci */ 13018c2ecf20Sopenharmony_ci if (vcpu->arch.shregs.msr & MSR_HV) { 13028c2ecf20Sopenharmony_ci printk(KERN_EMERG "KVM trap in HV mode!\n"); 13038c2ecf20Sopenharmony_ci printk(KERN_EMERG "trap=0x%x | pc=0x%lx | msr=0x%llx\n", 13048c2ecf20Sopenharmony_ci vcpu->arch.trap, kvmppc_get_pc(vcpu), 13058c2ecf20Sopenharmony_ci vcpu->arch.shregs.msr); 13068c2ecf20Sopenharmony_ci kvmppc_dump_regs(vcpu); 13078c2ecf20Sopenharmony_ci run->exit_reason = KVM_EXIT_INTERNAL_ERROR; 13088c2ecf20Sopenharmony_ci run->hw.hardware_exit_reason = vcpu->arch.trap; 13098c2ecf20Sopenharmony_ci return RESUME_HOST; 13108c2ecf20Sopenharmony_ci } 13118c2ecf20Sopenharmony_ci run->exit_reason = KVM_EXIT_UNKNOWN; 13128c2ecf20Sopenharmony_ci run->ready_for_interrupt_injection = 1; 13138c2ecf20Sopenharmony_ci switch (vcpu->arch.trap) { 13148c2ecf20Sopenharmony_ci /* We're good on these - the host merely wanted to get our attention */ 13158c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_HV_DECREMENTER: 13168c2ecf20Sopenharmony_ci vcpu->stat.dec_exits++; 13178c2ecf20Sopenharmony_ci r = RESUME_GUEST; 13188c2ecf20Sopenharmony_ci break; 13198c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_EXTERNAL: 13208c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_H_DOORBELL: 13218c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_H_VIRT: 13228c2ecf20Sopenharmony_ci vcpu->stat.ext_intr_exits++; 13238c2ecf20Sopenharmony_ci r = RESUME_GUEST; 13248c2ecf20Sopenharmony_ci break; 13258c2ecf20Sopenharmony_ci /* SR/HMI/PMI are HV interrupts that host has handled. Resume guest.*/ 13268c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_HMI: 13278c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_PERFMON: 13288c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_SYSTEM_RESET: 13298c2ecf20Sopenharmony_ci r = RESUME_GUEST; 13308c2ecf20Sopenharmony_ci break; 13318c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_MACHINE_CHECK: 13328c2ecf20Sopenharmony_ci /* Print the MCE event to host console. */ 13338c2ecf20Sopenharmony_ci machine_check_print_event_info(&vcpu->arch.mce_evt, false, true); 13348c2ecf20Sopenharmony_ci 13358c2ecf20Sopenharmony_ci /* 13368c2ecf20Sopenharmony_ci * If the guest can do FWNMI, exit to userspace so it can 13378c2ecf20Sopenharmony_ci * deliver a FWNMI to the guest. 13388c2ecf20Sopenharmony_ci * Otherwise we synthesize a machine check for the guest 13398c2ecf20Sopenharmony_ci * so that it knows that the machine check occurred. 13408c2ecf20Sopenharmony_ci */ 13418c2ecf20Sopenharmony_ci if (!vcpu->kvm->arch.fwnmi_enabled) { 13428c2ecf20Sopenharmony_ci ulong flags = vcpu->arch.shregs.msr & 0x083c0000; 13438c2ecf20Sopenharmony_ci kvmppc_core_queue_machine_check(vcpu, flags); 13448c2ecf20Sopenharmony_ci r = RESUME_GUEST; 13458c2ecf20Sopenharmony_ci break; 13468c2ecf20Sopenharmony_ci } 13478c2ecf20Sopenharmony_ci 13488c2ecf20Sopenharmony_ci /* Exit to guest with KVM_EXIT_NMI as exit reason */ 13498c2ecf20Sopenharmony_ci run->exit_reason = KVM_EXIT_NMI; 13508c2ecf20Sopenharmony_ci run->hw.hardware_exit_reason = vcpu->arch.trap; 13518c2ecf20Sopenharmony_ci /* Clear out the old NMI status from run->flags */ 13528c2ecf20Sopenharmony_ci run->flags &= ~KVM_RUN_PPC_NMI_DISP_MASK; 13538c2ecf20Sopenharmony_ci /* Now set the NMI status */ 13548c2ecf20Sopenharmony_ci if (vcpu->arch.mce_evt.disposition == MCE_DISPOSITION_RECOVERED) 13558c2ecf20Sopenharmony_ci run->flags |= KVM_RUN_PPC_NMI_DISP_FULLY_RECOV; 13568c2ecf20Sopenharmony_ci else 13578c2ecf20Sopenharmony_ci run->flags |= KVM_RUN_PPC_NMI_DISP_NOT_RECOV; 13588c2ecf20Sopenharmony_ci 13598c2ecf20Sopenharmony_ci r = RESUME_HOST; 13608c2ecf20Sopenharmony_ci break; 13618c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_PROGRAM: 13628c2ecf20Sopenharmony_ci { 13638c2ecf20Sopenharmony_ci ulong flags; 13648c2ecf20Sopenharmony_ci /* 13658c2ecf20Sopenharmony_ci * Normally program interrupts are delivered directly 13668c2ecf20Sopenharmony_ci * to the guest by the hardware, but we can get here 13678c2ecf20Sopenharmony_ci * as a result of a hypervisor emulation interrupt 13688c2ecf20Sopenharmony_ci * (e40) getting turned into a 700 by BML RTAS. 13698c2ecf20Sopenharmony_ci */ 13708c2ecf20Sopenharmony_ci flags = vcpu->arch.shregs.msr & 0x1f0000ull; 13718c2ecf20Sopenharmony_ci kvmppc_core_queue_program(vcpu, flags); 13728c2ecf20Sopenharmony_ci r = RESUME_GUEST; 13738c2ecf20Sopenharmony_ci break; 13748c2ecf20Sopenharmony_ci } 13758c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_SYSCALL: 13768c2ecf20Sopenharmony_ci { 13778c2ecf20Sopenharmony_ci /* hcall - punt to userspace */ 13788c2ecf20Sopenharmony_ci int i; 13798c2ecf20Sopenharmony_ci 13808c2ecf20Sopenharmony_ci /* hypercall with MSR_PR has already been handled in rmode, 13818c2ecf20Sopenharmony_ci * and never reaches here. 13828c2ecf20Sopenharmony_ci */ 13838c2ecf20Sopenharmony_ci 13848c2ecf20Sopenharmony_ci run->papr_hcall.nr = kvmppc_get_gpr(vcpu, 3); 13858c2ecf20Sopenharmony_ci for (i = 0; i < 9; ++i) 13868c2ecf20Sopenharmony_ci run->papr_hcall.args[i] = kvmppc_get_gpr(vcpu, 4 + i); 13878c2ecf20Sopenharmony_ci run->exit_reason = KVM_EXIT_PAPR_HCALL; 13888c2ecf20Sopenharmony_ci vcpu->arch.hcall_needed = 1; 13898c2ecf20Sopenharmony_ci r = RESUME_HOST; 13908c2ecf20Sopenharmony_ci break; 13918c2ecf20Sopenharmony_ci } 13928c2ecf20Sopenharmony_ci /* 13938c2ecf20Sopenharmony_ci * We get these next two if the guest accesses a page which it thinks 13948c2ecf20Sopenharmony_ci * it has mapped but which is not actually present, either because 13958c2ecf20Sopenharmony_ci * it is for an emulated I/O device or because the corresonding 13968c2ecf20Sopenharmony_ci * host page has been paged out. Any other HDSI/HISI interrupts 13978c2ecf20Sopenharmony_ci * have been handled already. 13988c2ecf20Sopenharmony_ci */ 13998c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_H_DATA_STORAGE: 14008c2ecf20Sopenharmony_ci r = RESUME_PAGE_FAULT; 14018c2ecf20Sopenharmony_ci break; 14028c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_H_INST_STORAGE: 14038c2ecf20Sopenharmony_ci vcpu->arch.fault_dar = kvmppc_get_pc(vcpu); 14048c2ecf20Sopenharmony_ci vcpu->arch.fault_dsisr = vcpu->arch.shregs.msr & 14058c2ecf20Sopenharmony_ci DSISR_SRR1_MATCH_64S; 14068c2ecf20Sopenharmony_ci if (vcpu->arch.shregs.msr & HSRR1_HISI_WRITE) 14078c2ecf20Sopenharmony_ci vcpu->arch.fault_dsisr |= DSISR_ISSTORE; 14088c2ecf20Sopenharmony_ci r = RESUME_PAGE_FAULT; 14098c2ecf20Sopenharmony_ci break; 14108c2ecf20Sopenharmony_ci /* 14118c2ecf20Sopenharmony_ci * This occurs if the guest executes an illegal instruction. 14128c2ecf20Sopenharmony_ci * If the guest debug is disabled, generate a program interrupt 14138c2ecf20Sopenharmony_ci * to the guest. If guest debug is enabled, we need to check 14148c2ecf20Sopenharmony_ci * whether the instruction is a software breakpoint instruction. 14158c2ecf20Sopenharmony_ci * Accordingly return to Guest or Host. 14168c2ecf20Sopenharmony_ci */ 14178c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_H_EMUL_ASSIST: 14188c2ecf20Sopenharmony_ci if (vcpu->arch.emul_inst != KVM_INST_FETCH_FAILED) 14198c2ecf20Sopenharmony_ci vcpu->arch.last_inst = kvmppc_need_byteswap(vcpu) ? 14208c2ecf20Sopenharmony_ci swab32(vcpu->arch.emul_inst) : 14218c2ecf20Sopenharmony_ci vcpu->arch.emul_inst; 14228c2ecf20Sopenharmony_ci if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP) { 14238c2ecf20Sopenharmony_ci r = kvmppc_emulate_debug_inst(vcpu); 14248c2ecf20Sopenharmony_ci } else { 14258c2ecf20Sopenharmony_ci kvmppc_core_queue_program(vcpu, SRR1_PROGILL); 14268c2ecf20Sopenharmony_ci r = RESUME_GUEST; 14278c2ecf20Sopenharmony_ci } 14288c2ecf20Sopenharmony_ci break; 14298c2ecf20Sopenharmony_ci /* 14308c2ecf20Sopenharmony_ci * This occurs if the guest (kernel or userspace), does something that 14318c2ecf20Sopenharmony_ci * is prohibited by HFSCR. 14328c2ecf20Sopenharmony_ci * On POWER9, this could be a doorbell instruction that we need 14338c2ecf20Sopenharmony_ci * to emulate. 14348c2ecf20Sopenharmony_ci * Otherwise, we just generate a program interrupt to the guest. 14358c2ecf20Sopenharmony_ci */ 14368c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_H_FAC_UNAVAIL: 14378c2ecf20Sopenharmony_ci r = EMULATE_FAIL; 14388c2ecf20Sopenharmony_ci if (((vcpu->arch.hfscr >> 56) == FSCR_MSGP_LG) && 14398c2ecf20Sopenharmony_ci cpu_has_feature(CPU_FTR_ARCH_300)) 14408c2ecf20Sopenharmony_ci r = kvmppc_emulate_doorbell_instr(vcpu); 14418c2ecf20Sopenharmony_ci if (r == EMULATE_FAIL) { 14428c2ecf20Sopenharmony_ci kvmppc_core_queue_program(vcpu, SRR1_PROGILL); 14438c2ecf20Sopenharmony_ci r = RESUME_GUEST; 14448c2ecf20Sopenharmony_ci } 14458c2ecf20Sopenharmony_ci break; 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_TRANSACTIONAL_MEM 14488c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_HV_SOFTPATCH: 14498c2ecf20Sopenharmony_ci /* 14508c2ecf20Sopenharmony_ci * This occurs for various TM-related instructions that 14518c2ecf20Sopenharmony_ci * we need to emulate on POWER9 DD2.2. We have already 14528c2ecf20Sopenharmony_ci * handled the cases where the guest was in real-suspend 14538c2ecf20Sopenharmony_ci * mode and was transitioning to transactional state. 14548c2ecf20Sopenharmony_ci */ 14558c2ecf20Sopenharmony_ci r = kvmhv_p9_tm_emulation(vcpu); 14568c2ecf20Sopenharmony_ci break; 14578c2ecf20Sopenharmony_ci#endif 14588c2ecf20Sopenharmony_ci 14598c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_HV_RM_HARD: 14608c2ecf20Sopenharmony_ci r = RESUME_PASSTHROUGH; 14618c2ecf20Sopenharmony_ci break; 14628c2ecf20Sopenharmony_ci default: 14638c2ecf20Sopenharmony_ci kvmppc_dump_regs(vcpu); 14648c2ecf20Sopenharmony_ci printk(KERN_EMERG "trap=0x%x | pc=0x%lx | msr=0x%llx\n", 14658c2ecf20Sopenharmony_ci vcpu->arch.trap, kvmppc_get_pc(vcpu), 14668c2ecf20Sopenharmony_ci vcpu->arch.shregs.msr); 14678c2ecf20Sopenharmony_ci run->hw.hardware_exit_reason = vcpu->arch.trap; 14688c2ecf20Sopenharmony_ci r = RESUME_HOST; 14698c2ecf20Sopenharmony_ci break; 14708c2ecf20Sopenharmony_ci } 14718c2ecf20Sopenharmony_ci 14728c2ecf20Sopenharmony_ci return r; 14738c2ecf20Sopenharmony_ci} 14748c2ecf20Sopenharmony_ci 14758c2ecf20Sopenharmony_cistatic int kvmppc_handle_nested_exit(struct kvm_vcpu *vcpu) 14768c2ecf20Sopenharmony_ci{ 14778c2ecf20Sopenharmony_ci int r; 14788c2ecf20Sopenharmony_ci int srcu_idx; 14798c2ecf20Sopenharmony_ci 14808c2ecf20Sopenharmony_ci vcpu->stat.sum_exits++; 14818c2ecf20Sopenharmony_ci 14828c2ecf20Sopenharmony_ci /* 14838c2ecf20Sopenharmony_ci * This can happen if an interrupt occurs in the last stages 14848c2ecf20Sopenharmony_ci * of guest entry or the first stages of guest exit (i.e. after 14858c2ecf20Sopenharmony_ci * setting paca->kvm_hstate.in_guest to KVM_GUEST_MODE_GUEST_HV 14868c2ecf20Sopenharmony_ci * and before setting it to KVM_GUEST_MODE_HOST_HV). 14878c2ecf20Sopenharmony_ci * That can happen due to a bug, or due to a machine check 14888c2ecf20Sopenharmony_ci * occurring at just the wrong time. 14898c2ecf20Sopenharmony_ci */ 14908c2ecf20Sopenharmony_ci if (vcpu->arch.shregs.msr & MSR_HV) { 14918c2ecf20Sopenharmony_ci pr_emerg("KVM trap in HV mode while nested!\n"); 14928c2ecf20Sopenharmony_ci pr_emerg("trap=0x%x | pc=0x%lx | msr=0x%llx\n", 14938c2ecf20Sopenharmony_ci vcpu->arch.trap, kvmppc_get_pc(vcpu), 14948c2ecf20Sopenharmony_ci vcpu->arch.shregs.msr); 14958c2ecf20Sopenharmony_ci kvmppc_dump_regs(vcpu); 14968c2ecf20Sopenharmony_ci return RESUME_HOST; 14978c2ecf20Sopenharmony_ci } 14988c2ecf20Sopenharmony_ci switch (vcpu->arch.trap) { 14998c2ecf20Sopenharmony_ci /* We're good on these - the host merely wanted to get our attention */ 15008c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_HV_DECREMENTER: 15018c2ecf20Sopenharmony_ci vcpu->stat.dec_exits++; 15028c2ecf20Sopenharmony_ci r = RESUME_GUEST; 15038c2ecf20Sopenharmony_ci break; 15048c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_EXTERNAL: 15058c2ecf20Sopenharmony_ci vcpu->stat.ext_intr_exits++; 15068c2ecf20Sopenharmony_ci r = RESUME_HOST; 15078c2ecf20Sopenharmony_ci break; 15088c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_H_DOORBELL: 15098c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_H_VIRT: 15108c2ecf20Sopenharmony_ci vcpu->stat.ext_intr_exits++; 15118c2ecf20Sopenharmony_ci r = RESUME_GUEST; 15128c2ecf20Sopenharmony_ci break; 15138c2ecf20Sopenharmony_ci /* SR/HMI/PMI are HV interrupts that host has handled. Resume guest.*/ 15148c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_HMI: 15158c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_PERFMON: 15168c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_SYSTEM_RESET: 15178c2ecf20Sopenharmony_ci r = RESUME_GUEST; 15188c2ecf20Sopenharmony_ci break; 15198c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_MACHINE_CHECK: 15208c2ecf20Sopenharmony_ci /* Pass the machine check to the L1 guest */ 15218c2ecf20Sopenharmony_ci r = RESUME_HOST; 15228c2ecf20Sopenharmony_ci /* Print the MCE event to host console. */ 15238c2ecf20Sopenharmony_ci machine_check_print_event_info(&vcpu->arch.mce_evt, false, true); 15248c2ecf20Sopenharmony_ci break; 15258c2ecf20Sopenharmony_ci /* 15268c2ecf20Sopenharmony_ci * We get these next two if the guest accesses a page which it thinks 15278c2ecf20Sopenharmony_ci * it has mapped but which is not actually present, either because 15288c2ecf20Sopenharmony_ci * it is for an emulated I/O device or because the corresonding 15298c2ecf20Sopenharmony_ci * host page has been paged out. 15308c2ecf20Sopenharmony_ci */ 15318c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_H_DATA_STORAGE: 15328c2ecf20Sopenharmony_ci srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); 15338c2ecf20Sopenharmony_ci r = kvmhv_nested_page_fault(vcpu); 15348c2ecf20Sopenharmony_ci srcu_read_unlock(&vcpu->kvm->srcu, srcu_idx); 15358c2ecf20Sopenharmony_ci break; 15368c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_H_INST_STORAGE: 15378c2ecf20Sopenharmony_ci vcpu->arch.fault_dar = kvmppc_get_pc(vcpu); 15388c2ecf20Sopenharmony_ci vcpu->arch.fault_dsisr = kvmppc_get_msr(vcpu) & 15398c2ecf20Sopenharmony_ci DSISR_SRR1_MATCH_64S; 15408c2ecf20Sopenharmony_ci if (vcpu->arch.shregs.msr & HSRR1_HISI_WRITE) 15418c2ecf20Sopenharmony_ci vcpu->arch.fault_dsisr |= DSISR_ISSTORE; 15428c2ecf20Sopenharmony_ci srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); 15438c2ecf20Sopenharmony_ci r = kvmhv_nested_page_fault(vcpu); 15448c2ecf20Sopenharmony_ci srcu_read_unlock(&vcpu->kvm->srcu, srcu_idx); 15458c2ecf20Sopenharmony_ci break; 15468c2ecf20Sopenharmony_ci 15478c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_TRANSACTIONAL_MEM 15488c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_HV_SOFTPATCH: 15498c2ecf20Sopenharmony_ci /* 15508c2ecf20Sopenharmony_ci * This occurs for various TM-related instructions that 15518c2ecf20Sopenharmony_ci * we need to emulate on POWER9 DD2.2. We have already 15528c2ecf20Sopenharmony_ci * handled the cases where the guest was in real-suspend 15538c2ecf20Sopenharmony_ci * mode and was transitioning to transactional state. 15548c2ecf20Sopenharmony_ci */ 15558c2ecf20Sopenharmony_ci r = kvmhv_p9_tm_emulation(vcpu); 15568c2ecf20Sopenharmony_ci break; 15578c2ecf20Sopenharmony_ci#endif 15588c2ecf20Sopenharmony_ci 15598c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_HV_RM_HARD: 15608c2ecf20Sopenharmony_ci vcpu->arch.trap = 0; 15618c2ecf20Sopenharmony_ci r = RESUME_GUEST; 15628c2ecf20Sopenharmony_ci if (!xics_on_xive()) 15638c2ecf20Sopenharmony_ci kvmppc_xics_rm_complete(vcpu, 0); 15648c2ecf20Sopenharmony_ci break; 15658c2ecf20Sopenharmony_ci default: 15668c2ecf20Sopenharmony_ci r = RESUME_HOST; 15678c2ecf20Sopenharmony_ci break; 15688c2ecf20Sopenharmony_ci } 15698c2ecf20Sopenharmony_ci 15708c2ecf20Sopenharmony_ci return r; 15718c2ecf20Sopenharmony_ci} 15728c2ecf20Sopenharmony_ci 15738c2ecf20Sopenharmony_cistatic int kvm_arch_vcpu_ioctl_get_sregs_hv(struct kvm_vcpu *vcpu, 15748c2ecf20Sopenharmony_ci struct kvm_sregs *sregs) 15758c2ecf20Sopenharmony_ci{ 15768c2ecf20Sopenharmony_ci int i; 15778c2ecf20Sopenharmony_ci 15788c2ecf20Sopenharmony_ci memset(sregs, 0, sizeof(struct kvm_sregs)); 15798c2ecf20Sopenharmony_ci sregs->pvr = vcpu->arch.pvr; 15808c2ecf20Sopenharmony_ci for (i = 0; i < vcpu->arch.slb_max; i++) { 15818c2ecf20Sopenharmony_ci sregs->u.s.ppc64.slb[i].slbe = vcpu->arch.slb[i].orige; 15828c2ecf20Sopenharmony_ci sregs->u.s.ppc64.slb[i].slbv = vcpu->arch.slb[i].origv; 15838c2ecf20Sopenharmony_ci } 15848c2ecf20Sopenharmony_ci 15858c2ecf20Sopenharmony_ci return 0; 15868c2ecf20Sopenharmony_ci} 15878c2ecf20Sopenharmony_ci 15888c2ecf20Sopenharmony_cistatic int kvm_arch_vcpu_ioctl_set_sregs_hv(struct kvm_vcpu *vcpu, 15898c2ecf20Sopenharmony_ci struct kvm_sregs *sregs) 15908c2ecf20Sopenharmony_ci{ 15918c2ecf20Sopenharmony_ci int i, j; 15928c2ecf20Sopenharmony_ci 15938c2ecf20Sopenharmony_ci /* Only accept the same PVR as the host's, since we can't spoof it */ 15948c2ecf20Sopenharmony_ci if (sregs->pvr != vcpu->arch.pvr) 15958c2ecf20Sopenharmony_ci return -EINVAL; 15968c2ecf20Sopenharmony_ci 15978c2ecf20Sopenharmony_ci j = 0; 15988c2ecf20Sopenharmony_ci for (i = 0; i < vcpu->arch.slb_nr; i++) { 15998c2ecf20Sopenharmony_ci if (sregs->u.s.ppc64.slb[i].slbe & SLB_ESID_V) { 16008c2ecf20Sopenharmony_ci vcpu->arch.slb[j].orige = sregs->u.s.ppc64.slb[i].slbe; 16018c2ecf20Sopenharmony_ci vcpu->arch.slb[j].origv = sregs->u.s.ppc64.slb[i].slbv; 16028c2ecf20Sopenharmony_ci ++j; 16038c2ecf20Sopenharmony_ci } 16048c2ecf20Sopenharmony_ci } 16058c2ecf20Sopenharmony_ci vcpu->arch.slb_max = j; 16068c2ecf20Sopenharmony_ci 16078c2ecf20Sopenharmony_ci return 0; 16088c2ecf20Sopenharmony_ci} 16098c2ecf20Sopenharmony_ci 16108c2ecf20Sopenharmony_cistatic void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr, 16118c2ecf20Sopenharmony_ci bool preserve_top32) 16128c2ecf20Sopenharmony_ci{ 16138c2ecf20Sopenharmony_ci struct kvm *kvm = vcpu->kvm; 16148c2ecf20Sopenharmony_ci struct kvmppc_vcore *vc = vcpu->arch.vcore; 16158c2ecf20Sopenharmony_ci u64 mask; 16168c2ecf20Sopenharmony_ci 16178c2ecf20Sopenharmony_ci spin_lock(&vc->lock); 16188c2ecf20Sopenharmony_ci /* 16198c2ecf20Sopenharmony_ci * If ILE (interrupt little-endian) has changed, update the 16208c2ecf20Sopenharmony_ci * MSR_LE bit in the intr_msr for each vcpu in this vcore. 16218c2ecf20Sopenharmony_ci */ 16228c2ecf20Sopenharmony_ci if ((new_lpcr & LPCR_ILE) != (vc->lpcr & LPCR_ILE)) { 16238c2ecf20Sopenharmony_ci struct kvm_vcpu *vcpu; 16248c2ecf20Sopenharmony_ci int i; 16258c2ecf20Sopenharmony_ci 16268c2ecf20Sopenharmony_ci kvm_for_each_vcpu(i, vcpu, kvm) { 16278c2ecf20Sopenharmony_ci if (vcpu->arch.vcore != vc) 16288c2ecf20Sopenharmony_ci continue; 16298c2ecf20Sopenharmony_ci if (new_lpcr & LPCR_ILE) 16308c2ecf20Sopenharmony_ci vcpu->arch.intr_msr |= MSR_LE; 16318c2ecf20Sopenharmony_ci else 16328c2ecf20Sopenharmony_ci vcpu->arch.intr_msr &= ~MSR_LE; 16338c2ecf20Sopenharmony_ci } 16348c2ecf20Sopenharmony_ci } 16358c2ecf20Sopenharmony_ci 16368c2ecf20Sopenharmony_ci /* 16378c2ecf20Sopenharmony_ci * Userspace can only modify DPFD (default prefetch depth), 16388c2ecf20Sopenharmony_ci * ILE (interrupt little-endian) and TC (translation control). 16398c2ecf20Sopenharmony_ci * On POWER8 and POWER9 userspace can also modify AIL (alt. interrupt loc.). 16408c2ecf20Sopenharmony_ci */ 16418c2ecf20Sopenharmony_ci mask = LPCR_DPFD | LPCR_ILE | LPCR_TC; 16428c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_207S)) 16438c2ecf20Sopenharmony_ci mask |= LPCR_AIL; 16448c2ecf20Sopenharmony_ci /* 16458c2ecf20Sopenharmony_ci * On POWER9, allow userspace to enable large decrementer for the 16468c2ecf20Sopenharmony_ci * guest, whether or not the host has it enabled. 16478c2ecf20Sopenharmony_ci */ 16488c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_300)) 16498c2ecf20Sopenharmony_ci mask |= LPCR_LD; 16508c2ecf20Sopenharmony_ci 16518c2ecf20Sopenharmony_ci /* Broken 32-bit version of LPCR must not clear top bits */ 16528c2ecf20Sopenharmony_ci if (preserve_top32) 16538c2ecf20Sopenharmony_ci mask &= 0xFFFFFFFF; 16548c2ecf20Sopenharmony_ci vc->lpcr = (vc->lpcr & ~mask) | (new_lpcr & mask); 16558c2ecf20Sopenharmony_ci spin_unlock(&vc->lock); 16568c2ecf20Sopenharmony_ci} 16578c2ecf20Sopenharmony_ci 16588c2ecf20Sopenharmony_cistatic int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, 16598c2ecf20Sopenharmony_ci union kvmppc_one_reg *val) 16608c2ecf20Sopenharmony_ci{ 16618c2ecf20Sopenharmony_ci int r = 0; 16628c2ecf20Sopenharmony_ci long int i; 16638c2ecf20Sopenharmony_ci 16648c2ecf20Sopenharmony_ci switch (id) { 16658c2ecf20Sopenharmony_ci case KVM_REG_PPC_DEBUG_INST: 16668c2ecf20Sopenharmony_ci *val = get_reg_val(id, KVMPPC_INST_SW_BREAKPOINT); 16678c2ecf20Sopenharmony_ci break; 16688c2ecf20Sopenharmony_ci case KVM_REG_PPC_HIOR: 16698c2ecf20Sopenharmony_ci *val = get_reg_val(id, 0); 16708c2ecf20Sopenharmony_ci break; 16718c2ecf20Sopenharmony_ci case KVM_REG_PPC_DABR: 16728c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.dabr); 16738c2ecf20Sopenharmony_ci break; 16748c2ecf20Sopenharmony_ci case KVM_REG_PPC_DABRX: 16758c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.dabrx); 16768c2ecf20Sopenharmony_ci break; 16778c2ecf20Sopenharmony_ci case KVM_REG_PPC_DSCR: 16788c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.dscr); 16798c2ecf20Sopenharmony_ci break; 16808c2ecf20Sopenharmony_ci case KVM_REG_PPC_PURR: 16818c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.purr); 16828c2ecf20Sopenharmony_ci break; 16838c2ecf20Sopenharmony_ci case KVM_REG_PPC_SPURR: 16848c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.spurr); 16858c2ecf20Sopenharmony_ci break; 16868c2ecf20Sopenharmony_ci case KVM_REG_PPC_AMR: 16878c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.amr); 16888c2ecf20Sopenharmony_ci break; 16898c2ecf20Sopenharmony_ci case KVM_REG_PPC_UAMOR: 16908c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.uamor); 16918c2ecf20Sopenharmony_ci break; 16928c2ecf20Sopenharmony_ci case KVM_REG_PPC_MMCR0 ... KVM_REG_PPC_MMCR1: 16938c2ecf20Sopenharmony_ci i = id - KVM_REG_PPC_MMCR0; 16948c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.mmcr[i]); 16958c2ecf20Sopenharmony_ci break; 16968c2ecf20Sopenharmony_ci case KVM_REG_PPC_MMCR2: 16978c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.mmcr[2]); 16988c2ecf20Sopenharmony_ci break; 16998c2ecf20Sopenharmony_ci case KVM_REG_PPC_MMCRA: 17008c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.mmcra); 17018c2ecf20Sopenharmony_ci break; 17028c2ecf20Sopenharmony_ci case KVM_REG_PPC_MMCRS: 17038c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.mmcrs); 17048c2ecf20Sopenharmony_ci break; 17058c2ecf20Sopenharmony_ci case KVM_REG_PPC_MMCR3: 17068c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.mmcr[3]); 17078c2ecf20Sopenharmony_ci break; 17088c2ecf20Sopenharmony_ci case KVM_REG_PPC_PMC1 ... KVM_REG_PPC_PMC8: 17098c2ecf20Sopenharmony_ci i = id - KVM_REG_PPC_PMC1; 17108c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.pmc[i]); 17118c2ecf20Sopenharmony_ci break; 17128c2ecf20Sopenharmony_ci case KVM_REG_PPC_SPMC1 ... KVM_REG_PPC_SPMC2: 17138c2ecf20Sopenharmony_ci i = id - KVM_REG_PPC_SPMC1; 17148c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.spmc[i]); 17158c2ecf20Sopenharmony_ci break; 17168c2ecf20Sopenharmony_ci case KVM_REG_PPC_SIAR: 17178c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.siar); 17188c2ecf20Sopenharmony_ci break; 17198c2ecf20Sopenharmony_ci case KVM_REG_PPC_SDAR: 17208c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.sdar); 17218c2ecf20Sopenharmony_ci break; 17228c2ecf20Sopenharmony_ci case KVM_REG_PPC_SIER: 17238c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.sier[0]); 17248c2ecf20Sopenharmony_ci break; 17258c2ecf20Sopenharmony_ci case KVM_REG_PPC_SIER2: 17268c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.sier[1]); 17278c2ecf20Sopenharmony_ci break; 17288c2ecf20Sopenharmony_ci case KVM_REG_PPC_SIER3: 17298c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.sier[2]); 17308c2ecf20Sopenharmony_ci break; 17318c2ecf20Sopenharmony_ci case KVM_REG_PPC_IAMR: 17328c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.iamr); 17338c2ecf20Sopenharmony_ci break; 17348c2ecf20Sopenharmony_ci case KVM_REG_PPC_PSPB: 17358c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.pspb); 17368c2ecf20Sopenharmony_ci break; 17378c2ecf20Sopenharmony_ci case KVM_REG_PPC_DPDES: 17388c2ecf20Sopenharmony_ci /* 17398c2ecf20Sopenharmony_ci * On POWER9, where we are emulating msgsndp etc., 17408c2ecf20Sopenharmony_ci * we return 1 bit for each vcpu, which can come from 17418c2ecf20Sopenharmony_ci * either vcore->dpdes or doorbell_request. 17428c2ecf20Sopenharmony_ci * On POWER8, doorbell_request is 0. 17438c2ecf20Sopenharmony_ci */ 17448c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.vcore->dpdes | 17458c2ecf20Sopenharmony_ci vcpu->arch.doorbell_request); 17468c2ecf20Sopenharmony_ci break; 17478c2ecf20Sopenharmony_ci case KVM_REG_PPC_VTB: 17488c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.vcore->vtb); 17498c2ecf20Sopenharmony_ci break; 17508c2ecf20Sopenharmony_ci case KVM_REG_PPC_DAWR: 17518c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.dawr); 17528c2ecf20Sopenharmony_ci break; 17538c2ecf20Sopenharmony_ci case KVM_REG_PPC_DAWRX: 17548c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.dawrx); 17558c2ecf20Sopenharmony_ci break; 17568c2ecf20Sopenharmony_ci case KVM_REG_PPC_CIABR: 17578c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.ciabr); 17588c2ecf20Sopenharmony_ci break; 17598c2ecf20Sopenharmony_ci case KVM_REG_PPC_CSIGR: 17608c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.csigr); 17618c2ecf20Sopenharmony_ci break; 17628c2ecf20Sopenharmony_ci case KVM_REG_PPC_TACR: 17638c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.tacr); 17648c2ecf20Sopenharmony_ci break; 17658c2ecf20Sopenharmony_ci case KVM_REG_PPC_TCSCR: 17668c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.tcscr); 17678c2ecf20Sopenharmony_ci break; 17688c2ecf20Sopenharmony_ci case KVM_REG_PPC_PID: 17698c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.pid); 17708c2ecf20Sopenharmony_ci break; 17718c2ecf20Sopenharmony_ci case KVM_REG_PPC_ACOP: 17728c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.acop); 17738c2ecf20Sopenharmony_ci break; 17748c2ecf20Sopenharmony_ci case KVM_REG_PPC_WORT: 17758c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.wort); 17768c2ecf20Sopenharmony_ci break; 17778c2ecf20Sopenharmony_ci case KVM_REG_PPC_TIDR: 17788c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.tid); 17798c2ecf20Sopenharmony_ci break; 17808c2ecf20Sopenharmony_ci case KVM_REG_PPC_PSSCR: 17818c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.psscr); 17828c2ecf20Sopenharmony_ci break; 17838c2ecf20Sopenharmony_ci case KVM_REG_PPC_VPA_ADDR: 17848c2ecf20Sopenharmony_ci spin_lock(&vcpu->arch.vpa_update_lock); 17858c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.vpa.next_gpa); 17868c2ecf20Sopenharmony_ci spin_unlock(&vcpu->arch.vpa_update_lock); 17878c2ecf20Sopenharmony_ci break; 17888c2ecf20Sopenharmony_ci case KVM_REG_PPC_VPA_SLB: 17898c2ecf20Sopenharmony_ci spin_lock(&vcpu->arch.vpa_update_lock); 17908c2ecf20Sopenharmony_ci val->vpaval.addr = vcpu->arch.slb_shadow.next_gpa; 17918c2ecf20Sopenharmony_ci val->vpaval.length = vcpu->arch.slb_shadow.len; 17928c2ecf20Sopenharmony_ci spin_unlock(&vcpu->arch.vpa_update_lock); 17938c2ecf20Sopenharmony_ci break; 17948c2ecf20Sopenharmony_ci case KVM_REG_PPC_VPA_DTL: 17958c2ecf20Sopenharmony_ci spin_lock(&vcpu->arch.vpa_update_lock); 17968c2ecf20Sopenharmony_ci val->vpaval.addr = vcpu->arch.dtl.next_gpa; 17978c2ecf20Sopenharmony_ci val->vpaval.length = vcpu->arch.dtl.len; 17988c2ecf20Sopenharmony_ci spin_unlock(&vcpu->arch.vpa_update_lock); 17998c2ecf20Sopenharmony_ci break; 18008c2ecf20Sopenharmony_ci case KVM_REG_PPC_TB_OFFSET: 18018c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.vcore->tb_offset); 18028c2ecf20Sopenharmony_ci break; 18038c2ecf20Sopenharmony_ci case KVM_REG_PPC_LPCR: 18048c2ecf20Sopenharmony_ci case KVM_REG_PPC_LPCR_64: 18058c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.vcore->lpcr); 18068c2ecf20Sopenharmony_ci break; 18078c2ecf20Sopenharmony_ci case KVM_REG_PPC_PPR: 18088c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.ppr); 18098c2ecf20Sopenharmony_ci break; 18108c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_TRANSACTIONAL_MEM 18118c2ecf20Sopenharmony_ci case KVM_REG_PPC_TFHAR: 18128c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.tfhar); 18138c2ecf20Sopenharmony_ci break; 18148c2ecf20Sopenharmony_ci case KVM_REG_PPC_TFIAR: 18158c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.tfiar); 18168c2ecf20Sopenharmony_ci break; 18178c2ecf20Sopenharmony_ci case KVM_REG_PPC_TEXASR: 18188c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.texasr); 18198c2ecf20Sopenharmony_ci break; 18208c2ecf20Sopenharmony_ci case KVM_REG_PPC_TM_GPR0 ... KVM_REG_PPC_TM_GPR31: 18218c2ecf20Sopenharmony_ci i = id - KVM_REG_PPC_TM_GPR0; 18228c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.gpr_tm[i]); 18238c2ecf20Sopenharmony_ci break; 18248c2ecf20Sopenharmony_ci case KVM_REG_PPC_TM_VSR0 ... KVM_REG_PPC_TM_VSR63: 18258c2ecf20Sopenharmony_ci { 18268c2ecf20Sopenharmony_ci int j; 18278c2ecf20Sopenharmony_ci i = id - KVM_REG_PPC_TM_VSR0; 18288c2ecf20Sopenharmony_ci if (i < 32) 18298c2ecf20Sopenharmony_ci for (j = 0; j < TS_FPRWIDTH; j++) 18308c2ecf20Sopenharmony_ci val->vsxval[j] = vcpu->arch.fp_tm.fpr[i][j]; 18318c2ecf20Sopenharmony_ci else { 18328c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ALTIVEC)) 18338c2ecf20Sopenharmony_ci val->vval = vcpu->arch.vr_tm.vr[i-32]; 18348c2ecf20Sopenharmony_ci else 18358c2ecf20Sopenharmony_ci r = -ENXIO; 18368c2ecf20Sopenharmony_ci } 18378c2ecf20Sopenharmony_ci break; 18388c2ecf20Sopenharmony_ci } 18398c2ecf20Sopenharmony_ci case KVM_REG_PPC_TM_CR: 18408c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.cr_tm); 18418c2ecf20Sopenharmony_ci break; 18428c2ecf20Sopenharmony_ci case KVM_REG_PPC_TM_XER: 18438c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.xer_tm); 18448c2ecf20Sopenharmony_ci break; 18458c2ecf20Sopenharmony_ci case KVM_REG_PPC_TM_LR: 18468c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.lr_tm); 18478c2ecf20Sopenharmony_ci break; 18488c2ecf20Sopenharmony_ci case KVM_REG_PPC_TM_CTR: 18498c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.ctr_tm); 18508c2ecf20Sopenharmony_ci break; 18518c2ecf20Sopenharmony_ci case KVM_REG_PPC_TM_FPSCR: 18528c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.fp_tm.fpscr); 18538c2ecf20Sopenharmony_ci break; 18548c2ecf20Sopenharmony_ci case KVM_REG_PPC_TM_AMR: 18558c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.amr_tm); 18568c2ecf20Sopenharmony_ci break; 18578c2ecf20Sopenharmony_ci case KVM_REG_PPC_TM_PPR: 18588c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.ppr_tm); 18598c2ecf20Sopenharmony_ci break; 18608c2ecf20Sopenharmony_ci case KVM_REG_PPC_TM_VRSAVE: 18618c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.vrsave_tm); 18628c2ecf20Sopenharmony_ci break; 18638c2ecf20Sopenharmony_ci case KVM_REG_PPC_TM_VSCR: 18648c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ALTIVEC)) 18658c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.vr_tm.vscr.u[3]); 18668c2ecf20Sopenharmony_ci else 18678c2ecf20Sopenharmony_ci r = -ENXIO; 18688c2ecf20Sopenharmony_ci break; 18698c2ecf20Sopenharmony_ci case KVM_REG_PPC_TM_DSCR: 18708c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.dscr_tm); 18718c2ecf20Sopenharmony_ci break; 18728c2ecf20Sopenharmony_ci case KVM_REG_PPC_TM_TAR: 18738c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.tar_tm); 18748c2ecf20Sopenharmony_ci break; 18758c2ecf20Sopenharmony_ci#endif 18768c2ecf20Sopenharmony_ci case KVM_REG_PPC_ARCH_COMPAT: 18778c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.vcore->arch_compat); 18788c2ecf20Sopenharmony_ci break; 18798c2ecf20Sopenharmony_ci case KVM_REG_PPC_DEC_EXPIRY: 18808c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.dec_expires + 18818c2ecf20Sopenharmony_ci vcpu->arch.vcore->tb_offset); 18828c2ecf20Sopenharmony_ci break; 18838c2ecf20Sopenharmony_ci case KVM_REG_PPC_ONLINE: 18848c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.online); 18858c2ecf20Sopenharmony_ci break; 18868c2ecf20Sopenharmony_ci case KVM_REG_PPC_PTCR: 18878c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->kvm->arch.l1_ptcr); 18888c2ecf20Sopenharmony_ci break; 18898c2ecf20Sopenharmony_ci default: 18908c2ecf20Sopenharmony_ci r = -EINVAL; 18918c2ecf20Sopenharmony_ci break; 18928c2ecf20Sopenharmony_ci } 18938c2ecf20Sopenharmony_ci 18948c2ecf20Sopenharmony_ci return r; 18958c2ecf20Sopenharmony_ci} 18968c2ecf20Sopenharmony_ci 18978c2ecf20Sopenharmony_cistatic int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, 18988c2ecf20Sopenharmony_ci union kvmppc_one_reg *val) 18998c2ecf20Sopenharmony_ci{ 19008c2ecf20Sopenharmony_ci int r = 0; 19018c2ecf20Sopenharmony_ci long int i; 19028c2ecf20Sopenharmony_ci unsigned long addr, len; 19038c2ecf20Sopenharmony_ci 19048c2ecf20Sopenharmony_ci switch (id) { 19058c2ecf20Sopenharmony_ci case KVM_REG_PPC_HIOR: 19068c2ecf20Sopenharmony_ci /* Only allow this to be set to zero */ 19078c2ecf20Sopenharmony_ci if (set_reg_val(id, *val)) 19088c2ecf20Sopenharmony_ci r = -EINVAL; 19098c2ecf20Sopenharmony_ci break; 19108c2ecf20Sopenharmony_ci case KVM_REG_PPC_DABR: 19118c2ecf20Sopenharmony_ci vcpu->arch.dabr = set_reg_val(id, *val); 19128c2ecf20Sopenharmony_ci break; 19138c2ecf20Sopenharmony_ci case KVM_REG_PPC_DABRX: 19148c2ecf20Sopenharmony_ci vcpu->arch.dabrx = set_reg_val(id, *val) & ~DABRX_HYP; 19158c2ecf20Sopenharmony_ci break; 19168c2ecf20Sopenharmony_ci case KVM_REG_PPC_DSCR: 19178c2ecf20Sopenharmony_ci vcpu->arch.dscr = set_reg_val(id, *val); 19188c2ecf20Sopenharmony_ci break; 19198c2ecf20Sopenharmony_ci case KVM_REG_PPC_PURR: 19208c2ecf20Sopenharmony_ci vcpu->arch.purr = set_reg_val(id, *val); 19218c2ecf20Sopenharmony_ci break; 19228c2ecf20Sopenharmony_ci case KVM_REG_PPC_SPURR: 19238c2ecf20Sopenharmony_ci vcpu->arch.spurr = set_reg_val(id, *val); 19248c2ecf20Sopenharmony_ci break; 19258c2ecf20Sopenharmony_ci case KVM_REG_PPC_AMR: 19268c2ecf20Sopenharmony_ci vcpu->arch.amr = set_reg_val(id, *val); 19278c2ecf20Sopenharmony_ci break; 19288c2ecf20Sopenharmony_ci case KVM_REG_PPC_UAMOR: 19298c2ecf20Sopenharmony_ci vcpu->arch.uamor = set_reg_val(id, *val); 19308c2ecf20Sopenharmony_ci break; 19318c2ecf20Sopenharmony_ci case KVM_REG_PPC_MMCR0 ... KVM_REG_PPC_MMCR1: 19328c2ecf20Sopenharmony_ci i = id - KVM_REG_PPC_MMCR0; 19338c2ecf20Sopenharmony_ci vcpu->arch.mmcr[i] = set_reg_val(id, *val); 19348c2ecf20Sopenharmony_ci break; 19358c2ecf20Sopenharmony_ci case KVM_REG_PPC_MMCR2: 19368c2ecf20Sopenharmony_ci vcpu->arch.mmcr[2] = set_reg_val(id, *val); 19378c2ecf20Sopenharmony_ci break; 19388c2ecf20Sopenharmony_ci case KVM_REG_PPC_MMCRA: 19398c2ecf20Sopenharmony_ci vcpu->arch.mmcra = set_reg_val(id, *val); 19408c2ecf20Sopenharmony_ci break; 19418c2ecf20Sopenharmony_ci case KVM_REG_PPC_MMCRS: 19428c2ecf20Sopenharmony_ci vcpu->arch.mmcrs = set_reg_val(id, *val); 19438c2ecf20Sopenharmony_ci break; 19448c2ecf20Sopenharmony_ci case KVM_REG_PPC_MMCR3: 19458c2ecf20Sopenharmony_ci *val = get_reg_val(id, vcpu->arch.mmcr[3]); 19468c2ecf20Sopenharmony_ci break; 19478c2ecf20Sopenharmony_ci case KVM_REG_PPC_PMC1 ... KVM_REG_PPC_PMC8: 19488c2ecf20Sopenharmony_ci i = id - KVM_REG_PPC_PMC1; 19498c2ecf20Sopenharmony_ci vcpu->arch.pmc[i] = set_reg_val(id, *val); 19508c2ecf20Sopenharmony_ci break; 19518c2ecf20Sopenharmony_ci case KVM_REG_PPC_SPMC1 ... KVM_REG_PPC_SPMC2: 19528c2ecf20Sopenharmony_ci i = id - KVM_REG_PPC_SPMC1; 19538c2ecf20Sopenharmony_ci vcpu->arch.spmc[i] = set_reg_val(id, *val); 19548c2ecf20Sopenharmony_ci break; 19558c2ecf20Sopenharmony_ci case KVM_REG_PPC_SIAR: 19568c2ecf20Sopenharmony_ci vcpu->arch.siar = set_reg_val(id, *val); 19578c2ecf20Sopenharmony_ci break; 19588c2ecf20Sopenharmony_ci case KVM_REG_PPC_SDAR: 19598c2ecf20Sopenharmony_ci vcpu->arch.sdar = set_reg_val(id, *val); 19608c2ecf20Sopenharmony_ci break; 19618c2ecf20Sopenharmony_ci case KVM_REG_PPC_SIER: 19628c2ecf20Sopenharmony_ci vcpu->arch.sier[0] = set_reg_val(id, *val); 19638c2ecf20Sopenharmony_ci break; 19648c2ecf20Sopenharmony_ci case KVM_REG_PPC_SIER2: 19658c2ecf20Sopenharmony_ci vcpu->arch.sier[1] = set_reg_val(id, *val); 19668c2ecf20Sopenharmony_ci break; 19678c2ecf20Sopenharmony_ci case KVM_REG_PPC_SIER3: 19688c2ecf20Sopenharmony_ci vcpu->arch.sier[2] = set_reg_val(id, *val); 19698c2ecf20Sopenharmony_ci break; 19708c2ecf20Sopenharmony_ci case KVM_REG_PPC_IAMR: 19718c2ecf20Sopenharmony_ci vcpu->arch.iamr = set_reg_val(id, *val); 19728c2ecf20Sopenharmony_ci break; 19738c2ecf20Sopenharmony_ci case KVM_REG_PPC_PSPB: 19748c2ecf20Sopenharmony_ci vcpu->arch.pspb = set_reg_val(id, *val); 19758c2ecf20Sopenharmony_ci break; 19768c2ecf20Sopenharmony_ci case KVM_REG_PPC_DPDES: 19778c2ecf20Sopenharmony_ci vcpu->arch.vcore->dpdes = set_reg_val(id, *val); 19788c2ecf20Sopenharmony_ci break; 19798c2ecf20Sopenharmony_ci case KVM_REG_PPC_VTB: 19808c2ecf20Sopenharmony_ci vcpu->arch.vcore->vtb = set_reg_val(id, *val); 19818c2ecf20Sopenharmony_ci break; 19828c2ecf20Sopenharmony_ci case KVM_REG_PPC_DAWR: 19838c2ecf20Sopenharmony_ci vcpu->arch.dawr = set_reg_val(id, *val); 19848c2ecf20Sopenharmony_ci break; 19858c2ecf20Sopenharmony_ci case KVM_REG_PPC_DAWRX: 19868c2ecf20Sopenharmony_ci vcpu->arch.dawrx = set_reg_val(id, *val) & ~DAWRX_HYP; 19878c2ecf20Sopenharmony_ci break; 19888c2ecf20Sopenharmony_ci case KVM_REG_PPC_CIABR: 19898c2ecf20Sopenharmony_ci vcpu->arch.ciabr = set_reg_val(id, *val); 19908c2ecf20Sopenharmony_ci /* Don't allow setting breakpoints in hypervisor code */ 19918c2ecf20Sopenharmony_ci if ((vcpu->arch.ciabr & CIABR_PRIV) == CIABR_PRIV_HYPER) 19928c2ecf20Sopenharmony_ci vcpu->arch.ciabr &= ~CIABR_PRIV; /* disable */ 19938c2ecf20Sopenharmony_ci break; 19948c2ecf20Sopenharmony_ci case KVM_REG_PPC_CSIGR: 19958c2ecf20Sopenharmony_ci vcpu->arch.csigr = set_reg_val(id, *val); 19968c2ecf20Sopenharmony_ci break; 19978c2ecf20Sopenharmony_ci case KVM_REG_PPC_TACR: 19988c2ecf20Sopenharmony_ci vcpu->arch.tacr = set_reg_val(id, *val); 19998c2ecf20Sopenharmony_ci break; 20008c2ecf20Sopenharmony_ci case KVM_REG_PPC_TCSCR: 20018c2ecf20Sopenharmony_ci vcpu->arch.tcscr = set_reg_val(id, *val); 20028c2ecf20Sopenharmony_ci break; 20038c2ecf20Sopenharmony_ci case KVM_REG_PPC_PID: 20048c2ecf20Sopenharmony_ci vcpu->arch.pid = set_reg_val(id, *val); 20058c2ecf20Sopenharmony_ci break; 20068c2ecf20Sopenharmony_ci case KVM_REG_PPC_ACOP: 20078c2ecf20Sopenharmony_ci vcpu->arch.acop = set_reg_val(id, *val); 20088c2ecf20Sopenharmony_ci break; 20098c2ecf20Sopenharmony_ci case KVM_REG_PPC_WORT: 20108c2ecf20Sopenharmony_ci vcpu->arch.wort = set_reg_val(id, *val); 20118c2ecf20Sopenharmony_ci break; 20128c2ecf20Sopenharmony_ci case KVM_REG_PPC_TIDR: 20138c2ecf20Sopenharmony_ci vcpu->arch.tid = set_reg_val(id, *val); 20148c2ecf20Sopenharmony_ci break; 20158c2ecf20Sopenharmony_ci case KVM_REG_PPC_PSSCR: 20168c2ecf20Sopenharmony_ci vcpu->arch.psscr = set_reg_val(id, *val) & PSSCR_GUEST_VIS; 20178c2ecf20Sopenharmony_ci break; 20188c2ecf20Sopenharmony_ci case KVM_REG_PPC_VPA_ADDR: 20198c2ecf20Sopenharmony_ci addr = set_reg_val(id, *val); 20208c2ecf20Sopenharmony_ci r = -EINVAL; 20218c2ecf20Sopenharmony_ci if (!addr && (vcpu->arch.slb_shadow.next_gpa || 20228c2ecf20Sopenharmony_ci vcpu->arch.dtl.next_gpa)) 20238c2ecf20Sopenharmony_ci break; 20248c2ecf20Sopenharmony_ci r = set_vpa(vcpu, &vcpu->arch.vpa, addr, sizeof(struct lppaca)); 20258c2ecf20Sopenharmony_ci break; 20268c2ecf20Sopenharmony_ci case KVM_REG_PPC_VPA_SLB: 20278c2ecf20Sopenharmony_ci addr = val->vpaval.addr; 20288c2ecf20Sopenharmony_ci len = val->vpaval.length; 20298c2ecf20Sopenharmony_ci r = -EINVAL; 20308c2ecf20Sopenharmony_ci if (addr && !vcpu->arch.vpa.next_gpa) 20318c2ecf20Sopenharmony_ci break; 20328c2ecf20Sopenharmony_ci r = set_vpa(vcpu, &vcpu->arch.slb_shadow, addr, len); 20338c2ecf20Sopenharmony_ci break; 20348c2ecf20Sopenharmony_ci case KVM_REG_PPC_VPA_DTL: 20358c2ecf20Sopenharmony_ci addr = val->vpaval.addr; 20368c2ecf20Sopenharmony_ci len = val->vpaval.length; 20378c2ecf20Sopenharmony_ci r = -EINVAL; 20388c2ecf20Sopenharmony_ci if (addr && (len < sizeof(struct dtl_entry) || 20398c2ecf20Sopenharmony_ci !vcpu->arch.vpa.next_gpa)) 20408c2ecf20Sopenharmony_ci break; 20418c2ecf20Sopenharmony_ci len -= len % sizeof(struct dtl_entry); 20428c2ecf20Sopenharmony_ci r = set_vpa(vcpu, &vcpu->arch.dtl, addr, len); 20438c2ecf20Sopenharmony_ci break; 20448c2ecf20Sopenharmony_ci case KVM_REG_PPC_TB_OFFSET: 20458c2ecf20Sopenharmony_ci /* round up to multiple of 2^24 */ 20468c2ecf20Sopenharmony_ci vcpu->arch.vcore->tb_offset = 20478c2ecf20Sopenharmony_ci ALIGN(set_reg_val(id, *val), 1UL << 24); 20488c2ecf20Sopenharmony_ci break; 20498c2ecf20Sopenharmony_ci case KVM_REG_PPC_LPCR: 20508c2ecf20Sopenharmony_ci kvmppc_set_lpcr(vcpu, set_reg_val(id, *val), true); 20518c2ecf20Sopenharmony_ci break; 20528c2ecf20Sopenharmony_ci case KVM_REG_PPC_LPCR_64: 20538c2ecf20Sopenharmony_ci kvmppc_set_lpcr(vcpu, set_reg_val(id, *val), false); 20548c2ecf20Sopenharmony_ci break; 20558c2ecf20Sopenharmony_ci case KVM_REG_PPC_PPR: 20568c2ecf20Sopenharmony_ci vcpu->arch.ppr = set_reg_val(id, *val); 20578c2ecf20Sopenharmony_ci break; 20588c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_TRANSACTIONAL_MEM 20598c2ecf20Sopenharmony_ci case KVM_REG_PPC_TFHAR: 20608c2ecf20Sopenharmony_ci vcpu->arch.tfhar = set_reg_val(id, *val); 20618c2ecf20Sopenharmony_ci break; 20628c2ecf20Sopenharmony_ci case KVM_REG_PPC_TFIAR: 20638c2ecf20Sopenharmony_ci vcpu->arch.tfiar = set_reg_val(id, *val); 20648c2ecf20Sopenharmony_ci break; 20658c2ecf20Sopenharmony_ci case KVM_REG_PPC_TEXASR: 20668c2ecf20Sopenharmony_ci vcpu->arch.texasr = set_reg_val(id, *val); 20678c2ecf20Sopenharmony_ci break; 20688c2ecf20Sopenharmony_ci case KVM_REG_PPC_TM_GPR0 ... KVM_REG_PPC_TM_GPR31: 20698c2ecf20Sopenharmony_ci i = id - KVM_REG_PPC_TM_GPR0; 20708c2ecf20Sopenharmony_ci vcpu->arch.gpr_tm[i] = set_reg_val(id, *val); 20718c2ecf20Sopenharmony_ci break; 20728c2ecf20Sopenharmony_ci case KVM_REG_PPC_TM_VSR0 ... KVM_REG_PPC_TM_VSR63: 20738c2ecf20Sopenharmony_ci { 20748c2ecf20Sopenharmony_ci int j; 20758c2ecf20Sopenharmony_ci i = id - KVM_REG_PPC_TM_VSR0; 20768c2ecf20Sopenharmony_ci if (i < 32) 20778c2ecf20Sopenharmony_ci for (j = 0; j < TS_FPRWIDTH; j++) 20788c2ecf20Sopenharmony_ci vcpu->arch.fp_tm.fpr[i][j] = val->vsxval[j]; 20798c2ecf20Sopenharmony_ci else 20808c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ALTIVEC)) 20818c2ecf20Sopenharmony_ci vcpu->arch.vr_tm.vr[i-32] = val->vval; 20828c2ecf20Sopenharmony_ci else 20838c2ecf20Sopenharmony_ci r = -ENXIO; 20848c2ecf20Sopenharmony_ci break; 20858c2ecf20Sopenharmony_ci } 20868c2ecf20Sopenharmony_ci case KVM_REG_PPC_TM_CR: 20878c2ecf20Sopenharmony_ci vcpu->arch.cr_tm = set_reg_val(id, *val); 20888c2ecf20Sopenharmony_ci break; 20898c2ecf20Sopenharmony_ci case KVM_REG_PPC_TM_XER: 20908c2ecf20Sopenharmony_ci vcpu->arch.xer_tm = set_reg_val(id, *val); 20918c2ecf20Sopenharmony_ci break; 20928c2ecf20Sopenharmony_ci case KVM_REG_PPC_TM_LR: 20938c2ecf20Sopenharmony_ci vcpu->arch.lr_tm = set_reg_val(id, *val); 20948c2ecf20Sopenharmony_ci break; 20958c2ecf20Sopenharmony_ci case KVM_REG_PPC_TM_CTR: 20968c2ecf20Sopenharmony_ci vcpu->arch.ctr_tm = set_reg_val(id, *val); 20978c2ecf20Sopenharmony_ci break; 20988c2ecf20Sopenharmony_ci case KVM_REG_PPC_TM_FPSCR: 20998c2ecf20Sopenharmony_ci vcpu->arch.fp_tm.fpscr = set_reg_val(id, *val); 21008c2ecf20Sopenharmony_ci break; 21018c2ecf20Sopenharmony_ci case KVM_REG_PPC_TM_AMR: 21028c2ecf20Sopenharmony_ci vcpu->arch.amr_tm = set_reg_val(id, *val); 21038c2ecf20Sopenharmony_ci break; 21048c2ecf20Sopenharmony_ci case KVM_REG_PPC_TM_PPR: 21058c2ecf20Sopenharmony_ci vcpu->arch.ppr_tm = set_reg_val(id, *val); 21068c2ecf20Sopenharmony_ci break; 21078c2ecf20Sopenharmony_ci case KVM_REG_PPC_TM_VRSAVE: 21088c2ecf20Sopenharmony_ci vcpu->arch.vrsave_tm = set_reg_val(id, *val); 21098c2ecf20Sopenharmony_ci break; 21108c2ecf20Sopenharmony_ci case KVM_REG_PPC_TM_VSCR: 21118c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ALTIVEC)) 21128c2ecf20Sopenharmony_ci vcpu->arch.vr.vscr.u[3] = set_reg_val(id, *val); 21138c2ecf20Sopenharmony_ci else 21148c2ecf20Sopenharmony_ci r = - ENXIO; 21158c2ecf20Sopenharmony_ci break; 21168c2ecf20Sopenharmony_ci case KVM_REG_PPC_TM_DSCR: 21178c2ecf20Sopenharmony_ci vcpu->arch.dscr_tm = set_reg_val(id, *val); 21188c2ecf20Sopenharmony_ci break; 21198c2ecf20Sopenharmony_ci case KVM_REG_PPC_TM_TAR: 21208c2ecf20Sopenharmony_ci vcpu->arch.tar_tm = set_reg_val(id, *val); 21218c2ecf20Sopenharmony_ci break; 21228c2ecf20Sopenharmony_ci#endif 21238c2ecf20Sopenharmony_ci case KVM_REG_PPC_ARCH_COMPAT: 21248c2ecf20Sopenharmony_ci r = kvmppc_set_arch_compat(vcpu, set_reg_val(id, *val)); 21258c2ecf20Sopenharmony_ci break; 21268c2ecf20Sopenharmony_ci case KVM_REG_PPC_DEC_EXPIRY: 21278c2ecf20Sopenharmony_ci vcpu->arch.dec_expires = set_reg_val(id, *val) - 21288c2ecf20Sopenharmony_ci vcpu->arch.vcore->tb_offset; 21298c2ecf20Sopenharmony_ci break; 21308c2ecf20Sopenharmony_ci case KVM_REG_PPC_ONLINE: 21318c2ecf20Sopenharmony_ci i = set_reg_val(id, *val); 21328c2ecf20Sopenharmony_ci if (i && !vcpu->arch.online) 21338c2ecf20Sopenharmony_ci atomic_inc(&vcpu->arch.vcore->online_count); 21348c2ecf20Sopenharmony_ci else if (!i && vcpu->arch.online) 21358c2ecf20Sopenharmony_ci atomic_dec(&vcpu->arch.vcore->online_count); 21368c2ecf20Sopenharmony_ci vcpu->arch.online = i; 21378c2ecf20Sopenharmony_ci break; 21388c2ecf20Sopenharmony_ci case KVM_REG_PPC_PTCR: 21398c2ecf20Sopenharmony_ci vcpu->kvm->arch.l1_ptcr = set_reg_val(id, *val); 21408c2ecf20Sopenharmony_ci break; 21418c2ecf20Sopenharmony_ci default: 21428c2ecf20Sopenharmony_ci r = -EINVAL; 21438c2ecf20Sopenharmony_ci break; 21448c2ecf20Sopenharmony_ci } 21458c2ecf20Sopenharmony_ci 21468c2ecf20Sopenharmony_ci return r; 21478c2ecf20Sopenharmony_ci} 21488c2ecf20Sopenharmony_ci 21498c2ecf20Sopenharmony_ci/* 21508c2ecf20Sopenharmony_ci * On POWER9, threads are independent and can be in different partitions. 21518c2ecf20Sopenharmony_ci * Therefore we consider each thread to be a subcore. 21528c2ecf20Sopenharmony_ci * There is a restriction that all threads have to be in the same 21538c2ecf20Sopenharmony_ci * MMU mode (radix or HPT), unfortunately, but since we only support 21548c2ecf20Sopenharmony_ci * HPT guests on a HPT host so far, that isn't an impediment yet. 21558c2ecf20Sopenharmony_ci */ 21568c2ecf20Sopenharmony_cistatic int threads_per_vcore(struct kvm *kvm) 21578c2ecf20Sopenharmony_ci{ 21588c2ecf20Sopenharmony_ci if (kvm->arch.threads_indep) 21598c2ecf20Sopenharmony_ci return 1; 21608c2ecf20Sopenharmony_ci return threads_per_subcore; 21618c2ecf20Sopenharmony_ci} 21628c2ecf20Sopenharmony_ci 21638c2ecf20Sopenharmony_cistatic struct kvmppc_vcore *kvmppc_vcore_create(struct kvm *kvm, int id) 21648c2ecf20Sopenharmony_ci{ 21658c2ecf20Sopenharmony_ci struct kvmppc_vcore *vcore; 21668c2ecf20Sopenharmony_ci 21678c2ecf20Sopenharmony_ci vcore = kzalloc(sizeof(struct kvmppc_vcore), GFP_KERNEL); 21688c2ecf20Sopenharmony_ci 21698c2ecf20Sopenharmony_ci if (vcore == NULL) 21708c2ecf20Sopenharmony_ci return NULL; 21718c2ecf20Sopenharmony_ci 21728c2ecf20Sopenharmony_ci spin_lock_init(&vcore->lock); 21738c2ecf20Sopenharmony_ci spin_lock_init(&vcore->stoltb_lock); 21748c2ecf20Sopenharmony_ci rcuwait_init(&vcore->wait); 21758c2ecf20Sopenharmony_ci vcore->preempt_tb = TB_NIL; 21768c2ecf20Sopenharmony_ci vcore->lpcr = kvm->arch.lpcr; 21778c2ecf20Sopenharmony_ci vcore->first_vcpuid = id; 21788c2ecf20Sopenharmony_ci vcore->kvm = kvm; 21798c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&vcore->preempt_list); 21808c2ecf20Sopenharmony_ci 21818c2ecf20Sopenharmony_ci return vcore; 21828c2ecf20Sopenharmony_ci} 21838c2ecf20Sopenharmony_ci 21848c2ecf20Sopenharmony_ci#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING 21858c2ecf20Sopenharmony_cistatic struct debugfs_timings_element { 21868c2ecf20Sopenharmony_ci const char *name; 21878c2ecf20Sopenharmony_ci size_t offset; 21888c2ecf20Sopenharmony_ci} timings[] = { 21898c2ecf20Sopenharmony_ci {"rm_entry", offsetof(struct kvm_vcpu, arch.rm_entry)}, 21908c2ecf20Sopenharmony_ci {"rm_intr", offsetof(struct kvm_vcpu, arch.rm_intr)}, 21918c2ecf20Sopenharmony_ci {"rm_exit", offsetof(struct kvm_vcpu, arch.rm_exit)}, 21928c2ecf20Sopenharmony_ci {"guest", offsetof(struct kvm_vcpu, arch.guest_time)}, 21938c2ecf20Sopenharmony_ci {"cede", offsetof(struct kvm_vcpu, arch.cede_time)}, 21948c2ecf20Sopenharmony_ci}; 21958c2ecf20Sopenharmony_ci 21968c2ecf20Sopenharmony_ci#define N_TIMINGS (ARRAY_SIZE(timings)) 21978c2ecf20Sopenharmony_ci 21988c2ecf20Sopenharmony_cistruct debugfs_timings_state { 21998c2ecf20Sopenharmony_ci struct kvm_vcpu *vcpu; 22008c2ecf20Sopenharmony_ci unsigned int buflen; 22018c2ecf20Sopenharmony_ci char buf[N_TIMINGS * 100]; 22028c2ecf20Sopenharmony_ci}; 22038c2ecf20Sopenharmony_ci 22048c2ecf20Sopenharmony_cistatic int debugfs_timings_open(struct inode *inode, struct file *file) 22058c2ecf20Sopenharmony_ci{ 22068c2ecf20Sopenharmony_ci struct kvm_vcpu *vcpu = inode->i_private; 22078c2ecf20Sopenharmony_ci struct debugfs_timings_state *p; 22088c2ecf20Sopenharmony_ci 22098c2ecf20Sopenharmony_ci p = kzalloc(sizeof(*p), GFP_KERNEL); 22108c2ecf20Sopenharmony_ci if (!p) 22118c2ecf20Sopenharmony_ci return -ENOMEM; 22128c2ecf20Sopenharmony_ci 22138c2ecf20Sopenharmony_ci kvm_get_kvm(vcpu->kvm); 22148c2ecf20Sopenharmony_ci p->vcpu = vcpu; 22158c2ecf20Sopenharmony_ci file->private_data = p; 22168c2ecf20Sopenharmony_ci 22178c2ecf20Sopenharmony_ci return nonseekable_open(inode, file); 22188c2ecf20Sopenharmony_ci} 22198c2ecf20Sopenharmony_ci 22208c2ecf20Sopenharmony_cistatic int debugfs_timings_release(struct inode *inode, struct file *file) 22218c2ecf20Sopenharmony_ci{ 22228c2ecf20Sopenharmony_ci struct debugfs_timings_state *p = file->private_data; 22238c2ecf20Sopenharmony_ci 22248c2ecf20Sopenharmony_ci kvm_put_kvm(p->vcpu->kvm); 22258c2ecf20Sopenharmony_ci kfree(p); 22268c2ecf20Sopenharmony_ci return 0; 22278c2ecf20Sopenharmony_ci} 22288c2ecf20Sopenharmony_ci 22298c2ecf20Sopenharmony_cistatic ssize_t debugfs_timings_read(struct file *file, char __user *buf, 22308c2ecf20Sopenharmony_ci size_t len, loff_t *ppos) 22318c2ecf20Sopenharmony_ci{ 22328c2ecf20Sopenharmony_ci struct debugfs_timings_state *p = file->private_data; 22338c2ecf20Sopenharmony_ci struct kvm_vcpu *vcpu = p->vcpu; 22348c2ecf20Sopenharmony_ci char *s, *buf_end; 22358c2ecf20Sopenharmony_ci struct kvmhv_tb_accumulator tb; 22368c2ecf20Sopenharmony_ci u64 count; 22378c2ecf20Sopenharmony_ci loff_t pos; 22388c2ecf20Sopenharmony_ci ssize_t n; 22398c2ecf20Sopenharmony_ci int i, loops; 22408c2ecf20Sopenharmony_ci bool ok; 22418c2ecf20Sopenharmony_ci 22428c2ecf20Sopenharmony_ci if (!p->buflen) { 22438c2ecf20Sopenharmony_ci s = p->buf; 22448c2ecf20Sopenharmony_ci buf_end = s + sizeof(p->buf); 22458c2ecf20Sopenharmony_ci for (i = 0; i < N_TIMINGS; ++i) { 22468c2ecf20Sopenharmony_ci struct kvmhv_tb_accumulator *acc; 22478c2ecf20Sopenharmony_ci 22488c2ecf20Sopenharmony_ci acc = (struct kvmhv_tb_accumulator *) 22498c2ecf20Sopenharmony_ci ((unsigned long)vcpu + timings[i].offset); 22508c2ecf20Sopenharmony_ci ok = false; 22518c2ecf20Sopenharmony_ci for (loops = 0; loops < 1000; ++loops) { 22528c2ecf20Sopenharmony_ci count = acc->seqcount; 22538c2ecf20Sopenharmony_ci if (!(count & 1)) { 22548c2ecf20Sopenharmony_ci smp_rmb(); 22558c2ecf20Sopenharmony_ci tb = *acc; 22568c2ecf20Sopenharmony_ci smp_rmb(); 22578c2ecf20Sopenharmony_ci if (count == acc->seqcount) { 22588c2ecf20Sopenharmony_ci ok = true; 22598c2ecf20Sopenharmony_ci break; 22608c2ecf20Sopenharmony_ci } 22618c2ecf20Sopenharmony_ci } 22628c2ecf20Sopenharmony_ci udelay(1); 22638c2ecf20Sopenharmony_ci } 22648c2ecf20Sopenharmony_ci if (!ok) 22658c2ecf20Sopenharmony_ci snprintf(s, buf_end - s, "%s: stuck\n", 22668c2ecf20Sopenharmony_ci timings[i].name); 22678c2ecf20Sopenharmony_ci else 22688c2ecf20Sopenharmony_ci snprintf(s, buf_end - s, 22698c2ecf20Sopenharmony_ci "%s: %llu %llu %llu %llu\n", 22708c2ecf20Sopenharmony_ci timings[i].name, count / 2, 22718c2ecf20Sopenharmony_ci tb_to_ns(tb.tb_total), 22728c2ecf20Sopenharmony_ci tb_to_ns(tb.tb_min), 22738c2ecf20Sopenharmony_ci tb_to_ns(tb.tb_max)); 22748c2ecf20Sopenharmony_ci s += strlen(s); 22758c2ecf20Sopenharmony_ci } 22768c2ecf20Sopenharmony_ci p->buflen = s - p->buf; 22778c2ecf20Sopenharmony_ci } 22788c2ecf20Sopenharmony_ci 22798c2ecf20Sopenharmony_ci pos = *ppos; 22808c2ecf20Sopenharmony_ci if (pos >= p->buflen) 22818c2ecf20Sopenharmony_ci return 0; 22828c2ecf20Sopenharmony_ci if (len > p->buflen - pos) 22838c2ecf20Sopenharmony_ci len = p->buflen - pos; 22848c2ecf20Sopenharmony_ci n = copy_to_user(buf, p->buf + pos, len); 22858c2ecf20Sopenharmony_ci if (n) { 22868c2ecf20Sopenharmony_ci if (n == len) 22878c2ecf20Sopenharmony_ci return -EFAULT; 22888c2ecf20Sopenharmony_ci len -= n; 22898c2ecf20Sopenharmony_ci } 22908c2ecf20Sopenharmony_ci *ppos = pos + len; 22918c2ecf20Sopenharmony_ci return len; 22928c2ecf20Sopenharmony_ci} 22938c2ecf20Sopenharmony_ci 22948c2ecf20Sopenharmony_cistatic ssize_t debugfs_timings_write(struct file *file, const char __user *buf, 22958c2ecf20Sopenharmony_ci size_t len, loff_t *ppos) 22968c2ecf20Sopenharmony_ci{ 22978c2ecf20Sopenharmony_ci return -EACCES; 22988c2ecf20Sopenharmony_ci} 22998c2ecf20Sopenharmony_ci 23008c2ecf20Sopenharmony_cistatic const struct file_operations debugfs_timings_ops = { 23018c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 23028c2ecf20Sopenharmony_ci .open = debugfs_timings_open, 23038c2ecf20Sopenharmony_ci .release = debugfs_timings_release, 23048c2ecf20Sopenharmony_ci .read = debugfs_timings_read, 23058c2ecf20Sopenharmony_ci .write = debugfs_timings_write, 23068c2ecf20Sopenharmony_ci .llseek = generic_file_llseek, 23078c2ecf20Sopenharmony_ci}; 23088c2ecf20Sopenharmony_ci 23098c2ecf20Sopenharmony_ci/* Create a debugfs directory for the vcpu */ 23108c2ecf20Sopenharmony_cistatic void debugfs_vcpu_init(struct kvm_vcpu *vcpu, unsigned int id) 23118c2ecf20Sopenharmony_ci{ 23128c2ecf20Sopenharmony_ci char buf[16]; 23138c2ecf20Sopenharmony_ci struct kvm *kvm = vcpu->kvm; 23148c2ecf20Sopenharmony_ci 23158c2ecf20Sopenharmony_ci snprintf(buf, sizeof(buf), "vcpu%u", id); 23168c2ecf20Sopenharmony_ci vcpu->arch.debugfs_dir = debugfs_create_dir(buf, kvm->arch.debugfs_dir); 23178c2ecf20Sopenharmony_ci debugfs_create_file("timings", 0444, vcpu->arch.debugfs_dir, vcpu, 23188c2ecf20Sopenharmony_ci &debugfs_timings_ops); 23198c2ecf20Sopenharmony_ci} 23208c2ecf20Sopenharmony_ci 23218c2ecf20Sopenharmony_ci#else /* CONFIG_KVM_BOOK3S_HV_EXIT_TIMING */ 23228c2ecf20Sopenharmony_cistatic void debugfs_vcpu_init(struct kvm_vcpu *vcpu, unsigned int id) 23238c2ecf20Sopenharmony_ci{ 23248c2ecf20Sopenharmony_ci} 23258c2ecf20Sopenharmony_ci#endif /* CONFIG_KVM_BOOK3S_HV_EXIT_TIMING */ 23268c2ecf20Sopenharmony_ci 23278c2ecf20Sopenharmony_cistatic int kvmppc_core_vcpu_create_hv(struct kvm_vcpu *vcpu) 23288c2ecf20Sopenharmony_ci{ 23298c2ecf20Sopenharmony_ci int err; 23308c2ecf20Sopenharmony_ci int core; 23318c2ecf20Sopenharmony_ci struct kvmppc_vcore *vcore; 23328c2ecf20Sopenharmony_ci struct kvm *kvm; 23338c2ecf20Sopenharmony_ci unsigned int id; 23348c2ecf20Sopenharmony_ci 23358c2ecf20Sopenharmony_ci kvm = vcpu->kvm; 23368c2ecf20Sopenharmony_ci id = vcpu->vcpu_id; 23378c2ecf20Sopenharmony_ci 23388c2ecf20Sopenharmony_ci vcpu->arch.shared = &vcpu->arch.shregs; 23398c2ecf20Sopenharmony_ci#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE 23408c2ecf20Sopenharmony_ci /* 23418c2ecf20Sopenharmony_ci * The shared struct is never shared on HV, 23428c2ecf20Sopenharmony_ci * so we can always use host endianness 23438c2ecf20Sopenharmony_ci */ 23448c2ecf20Sopenharmony_ci#ifdef __BIG_ENDIAN__ 23458c2ecf20Sopenharmony_ci vcpu->arch.shared_big_endian = true; 23468c2ecf20Sopenharmony_ci#else 23478c2ecf20Sopenharmony_ci vcpu->arch.shared_big_endian = false; 23488c2ecf20Sopenharmony_ci#endif 23498c2ecf20Sopenharmony_ci#endif 23508c2ecf20Sopenharmony_ci vcpu->arch.mmcr[0] = MMCR0_FC; 23518c2ecf20Sopenharmony_ci vcpu->arch.ctrl = CTRL_RUNLATCH; 23528c2ecf20Sopenharmony_ci /* default to host PVR, since we can't spoof it */ 23538c2ecf20Sopenharmony_ci kvmppc_set_pvr_hv(vcpu, mfspr(SPRN_PVR)); 23548c2ecf20Sopenharmony_ci spin_lock_init(&vcpu->arch.vpa_update_lock); 23558c2ecf20Sopenharmony_ci spin_lock_init(&vcpu->arch.tbacct_lock); 23568c2ecf20Sopenharmony_ci vcpu->arch.busy_preempt = TB_NIL; 23578c2ecf20Sopenharmony_ci vcpu->arch.intr_msr = MSR_SF | MSR_ME; 23588c2ecf20Sopenharmony_ci 23598c2ecf20Sopenharmony_ci /* 23608c2ecf20Sopenharmony_ci * Set the default HFSCR for the guest from the host value. 23618c2ecf20Sopenharmony_ci * This value is only used on POWER9. 23628c2ecf20Sopenharmony_ci * On POWER9, we want to virtualize the doorbell facility, so we 23638c2ecf20Sopenharmony_ci * don't set the HFSCR_MSGP bit, and that causes those instructions 23648c2ecf20Sopenharmony_ci * to trap and then we emulate them. 23658c2ecf20Sopenharmony_ci */ 23668c2ecf20Sopenharmony_ci vcpu->arch.hfscr = HFSCR_TAR | HFSCR_EBB | HFSCR_PM | HFSCR_BHRB | 23678c2ecf20Sopenharmony_ci HFSCR_DSCR | HFSCR_VECVSX | HFSCR_FP | HFSCR_PREFIX; 23688c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_HVMODE)) { 23698c2ecf20Sopenharmony_ci vcpu->arch.hfscr &= mfspr(SPRN_HFSCR); 23708c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_TRANSACTIONAL_MEM 23718c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_P9_TM_HV_ASSIST)) 23728c2ecf20Sopenharmony_ci vcpu->arch.hfscr |= HFSCR_TM; 23738c2ecf20Sopenharmony_ci#endif 23748c2ecf20Sopenharmony_ci } 23758c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_TM_COMP)) 23768c2ecf20Sopenharmony_ci vcpu->arch.hfscr |= HFSCR_TM; 23778c2ecf20Sopenharmony_ci 23788c2ecf20Sopenharmony_ci kvmppc_mmu_book3s_hv_init(vcpu); 23798c2ecf20Sopenharmony_ci 23808c2ecf20Sopenharmony_ci vcpu->arch.state = KVMPPC_VCPU_NOTREADY; 23818c2ecf20Sopenharmony_ci 23828c2ecf20Sopenharmony_ci init_waitqueue_head(&vcpu->arch.cpu_run); 23838c2ecf20Sopenharmony_ci 23848c2ecf20Sopenharmony_ci mutex_lock(&kvm->lock); 23858c2ecf20Sopenharmony_ci vcore = NULL; 23868c2ecf20Sopenharmony_ci err = -EINVAL; 23878c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_300)) { 23888c2ecf20Sopenharmony_ci if (id >= (KVM_MAX_VCPUS * kvm->arch.emul_smt_mode)) { 23898c2ecf20Sopenharmony_ci pr_devel("KVM: VCPU ID too high\n"); 23908c2ecf20Sopenharmony_ci core = KVM_MAX_VCORES; 23918c2ecf20Sopenharmony_ci } else { 23928c2ecf20Sopenharmony_ci BUG_ON(kvm->arch.smt_mode != 1); 23938c2ecf20Sopenharmony_ci core = kvmppc_pack_vcpu_id(kvm, id); 23948c2ecf20Sopenharmony_ci } 23958c2ecf20Sopenharmony_ci } else { 23968c2ecf20Sopenharmony_ci core = id / kvm->arch.smt_mode; 23978c2ecf20Sopenharmony_ci } 23988c2ecf20Sopenharmony_ci if (core < KVM_MAX_VCORES) { 23998c2ecf20Sopenharmony_ci vcore = kvm->arch.vcores[core]; 24008c2ecf20Sopenharmony_ci if (vcore && cpu_has_feature(CPU_FTR_ARCH_300)) { 24018c2ecf20Sopenharmony_ci pr_devel("KVM: collision on id %u", id); 24028c2ecf20Sopenharmony_ci vcore = NULL; 24038c2ecf20Sopenharmony_ci } else if (!vcore) { 24048c2ecf20Sopenharmony_ci /* 24058c2ecf20Sopenharmony_ci * Take mmu_setup_lock for mutual exclusion 24068c2ecf20Sopenharmony_ci * with kvmppc_update_lpcr(). 24078c2ecf20Sopenharmony_ci */ 24088c2ecf20Sopenharmony_ci err = -ENOMEM; 24098c2ecf20Sopenharmony_ci vcore = kvmppc_vcore_create(kvm, 24108c2ecf20Sopenharmony_ci id & ~(kvm->arch.smt_mode - 1)); 24118c2ecf20Sopenharmony_ci mutex_lock(&kvm->arch.mmu_setup_lock); 24128c2ecf20Sopenharmony_ci kvm->arch.vcores[core] = vcore; 24138c2ecf20Sopenharmony_ci kvm->arch.online_vcores++; 24148c2ecf20Sopenharmony_ci mutex_unlock(&kvm->arch.mmu_setup_lock); 24158c2ecf20Sopenharmony_ci } 24168c2ecf20Sopenharmony_ci } 24178c2ecf20Sopenharmony_ci mutex_unlock(&kvm->lock); 24188c2ecf20Sopenharmony_ci 24198c2ecf20Sopenharmony_ci if (!vcore) 24208c2ecf20Sopenharmony_ci return err; 24218c2ecf20Sopenharmony_ci 24228c2ecf20Sopenharmony_ci spin_lock(&vcore->lock); 24238c2ecf20Sopenharmony_ci ++vcore->num_threads; 24248c2ecf20Sopenharmony_ci spin_unlock(&vcore->lock); 24258c2ecf20Sopenharmony_ci vcpu->arch.vcore = vcore; 24268c2ecf20Sopenharmony_ci vcpu->arch.ptid = vcpu->vcpu_id - vcore->first_vcpuid; 24278c2ecf20Sopenharmony_ci vcpu->arch.thread_cpu = -1; 24288c2ecf20Sopenharmony_ci vcpu->arch.prev_cpu = -1; 24298c2ecf20Sopenharmony_ci 24308c2ecf20Sopenharmony_ci vcpu->arch.cpu_type = KVM_CPU_3S_64; 24318c2ecf20Sopenharmony_ci kvmppc_sanity_check(vcpu); 24328c2ecf20Sopenharmony_ci 24338c2ecf20Sopenharmony_ci debugfs_vcpu_init(vcpu, id); 24348c2ecf20Sopenharmony_ci 24358c2ecf20Sopenharmony_ci return 0; 24368c2ecf20Sopenharmony_ci} 24378c2ecf20Sopenharmony_ci 24388c2ecf20Sopenharmony_cistatic int kvmhv_set_smt_mode(struct kvm *kvm, unsigned long smt_mode, 24398c2ecf20Sopenharmony_ci unsigned long flags) 24408c2ecf20Sopenharmony_ci{ 24418c2ecf20Sopenharmony_ci int err; 24428c2ecf20Sopenharmony_ci int esmt = 0; 24438c2ecf20Sopenharmony_ci 24448c2ecf20Sopenharmony_ci if (flags) 24458c2ecf20Sopenharmony_ci return -EINVAL; 24468c2ecf20Sopenharmony_ci if (smt_mode > MAX_SMT_THREADS || !is_power_of_2(smt_mode)) 24478c2ecf20Sopenharmony_ci return -EINVAL; 24488c2ecf20Sopenharmony_ci if (!cpu_has_feature(CPU_FTR_ARCH_300)) { 24498c2ecf20Sopenharmony_ci /* 24508c2ecf20Sopenharmony_ci * On POWER8 (or POWER7), the threading mode is "strict", 24518c2ecf20Sopenharmony_ci * so we pack smt_mode vcpus per vcore. 24528c2ecf20Sopenharmony_ci */ 24538c2ecf20Sopenharmony_ci if (smt_mode > threads_per_subcore) 24548c2ecf20Sopenharmony_ci return -EINVAL; 24558c2ecf20Sopenharmony_ci } else { 24568c2ecf20Sopenharmony_ci /* 24578c2ecf20Sopenharmony_ci * On POWER9, the threading mode is "loose", 24588c2ecf20Sopenharmony_ci * so each vcpu gets its own vcore. 24598c2ecf20Sopenharmony_ci */ 24608c2ecf20Sopenharmony_ci esmt = smt_mode; 24618c2ecf20Sopenharmony_ci smt_mode = 1; 24628c2ecf20Sopenharmony_ci } 24638c2ecf20Sopenharmony_ci mutex_lock(&kvm->lock); 24648c2ecf20Sopenharmony_ci err = -EBUSY; 24658c2ecf20Sopenharmony_ci if (!kvm->arch.online_vcores) { 24668c2ecf20Sopenharmony_ci kvm->arch.smt_mode = smt_mode; 24678c2ecf20Sopenharmony_ci kvm->arch.emul_smt_mode = esmt; 24688c2ecf20Sopenharmony_ci err = 0; 24698c2ecf20Sopenharmony_ci } 24708c2ecf20Sopenharmony_ci mutex_unlock(&kvm->lock); 24718c2ecf20Sopenharmony_ci 24728c2ecf20Sopenharmony_ci return err; 24738c2ecf20Sopenharmony_ci} 24748c2ecf20Sopenharmony_ci 24758c2ecf20Sopenharmony_cistatic void unpin_vpa(struct kvm *kvm, struct kvmppc_vpa *vpa) 24768c2ecf20Sopenharmony_ci{ 24778c2ecf20Sopenharmony_ci if (vpa->pinned_addr) 24788c2ecf20Sopenharmony_ci kvmppc_unpin_guest_page(kvm, vpa->pinned_addr, vpa->gpa, 24798c2ecf20Sopenharmony_ci vpa->dirty); 24808c2ecf20Sopenharmony_ci} 24818c2ecf20Sopenharmony_ci 24828c2ecf20Sopenharmony_cistatic void kvmppc_core_vcpu_free_hv(struct kvm_vcpu *vcpu) 24838c2ecf20Sopenharmony_ci{ 24848c2ecf20Sopenharmony_ci spin_lock(&vcpu->arch.vpa_update_lock); 24858c2ecf20Sopenharmony_ci unpin_vpa(vcpu->kvm, &vcpu->arch.dtl); 24868c2ecf20Sopenharmony_ci unpin_vpa(vcpu->kvm, &vcpu->arch.slb_shadow); 24878c2ecf20Sopenharmony_ci unpin_vpa(vcpu->kvm, &vcpu->arch.vpa); 24888c2ecf20Sopenharmony_ci spin_unlock(&vcpu->arch.vpa_update_lock); 24898c2ecf20Sopenharmony_ci} 24908c2ecf20Sopenharmony_ci 24918c2ecf20Sopenharmony_cistatic int kvmppc_core_check_requests_hv(struct kvm_vcpu *vcpu) 24928c2ecf20Sopenharmony_ci{ 24938c2ecf20Sopenharmony_ci /* Indicate we want to get back into the guest */ 24948c2ecf20Sopenharmony_ci return 1; 24958c2ecf20Sopenharmony_ci} 24968c2ecf20Sopenharmony_ci 24978c2ecf20Sopenharmony_cistatic void kvmppc_set_timer(struct kvm_vcpu *vcpu) 24988c2ecf20Sopenharmony_ci{ 24998c2ecf20Sopenharmony_ci unsigned long dec_nsec, now; 25008c2ecf20Sopenharmony_ci 25018c2ecf20Sopenharmony_ci now = get_tb(); 25028c2ecf20Sopenharmony_ci if (now > vcpu->arch.dec_expires) { 25038c2ecf20Sopenharmony_ci /* decrementer has already gone negative */ 25048c2ecf20Sopenharmony_ci kvmppc_core_queue_dec(vcpu); 25058c2ecf20Sopenharmony_ci kvmppc_core_prepare_to_enter(vcpu); 25068c2ecf20Sopenharmony_ci return; 25078c2ecf20Sopenharmony_ci } 25088c2ecf20Sopenharmony_ci dec_nsec = tb_to_ns(vcpu->arch.dec_expires - now); 25098c2ecf20Sopenharmony_ci hrtimer_start(&vcpu->arch.dec_timer, dec_nsec, HRTIMER_MODE_REL); 25108c2ecf20Sopenharmony_ci vcpu->arch.timer_running = 1; 25118c2ecf20Sopenharmony_ci} 25128c2ecf20Sopenharmony_ci 25138c2ecf20Sopenharmony_ciextern int __kvmppc_vcore_entry(void); 25148c2ecf20Sopenharmony_ci 25158c2ecf20Sopenharmony_cistatic void kvmppc_remove_runnable(struct kvmppc_vcore *vc, 25168c2ecf20Sopenharmony_ci struct kvm_vcpu *vcpu) 25178c2ecf20Sopenharmony_ci{ 25188c2ecf20Sopenharmony_ci u64 now; 25198c2ecf20Sopenharmony_ci 25208c2ecf20Sopenharmony_ci if (vcpu->arch.state != KVMPPC_VCPU_RUNNABLE) 25218c2ecf20Sopenharmony_ci return; 25228c2ecf20Sopenharmony_ci spin_lock_irq(&vcpu->arch.tbacct_lock); 25238c2ecf20Sopenharmony_ci now = mftb(); 25248c2ecf20Sopenharmony_ci vcpu->arch.busy_stolen += vcore_stolen_time(vc, now) - 25258c2ecf20Sopenharmony_ci vcpu->arch.stolen_logged; 25268c2ecf20Sopenharmony_ci vcpu->arch.busy_preempt = now; 25278c2ecf20Sopenharmony_ci vcpu->arch.state = KVMPPC_VCPU_BUSY_IN_HOST; 25288c2ecf20Sopenharmony_ci spin_unlock_irq(&vcpu->arch.tbacct_lock); 25298c2ecf20Sopenharmony_ci --vc->n_runnable; 25308c2ecf20Sopenharmony_ci WRITE_ONCE(vc->runnable_threads[vcpu->arch.ptid], NULL); 25318c2ecf20Sopenharmony_ci} 25328c2ecf20Sopenharmony_ci 25338c2ecf20Sopenharmony_cistatic int kvmppc_grab_hwthread(int cpu) 25348c2ecf20Sopenharmony_ci{ 25358c2ecf20Sopenharmony_ci struct paca_struct *tpaca; 25368c2ecf20Sopenharmony_ci long timeout = 10000; 25378c2ecf20Sopenharmony_ci 25388c2ecf20Sopenharmony_ci tpaca = paca_ptrs[cpu]; 25398c2ecf20Sopenharmony_ci 25408c2ecf20Sopenharmony_ci /* Ensure the thread won't go into the kernel if it wakes */ 25418c2ecf20Sopenharmony_ci tpaca->kvm_hstate.kvm_vcpu = NULL; 25428c2ecf20Sopenharmony_ci tpaca->kvm_hstate.kvm_vcore = NULL; 25438c2ecf20Sopenharmony_ci tpaca->kvm_hstate.napping = 0; 25448c2ecf20Sopenharmony_ci smp_wmb(); 25458c2ecf20Sopenharmony_ci tpaca->kvm_hstate.hwthread_req = 1; 25468c2ecf20Sopenharmony_ci 25478c2ecf20Sopenharmony_ci /* 25488c2ecf20Sopenharmony_ci * If the thread is already executing in the kernel (e.g. handling 25498c2ecf20Sopenharmony_ci * a stray interrupt), wait for it to get back to nap mode. 25508c2ecf20Sopenharmony_ci * The smp_mb() is to ensure that our setting of hwthread_req 25518c2ecf20Sopenharmony_ci * is visible before we look at hwthread_state, so if this 25528c2ecf20Sopenharmony_ci * races with the code at system_reset_pSeries and the thread 25538c2ecf20Sopenharmony_ci * misses our setting of hwthread_req, we are sure to see its 25548c2ecf20Sopenharmony_ci * setting of hwthread_state, and vice versa. 25558c2ecf20Sopenharmony_ci */ 25568c2ecf20Sopenharmony_ci smp_mb(); 25578c2ecf20Sopenharmony_ci while (tpaca->kvm_hstate.hwthread_state == KVM_HWTHREAD_IN_KERNEL) { 25588c2ecf20Sopenharmony_ci if (--timeout <= 0) { 25598c2ecf20Sopenharmony_ci pr_err("KVM: couldn't grab cpu %d\n", cpu); 25608c2ecf20Sopenharmony_ci return -EBUSY; 25618c2ecf20Sopenharmony_ci } 25628c2ecf20Sopenharmony_ci udelay(1); 25638c2ecf20Sopenharmony_ci } 25648c2ecf20Sopenharmony_ci return 0; 25658c2ecf20Sopenharmony_ci} 25668c2ecf20Sopenharmony_ci 25678c2ecf20Sopenharmony_cistatic void kvmppc_release_hwthread(int cpu) 25688c2ecf20Sopenharmony_ci{ 25698c2ecf20Sopenharmony_ci struct paca_struct *tpaca; 25708c2ecf20Sopenharmony_ci 25718c2ecf20Sopenharmony_ci tpaca = paca_ptrs[cpu]; 25728c2ecf20Sopenharmony_ci tpaca->kvm_hstate.hwthread_req = 0; 25738c2ecf20Sopenharmony_ci tpaca->kvm_hstate.kvm_vcpu = NULL; 25748c2ecf20Sopenharmony_ci tpaca->kvm_hstate.kvm_vcore = NULL; 25758c2ecf20Sopenharmony_ci tpaca->kvm_hstate.kvm_split_mode = NULL; 25768c2ecf20Sopenharmony_ci} 25778c2ecf20Sopenharmony_ci 25788c2ecf20Sopenharmony_cistatic void radix_flush_cpu(struct kvm *kvm, int cpu, struct kvm_vcpu *vcpu) 25798c2ecf20Sopenharmony_ci{ 25808c2ecf20Sopenharmony_ci struct kvm_nested_guest *nested = vcpu->arch.nested; 25818c2ecf20Sopenharmony_ci cpumask_t *cpu_in_guest; 25828c2ecf20Sopenharmony_ci int i; 25838c2ecf20Sopenharmony_ci 25848c2ecf20Sopenharmony_ci cpu = cpu_first_tlb_thread_sibling(cpu); 25858c2ecf20Sopenharmony_ci if (nested) { 25868c2ecf20Sopenharmony_ci cpumask_set_cpu(cpu, &nested->need_tlb_flush); 25878c2ecf20Sopenharmony_ci cpu_in_guest = &nested->cpu_in_guest; 25888c2ecf20Sopenharmony_ci } else { 25898c2ecf20Sopenharmony_ci cpumask_set_cpu(cpu, &kvm->arch.need_tlb_flush); 25908c2ecf20Sopenharmony_ci cpu_in_guest = &kvm->arch.cpu_in_guest; 25918c2ecf20Sopenharmony_ci } 25928c2ecf20Sopenharmony_ci /* 25938c2ecf20Sopenharmony_ci * Make sure setting of bit in need_tlb_flush precedes 25948c2ecf20Sopenharmony_ci * testing of cpu_in_guest bits. The matching barrier on 25958c2ecf20Sopenharmony_ci * the other side is the first smp_mb() in kvmppc_run_core(). 25968c2ecf20Sopenharmony_ci */ 25978c2ecf20Sopenharmony_ci smp_mb(); 25988c2ecf20Sopenharmony_ci for (i = cpu; i <= cpu_last_tlb_thread_sibling(cpu); 25998c2ecf20Sopenharmony_ci i += cpu_tlb_thread_sibling_step()) 26008c2ecf20Sopenharmony_ci if (cpumask_test_cpu(i, cpu_in_guest)) 26018c2ecf20Sopenharmony_ci smp_call_function_single(i, do_nothing, NULL, 1); 26028c2ecf20Sopenharmony_ci} 26038c2ecf20Sopenharmony_ci 26048c2ecf20Sopenharmony_cistatic void kvmppc_prepare_radix_vcpu(struct kvm_vcpu *vcpu, int pcpu) 26058c2ecf20Sopenharmony_ci{ 26068c2ecf20Sopenharmony_ci struct kvm_nested_guest *nested = vcpu->arch.nested; 26078c2ecf20Sopenharmony_ci struct kvm *kvm = vcpu->kvm; 26088c2ecf20Sopenharmony_ci int prev_cpu; 26098c2ecf20Sopenharmony_ci 26108c2ecf20Sopenharmony_ci if (!cpu_has_feature(CPU_FTR_HVMODE)) 26118c2ecf20Sopenharmony_ci return; 26128c2ecf20Sopenharmony_ci 26138c2ecf20Sopenharmony_ci if (nested) 26148c2ecf20Sopenharmony_ci prev_cpu = nested->prev_cpu[vcpu->arch.nested_vcpu_id]; 26158c2ecf20Sopenharmony_ci else 26168c2ecf20Sopenharmony_ci prev_cpu = vcpu->arch.prev_cpu; 26178c2ecf20Sopenharmony_ci 26188c2ecf20Sopenharmony_ci /* 26198c2ecf20Sopenharmony_ci * With radix, the guest can do TLB invalidations itself, 26208c2ecf20Sopenharmony_ci * and it could choose to use the local form (tlbiel) if 26218c2ecf20Sopenharmony_ci * it is invalidating a translation that has only ever been 26228c2ecf20Sopenharmony_ci * used on one vcpu. However, that doesn't mean it has 26238c2ecf20Sopenharmony_ci * only ever been used on one physical cpu, since vcpus 26248c2ecf20Sopenharmony_ci * can move around between pcpus. To cope with this, when 26258c2ecf20Sopenharmony_ci * a vcpu moves from one pcpu to another, we need to tell 26268c2ecf20Sopenharmony_ci * any vcpus running on the same core as this vcpu previously 26278c2ecf20Sopenharmony_ci * ran to flush the TLB. The TLB is shared between threads, 26288c2ecf20Sopenharmony_ci * so we use a single bit in .need_tlb_flush for all 4 threads. 26298c2ecf20Sopenharmony_ci */ 26308c2ecf20Sopenharmony_ci if (prev_cpu != pcpu) { 26318c2ecf20Sopenharmony_ci if (prev_cpu >= 0 && 26328c2ecf20Sopenharmony_ci cpu_first_tlb_thread_sibling(prev_cpu) != 26338c2ecf20Sopenharmony_ci cpu_first_tlb_thread_sibling(pcpu)) 26348c2ecf20Sopenharmony_ci radix_flush_cpu(kvm, prev_cpu, vcpu); 26358c2ecf20Sopenharmony_ci if (nested) 26368c2ecf20Sopenharmony_ci nested->prev_cpu[vcpu->arch.nested_vcpu_id] = pcpu; 26378c2ecf20Sopenharmony_ci else 26388c2ecf20Sopenharmony_ci vcpu->arch.prev_cpu = pcpu; 26398c2ecf20Sopenharmony_ci } 26408c2ecf20Sopenharmony_ci} 26418c2ecf20Sopenharmony_ci 26428c2ecf20Sopenharmony_cistatic void kvmppc_start_thread(struct kvm_vcpu *vcpu, struct kvmppc_vcore *vc) 26438c2ecf20Sopenharmony_ci{ 26448c2ecf20Sopenharmony_ci int cpu; 26458c2ecf20Sopenharmony_ci struct paca_struct *tpaca; 26468c2ecf20Sopenharmony_ci struct kvm *kvm = vc->kvm; 26478c2ecf20Sopenharmony_ci 26488c2ecf20Sopenharmony_ci cpu = vc->pcpu; 26498c2ecf20Sopenharmony_ci if (vcpu) { 26508c2ecf20Sopenharmony_ci if (vcpu->arch.timer_running) { 26518c2ecf20Sopenharmony_ci hrtimer_try_to_cancel(&vcpu->arch.dec_timer); 26528c2ecf20Sopenharmony_ci vcpu->arch.timer_running = 0; 26538c2ecf20Sopenharmony_ci } 26548c2ecf20Sopenharmony_ci cpu += vcpu->arch.ptid; 26558c2ecf20Sopenharmony_ci vcpu->cpu = vc->pcpu; 26568c2ecf20Sopenharmony_ci vcpu->arch.thread_cpu = cpu; 26578c2ecf20Sopenharmony_ci cpumask_set_cpu(cpu, &kvm->arch.cpu_in_guest); 26588c2ecf20Sopenharmony_ci } 26598c2ecf20Sopenharmony_ci tpaca = paca_ptrs[cpu]; 26608c2ecf20Sopenharmony_ci tpaca->kvm_hstate.kvm_vcpu = vcpu; 26618c2ecf20Sopenharmony_ci tpaca->kvm_hstate.ptid = cpu - vc->pcpu; 26628c2ecf20Sopenharmony_ci tpaca->kvm_hstate.fake_suspend = 0; 26638c2ecf20Sopenharmony_ci /* Order stores to hstate.kvm_vcpu etc. before store to kvm_vcore */ 26648c2ecf20Sopenharmony_ci smp_wmb(); 26658c2ecf20Sopenharmony_ci tpaca->kvm_hstate.kvm_vcore = vc; 26668c2ecf20Sopenharmony_ci if (cpu != smp_processor_id()) 26678c2ecf20Sopenharmony_ci kvmppc_ipi_thread(cpu); 26688c2ecf20Sopenharmony_ci} 26698c2ecf20Sopenharmony_ci 26708c2ecf20Sopenharmony_cistatic void kvmppc_wait_for_nap(int n_threads) 26718c2ecf20Sopenharmony_ci{ 26728c2ecf20Sopenharmony_ci int cpu = smp_processor_id(); 26738c2ecf20Sopenharmony_ci int i, loops; 26748c2ecf20Sopenharmony_ci 26758c2ecf20Sopenharmony_ci if (n_threads <= 1) 26768c2ecf20Sopenharmony_ci return; 26778c2ecf20Sopenharmony_ci for (loops = 0; loops < 1000000; ++loops) { 26788c2ecf20Sopenharmony_ci /* 26798c2ecf20Sopenharmony_ci * Check if all threads are finished. 26808c2ecf20Sopenharmony_ci * We set the vcore pointer when starting a thread 26818c2ecf20Sopenharmony_ci * and the thread clears it when finished, so we look 26828c2ecf20Sopenharmony_ci * for any threads that still have a non-NULL vcore ptr. 26838c2ecf20Sopenharmony_ci */ 26848c2ecf20Sopenharmony_ci for (i = 1; i < n_threads; ++i) 26858c2ecf20Sopenharmony_ci if (paca_ptrs[cpu + i]->kvm_hstate.kvm_vcore) 26868c2ecf20Sopenharmony_ci break; 26878c2ecf20Sopenharmony_ci if (i == n_threads) { 26888c2ecf20Sopenharmony_ci HMT_medium(); 26898c2ecf20Sopenharmony_ci return; 26908c2ecf20Sopenharmony_ci } 26918c2ecf20Sopenharmony_ci HMT_low(); 26928c2ecf20Sopenharmony_ci } 26938c2ecf20Sopenharmony_ci HMT_medium(); 26948c2ecf20Sopenharmony_ci for (i = 1; i < n_threads; ++i) 26958c2ecf20Sopenharmony_ci if (paca_ptrs[cpu + i]->kvm_hstate.kvm_vcore) 26968c2ecf20Sopenharmony_ci pr_err("KVM: CPU %d seems to be stuck\n", cpu + i); 26978c2ecf20Sopenharmony_ci} 26988c2ecf20Sopenharmony_ci 26998c2ecf20Sopenharmony_ci/* 27008c2ecf20Sopenharmony_ci * Check that we are on thread 0 and that any other threads in 27018c2ecf20Sopenharmony_ci * this core are off-line. Then grab the threads so they can't 27028c2ecf20Sopenharmony_ci * enter the kernel. 27038c2ecf20Sopenharmony_ci */ 27048c2ecf20Sopenharmony_cistatic int on_primary_thread(void) 27058c2ecf20Sopenharmony_ci{ 27068c2ecf20Sopenharmony_ci int cpu = smp_processor_id(); 27078c2ecf20Sopenharmony_ci int thr; 27088c2ecf20Sopenharmony_ci 27098c2ecf20Sopenharmony_ci /* Are we on a primary subcore? */ 27108c2ecf20Sopenharmony_ci if (cpu_thread_in_subcore(cpu)) 27118c2ecf20Sopenharmony_ci return 0; 27128c2ecf20Sopenharmony_ci 27138c2ecf20Sopenharmony_ci thr = 0; 27148c2ecf20Sopenharmony_ci while (++thr < threads_per_subcore) 27158c2ecf20Sopenharmony_ci if (cpu_online(cpu + thr)) 27168c2ecf20Sopenharmony_ci return 0; 27178c2ecf20Sopenharmony_ci 27188c2ecf20Sopenharmony_ci /* Grab all hw threads so they can't go into the kernel */ 27198c2ecf20Sopenharmony_ci for (thr = 1; thr < threads_per_subcore; ++thr) { 27208c2ecf20Sopenharmony_ci if (kvmppc_grab_hwthread(cpu + thr)) { 27218c2ecf20Sopenharmony_ci /* Couldn't grab one; let the others go */ 27228c2ecf20Sopenharmony_ci do { 27238c2ecf20Sopenharmony_ci kvmppc_release_hwthread(cpu + thr); 27248c2ecf20Sopenharmony_ci } while (--thr > 0); 27258c2ecf20Sopenharmony_ci return 0; 27268c2ecf20Sopenharmony_ci } 27278c2ecf20Sopenharmony_ci } 27288c2ecf20Sopenharmony_ci return 1; 27298c2ecf20Sopenharmony_ci} 27308c2ecf20Sopenharmony_ci 27318c2ecf20Sopenharmony_ci/* 27328c2ecf20Sopenharmony_ci * A list of virtual cores for each physical CPU. 27338c2ecf20Sopenharmony_ci * These are vcores that could run but their runner VCPU tasks are 27348c2ecf20Sopenharmony_ci * (or may be) preempted. 27358c2ecf20Sopenharmony_ci */ 27368c2ecf20Sopenharmony_cistruct preempted_vcore_list { 27378c2ecf20Sopenharmony_ci struct list_head list; 27388c2ecf20Sopenharmony_ci spinlock_t lock; 27398c2ecf20Sopenharmony_ci}; 27408c2ecf20Sopenharmony_ci 27418c2ecf20Sopenharmony_cistatic DEFINE_PER_CPU(struct preempted_vcore_list, preempted_vcores); 27428c2ecf20Sopenharmony_ci 27438c2ecf20Sopenharmony_cistatic void init_vcore_lists(void) 27448c2ecf20Sopenharmony_ci{ 27458c2ecf20Sopenharmony_ci int cpu; 27468c2ecf20Sopenharmony_ci 27478c2ecf20Sopenharmony_ci for_each_possible_cpu(cpu) { 27488c2ecf20Sopenharmony_ci struct preempted_vcore_list *lp = &per_cpu(preempted_vcores, cpu); 27498c2ecf20Sopenharmony_ci spin_lock_init(&lp->lock); 27508c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&lp->list); 27518c2ecf20Sopenharmony_ci } 27528c2ecf20Sopenharmony_ci} 27538c2ecf20Sopenharmony_ci 27548c2ecf20Sopenharmony_cistatic void kvmppc_vcore_preempt(struct kvmppc_vcore *vc) 27558c2ecf20Sopenharmony_ci{ 27568c2ecf20Sopenharmony_ci struct preempted_vcore_list *lp = this_cpu_ptr(&preempted_vcores); 27578c2ecf20Sopenharmony_ci 27588c2ecf20Sopenharmony_ci vc->vcore_state = VCORE_PREEMPT; 27598c2ecf20Sopenharmony_ci vc->pcpu = smp_processor_id(); 27608c2ecf20Sopenharmony_ci if (vc->num_threads < threads_per_vcore(vc->kvm)) { 27618c2ecf20Sopenharmony_ci spin_lock(&lp->lock); 27628c2ecf20Sopenharmony_ci list_add_tail(&vc->preempt_list, &lp->list); 27638c2ecf20Sopenharmony_ci spin_unlock(&lp->lock); 27648c2ecf20Sopenharmony_ci } 27658c2ecf20Sopenharmony_ci 27668c2ecf20Sopenharmony_ci /* Start accumulating stolen time */ 27678c2ecf20Sopenharmony_ci kvmppc_core_start_stolen(vc); 27688c2ecf20Sopenharmony_ci} 27698c2ecf20Sopenharmony_ci 27708c2ecf20Sopenharmony_cistatic void kvmppc_vcore_end_preempt(struct kvmppc_vcore *vc) 27718c2ecf20Sopenharmony_ci{ 27728c2ecf20Sopenharmony_ci struct preempted_vcore_list *lp; 27738c2ecf20Sopenharmony_ci 27748c2ecf20Sopenharmony_ci kvmppc_core_end_stolen(vc); 27758c2ecf20Sopenharmony_ci if (!list_empty(&vc->preempt_list)) { 27768c2ecf20Sopenharmony_ci lp = &per_cpu(preempted_vcores, vc->pcpu); 27778c2ecf20Sopenharmony_ci spin_lock(&lp->lock); 27788c2ecf20Sopenharmony_ci list_del_init(&vc->preempt_list); 27798c2ecf20Sopenharmony_ci spin_unlock(&lp->lock); 27808c2ecf20Sopenharmony_ci } 27818c2ecf20Sopenharmony_ci vc->vcore_state = VCORE_INACTIVE; 27828c2ecf20Sopenharmony_ci} 27838c2ecf20Sopenharmony_ci 27848c2ecf20Sopenharmony_ci/* 27858c2ecf20Sopenharmony_ci * This stores information about the virtual cores currently 27868c2ecf20Sopenharmony_ci * assigned to a physical core. 27878c2ecf20Sopenharmony_ci */ 27888c2ecf20Sopenharmony_cistruct core_info { 27898c2ecf20Sopenharmony_ci int n_subcores; 27908c2ecf20Sopenharmony_ci int max_subcore_threads; 27918c2ecf20Sopenharmony_ci int total_threads; 27928c2ecf20Sopenharmony_ci int subcore_threads[MAX_SUBCORES]; 27938c2ecf20Sopenharmony_ci struct kvmppc_vcore *vc[MAX_SUBCORES]; 27948c2ecf20Sopenharmony_ci}; 27958c2ecf20Sopenharmony_ci 27968c2ecf20Sopenharmony_ci/* 27978c2ecf20Sopenharmony_ci * This mapping means subcores 0 and 1 can use threads 0-3 and 4-7 27988c2ecf20Sopenharmony_ci * respectively in 2-way micro-threading (split-core) mode on POWER8. 27998c2ecf20Sopenharmony_ci */ 28008c2ecf20Sopenharmony_cistatic int subcore_thread_map[MAX_SUBCORES] = { 0, 4, 2, 6 }; 28018c2ecf20Sopenharmony_ci 28028c2ecf20Sopenharmony_cistatic void init_core_info(struct core_info *cip, struct kvmppc_vcore *vc) 28038c2ecf20Sopenharmony_ci{ 28048c2ecf20Sopenharmony_ci memset(cip, 0, sizeof(*cip)); 28058c2ecf20Sopenharmony_ci cip->n_subcores = 1; 28068c2ecf20Sopenharmony_ci cip->max_subcore_threads = vc->num_threads; 28078c2ecf20Sopenharmony_ci cip->total_threads = vc->num_threads; 28088c2ecf20Sopenharmony_ci cip->subcore_threads[0] = vc->num_threads; 28098c2ecf20Sopenharmony_ci cip->vc[0] = vc; 28108c2ecf20Sopenharmony_ci} 28118c2ecf20Sopenharmony_ci 28128c2ecf20Sopenharmony_cistatic bool subcore_config_ok(int n_subcores, int n_threads) 28138c2ecf20Sopenharmony_ci{ 28148c2ecf20Sopenharmony_ci /* 28158c2ecf20Sopenharmony_ci * POWER9 "SMT4" cores are permanently in what is effectively a 4-way 28168c2ecf20Sopenharmony_ci * split-core mode, with one thread per subcore. 28178c2ecf20Sopenharmony_ci */ 28188c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_300)) 28198c2ecf20Sopenharmony_ci return n_subcores <= 4 && n_threads == 1; 28208c2ecf20Sopenharmony_ci 28218c2ecf20Sopenharmony_ci /* On POWER8, can only dynamically split if unsplit to begin with */ 28228c2ecf20Sopenharmony_ci if (n_subcores > 1 && threads_per_subcore < MAX_SMT_THREADS) 28238c2ecf20Sopenharmony_ci return false; 28248c2ecf20Sopenharmony_ci if (n_subcores > MAX_SUBCORES) 28258c2ecf20Sopenharmony_ci return false; 28268c2ecf20Sopenharmony_ci if (n_subcores > 1) { 28278c2ecf20Sopenharmony_ci if (!(dynamic_mt_modes & 2)) 28288c2ecf20Sopenharmony_ci n_subcores = 4; 28298c2ecf20Sopenharmony_ci if (n_subcores > 2 && !(dynamic_mt_modes & 4)) 28308c2ecf20Sopenharmony_ci return false; 28318c2ecf20Sopenharmony_ci } 28328c2ecf20Sopenharmony_ci 28338c2ecf20Sopenharmony_ci return n_subcores * roundup_pow_of_two(n_threads) <= MAX_SMT_THREADS; 28348c2ecf20Sopenharmony_ci} 28358c2ecf20Sopenharmony_ci 28368c2ecf20Sopenharmony_cistatic void init_vcore_to_run(struct kvmppc_vcore *vc) 28378c2ecf20Sopenharmony_ci{ 28388c2ecf20Sopenharmony_ci vc->entry_exit_map = 0; 28398c2ecf20Sopenharmony_ci vc->in_guest = 0; 28408c2ecf20Sopenharmony_ci vc->napping_threads = 0; 28418c2ecf20Sopenharmony_ci vc->conferring_threads = 0; 28428c2ecf20Sopenharmony_ci vc->tb_offset_applied = 0; 28438c2ecf20Sopenharmony_ci} 28448c2ecf20Sopenharmony_ci 28458c2ecf20Sopenharmony_cistatic bool can_dynamic_split(struct kvmppc_vcore *vc, struct core_info *cip) 28468c2ecf20Sopenharmony_ci{ 28478c2ecf20Sopenharmony_ci int n_threads = vc->num_threads; 28488c2ecf20Sopenharmony_ci int sub; 28498c2ecf20Sopenharmony_ci 28508c2ecf20Sopenharmony_ci if (!cpu_has_feature(CPU_FTR_ARCH_207S)) 28518c2ecf20Sopenharmony_ci return false; 28528c2ecf20Sopenharmony_ci 28538c2ecf20Sopenharmony_ci /* In one_vm_per_core mode, require all vcores to be from the same vm */ 28548c2ecf20Sopenharmony_ci if (one_vm_per_core && vc->kvm != cip->vc[0]->kvm) 28558c2ecf20Sopenharmony_ci return false; 28568c2ecf20Sopenharmony_ci 28578c2ecf20Sopenharmony_ci /* Some POWER9 chips require all threads to be in the same MMU mode */ 28588c2ecf20Sopenharmony_ci if (no_mixing_hpt_and_radix && 28598c2ecf20Sopenharmony_ci kvm_is_radix(vc->kvm) != kvm_is_radix(cip->vc[0]->kvm)) 28608c2ecf20Sopenharmony_ci return false; 28618c2ecf20Sopenharmony_ci 28628c2ecf20Sopenharmony_ci if (n_threads < cip->max_subcore_threads) 28638c2ecf20Sopenharmony_ci n_threads = cip->max_subcore_threads; 28648c2ecf20Sopenharmony_ci if (!subcore_config_ok(cip->n_subcores + 1, n_threads)) 28658c2ecf20Sopenharmony_ci return false; 28668c2ecf20Sopenharmony_ci cip->max_subcore_threads = n_threads; 28678c2ecf20Sopenharmony_ci 28688c2ecf20Sopenharmony_ci sub = cip->n_subcores; 28698c2ecf20Sopenharmony_ci ++cip->n_subcores; 28708c2ecf20Sopenharmony_ci cip->total_threads += vc->num_threads; 28718c2ecf20Sopenharmony_ci cip->subcore_threads[sub] = vc->num_threads; 28728c2ecf20Sopenharmony_ci cip->vc[sub] = vc; 28738c2ecf20Sopenharmony_ci init_vcore_to_run(vc); 28748c2ecf20Sopenharmony_ci list_del_init(&vc->preempt_list); 28758c2ecf20Sopenharmony_ci 28768c2ecf20Sopenharmony_ci return true; 28778c2ecf20Sopenharmony_ci} 28788c2ecf20Sopenharmony_ci 28798c2ecf20Sopenharmony_ci/* 28808c2ecf20Sopenharmony_ci * Work out whether it is possible to piggyback the execution of 28818c2ecf20Sopenharmony_ci * vcore *pvc onto the execution of the other vcores described in *cip. 28828c2ecf20Sopenharmony_ci */ 28838c2ecf20Sopenharmony_cistatic bool can_piggyback(struct kvmppc_vcore *pvc, struct core_info *cip, 28848c2ecf20Sopenharmony_ci int target_threads) 28858c2ecf20Sopenharmony_ci{ 28868c2ecf20Sopenharmony_ci if (cip->total_threads + pvc->num_threads > target_threads) 28878c2ecf20Sopenharmony_ci return false; 28888c2ecf20Sopenharmony_ci 28898c2ecf20Sopenharmony_ci return can_dynamic_split(pvc, cip); 28908c2ecf20Sopenharmony_ci} 28918c2ecf20Sopenharmony_ci 28928c2ecf20Sopenharmony_cistatic void prepare_threads(struct kvmppc_vcore *vc) 28938c2ecf20Sopenharmony_ci{ 28948c2ecf20Sopenharmony_ci int i; 28958c2ecf20Sopenharmony_ci struct kvm_vcpu *vcpu; 28968c2ecf20Sopenharmony_ci 28978c2ecf20Sopenharmony_ci for_each_runnable_thread(i, vcpu, vc) { 28988c2ecf20Sopenharmony_ci if (signal_pending(vcpu->arch.run_task)) 28998c2ecf20Sopenharmony_ci vcpu->arch.ret = -EINTR; 29008c2ecf20Sopenharmony_ci else if (vcpu->arch.vpa.update_pending || 29018c2ecf20Sopenharmony_ci vcpu->arch.slb_shadow.update_pending || 29028c2ecf20Sopenharmony_ci vcpu->arch.dtl.update_pending) 29038c2ecf20Sopenharmony_ci vcpu->arch.ret = RESUME_GUEST; 29048c2ecf20Sopenharmony_ci else 29058c2ecf20Sopenharmony_ci continue; 29068c2ecf20Sopenharmony_ci kvmppc_remove_runnable(vc, vcpu); 29078c2ecf20Sopenharmony_ci wake_up(&vcpu->arch.cpu_run); 29088c2ecf20Sopenharmony_ci } 29098c2ecf20Sopenharmony_ci} 29108c2ecf20Sopenharmony_ci 29118c2ecf20Sopenharmony_cistatic void collect_piggybacks(struct core_info *cip, int target_threads) 29128c2ecf20Sopenharmony_ci{ 29138c2ecf20Sopenharmony_ci struct preempted_vcore_list *lp = this_cpu_ptr(&preempted_vcores); 29148c2ecf20Sopenharmony_ci struct kvmppc_vcore *pvc, *vcnext; 29158c2ecf20Sopenharmony_ci 29168c2ecf20Sopenharmony_ci spin_lock(&lp->lock); 29178c2ecf20Sopenharmony_ci list_for_each_entry_safe(pvc, vcnext, &lp->list, preempt_list) { 29188c2ecf20Sopenharmony_ci if (!spin_trylock(&pvc->lock)) 29198c2ecf20Sopenharmony_ci continue; 29208c2ecf20Sopenharmony_ci prepare_threads(pvc); 29218c2ecf20Sopenharmony_ci if (!pvc->n_runnable || !pvc->kvm->arch.mmu_ready) { 29228c2ecf20Sopenharmony_ci list_del_init(&pvc->preempt_list); 29238c2ecf20Sopenharmony_ci if (pvc->runner == NULL) { 29248c2ecf20Sopenharmony_ci pvc->vcore_state = VCORE_INACTIVE; 29258c2ecf20Sopenharmony_ci kvmppc_core_end_stolen(pvc); 29268c2ecf20Sopenharmony_ci } 29278c2ecf20Sopenharmony_ci spin_unlock(&pvc->lock); 29288c2ecf20Sopenharmony_ci continue; 29298c2ecf20Sopenharmony_ci } 29308c2ecf20Sopenharmony_ci if (!can_piggyback(pvc, cip, target_threads)) { 29318c2ecf20Sopenharmony_ci spin_unlock(&pvc->lock); 29328c2ecf20Sopenharmony_ci continue; 29338c2ecf20Sopenharmony_ci } 29348c2ecf20Sopenharmony_ci kvmppc_core_end_stolen(pvc); 29358c2ecf20Sopenharmony_ci pvc->vcore_state = VCORE_PIGGYBACK; 29368c2ecf20Sopenharmony_ci if (cip->total_threads >= target_threads) 29378c2ecf20Sopenharmony_ci break; 29388c2ecf20Sopenharmony_ci } 29398c2ecf20Sopenharmony_ci spin_unlock(&lp->lock); 29408c2ecf20Sopenharmony_ci} 29418c2ecf20Sopenharmony_ci 29428c2ecf20Sopenharmony_cistatic bool recheck_signals_and_mmu(struct core_info *cip) 29438c2ecf20Sopenharmony_ci{ 29448c2ecf20Sopenharmony_ci int sub, i; 29458c2ecf20Sopenharmony_ci struct kvm_vcpu *vcpu; 29468c2ecf20Sopenharmony_ci struct kvmppc_vcore *vc; 29478c2ecf20Sopenharmony_ci 29488c2ecf20Sopenharmony_ci for (sub = 0; sub < cip->n_subcores; ++sub) { 29498c2ecf20Sopenharmony_ci vc = cip->vc[sub]; 29508c2ecf20Sopenharmony_ci if (!vc->kvm->arch.mmu_ready) 29518c2ecf20Sopenharmony_ci return true; 29528c2ecf20Sopenharmony_ci for_each_runnable_thread(i, vcpu, vc) 29538c2ecf20Sopenharmony_ci if (signal_pending(vcpu->arch.run_task)) 29548c2ecf20Sopenharmony_ci return true; 29558c2ecf20Sopenharmony_ci } 29568c2ecf20Sopenharmony_ci return false; 29578c2ecf20Sopenharmony_ci} 29588c2ecf20Sopenharmony_ci 29598c2ecf20Sopenharmony_cistatic void post_guest_process(struct kvmppc_vcore *vc, bool is_master) 29608c2ecf20Sopenharmony_ci{ 29618c2ecf20Sopenharmony_ci int still_running = 0, i; 29628c2ecf20Sopenharmony_ci u64 now; 29638c2ecf20Sopenharmony_ci long ret; 29648c2ecf20Sopenharmony_ci struct kvm_vcpu *vcpu; 29658c2ecf20Sopenharmony_ci 29668c2ecf20Sopenharmony_ci spin_lock(&vc->lock); 29678c2ecf20Sopenharmony_ci now = get_tb(); 29688c2ecf20Sopenharmony_ci for_each_runnable_thread(i, vcpu, vc) { 29698c2ecf20Sopenharmony_ci /* 29708c2ecf20Sopenharmony_ci * It's safe to unlock the vcore in the loop here, because 29718c2ecf20Sopenharmony_ci * for_each_runnable_thread() is safe against removal of 29728c2ecf20Sopenharmony_ci * the vcpu, and the vcore state is VCORE_EXITING here, 29738c2ecf20Sopenharmony_ci * so any vcpus becoming runnable will have their arch.trap 29748c2ecf20Sopenharmony_ci * set to zero and can't actually run in the guest. 29758c2ecf20Sopenharmony_ci */ 29768c2ecf20Sopenharmony_ci spin_unlock(&vc->lock); 29778c2ecf20Sopenharmony_ci /* cancel pending dec exception if dec is positive */ 29788c2ecf20Sopenharmony_ci if (now < vcpu->arch.dec_expires && 29798c2ecf20Sopenharmony_ci kvmppc_core_pending_dec(vcpu)) 29808c2ecf20Sopenharmony_ci kvmppc_core_dequeue_dec(vcpu); 29818c2ecf20Sopenharmony_ci 29828c2ecf20Sopenharmony_ci trace_kvm_guest_exit(vcpu); 29838c2ecf20Sopenharmony_ci 29848c2ecf20Sopenharmony_ci ret = RESUME_GUEST; 29858c2ecf20Sopenharmony_ci if (vcpu->arch.trap) 29868c2ecf20Sopenharmony_ci ret = kvmppc_handle_exit_hv(vcpu, 29878c2ecf20Sopenharmony_ci vcpu->arch.run_task); 29888c2ecf20Sopenharmony_ci 29898c2ecf20Sopenharmony_ci vcpu->arch.ret = ret; 29908c2ecf20Sopenharmony_ci vcpu->arch.trap = 0; 29918c2ecf20Sopenharmony_ci 29928c2ecf20Sopenharmony_ci spin_lock(&vc->lock); 29938c2ecf20Sopenharmony_ci if (is_kvmppc_resume_guest(vcpu->arch.ret)) { 29948c2ecf20Sopenharmony_ci if (vcpu->arch.pending_exceptions) 29958c2ecf20Sopenharmony_ci kvmppc_core_prepare_to_enter(vcpu); 29968c2ecf20Sopenharmony_ci if (vcpu->arch.ceded) 29978c2ecf20Sopenharmony_ci kvmppc_set_timer(vcpu); 29988c2ecf20Sopenharmony_ci else 29998c2ecf20Sopenharmony_ci ++still_running; 30008c2ecf20Sopenharmony_ci } else { 30018c2ecf20Sopenharmony_ci kvmppc_remove_runnable(vc, vcpu); 30028c2ecf20Sopenharmony_ci wake_up(&vcpu->arch.cpu_run); 30038c2ecf20Sopenharmony_ci } 30048c2ecf20Sopenharmony_ci } 30058c2ecf20Sopenharmony_ci if (!is_master) { 30068c2ecf20Sopenharmony_ci if (still_running > 0) { 30078c2ecf20Sopenharmony_ci kvmppc_vcore_preempt(vc); 30088c2ecf20Sopenharmony_ci } else if (vc->runner) { 30098c2ecf20Sopenharmony_ci vc->vcore_state = VCORE_PREEMPT; 30108c2ecf20Sopenharmony_ci kvmppc_core_start_stolen(vc); 30118c2ecf20Sopenharmony_ci } else { 30128c2ecf20Sopenharmony_ci vc->vcore_state = VCORE_INACTIVE; 30138c2ecf20Sopenharmony_ci } 30148c2ecf20Sopenharmony_ci if (vc->n_runnable > 0 && vc->runner == NULL) { 30158c2ecf20Sopenharmony_ci /* make sure there's a candidate runner awake */ 30168c2ecf20Sopenharmony_ci i = -1; 30178c2ecf20Sopenharmony_ci vcpu = next_runnable_thread(vc, &i); 30188c2ecf20Sopenharmony_ci wake_up(&vcpu->arch.cpu_run); 30198c2ecf20Sopenharmony_ci } 30208c2ecf20Sopenharmony_ci } 30218c2ecf20Sopenharmony_ci spin_unlock(&vc->lock); 30228c2ecf20Sopenharmony_ci} 30238c2ecf20Sopenharmony_ci 30248c2ecf20Sopenharmony_ci/* 30258c2ecf20Sopenharmony_ci * Clear core from the list of active host cores as we are about to 30268c2ecf20Sopenharmony_ci * enter the guest. Only do this if it is the primary thread of the 30278c2ecf20Sopenharmony_ci * core (not if a subcore) that is entering the guest. 30288c2ecf20Sopenharmony_ci */ 30298c2ecf20Sopenharmony_cistatic inline int kvmppc_clear_host_core(unsigned int cpu) 30308c2ecf20Sopenharmony_ci{ 30318c2ecf20Sopenharmony_ci int core; 30328c2ecf20Sopenharmony_ci 30338c2ecf20Sopenharmony_ci if (!kvmppc_host_rm_ops_hv || cpu_thread_in_core(cpu)) 30348c2ecf20Sopenharmony_ci return 0; 30358c2ecf20Sopenharmony_ci /* 30368c2ecf20Sopenharmony_ci * Memory barrier can be omitted here as we will do a smp_wmb() 30378c2ecf20Sopenharmony_ci * later in kvmppc_start_thread and we need ensure that state is 30388c2ecf20Sopenharmony_ci * visible to other CPUs only after we enter guest. 30398c2ecf20Sopenharmony_ci */ 30408c2ecf20Sopenharmony_ci core = cpu >> threads_shift; 30418c2ecf20Sopenharmony_ci kvmppc_host_rm_ops_hv->rm_core[core].rm_state.in_host = 0; 30428c2ecf20Sopenharmony_ci return 0; 30438c2ecf20Sopenharmony_ci} 30448c2ecf20Sopenharmony_ci 30458c2ecf20Sopenharmony_ci/* 30468c2ecf20Sopenharmony_ci * Advertise this core as an active host core since we exited the guest 30478c2ecf20Sopenharmony_ci * Only need to do this if it is the primary thread of the core that is 30488c2ecf20Sopenharmony_ci * exiting. 30498c2ecf20Sopenharmony_ci */ 30508c2ecf20Sopenharmony_cistatic inline int kvmppc_set_host_core(unsigned int cpu) 30518c2ecf20Sopenharmony_ci{ 30528c2ecf20Sopenharmony_ci int core; 30538c2ecf20Sopenharmony_ci 30548c2ecf20Sopenharmony_ci if (!kvmppc_host_rm_ops_hv || cpu_thread_in_core(cpu)) 30558c2ecf20Sopenharmony_ci return 0; 30568c2ecf20Sopenharmony_ci 30578c2ecf20Sopenharmony_ci /* 30588c2ecf20Sopenharmony_ci * Memory barrier can be omitted here because we do a spin_unlock 30598c2ecf20Sopenharmony_ci * immediately after this which provides the memory barrier. 30608c2ecf20Sopenharmony_ci */ 30618c2ecf20Sopenharmony_ci core = cpu >> threads_shift; 30628c2ecf20Sopenharmony_ci kvmppc_host_rm_ops_hv->rm_core[core].rm_state.in_host = 1; 30638c2ecf20Sopenharmony_ci return 0; 30648c2ecf20Sopenharmony_ci} 30658c2ecf20Sopenharmony_ci 30668c2ecf20Sopenharmony_cistatic void set_irq_happened(int trap) 30678c2ecf20Sopenharmony_ci{ 30688c2ecf20Sopenharmony_ci switch (trap) { 30698c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_EXTERNAL: 30708c2ecf20Sopenharmony_ci local_paca->irq_happened |= PACA_IRQ_EE; 30718c2ecf20Sopenharmony_ci break; 30728c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_H_DOORBELL: 30738c2ecf20Sopenharmony_ci local_paca->irq_happened |= PACA_IRQ_DBELL; 30748c2ecf20Sopenharmony_ci break; 30758c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_HMI: 30768c2ecf20Sopenharmony_ci local_paca->irq_happened |= PACA_IRQ_HMI; 30778c2ecf20Sopenharmony_ci break; 30788c2ecf20Sopenharmony_ci case BOOK3S_INTERRUPT_SYSTEM_RESET: 30798c2ecf20Sopenharmony_ci replay_system_reset(); 30808c2ecf20Sopenharmony_ci break; 30818c2ecf20Sopenharmony_ci } 30828c2ecf20Sopenharmony_ci} 30838c2ecf20Sopenharmony_ci 30848c2ecf20Sopenharmony_ci/* 30858c2ecf20Sopenharmony_ci * Run a set of guest threads on a physical core. 30868c2ecf20Sopenharmony_ci * Called with vc->lock held. 30878c2ecf20Sopenharmony_ci */ 30888c2ecf20Sopenharmony_cistatic noinline void kvmppc_run_core(struct kvmppc_vcore *vc) 30898c2ecf20Sopenharmony_ci{ 30908c2ecf20Sopenharmony_ci struct kvm_vcpu *vcpu; 30918c2ecf20Sopenharmony_ci int i; 30928c2ecf20Sopenharmony_ci int srcu_idx; 30938c2ecf20Sopenharmony_ci struct core_info core_info; 30948c2ecf20Sopenharmony_ci struct kvmppc_vcore *pvc; 30958c2ecf20Sopenharmony_ci struct kvm_split_mode split_info, *sip; 30968c2ecf20Sopenharmony_ci int split, subcore_size, active; 30978c2ecf20Sopenharmony_ci int sub; 30988c2ecf20Sopenharmony_ci bool thr0_done; 30998c2ecf20Sopenharmony_ci unsigned long cmd_bit, stat_bit; 31008c2ecf20Sopenharmony_ci int pcpu, thr; 31018c2ecf20Sopenharmony_ci int target_threads; 31028c2ecf20Sopenharmony_ci int controlled_threads; 31038c2ecf20Sopenharmony_ci int trap; 31048c2ecf20Sopenharmony_ci bool is_power8; 31058c2ecf20Sopenharmony_ci bool hpt_on_radix; 31068c2ecf20Sopenharmony_ci 31078c2ecf20Sopenharmony_ci /* 31088c2ecf20Sopenharmony_ci * Remove from the list any threads that have a signal pending 31098c2ecf20Sopenharmony_ci * or need a VPA update done 31108c2ecf20Sopenharmony_ci */ 31118c2ecf20Sopenharmony_ci prepare_threads(vc); 31128c2ecf20Sopenharmony_ci 31138c2ecf20Sopenharmony_ci /* if the runner is no longer runnable, let the caller pick a new one */ 31148c2ecf20Sopenharmony_ci if (vc->runner->arch.state != KVMPPC_VCPU_RUNNABLE) 31158c2ecf20Sopenharmony_ci return; 31168c2ecf20Sopenharmony_ci 31178c2ecf20Sopenharmony_ci /* 31188c2ecf20Sopenharmony_ci * Initialize *vc. 31198c2ecf20Sopenharmony_ci */ 31208c2ecf20Sopenharmony_ci init_vcore_to_run(vc); 31218c2ecf20Sopenharmony_ci vc->preempt_tb = TB_NIL; 31228c2ecf20Sopenharmony_ci 31238c2ecf20Sopenharmony_ci /* 31248c2ecf20Sopenharmony_ci * Number of threads that we will be controlling: the same as 31258c2ecf20Sopenharmony_ci * the number of threads per subcore, except on POWER9, 31268c2ecf20Sopenharmony_ci * where it's 1 because the threads are (mostly) independent. 31278c2ecf20Sopenharmony_ci */ 31288c2ecf20Sopenharmony_ci controlled_threads = threads_per_vcore(vc->kvm); 31298c2ecf20Sopenharmony_ci 31308c2ecf20Sopenharmony_ci /* 31318c2ecf20Sopenharmony_ci * Make sure we are running on primary threads, and that secondary 31328c2ecf20Sopenharmony_ci * threads are offline. Also check if the number of threads in this 31338c2ecf20Sopenharmony_ci * guest are greater than the current system threads per guest. 31348c2ecf20Sopenharmony_ci * On POWER9, we need to be not in independent-threads mode if 31358c2ecf20Sopenharmony_ci * this is a HPT guest on a radix host machine where the 31368c2ecf20Sopenharmony_ci * CPU threads may not be in different MMU modes. 31378c2ecf20Sopenharmony_ci */ 31388c2ecf20Sopenharmony_ci hpt_on_radix = no_mixing_hpt_and_radix && radix_enabled() && 31398c2ecf20Sopenharmony_ci !kvm_is_radix(vc->kvm); 31408c2ecf20Sopenharmony_ci if (((controlled_threads > 1) && 31418c2ecf20Sopenharmony_ci ((vc->num_threads > threads_per_subcore) || !on_primary_thread())) || 31428c2ecf20Sopenharmony_ci (hpt_on_radix && vc->kvm->arch.threads_indep)) { 31438c2ecf20Sopenharmony_ci for_each_runnable_thread(i, vcpu, vc) { 31448c2ecf20Sopenharmony_ci vcpu->arch.ret = -EBUSY; 31458c2ecf20Sopenharmony_ci kvmppc_remove_runnable(vc, vcpu); 31468c2ecf20Sopenharmony_ci wake_up(&vcpu->arch.cpu_run); 31478c2ecf20Sopenharmony_ci } 31488c2ecf20Sopenharmony_ci goto out; 31498c2ecf20Sopenharmony_ci } 31508c2ecf20Sopenharmony_ci 31518c2ecf20Sopenharmony_ci /* 31528c2ecf20Sopenharmony_ci * See if we could run any other vcores on the physical core 31538c2ecf20Sopenharmony_ci * along with this one. 31548c2ecf20Sopenharmony_ci */ 31558c2ecf20Sopenharmony_ci init_core_info(&core_info, vc); 31568c2ecf20Sopenharmony_ci pcpu = smp_processor_id(); 31578c2ecf20Sopenharmony_ci target_threads = controlled_threads; 31588c2ecf20Sopenharmony_ci if (target_smt_mode && target_smt_mode < target_threads) 31598c2ecf20Sopenharmony_ci target_threads = target_smt_mode; 31608c2ecf20Sopenharmony_ci if (vc->num_threads < target_threads) 31618c2ecf20Sopenharmony_ci collect_piggybacks(&core_info, target_threads); 31628c2ecf20Sopenharmony_ci 31638c2ecf20Sopenharmony_ci /* 31648c2ecf20Sopenharmony_ci * On radix, arrange for TLB flushing if necessary. 31658c2ecf20Sopenharmony_ci * This has to be done before disabling interrupts since 31668c2ecf20Sopenharmony_ci * it uses smp_call_function(). 31678c2ecf20Sopenharmony_ci */ 31688c2ecf20Sopenharmony_ci pcpu = smp_processor_id(); 31698c2ecf20Sopenharmony_ci if (kvm_is_radix(vc->kvm)) { 31708c2ecf20Sopenharmony_ci for (sub = 0; sub < core_info.n_subcores; ++sub) 31718c2ecf20Sopenharmony_ci for_each_runnable_thread(i, vcpu, core_info.vc[sub]) 31728c2ecf20Sopenharmony_ci kvmppc_prepare_radix_vcpu(vcpu, pcpu); 31738c2ecf20Sopenharmony_ci } 31748c2ecf20Sopenharmony_ci 31758c2ecf20Sopenharmony_ci /* 31768c2ecf20Sopenharmony_ci * Hard-disable interrupts, and check resched flag and signals. 31778c2ecf20Sopenharmony_ci * If we need to reschedule or deliver a signal, clean up 31788c2ecf20Sopenharmony_ci * and return without going into the guest(s). 31798c2ecf20Sopenharmony_ci * If the mmu_ready flag has been cleared, don't go into the 31808c2ecf20Sopenharmony_ci * guest because that means a HPT resize operation is in progress. 31818c2ecf20Sopenharmony_ci */ 31828c2ecf20Sopenharmony_ci local_irq_disable(); 31838c2ecf20Sopenharmony_ci hard_irq_disable(); 31848c2ecf20Sopenharmony_ci if (lazy_irq_pending() || need_resched() || 31858c2ecf20Sopenharmony_ci recheck_signals_and_mmu(&core_info)) { 31868c2ecf20Sopenharmony_ci local_irq_enable(); 31878c2ecf20Sopenharmony_ci vc->vcore_state = VCORE_INACTIVE; 31888c2ecf20Sopenharmony_ci /* Unlock all except the primary vcore */ 31898c2ecf20Sopenharmony_ci for (sub = 1; sub < core_info.n_subcores; ++sub) { 31908c2ecf20Sopenharmony_ci pvc = core_info.vc[sub]; 31918c2ecf20Sopenharmony_ci /* Put back on to the preempted vcores list */ 31928c2ecf20Sopenharmony_ci kvmppc_vcore_preempt(pvc); 31938c2ecf20Sopenharmony_ci spin_unlock(&pvc->lock); 31948c2ecf20Sopenharmony_ci } 31958c2ecf20Sopenharmony_ci for (i = 0; i < controlled_threads; ++i) 31968c2ecf20Sopenharmony_ci kvmppc_release_hwthread(pcpu + i); 31978c2ecf20Sopenharmony_ci return; 31988c2ecf20Sopenharmony_ci } 31998c2ecf20Sopenharmony_ci 32008c2ecf20Sopenharmony_ci kvmppc_clear_host_core(pcpu); 32018c2ecf20Sopenharmony_ci 32028c2ecf20Sopenharmony_ci /* Decide on micro-threading (split-core) mode */ 32038c2ecf20Sopenharmony_ci subcore_size = threads_per_subcore; 32048c2ecf20Sopenharmony_ci cmd_bit = stat_bit = 0; 32058c2ecf20Sopenharmony_ci split = core_info.n_subcores; 32068c2ecf20Sopenharmony_ci sip = NULL; 32078c2ecf20Sopenharmony_ci is_power8 = cpu_has_feature(CPU_FTR_ARCH_207S) 32088c2ecf20Sopenharmony_ci && !cpu_has_feature(CPU_FTR_ARCH_300); 32098c2ecf20Sopenharmony_ci 32108c2ecf20Sopenharmony_ci if (split > 1 || hpt_on_radix) { 32118c2ecf20Sopenharmony_ci sip = &split_info; 32128c2ecf20Sopenharmony_ci memset(&split_info, 0, sizeof(split_info)); 32138c2ecf20Sopenharmony_ci for (sub = 0; sub < core_info.n_subcores; ++sub) 32148c2ecf20Sopenharmony_ci split_info.vc[sub] = core_info.vc[sub]; 32158c2ecf20Sopenharmony_ci 32168c2ecf20Sopenharmony_ci if (is_power8) { 32178c2ecf20Sopenharmony_ci if (split == 2 && (dynamic_mt_modes & 2)) { 32188c2ecf20Sopenharmony_ci cmd_bit = HID0_POWER8_1TO2LPAR; 32198c2ecf20Sopenharmony_ci stat_bit = HID0_POWER8_2LPARMODE; 32208c2ecf20Sopenharmony_ci } else { 32218c2ecf20Sopenharmony_ci split = 4; 32228c2ecf20Sopenharmony_ci cmd_bit = HID0_POWER8_1TO4LPAR; 32238c2ecf20Sopenharmony_ci stat_bit = HID0_POWER8_4LPARMODE; 32248c2ecf20Sopenharmony_ci } 32258c2ecf20Sopenharmony_ci subcore_size = MAX_SMT_THREADS / split; 32268c2ecf20Sopenharmony_ci split_info.rpr = mfspr(SPRN_RPR); 32278c2ecf20Sopenharmony_ci split_info.pmmar = mfspr(SPRN_PMMAR); 32288c2ecf20Sopenharmony_ci split_info.ldbar = mfspr(SPRN_LDBAR); 32298c2ecf20Sopenharmony_ci split_info.subcore_size = subcore_size; 32308c2ecf20Sopenharmony_ci } else { 32318c2ecf20Sopenharmony_ci split_info.subcore_size = 1; 32328c2ecf20Sopenharmony_ci if (hpt_on_radix) { 32338c2ecf20Sopenharmony_ci /* Use the split_info for LPCR/LPIDR changes */ 32348c2ecf20Sopenharmony_ci split_info.lpcr_req = vc->lpcr; 32358c2ecf20Sopenharmony_ci split_info.lpidr_req = vc->kvm->arch.lpid; 32368c2ecf20Sopenharmony_ci split_info.host_lpcr = vc->kvm->arch.host_lpcr; 32378c2ecf20Sopenharmony_ci split_info.do_set = 1; 32388c2ecf20Sopenharmony_ci } 32398c2ecf20Sopenharmony_ci } 32408c2ecf20Sopenharmony_ci 32418c2ecf20Sopenharmony_ci /* order writes to split_info before kvm_split_mode pointer */ 32428c2ecf20Sopenharmony_ci smp_wmb(); 32438c2ecf20Sopenharmony_ci } 32448c2ecf20Sopenharmony_ci 32458c2ecf20Sopenharmony_ci for (thr = 0; thr < controlled_threads; ++thr) { 32468c2ecf20Sopenharmony_ci struct paca_struct *paca = paca_ptrs[pcpu + thr]; 32478c2ecf20Sopenharmony_ci 32488c2ecf20Sopenharmony_ci paca->kvm_hstate.tid = thr; 32498c2ecf20Sopenharmony_ci paca->kvm_hstate.napping = 0; 32508c2ecf20Sopenharmony_ci paca->kvm_hstate.kvm_split_mode = sip; 32518c2ecf20Sopenharmony_ci } 32528c2ecf20Sopenharmony_ci 32538c2ecf20Sopenharmony_ci /* Initiate micro-threading (split-core) on POWER8 if required */ 32548c2ecf20Sopenharmony_ci if (cmd_bit) { 32558c2ecf20Sopenharmony_ci unsigned long hid0 = mfspr(SPRN_HID0); 32568c2ecf20Sopenharmony_ci 32578c2ecf20Sopenharmony_ci hid0 |= cmd_bit | HID0_POWER8_DYNLPARDIS; 32588c2ecf20Sopenharmony_ci mb(); 32598c2ecf20Sopenharmony_ci mtspr(SPRN_HID0, hid0); 32608c2ecf20Sopenharmony_ci isync(); 32618c2ecf20Sopenharmony_ci for (;;) { 32628c2ecf20Sopenharmony_ci hid0 = mfspr(SPRN_HID0); 32638c2ecf20Sopenharmony_ci if (hid0 & stat_bit) 32648c2ecf20Sopenharmony_ci break; 32658c2ecf20Sopenharmony_ci cpu_relax(); 32668c2ecf20Sopenharmony_ci } 32678c2ecf20Sopenharmony_ci } 32688c2ecf20Sopenharmony_ci 32698c2ecf20Sopenharmony_ci /* 32708c2ecf20Sopenharmony_ci * On POWER8, set RWMR register. 32718c2ecf20Sopenharmony_ci * Since it only affects PURR and SPURR, it doesn't affect 32728c2ecf20Sopenharmony_ci * the host, so we don't save/restore the host value. 32738c2ecf20Sopenharmony_ci */ 32748c2ecf20Sopenharmony_ci if (is_power8) { 32758c2ecf20Sopenharmony_ci unsigned long rwmr_val = RWMR_RPA_P8_8THREAD; 32768c2ecf20Sopenharmony_ci int n_online = atomic_read(&vc->online_count); 32778c2ecf20Sopenharmony_ci 32788c2ecf20Sopenharmony_ci /* 32798c2ecf20Sopenharmony_ci * Use the 8-thread value if we're doing split-core 32808c2ecf20Sopenharmony_ci * or if the vcore's online count looks bogus. 32818c2ecf20Sopenharmony_ci */ 32828c2ecf20Sopenharmony_ci if (split == 1 && threads_per_subcore == MAX_SMT_THREADS && 32838c2ecf20Sopenharmony_ci n_online >= 1 && n_online <= MAX_SMT_THREADS) 32848c2ecf20Sopenharmony_ci rwmr_val = p8_rwmr_values[n_online]; 32858c2ecf20Sopenharmony_ci mtspr(SPRN_RWMR, rwmr_val); 32868c2ecf20Sopenharmony_ci } 32878c2ecf20Sopenharmony_ci 32888c2ecf20Sopenharmony_ci /* Start all the threads */ 32898c2ecf20Sopenharmony_ci active = 0; 32908c2ecf20Sopenharmony_ci for (sub = 0; sub < core_info.n_subcores; ++sub) { 32918c2ecf20Sopenharmony_ci thr = is_power8 ? subcore_thread_map[sub] : sub; 32928c2ecf20Sopenharmony_ci thr0_done = false; 32938c2ecf20Sopenharmony_ci active |= 1 << thr; 32948c2ecf20Sopenharmony_ci pvc = core_info.vc[sub]; 32958c2ecf20Sopenharmony_ci pvc->pcpu = pcpu + thr; 32968c2ecf20Sopenharmony_ci for_each_runnable_thread(i, vcpu, pvc) { 32978c2ecf20Sopenharmony_ci kvmppc_start_thread(vcpu, pvc); 32988c2ecf20Sopenharmony_ci kvmppc_create_dtl_entry(vcpu, pvc); 32998c2ecf20Sopenharmony_ci trace_kvm_guest_enter(vcpu); 33008c2ecf20Sopenharmony_ci if (!vcpu->arch.ptid) 33018c2ecf20Sopenharmony_ci thr0_done = true; 33028c2ecf20Sopenharmony_ci active |= 1 << (thr + vcpu->arch.ptid); 33038c2ecf20Sopenharmony_ci } 33048c2ecf20Sopenharmony_ci /* 33058c2ecf20Sopenharmony_ci * We need to start the first thread of each subcore 33068c2ecf20Sopenharmony_ci * even if it doesn't have a vcpu. 33078c2ecf20Sopenharmony_ci */ 33088c2ecf20Sopenharmony_ci if (!thr0_done) 33098c2ecf20Sopenharmony_ci kvmppc_start_thread(NULL, pvc); 33108c2ecf20Sopenharmony_ci } 33118c2ecf20Sopenharmony_ci 33128c2ecf20Sopenharmony_ci /* 33138c2ecf20Sopenharmony_ci * Ensure that split_info.do_nap is set after setting 33148c2ecf20Sopenharmony_ci * the vcore pointer in the PACA of the secondaries. 33158c2ecf20Sopenharmony_ci */ 33168c2ecf20Sopenharmony_ci smp_mb(); 33178c2ecf20Sopenharmony_ci 33188c2ecf20Sopenharmony_ci /* 33198c2ecf20Sopenharmony_ci * When doing micro-threading, poke the inactive threads as well. 33208c2ecf20Sopenharmony_ci * This gets them to the nap instruction after kvm_do_nap, 33218c2ecf20Sopenharmony_ci * which reduces the time taken to unsplit later. 33228c2ecf20Sopenharmony_ci * For POWER9 HPT guest on radix host, we need all the secondary 33238c2ecf20Sopenharmony_ci * threads woken up so they can do the LPCR/LPIDR change. 33248c2ecf20Sopenharmony_ci */ 33258c2ecf20Sopenharmony_ci if (cmd_bit || hpt_on_radix) { 33268c2ecf20Sopenharmony_ci split_info.do_nap = 1; /* ask secondaries to nap when done */ 33278c2ecf20Sopenharmony_ci for (thr = 1; thr < threads_per_subcore; ++thr) 33288c2ecf20Sopenharmony_ci if (!(active & (1 << thr))) 33298c2ecf20Sopenharmony_ci kvmppc_ipi_thread(pcpu + thr); 33308c2ecf20Sopenharmony_ci } 33318c2ecf20Sopenharmony_ci 33328c2ecf20Sopenharmony_ci vc->vcore_state = VCORE_RUNNING; 33338c2ecf20Sopenharmony_ci preempt_disable(); 33348c2ecf20Sopenharmony_ci 33358c2ecf20Sopenharmony_ci trace_kvmppc_run_core(vc, 0); 33368c2ecf20Sopenharmony_ci 33378c2ecf20Sopenharmony_ci for (sub = 0; sub < core_info.n_subcores; ++sub) 33388c2ecf20Sopenharmony_ci spin_unlock(&core_info.vc[sub]->lock); 33398c2ecf20Sopenharmony_ci 33408c2ecf20Sopenharmony_ci guest_enter_irqoff(); 33418c2ecf20Sopenharmony_ci 33428c2ecf20Sopenharmony_ci srcu_idx = srcu_read_lock(&vc->kvm->srcu); 33438c2ecf20Sopenharmony_ci 33448c2ecf20Sopenharmony_ci this_cpu_disable_ftrace(); 33458c2ecf20Sopenharmony_ci 33468c2ecf20Sopenharmony_ci /* 33478c2ecf20Sopenharmony_ci * Interrupts will be enabled once we get into the guest, 33488c2ecf20Sopenharmony_ci * so tell lockdep that we're about to enable interrupts. 33498c2ecf20Sopenharmony_ci */ 33508c2ecf20Sopenharmony_ci trace_hardirqs_on(); 33518c2ecf20Sopenharmony_ci 33528c2ecf20Sopenharmony_ci trap = __kvmppc_vcore_entry(); 33538c2ecf20Sopenharmony_ci 33548c2ecf20Sopenharmony_ci trace_hardirqs_off(); 33558c2ecf20Sopenharmony_ci 33568c2ecf20Sopenharmony_ci this_cpu_enable_ftrace(); 33578c2ecf20Sopenharmony_ci 33588c2ecf20Sopenharmony_ci srcu_read_unlock(&vc->kvm->srcu, srcu_idx); 33598c2ecf20Sopenharmony_ci 33608c2ecf20Sopenharmony_ci set_irq_happened(trap); 33618c2ecf20Sopenharmony_ci 33628c2ecf20Sopenharmony_ci spin_lock(&vc->lock); 33638c2ecf20Sopenharmony_ci /* prevent other vcpu threads from doing kvmppc_start_thread() now */ 33648c2ecf20Sopenharmony_ci vc->vcore_state = VCORE_EXITING; 33658c2ecf20Sopenharmony_ci 33668c2ecf20Sopenharmony_ci /* wait for secondary threads to finish writing their state to memory */ 33678c2ecf20Sopenharmony_ci kvmppc_wait_for_nap(controlled_threads); 33688c2ecf20Sopenharmony_ci 33698c2ecf20Sopenharmony_ci /* Return to whole-core mode if we split the core earlier */ 33708c2ecf20Sopenharmony_ci if (cmd_bit) { 33718c2ecf20Sopenharmony_ci unsigned long hid0 = mfspr(SPRN_HID0); 33728c2ecf20Sopenharmony_ci unsigned long loops = 0; 33738c2ecf20Sopenharmony_ci 33748c2ecf20Sopenharmony_ci hid0 &= ~HID0_POWER8_DYNLPARDIS; 33758c2ecf20Sopenharmony_ci stat_bit = HID0_POWER8_2LPARMODE | HID0_POWER8_4LPARMODE; 33768c2ecf20Sopenharmony_ci mb(); 33778c2ecf20Sopenharmony_ci mtspr(SPRN_HID0, hid0); 33788c2ecf20Sopenharmony_ci isync(); 33798c2ecf20Sopenharmony_ci for (;;) { 33808c2ecf20Sopenharmony_ci hid0 = mfspr(SPRN_HID0); 33818c2ecf20Sopenharmony_ci if (!(hid0 & stat_bit)) 33828c2ecf20Sopenharmony_ci break; 33838c2ecf20Sopenharmony_ci cpu_relax(); 33848c2ecf20Sopenharmony_ci ++loops; 33858c2ecf20Sopenharmony_ci } 33868c2ecf20Sopenharmony_ci } else if (hpt_on_radix) { 33878c2ecf20Sopenharmony_ci /* Wait for all threads to have seen final sync */ 33888c2ecf20Sopenharmony_ci for (thr = 1; thr < controlled_threads; ++thr) { 33898c2ecf20Sopenharmony_ci struct paca_struct *paca = paca_ptrs[pcpu + thr]; 33908c2ecf20Sopenharmony_ci 33918c2ecf20Sopenharmony_ci while (paca->kvm_hstate.kvm_split_mode) { 33928c2ecf20Sopenharmony_ci HMT_low(); 33938c2ecf20Sopenharmony_ci barrier(); 33948c2ecf20Sopenharmony_ci } 33958c2ecf20Sopenharmony_ci HMT_medium(); 33968c2ecf20Sopenharmony_ci } 33978c2ecf20Sopenharmony_ci } 33988c2ecf20Sopenharmony_ci split_info.do_nap = 0; 33998c2ecf20Sopenharmony_ci 34008c2ecf20Sopenharmony_ci kvmppc_set_host_core(pcpu); 34018c2ecf20Sopenharmony_ci 34028c2ecf20Sopenharmony_ci context_tracking_guest_exit(); 34038c2ecf20Sopenharmony_ci if (!vtime_accounting_enabled_this_cpu()) { 34048c2ecf20Sopenharmony_ci local_irq_enable(); 34058c2ecf20Sopenharmony_ci /* 34068c2ecf20Sopenharmony_ci * Service IRQs here before vtime_account_guest_exit() so any 34078c2ecf20Sopenharmony_ci * ticks that occurred while running the guest are accounted to 34088c2ecf20Sopenharmony_ci * the guest. If vtime accounting is enabled, accounting uses 34098c2ecf20Sopenharmony_ci * TB rather than ticks, so it can be done without enabling 34108c2ecf20Sopenharmony_ci * interrupts here, which has the problem that it accounts 34118c2ecf20Sopenharmony_ci * interrupt processing overhead to the host. 34128c2ecf20Sopenharmony_ci */ 34138c2ecf20Sopenharmony_ci local_irq_disable(); 34148c2ecf20Sopenharmony_ci } 34158c2ecf20Sopenharmony_ci vtime_account_guest_exit(); 34168c2ecf20Sopenharmony_ci 34178c2ecf20Sopenharmony_ci local_irq_enable(); 34188c2ecf20Sopenharmony_ci 34198c2ecf20Sopenharmony_ci /* Let secondaries go back to the offline loop */ 34208c2ecf20Sopenharmony_ci for (i = 0; i < controlled_threads; ++i) { 34218c2ecf20Sopenharmony_ci kvmppc_release_hwthread(pcpu + i); 34228c2ecf20Sopenharmony_ci if (sip && sip->napped[i]) 34238c2ecf20Sopenharmony_ci kvmppc_ipi_thread(pcpu + i); 34248c2ecf20Sopenharmony_ci cpumask_clear_cpu(pcpu + i, &vc->kvm->arch.cpu_in_guest); 34258c2ecf20Sopenharmony_ci } 34268c2ecf20Sopenharmony_ci 34278c2ecf20Sopenharmony_ci spin_unlock(&vc->lock); 34288c2ecf20Sopenharmony_ci 34298c2ecf20Sopenharmony_ci /* make sure updates to secondary vcpu structs are visible now */ 34308c2ecf20Sopenharmony_ci smp_mb(); 34318c2ecf20Sopenharmony_ci 34328c2ecf20Sopenharmony_ci preempt_enable(); 34338c2ecf20Sopenharmony_ci 34348c2ecf20Sopenharmony_ci for (sub = 0; sub < core_info.n_subcores; ++sub) { 34358c2ecf20Sopenharmony_ci pvc = core_info.vc[sub]; 34368c2ecf20Sopenharmony_ci post_guest_process(pvc, pvc == vc); 34378c2ecf20Sopenharmony_ci } 34388c2ecf20Sopenharmony_ci 34398c2ecf20Sopenharmony_ci spin_lock(&vc->lock); 34408c2ecf20Sopenharmony_ci 34418c2ecf20Sopenharmony_ci out: 34428c2ecf20Sopenharmony_ci vc->vcore_state = VCORE_INACTIVE; 34438c2ecf20Sopenharmony_ci trace_kvmppc_run_core(vc, 1); 34448c2ecf20Sopenharmony_ci} 34458c2ecf20Sopenharmony_ci 34468c2ecf20Sopenharmony_ci/* 34478c2ecf20Sopenharmony_ci * Load up hypervisor-mode registers on P9. 34488c2ecf20Sopenharmony_ci */ 34498c2ecf20Sopenharmony_cistatic int kvmhv_load_hv_regs_and_go(struct kvm_vcpu *vcpu, u64 time_limit, 34508c2ecf20Sopenharmony_ci unsigned long lpcr) 34518c2ecf20Sopenharmony_ci{ 34528c2ecf20Sopenharmony_ci struct kvmppc_vcore *vc = vcpu->arch.vcore; 34538c2ecf20Sopenharmony_ci s64 hdec; 34548c2ecf20Sopenharmony_ci u64 tb, purr, spurr; 34558c2ecf20Sopenharmony_ci int trap; 34568c2ecf20Sopenharmony_ci unsigned long host_hfscr = mfspr(SPRN_HFSCR); 34578c2ecf20Sopenharmony_ci unsigned long host_ciabr = mfspr(SPRN_CIABR); 34588c2ecf20Sopenharmony_ci unsigned long host_dawr = mfspr(SPRN_DAWR0); 34598c2ecf20Sopenharmony_ci unsigned long host_dawrx = mfspr(SPRN_DAWRX0); 34608c2ecf20Sopenharmony_ci unsigned long host_psscr = mfspr(SPRN_PSSCR); 34618c2ecf20Sopenharmony_ci unsigned long host_pidr = mfspr(SPRN_PID); 34628c2ecf20Sopenharmony_ci 34638c2ecf20Sopenharmony_ci /* 34648c2ecf20Sopenharmony_ci * P8 and P9 suppress the HDEC exception when LPCR[HDICE] = 0, 34658c2ecf20Sopenharmony_ci * so set HDICE before writing HDEC. 34668c2ecf20Sopenharmony_ci */ 34678c2ecf20Sopenharmony_ci mtspr(SPRN_LPCR, vcpu->kvm->arch.host_lpcr | LPCR_HDICE); 34688c2ecf20Sopenharmony_ci isync(); 34698c2ecf20Sopenharmony_ci 34708c2ecf20Sopenharmony_ci hdec = time_limit - mftb(); 34718c2ecf20Sopenharmony_ci if (hdec < 0) { 34728c2ecf20Sopenharmony_ci mtspr(SPRN_LPCR, vcpu->kvm->arch.host_lpcr); 34738c2ecf20Sopenharmony_ci isync(); 34748c2ecf20Sopenharmony_ci return BOOK3S_INTERRUPT_HV_DECREMENTER; 34758c2ecf20Sopenharmony_ci } 34768c2ecf20Sopenharmony_ci mtspr(SPRN_HDEC, hdec); 34778c2ecf20Sopenharmony_ci 34788c2ecf20Sopenharmony_ci if (vc->tb_offset) { 34798c2ecf20Sopenharmony_ci u64 new_tb = mftb() + vc->tb_offset; 34808c2ecf20Sopenharmony_ci mtspr(SPRN_TBU40, new_tb); 34818c2ecf20Sopenharmony_ci tb = mftb(); 34828c2ecf20Sopenharmony_ci if ((tb & 0xffffff) < (new_tb & 0xffffff)) 34838c2ecf20Sopenharmony_ci mtspr(SPRN_TBU40, new_tb + 0x1000000); 34848c2ecf20Sopenharmony_ci vc->tb_offset_applied = vc->tb_offset; 34858c2ecf20Sopenharmony_ci } 34868c2ecf20Sopenharmony_ci 34878c2ecf20Sopenharmony_ci if (vc->pcr) 34888c2ecf20Sopenharmony_ci mtspr(SPRN_PCR, vc->pcr | PCR_MASK); 34898c2ecf20Sopenharmony_ci mtspr(SPRN_DPDES, vc->dpdes); 34908c2ecf20Sopenharmony_ci mtspr(SPRN_VTB, vc->vtb); 34918c2ecf20Sopenharmony_ci 34928c2ecf20Sopenharmony_ci local_paca->kvm_hstate.host_purr = mfspr(SPRN_PURR); 34938c2ecf20Sopenharmony_ci local_paca->kvm_hstate.host_spurr = mfspr(SPRN_SPURR); 34948c2ecf20Sopenharmony_ci mtspr(SPRN_PURR, vcpu->arch.purr); 34958c2ecf20Sopenharmony_ci mtspr(SPRN_SPURR, vcpu->arch.spurr); 34968c2ecf20Sopenharmony_ci 34978c2ecf20Sopenharmony_ci if (dawr_enabled()) { 34988c2ecf20Sopenharmony_ci mtspr(SPRN_DAWR0, vcpu->arch.dawr); 34998c2ecf20Sopenharmony_ci mtspr(SPRN_DAWRX0, vcpu->arch.dawrx); 35008c2ecf20Sopenharmony_ci } 35018c2ecf20Sopenharmony_ci mtspr(SPRN_CIABR, vcpu->arch.ciabr); 35028c2ecf20Sopenharmony_ci mtspr(SPRN_IC, vcpu->arch.ic); 35038c2ecf20Sopenharmony_ci mtspr(SPRN_PID, vcpu->arch.pid); 35048c2ecf20Sopenharmony_ci 35058c2ecf20Sopenharmony_ci mtspr(SPRN_PSSCR, vcpu->arch.psscr | PSSCR_EC | 35068c2ecf20Sopenharmony_ci (local_paca->kvm_hstate.fake_suspend << PSSCR_FAKE_SUSPEND_LG)); 35078c2ecf20Sopenharmony_ci 35088c2ecf20Sopenharmony_ci mtspr(SPRN_HFSCR, vcpu->arch.hfscr); 35098c2ecf20Sopenharmony_ci 35108c2ecf20Sopenharmony_ci mtspr(SPRN_SPRG0, vcpu->arch.shregs.sprg0); 35118c2ecf20Sopenharmony_ci mtspr(SPRN_SPRG1, vcpu->arch.shregs.sprg1); 35128c2ecf20Sopenharmony_ci mtspr(SPRN_SPRG2, vcpu->arch.shregs.sprg2); 35138c2ecf20Sopenharmony_ci mtspr(SPRN_SPRG3, vcpu->arch.shregs.sprg3); 35148c2ecf20Sopenharmony_ci 35158c2ecf20Sopenharmony_ci mtspr(SPRN_AMOR, ~0UL); 35168c2ecf20Sopenharmony_ci 35178c2ecf20Sopenharmony_ci mtspr(SPRN_LPCR, lpcr); 35188c2ecf20Sopenharmony_ci isync(); 35198c2ecf20Sopenharmony_ci 35208c2ecf20Sopenharmony_ci kvmppc_xive_push_vcpu(vcpu); 35218c2ecf20Sopenharmony_ci 35228c2ecf20Sopenharmony_ci mtspr(SPRN_SRR0, vcpu->arch.shregs.srr0); 35238c2ecf20Sopenharmony_ci mtspr(SPRN_SRR1, vcpu->arch.shregs.srr1); 35248c2ecf20Sopenharmony_ci 35258c2ecf20Sopenharmony_ci trap = __kvmhv_vcpu_entry_p9(vcpu); 35268c2ecf20Sopenharmony_ci 35278c2ecf20Sopenharmony_ci /* Advance host PURR/SPURR by the amount used by guest */ 35288c2ecf20Sopenharmony_ci purr = mfspr(SPRN_PURR); 35298c2ecf20Sopenharmony_ci spurr = mfspr(SPRN_SPURR); 35308c2ecf20Sopenharmony_ci mtspr(SPRN_PURR, local_paca->kvm_hstate.host_purr + 35318c2ecf20Sopenharmony_ci purr - vcpu->arch.purr); 35328c2ecf20Sopenharmony_ci mtspr(SPRN_SPURR, local_paca->kvm_hstate.host_spurr + 35338c2ecf20Sopenharmony_ci spurr - vcpu->arch.spurr); 35348c2ecf20Sopenharmony_ci vcpu->arch.purr = purr; 35358c2ecf20Sopenharmony_ci vcpu->arch.spurr = spurr; 35368c2ecf20Sopenharmony_ci 35378c2ecf20Sopenharmony_ci vcpu->arch.ic = mfspr(SPRN_IC); 35388c2ecf20Sopenharmony_ci vcpu->arch.pid = mfspr(SPRN_PID); 35398c2ecf20Sopenharmony_ci vcpu->arch.psscr = mfspr(SPRN_PSSCR) & PSSCR_GUEST_VIS; 35408c2ecf20Sopenharmony_ci 35418c2ecf20Sopenharmony_ci vcpu->arch.shregs.sprg0 = mfspr(SPRN_SPRG0); 35428c2ecf20Sopenharmony_ci vcpu->arch.shregs.sprg1 = mfspr(SPRN_SPRG1); 35438c2ecf20Sopenharmony_ci vcpu->arch.shregs.sprg2 = mfspr(SPRN_SPRG2); 35448c2ecf20Sopenharmony_ci vcpu->arch.shregs.sprg3 = mfspr(SPRN_SPRG3); 35458c2ecf20Sopenharmony_ci 35468c2ecf20Sopenharmony_ci /* Preserve PSSCR[FAKE_SUSPEND] until we've called kvmppc_save_tm_hv */ 35478c2ecf20Sopenharmony_ci mtspr(SPRN_PSSCR, host_psscr | 35488c2ecf20Sopenharmony_ci (local_paca->kvm_hstate.fake_suspend << PSSCR_FAKE_SUSPEND_LG)); 35498c2ecf20Sopenharmony_ci mtspr(SPRN_HFSCR, host_hfscr); 35508c2ecf20Sopenharmony_ci mtspr(SPRN_CIABR, host_ciabr); 35518c2ecf20Sopenharmony_ci mtspr(SPRN_DAWR0, host_dawr); 35528c2ecf20Sopenharmony_ci mtspr(SPRN_DAWRX0, host_dawrx); 35538c2ecf20Sopenharmony_ci mtspr(SPRN_PID, host_pidr); 35548c2ecf20Sopenharmony_ci 35558c2ecf20Sopenharmony_ci /* 35568c2ecf20Sopenharmony_ci * Since this is radix, do a eieio; tlbsync; ptesync sequence in 35578c2ecf20Sopenharmony_ci * case we interrupted the guest between a tlbie and a ptesync. 35588c2ecf20Sopenharmony_ci */ 35598c2ecf20Sopenharmony_ci asm volatile("eieio; tlbsync; ptesync"); 35608c2ecf20Sopenharmony_ci 35618c2ecf20Sopenharmony_ci /* 35628c2ecf20Sopenharmony_ci * cp_abort is required if the processor supports local copy-paste 35638c2ecf20Sopenharmony_ci * to clear the copy buffer that was under control of the guest. 35648c2ecf20Sopenharmony_ci */ 35658c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_31)) 35668c2ecf20Sopenharmony_ci asm volatile(PPC_CP_ABORT); 35678c2ecf20Sopenharmony_ci 35688c2ecf20Sopenharmony_ci mtspr(SPRN_LPID, vcpu->kvm->arch.host_lpid); /* restore host LPID */ 35698c2ecf20Sopenharmony_ci isync(); 35708c2ecf20Sopenharmony_ci 35718c2ecf20Sopenharmony_ci vc->dpdes = mfspr(SPRN_DPDES); 35728c2ecf20Sopenharmony_ci vc->vtb = mfspr(SPRN_VTB); 35738c2ecf20Sopenharmony_ci mtspr(SPRN_DPDES, 0); 35748c2ecf20Sopenharmony_ci if (vc->pcr) 35758c2ecf20Sopenharmony_ci mtspr(SPRN_PCR, PCR_MASK); 35768c2ecf20Sopenharmony_ci 35778c2ecf20Sopenharmony_ci if (vc->tb_offset_applied) { 35788c2ecf20Sopenharmony_ci u64 new_tb = mftb() - vc->tb_offset_applied; 35798c2ecf20Sopenharmony_ci mtspr(SPRN_TBU40, new_tb); 35808c2ecf20Sopenharmony_ci tb = mftb(); 35818c2ecf20Sopenharmony_ci if ((tb & 0xffffff) < (new_tb & 0xffffff)) 35828c2ecf20Sopenharmony_ci mtspr(SPRN_TBU40, new_tb + 0x1000000); 35838c2ecf20Sopenharmony_ci vc->tb_offset_applied = 0; 35848c2ecf20Sopenharmony_ci } 35858c2ecf20Sopenharmony_ci 35868c2ecf20Sopenharmony_ci mtspr(SPRN_HDEC, 0x7fffffff); 35878c2ecf20Sopenharmony_ci mtspr(SPRN_LPCR, vcpu->kvm->arch.host_lpcr); 35888c2ecf20Sopenharmony_ci 35898c2ecf20Sopenharmony_ci return trap; 35908c2ecf20Sopenharmony_ci} 35918c2ecf20Sopenharmony_ci 35928c2ecf20Sopenharmony_ci/* 35938c2ecf20Sopenharmony_ci * Virtual-mode guest entry for POWER9 and later when the host and 35948c2ecf20Sopenharmony_ci * guest are both using the radix MMU. The LPIDR has already been set. 35958c2ecf20Sopenharmony_ci */ 35968c2ecf20Sopenharmony_cistatic int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit, 35978c2ecf20Sopenharmony_ci unsigned long lpcr) 35988c2ecf20Sopenharmony_ci{ 35998c2ecf20Sopenharmony_ci struct kvmppc_vcore *vc = vcpu->arch.vcore; 36008c2ecf20Sopenharmony_ci unsigned long host_dscr = mfspr(SPRN_DSCR); 36018c2ecf20Sopenharmony_ci unsigned long host_tidr = mfspr(SPRN_TIDR); 36028c2ecf20Sopenharmony_ci unsigned long host_iamr = mfspr(SPRN_IAMR); 36038c2ecf20Sopenharmony_ci unsigned long host_amr = mfspr(SPRN_AMR); 36048c2ecf20Sopenharmony_ci unsigned long host_fscr = mfspr(SPRN_FSCR); 36058c2ecf20Sopenharmony_ci s64 dec; 36068c2ecf20Sopenharmony_ci u64 tb; 36078c2ecf20Sopenharmony_ci int trap, save_pmu; 36088c2ecf20Sopenharmony_ci 36098c2ecf20Sopenharmony_ci dec = mfspr(SPRN_DEC); 36108c2ecf20Sopenharmony_ci tb = mftb(); 36118c2ecf20Sopenharmony_ci if (dec < 0) 36128c2ecf20Sopenharmony_ci return BOOK3S_INTERRUPT_HV_DECREMENTER; 36138c2ecf20Sopenharmony_ci local_paca->kvm_hstate.dec_expires = dec + tb; 36148c2ecf20Sopenharmony_ci if (local_paca->kvm_hstate.dec_expires < time_limit) 36158c2ecf20Sopenharmony_ci time_limit = local_paca->kvm_hstate.dec_expires; 36168c2ecf20Sopenharmony_ci 36178c2ecf20Sopenharmony_ci vcpu->arch.ceded = 0; 36188c2ecf20Sopenharmony_ci 36198c2ecf20Sopenharmony_ci kvmhv_save_host_pmu(); /* saves it to PACA kvm_hstate */ 36208c2ecf20Sopenharmony_ci 36218c2ecf20Sopenharmony_ci kvmppc_subcore_enter_guest(); 36228c2ecf20Sopenharmony_ci 36238c2ecf20Sopenharmony_ci vc->entry_exit_map = 1; 36248c2ecf20Sopenharmony_ci vc->in_guest = 1; 36258c2ecf20Sopenharmony_ci 36268c2ecf20Sopenharmony_ci if (vcpu->arch.vpa.pinned_addr) { 36278c2ecf20Sopenharmony_ci struct lppaca *lp = vcpu->arch.vpa.pinned_addr; 36288c2ecf20Sopenharmony_ci u32 yield_count = be32_to_cpu(lp->yield_count) + 1; 36298c2ecf20Sopenharmony_ci lp->yield_count = cpu_to_be32(yield_count); 36308c2ecf20Sopenharmony_ci vcpu->arch.vpa.dirty = 1; 36318c2ecf20Sopenharmony_ci } 36328c2ecf20Sopenharmony_ci 36338c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_TM) || 36348c2ecf20Sopenharmony_ci cpu_has_feature(CPU_FTR_P9_TM_HV_ASSIST)) 36358c2ecf20Sopenharmony_ci kvmppc_restore_tm_hv(vcpu, vcpu->arch.shregs.msr, true); 36368c2ecf20Sopenharmony_ci 36378c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_PSERIES 36388c2ecf20Sopenharmony_ci if (kvmhv_on_pseries()) { 36398c2ecf20Sopenharmony_ci barrier(); 36408c2ecf20Sopenharmony_ci if (vcpu->arch.vpa.pinned_addr) { 36418c2ecf20Sopenharmony_ci struct lppaca *lp = vcpu->arch.vpa.pinned_addr; 36428c2ecf20Sopenharmony_ci get_lppaca()->pmcregs_in_use = lp->pmcregs_in_use; 36438c2ecf20Sopenharmony_ci } else { 36448c2ecf20Sopenharmony_ci get_lppaca()->pmcregs_in_use = 1; 36458c2ecf20Sopenharmony_ci } 36468c2ecf20Sopenharmony_ci barrier(); 36478c2ecf20Sopenharmony_ci } 36488c2ecf20Sopenharmony_ci#endif 36498c2ecf20Sopenharmony_ci kvmhv_load_guest_pmu(vcpu); 36508c2ecf20Sopenharmony_ci 36518c2ecf20Sopenharmony_ci msr_check_and_set(MSR_FP | MSR_VEC | MSR_VSX); 36528c2ecf20Sopenharmony_ci load_fp_state(&vcpu->arch.fp); 36538c2ecf20Sopenharmony_ci#ifdef CONFIG_ALTIVEC 36548c2ecf20Sopenharmony_ci load_vr_state(&vcpu->arch.vr); 36558c2ecf20Sopenharmony_ci#endif 36568c2ecf20Sopenharmony_ci mtspr(SPRN_VRSAVE, vcpu->arch.vrsave); 36578c2ecf20Sopenharmony_ci 36588c2ecf20Sopenharmony_ci mtspr(SPRN_DSCR, vcpu->arch.dscr); 36598c2ecf20Sopenharmony_ci mtspr(SPRN_IAMR, vcpu->arch.iamr); 36608c2ecf20Sopenharmony_ci mtspr(SPRN_PSPB, vcpu->arch.pspb); 36618c2ecf20Sopenharmony_ci mtspr(SPRN_FSCR, vcpu->arch.fscr); 36628c2ecf20Sopenharmony_ci mtspr(SPRN_TAR, vcpu->arch.tar); 36638c2ecf20Sopenharmony_ci mtspr(SPRN_EBBHR, vcpu->arch.ebbhr); 36648c2ecf20Sopenharmony_ci mtspr(SPRN_EBBRR, vcpu->arch.ebbrr); 36658c2ecf20Sopenharmony_ci mtspr(SPRN_BESCR, vcpu->arch.bescr); 36668c2ecf20Sopenharmony_ci mtspr(SPRN_WORT, vcpu->arch.wort); 36678c2ecf20Sopenharmony_ci mtspr(SPRN_TIDR, vcpu->arch.tid); 36688c2ecf20Sopenharmony_ci mtspr(SPRN_DAR, vcpu->arch.shregs.dar); 36698c2ecf20Sopenharmony_ci mtspr(SPRN_DSISR, vcpu->arch.shregs.dsisr); 36708c2ecf20Sopenharmony_ci mtspr(SPRN_AMR, vcpu->arch.amr); 36718c2ecf20Sopenharmony_ci mtspr(SPRN_UAMOR, vcpu->arch.uamor); 36728c2ecf20Sopenharmony_ci 36738c2ecf20Sopenharmony_ci if (!(vcpu->arch.ctrl & 1)) 36748c2ecf20Sopenharmony_ci mtspr(SPRN_CTRLT, mfspr(SPRN_CTRLF) & ~1); 36758c2ecf20Sopenharmony_ci 36768c2ecf20Sopenharmony_ci mtspr(SPRN_DEC, vcpu->arch.dec_expires - mftb()); 36778c2ecf20Sopenharmony_ci 36788c2ecf20Sopenharmony_ci if (kvmhv_on_pseries()) { 36798c2ecf20Sopenharmony_ci /* 36808c2ecf20Sopenharmony_ci * We need to save and restore the guest visible part of the 36818c2ecf20Sopenharmony_ci * psscr (i.e. using SPRN_PSSCR_PR) since the hypervisor 36828c2ecf20Sopenharmony_ci * doesn't do this for us. Note only required if pseries since 36838c2ecf20Sopenharmony_ci * this is done in kvmhv_load_hv_regs_and_go() below otherwise. 36848c2ecf20Sopenharmony_ci */ 36858c2ecf20Sopenharmony_ci unsigned long host_psscr; 36868c2ecf20Sopenharmony_ci /* call our hypervisor to load up HV regs and go */ 36878c2ecf20Sopenharmony_ci struct hv_guest_state hvregs; 36888c2ecf20Sopenharmony_ci 36898c2ecf20Sopenharmony_ci host_psscr = mfspr(SPRN_PSSCR_PR); 36908c2ecf20Sopenharmony_ci mtspr(SPRN_PSSCR_PR, vcpu->arch.psscr); 36918c2ecf20Sopenharmony_ci kvmhv_save_hv_regs(vcpu, &hvregs); 36928c2ecf20Sopenharmony_ci hvregs.lpcr = lpcr; 36938c2ecf20Sopenharmony_ci vcpu->arch.regs.msr = vcpu->arch.shregs.msr; 36948c2ecf20Sopenharmony_ci hvregs.version = HV_GUEST_STATE_VERSION; 36958c2ecf20Sopenharmony_ci if (vcpu->arch.nested) { 36968c2ecf20Sopenharmony_ci hvregs.lpid = vcpu->arch.nested->shadow_lpid; 36978c2ecf20Sopenharmony_ci hvregs.vcpu_token = vcpu->arch.nested_vcpu_id; 36988c2ecf20Sopenharmony_ci } else { 36998c2ecf20Sopenharmony_ci hvregs.lpid = vcpu->kvm->arch.lpid; 37008c2ecf20Sopenharmony_ci hvregs.vcpu_token = vcpu->vcpu_id; 37018c2ecf20Sopenharmony_ci } 37028c2ecf20Sopenharmony_ci hvregs.hdec_expiry = time_limit; 37038c2ecf20Sopenharmony_ci trap = plpar_hcall_norets(H_ENTER_NESTED, __pa(&hvregs), 37048c2ecf20Sopenharmony_ci __pa(&vcpu->arch.regs)); 37058c2ecf20Sopenharmony_ci kvmhv_restore_hv_return_state(vcpu, &hvregs); 37068c2ecf20Sopenharmony_ci vcpu->arch.shregs.msr = vcpu->arch.regs.msr; 37078c2ecf20Sopenharmony_ci vcpu->arch.shregs.dar = mfspr(SPRN_DAR); 37088c2ecf20Sopenharmony_ci vcpu->arch.shregs.dsisr = mfspr(SPRN_DSISR); 37098c2ecf20Sopenharmony_ci vcpu->arch.psscr = mfspr(SPRN_PSSCR_PR); 37108c2ecf20Sopenharmony_ci mtspr(SPRN_PSSCR_PR, host_psscr); 37118c2ecf20Sopenharmony_ci 37128c2ecf20Sopenharmony_ci /* H_CEDE has to be handled now, not later */ 37138c2ecf20Sopenharmony_ci if (trap == BOOK3S_INTERRUPT_SYSCALL && !vcpu->arch.nested && 37148c2ecf20Sopenharmony_ci kvmppc_get_gpr(vcpu, 3) == H_CEDE) { 37158c2ecf20Sopenharmony_ci kvmppc_nested_cede(vcpu); 37168c2ecf20Sopenharmony_ci kvmppc_set_gpr(vcpu, 3, 0); 37178c2ecf20Sopenharmony_ci trap = 0; 37188c2ecf20Sopenharmony_ci } 37198c2ecf20Sopenharmony_ci } else { 37208c2ecf20Sopenharmony_ci trap = kvmhv_load_hv_regs_and_go(vcpu, time_limit, lpcr); 37218c2ecf20Sopenharmony_ci } 37228c2ecf20Sopenharmony_ci 37238c2ecf20Sopenharmony_ci vcpu->arch.slb_max = 0; 37248c2ecf20Sopenharmony_ci dec = mfspr(SPRN_DEC); 37258c2ecf20Sopenharmony_ci if (!(lpcr & LPCR_LD)) /* Sign extend if not using large decrementer */ 37268c2ecf20Sopenharmony_ci dec = (s32) dec; 37278c2ecf20Sopenharmony_ci tb = mftb(); 37288c2ecf20Sopenharmony_ci vcpu->arch.dec_expires = dec + tb; 37298c2ecf20Sopenharmony_ci vcpu->cpu = -1; 37308c2ecf20Sopenharmony_ci vcpu->arch.thread_cpu = -1; 37318c2ecf20Sopenharmony_ci /* Save guest CTRL register, set runlatch to 1 */ 37328c2ecf20Sopenharmony_ci vcpu->arch.ctrl = mfspr(SPRN_CTRLF); 37338c2ecf20Sopenharmony_ci if (!(vcpu->arch.ctrl & 1)) 37348c2ecf20Sopenharmony_ci mtspr(SPRN_CTRLT, vcpu->arch.ctrl | 1); 37358c2ecf20Sopenharmony_ci 37368c2ecf20Sopenharmony_ci vcpu->arch.iamr = mfspr(SPRN_IAMR); 37378c2ecf20Sopenharmony_ci vcpu->arch.pspb = mfspr(SPRN_PSPB); 37388c2ecf20Sopenharmony_ci vcpu->arch.fscr = mfspr(SPRN_FSCR); 37398c2ecf20Sopenharmony_ci vcpu->arch.tar = mfspr(SPRN_TAR); 37408c2ecf20Sopenharmony_ci vcpu->arch.ebbhr = mfspr(SPRN_EBBHR); 37418c2ecf20Sopenharmony_ci vcpu->arch.ebbrr = mfspr(SPRN_EBBRR); 37428c2ecf20Sopenharmony_ci vcpu->arch.bescr = mfspr(SPRN_BESCR); 37438c2ecf20Sopenharmony_ci vcpu->arch.wort = mfspr(SPRN_WORT); 37448c2ecf20Sopenharmony_ci vcpu->arch.tid = mfspr(SPRN_TIDR); 37458c2ecf20Sopenharmony_ci vcpu->arch.amr = mfspr(SPRN_AMR); 37468c2ecf20Sopenharmony_ci vcpu->arch.uamor = mfspr(SPRN_UAMOR); 37478c2ecf20Sopenharmony_ci vcpu->arch.dscr = mfspr(SPRN_DSCR); 37488c2ecf20Sopenharmony_ci 37498c2ecf20Sopenharmony_ci mtspr(SPRN_PSPB, 0); 37508c2ecf20Sopenharmony_ci mtspr(SPRN_WORT, 0); 37518c2ecf20Sopenharmony_ci mtspr(SPRN_UAMOR, 0); 37528c2ecf20Sopenharmony_ci mtspr(SPRN_DSCR, host_dscr); 37538c2ecf20Sopenharmony_ci mtspr(SPRN_TIDR, host_tidr); 37548c2ecf20Sopenharmony_ci mtspr(SPRN_IAMR, host_iamr); 37558c2ecf20Sopenharmony_ci mtspr(SPRN_PSPB, 0); 37568c2ecf20Sopenharmony_ci 37578c2ecf20Sopenharmony_ci if (host_amr != vcpu->arch.amr) 37588c2ecf20Sopenharmony_ci mtspr(SPRN_AMR, host_amr); 37598c2ecf20Sopenharmony_ci 37608c2ecf20Sopenharmony_ci if (host_fscr != vcpu->arch.fscr) 37618c2ecf20Sopenharmony_ci mtspr(SPRN_FSCR, host_fscr); 37628c2ecf20Sopenharmony_ci 37638c2ecf20Sopenharmony_ci msr_check_and_set(MSR_FP | MSR_VEC | MSR_VSX); 37648c2ecf20Sopenharmony_ci store_fp_state(&vcpu->arch.fp); 37658c2ecf20Sopenharmony_ci#ifdef CONFIG_ALTIVEC 37668c2ecf20Sopenharmony_ci store_vr_state(&vcpu->arch.vr); 37678c2ecf20Sopenharmony_ci#endif 37688c2ecf20Sopenharmony_ci vcpu->arch.vrsave = mfspr(SPRN_VRSAVE); 37698c2ecf20Sopenharmony_ci 37708c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_TM) || 37718c2ecf20Sopenharmony_ci cpu_has_feature(CPU_FTR_P9_TM_HV_ASSIST)) 37728c2ecf20Sopenharmony_ci kvmppc_save_tm_hv(vcpu, vcpu->arch.shregs.msr, true); 37738c2ecf20Sopenharmony_ci 37748c2ecf20Sopenharmony_ci save_pmu = 1; 37758c2ecf20Sopenharmony_ci if (vcpu->arch.vpa.pinned_addr) { 37768c2ecf20Sopenharmony_ci struct lppaca *lp = vcpu->arch.vpa.pinned_addr; 37778c2ecf20Sopenharmony_ci u32 yield_count = be32_to_cpu(lp->yield_count) + 1; 37788c2ecf20Sopenharmony_ci lp->yield_count = cpu_to_be32(yield_count); 37798c2ecf20Sopenharmony_ci vcpu->arch.vpa.dirty = 1; 37808c2ecf20Sopenharmony_ci save_pmu = lp->pmcregs_in_use; 37818c2ecf20Sopenharmony_ci } 37828c2ecf20Sopenharmony_ci /* Must save pmu if this guest is capable of running nested guests */ 37838c2ecf20Sopenharmony_ci save_pmu |= nesting_enabled(vcpu->kvm); 37848c2ecf20Sopenharmony_ci 37858c2ecf20Sopenharmony_ci kvmhv_save_guest_pmu(vcpu, save_pmu); 37868c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_PSERIES 37878c2ecf20Sopenharmony_ci if (kvmhv_on_pseries()) { 37888c2ecf20Sopenharmony_ci barrier(); 37898c2ecf20Sopenharmony_ci get_lppaca()->pmcregs_in_use = ppc_get_pmu_inuse(); 37908c2ecf20Sopenharmony_ci barrier(); 37918c2ecf20Sopenharmony_ci } 37928c2ecf20Sopenharmony_ci#endif 37938c2ecf20Sopenharmony_ci 37948c2ecf20Sopenharmony_ci vc->entry_exit_map = 0x101; 37958c2ecf20Sopenharmony_ci vc->in_guest = 0; 37968c2ecf20Sopenharmony_ci 37978c2ecf20Sopenharmony_ci mtspr(SPRN_DEC, local_paca->kvm_hstate.dec_expires - mftb()); 37988c2ecf20Sopenharmony_ci mtspr(SPRN_SPRG_VDSO_WRITE, local_paca->sprg_vdso); 37998c2ecf20Sopenharmony_ci 38008c2ecf20Sopenharmony_ci kvmhv_load_host_pmu(); 38018c2ecf20Sopenharmony_ci 38028c2ecf20Sopenharmony_ci kvmppc_subcore_exit_guest(); 38038c2ecf20Sopenharmony_ci 38048c2ecf20Sopenharmony_ci return trap; 38058c2ecf20Sopenharmony_ci} 38068c2ecf20Sopenharmony_ci 38078c2ecf20Sopenharmony_ci/* 38088c2ecf20Sopenharmony_ci * Wait for some other vcpu thread to execute us, and 38098c2ecf20Sopenharmony_ci * wake us up when we need to handle something in the host. 38108c2ecf20Sopenharmony_ci */ 38118c2ecf20Sopenharmony_cistatic void kvmppc_wait_for_exec(struct kvmppc_vcore *vc, 38128c2ecf20Sopenharmony_ci struct kvm_vcpu *vcpu, int wait_state) 38138c2ecf20Sopenharmony_ci{ 38148c2ecf20Sopenharmony_ci DEFINE_WAIT(wait); 38158c2ecf20Sopenharmony_ci 38168c2ecf20Sopenharmony_ci prepare_to_wait(&vcpu->arch.cpu_run, &wait, wait_state); 38178c2ecf20Sopenharmony_ci if (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE) { 38188c2ecf20Sopenharmony_ci spin_unlock(&vc->lock); 38198c2ecf20Sopenharmony_ci schedule(); 38208c2ecf20Sopenharmony_ci spin_lock(&vc->lock); 38218c2ecf20Sopenharmony_ci } 38228c2ecf20Sopenharmony_ci finish_wait(&vcpu->arch.cpu_run, &wait); 38238c2ecf20Sopenharmony_ci} 38248c2ecf20Sopenharmony_ci 38258c2ecf20Sopenharmony_cistatic void grow_halt_poll_ns(struct kvmppc_vcore *vc) 38268c2ecf20Sopenharmony_ci{ 38278c2ecf20Sopenharmony_ci if (!halt_poll_ns_grow) 38288c2ecf20Sopenharmony_ci return; 38298c2ecf20Sopenharmony_ci 38308c2ecf20Sopenharmony_ci vc->halt_poll_ns *= halt_poll_ns_grow; 38318c2ecf20Sopenharmony_ci if (vc->halt_poll_ns < halt_poll_ns_grow_start) 38328c2ecf20Sopenharmony_ci vc->halt_poll_ns = halt_poll_ns_grow_start; 38338c2ecf20Sopenharmony_ci} 38348c2ecf20Sopenharmony_ci 38358c2ecf20Sopenharmony_cistatic void shrink_halt_poll_ns(struct kvmppc_vcore *vc) 38368c2ecf20Sopenharmony_ci{ 38378c2ecf20Sopenharmony_ci if (halt_poll_ns_shrink == 0) 38388c2ecf20Sopenharmony_ci vc->halt_poll_ns = 0; 38398c2ecf20Sopenharmony_ci else 38408c2ecf20Sopenharmony_ci vc->halt_poll_ns /= halt_poll_ns_shrink; 38418c2ecf20Sopenharmony_ci} 38428c2ecf20Sopenharmony_ci 38438c2ecf20Sopenharmony_ci#ifdef CONFIG_KVM_XICS 38448c2ecf20Sopenharmony_cistatic inline bool xive_interrupt_pending(struct kvm_vcpu *vcpu) 38458c2ecf20Sopenharmony_ci{ 38468c2ecf20Sopenharmony_ci if (!xics_on_xive()) 38478c2ecf20Sopenharmony_ci return false; 38488c2ecf20Sopenharmony_ci return vcpu->arch.irq_pending || vcpu->arch.xive_saved_state.pipr < 38498c2ecf20Sopenharmony_ci vcpu->arch.xive_saved_state.cppr; 38508c2ecf20Sopenharmony_ci} 38518c2ecf20Sopenharmony_ci#else 38528c2ecf20Sopenharmony_cistatic inline bool xive_interrupt_pending(struct kvm_vcpu *vcpu) 38538c2ecf20Sopenharmony_ci{ 38548c2ecf20Sopenharmony_ci return false; 38558c2ecf20Sopenharmony_ci} 38568c2ecf20Sopenharmony_ci#endif /* CONFIG_KVM_XICS */ 38578c2ecf20Sopenharmony_ci 38588c2ecf20Sopenharmony_cistatic bool kvmppc_vcpu_woken(struct kvm_vcpu *vcpu) 38598c2ecf20Sopenharmony_ci{ 38608c2ecf20Sopenharmony_ci if (vcpu->arch.pending_exceptions || vcpu->arch.prodded || 38618c2ecf20Sopenharmony_ci kvmppc_doorbell_pending(vcpu) || xive_interrupt_pending(vcpu)) 38628c2ecf20Sopenharmony_ci return true; 38638c2ecf20Sopenharmony_ci 38648c2ecf20Sopenharmony_ci return false; 38658c2ecf20Sopenharmony_ci} 38668c2ecf20Sopenharmony_ci 38678c2ecf20Sopenharmony_ci/* 38688c2ecf20Sopenharmony_ci * Check to see if any of the runnable vcpus on the vcore have pending 38698c2ecf20Sopenharmony_ci * exceptions or are no longer ceded 38708c2ecf20Sopenharmony_ci */ 38718c2ecf20Sopenharmony_cistatic int kvmppc_vcore_check_block(struct kvmppc_vcore *vc) 38728c2ecf20Sopenharmony_ci{ 38738c2ecf20Sopenharmony_ci struct kvm_vcpu *vcpu; 38748c2ecf20Sopenharmony_ci int i; 38758c2ecf20Sopenharmony_ci 38768c2ecf20Sopenharmony_ci for_each_runnable_thread(i, vcpu, vc) { 38778c2ecf20Sopenharmony_ci if (!vcpu->arch.ceded || kvmppc_vcpu_woken(vcpu)) 38788c2ecf20Sopenharmony_ci return 1; 38798c2ecf20Sopenharmony_ci } 38808c2ecf20Sopenharmony_ci 38818c2ecf20Sopenharmony_ci return 0; 38828c2ecf20Sopenharmony_ci} 38838c2ecf20Sopenharmony_ci 38848c2ecf20Sopenharmony_ci/* 38858c2ecf20Sopenharmony_ci * All the vcpus in this vcore are idle, so wait for a decrementer 38868c2ecf20Sopenharmony_ci * or external interrupt to one of the vcpus. vc->lock is held. 38878c2ecf20Sopenharmony_ci */ 38888c2ecf20Sopenharmony_cistatic void kvmppc_vcore_blocked(struct kvmppc_vcore *vc) 38898c2ecf20Sopenharmony_ci{ 38908c2ecf20Sopenharmony_ci ktime_t cur, start_poll, start_wait; 38918c2ecf20Sopenharmony_ci int do_sleep = 1; 38928c2ecf20Sopenharmony_ci u64 block_ns; 38938c2ecf20Sopenharmony_ci 38948c2ecf20Sopenharmony_ci /* Poll for pending exceptions and ceded state */ 38958c2ecf20Sopenharmony_ci cur = start_poll = ktime_get(); 38968c2ecf20Sopenharmony_ci if (vc->halt_poll_ns) { 38978c2ecf20Sopenharmony_ci ktime_t stop = ktime_add_ns(start_poll, vc->halt_poll_ns); 38988c2ecf20Sopenharmony_ci ++vc->runner->stat.halt_attempted_poll; 38998c2ecf20Sopenharmony_ci 39008c2ecf20Sopenharmony_ci vc->vcore_state = VCORE_POLLING; 39018c2ecf20Sopenharmony_ci spin_unlock(&vc->lock); 39028c2ecf20Sopenharmony_ci 39038c2ecf20Sopenharmony_ci do { 39048c2ecf20Sopenharmony_ci if (kvmppc_vcore_check_block(vc)) { 39058c2ecf20Sopenharmony_ci do_sleep = 0; 39068c2ecf20Sopenharmony_ci break; 39078c2ecf20Sopenharmony_ci } 39088c2ecf20Sopenharmony_ci cur = ktime_get(); 39098c2ecf20Sopenharmony_ci } while (single_task_running() && ktime_before(cur, stop)); 39108c2ecf20Sopenharmony_ci 39118c2ecf20Sopenharmony_ci spin_lock(&vc->lock); 39128c2ecf20Sopenharmony_ci vc->vcore_state = VCORE_INACTIVE; 39138c2ecf20Sopenharmony_ci 39148c2ecf20Sopenharmony_ci if (!do_sleep) { 39158c2ecf20Sopenharmony_ci ++vc->runner->stat.halt_successful_poll; 39168c2ecf20Sopenharmony_ci goto out; 39178c2ecf20Sopenharmony_ci } 39188c2ecf20Sopenharmony_ci } 39198c2ecf20Sopenharmony_ci 39208c2ecf20Sopenharmony_ci prepare_to_rcuwait(&vc->wait); 39218c2ecf20Sopenharmony_ci set_current_state(TASK_INTERRUPTIBLE); 39228c2ecf20Sopenharmony_ci if (kvmppc_vcore_check_block(vc)) { 39238c2ecf20Sopenharmony_ci finish_rcuwait(&vc->wait); 39248c2ecf20Sopenharmony_ci do_sleep = 0; 39258c2ecf20Sopenharmony_ci /* If we polled, count this as a successful poll */ 39268c2ecf20Sopenharmony_ci if (vc->halt_poll_ns) 39278c2ecf20Sopenharmony_ci ++vc->runner->stat.halt_successful_poll; 39288c2ecf20Sopenharmony_ci goto out; 39298c2ecf20Sopenharmony_ci } 39308c2ecf20Sopenharmony_ci 39318c2ecf20Sopenharmony_ci start_wait = ktime_get(); 39328c2ecf20Sopenharmony_ci 39338c2ecf20Sopenharmony_ci vc->vcore_state = VCORE_SLEEPING; 39348c2ecf20Sopenharmony_ci trace_kvmppc_vcore_blocked(vc, 0); 39358c2ecf20Sopenharmony_ci spin_unlock(&vc->lock); 39368c2ecf20Sopenharmony_ci schedule(); 39378c2ecf20Sopenharmony_ci finish_rcuwait(&vc->wait); 39388c2ecf20Sopenharmony_ci spin_lock(&vc->lock); 39398c2ecf20Sopenharmony_ci vc->vcore_state = VCORE_INACTIVE; 39408c2ecf20Sopenharmony_ci trace_kvmppc_vcore_blocked(vc, 1); 39418c2ecf20Sopenharmony_ci ++vc->runner->stat.halt_successful_wait; 39428c2ecf20Sopenharmony_ci 39438c2ecf20Sopenharmony_ci cur = ktime_get(); 39448c2ecf20Sopenharmony_ci 39458c2ecf20Sopenharmony_ciout: 39468c2ecf20Sopenharmony_ci block_ns = ktime_to_ns(cur) - ktime_to_ns(start_poll); 39478c2ecf20Sopenharmony_ci 39488c2ecf20Sopenharmony_ci /* Attribute wait time */ 39498c2ecf20Sopenharmony_ci if (do_sleep) { 39508c2ecf20Sopenharmony_ci vc->runner->stat.halt_wait_ns += 39518c2ecf20Sopenharmony_ci ktime_to_ns(cur) - ktime_to_ns(start_wait); 39528c2ecf20Sopenharmony_ci /* Attribute failed poll time */ 39538c2ecf20Sopenharmony_ci if (vc->halt_poll_ns) 39548c2ecf20Sopenharmony_ci vc->runner->stat.halt_poll_fail_ns += 39558c2ecf20Sopenharmony_ci ktime_to_ns(start_wait) - 39568c2ecf20Sopenharmony_ci ktime_to_ns(start_poll); 39578c2ecf20Sopenharmony_ci } else { 39588c2ecf20Sopenharmony_ci /* Attribute successful poll time */ 39598c2ecf20Sopenharmony_ci if (vc->halt_poll_ns) 39608c2ecf20Sopenharmony_ci vc->runner->stat.halt_poll_success_ns += 39618c2ecf20Sopenharmony_ci ktime_to_ns(cur) - 39628c2ecf20Sopenharmony_ci ktime_to_ns(start_poll); 39638c2ecf20Sopenharmony_ci } 39648c2ecf20Sopenharmony_ci 39658c2ecf20Sopenharmony_ci /* Adjust poll time */ 39668c2ecf20Sopenharmony_ci if (halt_poll_ns) { 39678c2ecf20Sopenharmony_ci if (block_ns <= vc->halt_poll_ns) 39688c2ecf20Sopenharmony_ci ; 39698c2ecf20Sopenharmony_ci /* We slept and blocked for longer than the max halt time */ 39708c2ecf20Sopenharmony_ci else if (vc->halt_poll_ns && block_ns > halt_poll_ns) 39718c2ecf20Sopenharmony_ci shrink_halt_poll_ns(vc); 39728c2ecf20Sopenharmony_ci /* We slept and our poll time is too small */ 39738c2ecf20Sopenharmony_ci else if (vc->halt_poll_ns < halt_poll_ns && 39748c2ecf20Sopenharmony_ci block_ns < halt_poll_ns) 39758c2ecf20Sopenharmony_ci grow_halt_poll_ns(vc); 39768c2ecf20Sopenharmony_ci if (vc->halt_poll_ns > halt_poll_ns) 39778c2ecf20Sopenharmony_ci vc->halt_poll_ns = halt_poll_ns; 39788c2ecf20Sopenharmony_ci } else 39798c2ecf20Sopenharmony_ci vc->halt_poll_ns = 0; 39808c2ecf20Sopenharmony_ci 39818c2ecf20Sopenharmony_ci trace_kvmppc_vcore_wakeup(do_sleep, block_ns); 39828c2ecf20Sopenharmony_ci} 39838c2ecf20Sopenharmony_ci 39848c2ecf20Sopenharmony_ci/* 39858c2ecf20Sopenharmony_ci * This never fails for a radix guest, as none of the operations it does 39868c2ecf20Sopenharmony_ci * for a radix guest can fail or have a way to report failure. 39878c2ecf20Sopenharmony_ci * kvmhv_run_single_vcpu() relies on this fact. 39888c2ecf20Sopenharmony_ci */ 39898c2ecf20Sopenharmony_cistatic int kvmhv_setup_mmu(struct kvm_vcpu *vcpu) 39908c2ecf20Sopenharmony_ci{ 39918c2ecf20Sopenharmony_ci int r = 0; 39928c2ecf20Sopenharmony_ci struct kvm *kvm = vcpu->kvm; 39938c2ecf20Sopenharmony_ci 39948c2ecf20Sopenharmony_ci mutex_lock(&kvm->arch.mmu_setup_lock); 39958c2ecf20Sopenharmony_ci if (!kvm->arch.mmu_ready) { 39968c2ecf20Sopenharmony_ci if (!kvm_is_radix(kvm)) 39978c2ecf20Sopenharmony_ci r = kvmppc_hv_setup_htab_rma(vcpu); 39988c2ecf20Sopenharmony_ci if (!r) { 39998c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_300)) 40008c2ecf20Sopenharmony_ci kvmppc_setup_partition_table(kvm); 40018c2ecf20Sopenharmony_ci kvm->arch.mmu_ready = 1; 40028c2ecf20Sopenharmony_ci } 40038c2ecf20Sopenharmony_ci } 40048c2ecf20Sopenharmony_ci mutex_unlock(&kvm->arch.mmu_setup_lock); 40058c2ecf20Sopenharmony_ci return r; 40068c2ecf20Sopenharmony_ci} 40078c2ecf20Sopenharmony_ci 40088c2ecf20Sopenharmony_cistatic int kvmppc_run_vcpu(struct kvm_vcpu *vcpu) 40098c2ecf20Sopenharmony_ci{ 40108c2ecf20Sopenharmony_ci struct kvm_run *run = vcpu->run; 40118c2ecf20Sopenharmony_ci int n_ceded, i, r; 40128c2ecf20Sopenharmony_ci struct kvmppc_vcore *vc; 40138c2ecf20Sopenharmony_ci struct kvm_vcpu *v; 40148c2ecf20Sopenharmony_ci 40158c2ecf20Sopenharmony_ci trace_kvmppc_run_vcpu_enter(vcpu); 40168c2ecf20Sopenharmony_ci 40178c2ecf20Sopenharmony_ci run->exit_reason = 0; 40188c2ecf20Sopenharmony_ci vcpu->arch.ret = RESUME_GUEST; 40198c2ecf20Sopenharmony_ci vcpu->arch.trap = 0; 40208c2ecf20Sopenharmony_ci kvmppc_update_vpas(vcpu); 40218c2ecf20Sopenharmony_ci 40228c2ecf20Sopenharmony_ci /* 40238c2ecf20Sopenharmony_ci * Synchronize with other threads in this virtual core 40248c2ecf20Sopenharmony_ci */ 40258c2ecf20Sopenharmony_ci vc = vcpu->arch.vcore; 40268c2ecf20Sopenharmony_ci spin_lock(&vc->lock); 40278c2ecf20Sopenharmony_ci vcpu->arch.ceded = 0; 40288c2ecf20Sopenharmony_ci vcpu->arch.run_task = current; 40298c2ecf20Sopenharmony_ci vcpu->arch.stolen_logged = vcore_stolen_time(vc, mftb()); 40308c2ecf20Sopenharmony_ci vcpu->arch.state = KVMPPC_VCPU_RUNNABLE; 40318c2ecf20Sopenharmony_ci vcpu->arch.busy_preempt = TB_NIL; 40328c2ecf20Sopenharmony_ci WRITE_ONCE(vc->runnable_threads[vcpu->arch.ptid], vcpu); 40338c2ecf20Sopenharmony_ci ++vc->n_runnable; 40348c2ecf20Sopenharmony_ci 40358c2ecf20Sopenharmony_ci /* 40368c2ecf20Sopenharmony_ci * This happens the first time this is called for a vcpu. 40378c2ecf20Sopenharmony_ci * If the vcore is already running, we may be able to start 40388c2ecf20Sopenharmony_ci * this thread straight away and have it join in. 40398c2ecf20Sopenharmony_ci */ 40408c2ecf20Sopenharmony_ci if (!signal_pending(current)) { 40418c2ecf20Sopenharmony_ci if ((vc->vcore_state == VCORE_PIGGYBACK || 40428c2ecf20Sopenharmony_ci vc->vcore_state == VCORE_RUNNING) && 40438c2ecf20Sopenharmony_ci !VCORE_IS_EXITING(vc)) { 40448c2ecf20Sopenharmony_ci kvmppc_create_dtl_entry(vcpu, vc); 40458c2ecf20Sopenharmony_ci kvmppc_start_thread(vcpu, vc); 40468c2ecf20Sopenharmony_ci trace_kvm_guest_enter(vcpu); 40478c2ecf20Sopenharmony_ci } else if (vc->vcore_state == VCORE_SLEEPING) { 40488c2ecf20Sopenharmony_ci rcuwait_wake_up(&vc->wait); 40498c2ecf20Sopenharmony_ci } 40508c2ecf20Sopenharmony_ci 40518c2ecf20Sopenharmony_ci } 40528c2ecf20Sopenharmony_ci 40538c2ecf20Sopenharmony_ci while (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE && 40548c2ecf20Sopenharmony_ci !signal_pending(current)) { 40558c2ecf20Sopenharmony_ci /* See if the MMU is ready to go */ 40568c2ecf20Sopenharmony_ci if (!vcpu->kvm->arch.mmu_ready) { 40578c2ecf20Sopenharmony_ci spin_unlock(&vc->lock); 40588c2ecf20Sopenharmony_ci r = kvmhv_setup_mmu(vcpu); 40598c2ecf20Sopenharmony_ci spin_lock(&vc->lock); 40608c2ecf20Sopenharmony_ci if (r) { 40618c2ecf20Sopenharmony_ci run->exit_reason = KVM_EXIT_FAIL_ENTRY; 40628c2ecf20Sopenharmony_ci run->fail_entry. 40638c2ecf20Sopenharmony_ci hardware_entry_failure_reason = 0; 40648c2ecf20Sopenharmony_ci vcpu->arch.ret = r; 40658c2ecf20Sopenharmony_ci break; 40668c2ecf20Sopenharmony_ci } 40678c2ecf20Sopenharmony_ci } 40688c2ecf20Sopenharmony_ci 40698c2ecf20Sopenharmony_ci if (vc->vcore_state == VCORE_PREEMPT && vc->runner == NULL) 40708c2ecf20Sopenharmony_ci kvmppc_vcore_end_preempt(vc); 40718c2ecf20Sopenharmony_ci 40728c2ecf20Sopenharmony_ci if (vc->vcore_state != VCORE_INACTIVE) { 40738c2ecf20Sopenharmony_ci kvmppc_wait_for_exec(vc, vcpu, TASK_INTERRUPTIBLE); 40748c2ecf20Sopenharmony_ci continue; 40758c2ecf20Sopenharmony_ci } 40768c2ecf20Sopenharmony_ci for_each_runnable_thread(i, v, vc) { 40778c2ecf20Sopenharmony_ci kvmppc_core_prepare_to_enter(v); 40788c2ecf20Sopenharmony_ci if (signal_pending(v->arch.run_task)) { 40798c2ecf20Sopenharmony_ci kvmppc_remove_runnable(vc, v); 40808c2ecf20Sopenharmony_ci v->stat.signal_exits++; 40818c2ecf20Sopenharmony_ci v->run->exit_reason = KVM_EXIT_INTR; 40828c2ecf20Sopenharmony_ci v->arch.ret = -EINTR; 40838c2ecf20Sopenharmony_ci wake_up(&v->arch.cpu_run); 40848c2ecf20Sopenharmony_ci } 40858c2ecf20Sopenharmony_ci } 40868c2ecf20Sopenharmony_ci if (!vc->n_runnable || vcpu->arch.state != KVMPPC_VCPU_RUNNABLE) 40878c2ecf20Sopenharmony_ci break; 40888c2ecf20Sopenharmony_ci n_ceded = 0; 40898c2ecf20Sopenharmony_ci for_each_runnable_thread(i, v, vc) { 40908c2ecf20Sopenharmony_ci if (!kvmppc_vcpu_woken(v)) 40918c2ecf20Sopenharmony_ci n_ceded += v->arch.ceded; 40928c2ecf20Sopenharmony_ci else 40938c2ecf20Sopenharmony_ci v->arch.ceded = 0; 40948c2ecf20Sopenharmony_ci } 40958c2ecf20Sopenharmony_ci vc->runner = vcpu; 40968c2ecf20Sopenharmony_ci if (n_ceded == vc->n_runnable) { 40978c2ecf20Sopenharmony_ci kvmppc_vcore_blocked(vc); 40988c2ecf20Sopenharmony_ci } else if (need_resched()) { 40998c2ecf20Sopenharmony_ci kvmppc_vcore_preempt(vc); 41008c2ecf20Sopenharmony_ci /* Let something else run */ 41018c2ecf20Sopenharmony_ci cond_resched_lock(&vc->lock); 41028c2ecf20Sopenharmony_ci if (vc->vcore_state == VCORE_PREEMPT) 41038c2ecf20Sopenharmony_ci kvmppc_vcore_end_preempt(vc); 41048c2ecf20Sopenharmony_ci } else { 41058c2ecf20Sopenharmony_ci kvmppc_run_core(vc); 41068c2ecf20Sopenharmony_ci } 41078c2ecf20Sopenharmony_ci vc->runner = NULL; 41088c2ecf20Sopenharmony_ci } 41098c2ecf20Sopenharmony_ci 41108c2ecf20Sopenharmony_ci while (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE && 41118c2ecf20Sopenharmony_ci (vc->vcore_state == VCORE_RUNNING || 41128c2ecf20Sopenharmony_ci vc->vcore_state == VCORE_EXITING || 41138c2ecf20Sopenharmony_ci vc->vcore_state == VCORE_PIGGYBACK)) 41148c2ecf20Sopenharmony_ci kvmppc_wait_for_exec(vc, vcpu, TASK_UNINTERRUPTIBLE); 41158c2ecf20Sopenharmony_ci 41168c2ecf20Sopenharmony_ci if (vc->vcore_state == VCORE_PREEMPT && vc->runner == NULL) 41178c2ecf20Sopenharmony_ci kvmppc_vcore_end_preempt(vc); 41188c2ecf20Sopenharmony_ci 41198c2ecf20Sopenharmony_ci if (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE) { 41208c2ecf20Sopenharmony_ci kvmppc_remove_runnable(vc, vcpu); 41218c2ecf20Sopenharmony_ci vcpu->stat.signal_exits++; 41228c2ecf20Sopenharmony_ci run->exit_reason = KVM_EXIT_INTR; 41238c2ecf20Sopenharmony_ci vcpu->arch.ret = -EINTR; 41248c2ecf20Sopenharmony_ci } 41258c2ecf20Sopenharmony_ci 41268c2ecf20Sopenharmony_ci if (vc->n_runnable && vc->vcore_state == VCORE_INACTIVE) { 41278c2ecf20Sopenharmony_ci /* Wake up some vcpu to run the core */ 41288c2ecf20Sopenharmony_ci i = -1; 41298c2ecf20Sopenharmony_ci v = next_runnable_thread(vc, &i); 41308c2ecf20Sopenharmony_ci wake_up(&v->arch.cpu_run); 41318c2ecf20Sopenharmony_ci } 41328c2ecf20Sopenharmony_ci 41338c2ecf20Sopenharmony_ci trace_kvmppc_run_vcpu_exit(vcpu); 41348c2ecf20Sopenharmony_ci spin_unlock(&vc->lock); 41358c2ecf20Sopenharmony_ci return vcpu->arch.ret; 41368c2ecf20Sopenharmony_ci} 41378c2ecf20Sopenharmony_ci 41388c2ecf20Sopenharmony_ciint kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit, 41398c2ecf20Sopenharmony_ci unsigned long lpcr) 41408c2ecf20Sopenharmony_ci{ 41418c2ecf20Sopenharmony_ci struct kvm_run *run = vcpu->run; 41428c2ecf20Sopenharmony_ci int trap, r, pcpu; 41438c2ecf20Sopenharmony_ci int srcu_idx, lpid; 41448c2ecf20Sopenharmony_ci struct kvmppc_vcore *vc; 41458c2ecf20Sopenharmony_ci struct kvm *kvm = vcpu->kvm; 41468c2ecf20Sopenharmony_ci struct kvm_nested_guest *nested = vcpu->arch.nested; 41478c2ecf20Sopenharmony_ci 41488c2ecf20Sopenharmony_ci trace_kvmppc_run_vcpu_enter(vcpu); 41498c2ecf20Sopenharmony_ci 41508c2ecf20Sopenharmony_ci run->exit_reason = 0; 41518c2ecf20Sopenharmony_ci vcpu->arch.ret = RESUME_GUEST; 41528c2ecf20Sopenharmony_ci vcpu->arch.trap = 0; 41538c2ecf20Sopenharmony_ci 41548c2ecf20Sopenharmony_ci vc = vcpu->arch.vcore; 41558c2ecf20Sopenharmony_ci vcpu->arch.ceded = 0; 41568c2ecf20Sopenharmony_ci vcpu->arch.run_task = current; 41578c2ecf20Sopenharmony_ci vcpu->arch.stolen_logged = vcore_stolen_time(vc, mftb()); 41588c2ecf20Sopenharmony_ci vcpu->arch.state = KVMPPC_VCPU_RUNNABLE; 41598c2ecf20Sopenharmony_ci vcpu->arch.busy_preempt = TB_NIL; 41608c2ecf20Sopenharmony_ci vcpu->arch.last_inst = KVM_INST_FETCH_FAILED; 41618c2ecf20Sopenharmony_ci vc->runnable_threads[0] = vcpu; 41628c2ecf20Sopenharmony_ci vc->n_runnable = 1; 41638c2ecf20Sopenharmony_ci vc->runner = vcpu; 41648c2ecf20Sopenharmony_ci 41658c2ecf20Sopenharmony_ci /* See if the MMU is ready to go */ 41668c2ecf20Sopenharmony_ci if (!kvm->arch.mmu_ready) 41678c2ecf20Sopenharmony_ci kvmhv_setup_mmu(vcpu); 41688c2ecf20Sopenharmony_ci 41698c2ecf20Sopenharmony_ci if (need_resched()) 41708c2ecf20Sopenharmony_ci cond_resched(); 41718c2ecf20Sopenharmony_ci 41728c2ecf20Sopenharmony_ci kvmppc_update_vpas(vcpu); 41738c2ecf20Sopenharmony_ci 41748c2ecf20Sopenharmony_ci init_vcore_to_run(vc); 41758c2ecf20Sopenharmony_ci vc->preempt_tb = TB_NIL; 41768c2ecf20Sopenharmony_ci 41778c2ecf20Sopenharmony_ci preempt_disable(); 41788c2ecf20Sopenharmony_ci pcpu = smp_processor_id(); 41798c2ecf20Sopenharmony_ci vc->pcpu = pcpu; 41808c2ecf20Sopenharmony_ci kvmppc_prepare_radix_vcpu(vcpu, pcpu); 41818c2ecf20Sopenharmony_ci 41828c2ecf20Sopenharmony_ci local_irq_disable(); 41838c2ecf20Sopenharmony_ci hard_irq_disable(); 41848c2ecf20Sopenharmony_ci if (signal_pending(current)) 41858c2ecf20Sopenharmony_ci goto sigpend; 41868c2ecf20Sopenharmony_ci if (lazy_irq_pending() || need_resched() || !kvm->arch.mmu_ready) 41878c2ecf20Sopenharmony_ci goto out; 41888c2ecf20Sopenharmony_ci 41898c2ecf20Sopenharmony_ci if (!nested) { 41908c2ecf20Sopenharmony_ci kvmppc_core_prepare_to_enter(vcpu); 41918c2ecf20Sopenharmony_ci if (vcpu->arch.doorbell_request) { 41928c2ecf20Sopenharmony_ci vc->dpdes = 1; 41938c2ecf20Sopenharmony_ci smp_wmb(); 41948c2ecf20Sopenharmony_ci vcpu->arch.doorbell_request = 0; 41958c2ecf20Sopenharmony_ci } 41968c2ecf20Sopenharmony_ci if (test_bit(BOOK3S_IRQPRIO_EXTERNAL, 41978c2ecf20Sopenharmony_ci &vcpu->arch.pending_exceptions)) 41988c2ecf20Sopenharmony_ci lpcr |= LPCR_MER; 41998c2ecf20Sopenharmony_ci } else if (vcpu->arch.pending_exceptions || 42008c2ecf20Sopenharmony_ci vcpu->arch.doorbell_request || 42018c2ecf20Sopenharmony_ci xive_interrupt_pending(vcpu)) { 42028c2ecf20Sopenharmony_ci vcpu->arch.ret = RESUME_HOST; 42038c2ecf20Sopenharmony_ci goto out; 42048c2ecf20Sopenharmony_ci } 42058c2ecf20Sopenharmony_ci 42068c2ecf20Sopenharmony_ci kvmppc_clear_host_core(pcpu); 42078c2ecf20Sopenharmony_ci 42088c2ecf20Sopenharmony_ci local_paca->kvm_hstate.tid = 0; 42098c2ecf20Sopenharmony_ci local_paca->kvm_hstate.napping = 0; 42108c2ecf20Sopenharmony_ci local_paca->kvm_hstate.kvm_split_mode = NULL; 42118c2ecf20Sopenharmony_ci kvmppc_start_thread(vcpu, vc); 42128c2ecf20Sopenharmony_ci kvmppc_create_dtl_entry(vcpu, vc); 42138c2ecf20Sopenharmony_ci trace_kvm_guest_enter(vcpu); 42148c2ecf20Sopenharmony_ci 42158c2ecf20Sopenharmony_ci vc->vcore_state = VCORE_RUNNING; 42168c2ecf20Sopenharmony_ci trace_kvmppc_run_core(vc, 0); 42178c2ecf20Sopenharmony_ci 42188c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_HVMODE)) { 42198c2ecf20Sopenharmony_ci lpid = nested ? nested->shadow_lpid : kvm->arch.lpid; 42208c2ecf20Sopenharmony_ci mtspr(SPRN_LPID, lpid); 42218c2ecf20Sopenharmony_ci isync(); 42228c2ecf20Sopenharmony_ci kvmppc_check_need_tlb_flush(kvm, pcpu, nested); 42238c2ecf20Sopenharmony_ci } 42248c2ecf20Sopenharmony_ci 42258c2ecf20Sopenharmony_ci guest_enter_irqoff(); 42268c2ecf20Sopenharmony_ci 42278c2ecf20Sopenharmony_ci srcu_idx = srcu_read_lock(&kvm->srcu); 42288c2ecf20Sopenharmony_ci 42298c2ecf20Sopenharmony_ci this_cpu_disable_ftrace(); 42308c2ecf20Sopenharmony_ci 42318c2ecf20Sopenharmony_ci /* Tell lockdep that we're about to enable interrupts */ 42328c2ecf20Sopenharmony_ci trace_hardirqs_on(); 42338c2ecf20Sopenharmony_ci 42348c2ecf20Sopenharmony_ci trap = kvmhv_p9_guest_entry(vcpu, time_limit, lpcr); 42358c2ecf20Sopenharmony_ci vcpu->arch.trap = trap; 42368c2ecf20Sopenharmony_ci 42378c2ecf20Sopenharmony_ci trace_hardirqs_off(); 42388c2ecf20Sopenharmony_ci 42398c2ecf20Sopenharmony_ci this_cpu_enable_ftrace(); 42408c2ecf20Sopenharmony_ci 42418c2ecf20Sopenharmony_ci srcu_read_unlock(&kvm->srcu, srcu_idx); 42428c2ecf20Sopenharmony_ci 42438c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_HVMODE)) { 42448c2ecf20Sopenharmony_ci mtspr(SPRN_LPID, kvm->arch.host_lpid); 42458c2ecf20Sopenharmony_ci isync(); 42468c2ecf20Sopenharmony_ci } 42478c2ecf20Sopenharmony_ci 42488c2ecf20Sopenharmony_ci set_irq_happened(trap); 42498c2ecf20Sopenharmony_ci 42508c2ecf20Sopenharmony_ci kvmppc_set_host_core(pcpu); 42518c2ecf20Sopenharmony_ci 42528c2ecf20Sopenharmony_ci context_tracking_guest_exit(); 42538c2ecf20Sopenharmony_ci if (!vtime_accounting_enabled_this_cpu()) { 42548c2ecf20Sopenharmony_ci local_irq_enable(); 42558c2ecf20Sopenharmony_ci /* 42568c2ecf20Sopenharmony_ci * Service IRQs here before vtime_account_guest_exit() so any 42578c2ecf20Sopenharmony_ci * ticks that occurred while running the guest are accounted to 42588c2ecf20Sopenharmony_ci * the guest. If vtime accounting is enabled, accounting uses 42598c2ecf20Sopenharmony_ci * TB rather than ticks, so it can be done without enabling 42608c2ecf20Sopenharmony_ci * interrupts here, which has the problem that it accounts 42618c2ecf20Sopenharmony_ci * interrupt processing overhead to the host. 42628c2ecf20Sopenharmony_ci */ 42638c2ecf20Sopenharmony_ci local_irq_disable(); 42648c2ecf20Sopenharmony_ci } 42658c2ecf20Sopenharmony_ci vtime_account_guest_exit(); 42668c2ecf20Sopenharmony_ci 42678c2ecf20Sopenharmony_ci local_irq_enable(); 42688c2ecf20Sopenharmony_ci 42698c2ecf20Sopenharmony_ci cpumask_clear_cpu(pcpu, &kvm->arch.cpu_in_guest); 42708c2ecf20Sopenharmony_ci 42718c2ecf20Sopenharmony_ci preempt_enable(); 42728c2ecf20Sopenharmony_ci 42738c2ecf20Sopenharmony_ci /* 42748c2ecf20Sopenharmony_ci * cancel pending decrementer exception if DEC is now positive, or if 42758c2ecf20Sopenharmony_ci * entering a nested guest in which case the decrementer is now owned 42768c2ecf20Sopenharmony_ci * by L2 and the L1 decrementer is provided in hdec_expires 42778c2ecf20Sopenharmony_ci */ 42788c2ecf20Sopenharmony_ci if (kvmppc_core_pending_dec(vcpu) && 42798c2ecf20Sopenharmony_ci ((get_tb() < vcpu->arch.dec_expires) || 42808c2ecf20Sopenharmony_ci (trap == BOOK3S_INTERRUPT_SYSCALL && 42818c2ecf20Sopenharmony_ci kvmppc_get_gpr(vcpu, 3) == H_ENTER_NESTED))) 42828c2ecf20Sopenharmony_ci kvmppc_core_dequeue_dec(vcpu); 42838c2ecf20Sopenharmony_ci 42848c2ecf20Sopenharmony_ci trace_kvm_guest_exit(vcpu); 42858c2ecf20Sopenharmony_ci r = RESUME_GUEST; 42868c2ecf20Sopenharmony_ci if (trap) { 42878c2ecf20Sopenharmony_ci if (!nested) 42888c2ecf20Sopenharmony_ci r = kvmppc_handle_exit_hv(vcpu, current); 42898c2ecf20Sopenharmony_ci else 42908c2ecf20Sopenharmony_ci r = kvmppc_handle_nested_exit(vcpu); 42918c2ecf20Sopenharmony_ci } 42928c2ecf20Sopenharmony_ci vcpu->arch.ret = r; 42938c2ecf20Sopenharmony_ci 42948c2ecf20Sopenharmony_ci if (is_kvmppc_resume_guest(r) && vcpu->arch.ceded && 42958c2ecf20Sopenharmony_ci !kvmppc_vcpu_woken(vcpu)) { 42968c2ecf20Sopenharmony_ci kvmppc_set_timer(vcpu); 42978c2ecf20Sopenharmony_ci while (vcpu->arch.ceded && !kvmppc_vcpu_woken(vcpu)) { 42988c2ecf20Sopenharmony_ci if (signal_pending(current)) { 42998c2ecf20Sopenharmony_ci vcpu->stat.signal_exits++; 43008c2ecf20Sopenharmony_ci run->exit_reason = KVM_EXIT_INTR; 43018c2ecf20Sopenharmony_ci vcpu->arch.ret = -EINTR; 43028c2ecf20Sopenharmony_ci break; 43038c2ecf20Sopenharmony_ci } 43048c2ecf20Sopenharmony_ci spin_lock(&vc->lock); 43058c2ecf20Sopenharmony_ci kvmppc_vcore_blocked(vc); 43068c2ecf20Sopenharmony_ci spin_unlock(&vc->lock); 43078c2ecf20Sopenharmony_ci } 43088c2ecf20Sopenharmony_ci } 43098c2ecf20Sopenharmony_ci vcpu->arch.ceded = 0; 43108c2ecf20Sopenharmony_ci 43118c2ecf20Sopenharmony_ci vc->vcore_state = VCORE_INACTIVE; 43128c2ecf20Sopenharmony_ci trace_kvmppc_run_core(vc, 1); 43138c2ecf20Sopenharmony_ci 43148c2ecf20Sopenharmony_ci done: 43158c2ecf20Sopenharmony_ci kvmppc_remove_runnable(vc, vcpu); 43168c2ecf20Sopenharmony_ci trace_kvmppc_run_vcpu_exit(vcpu); 43178c2ecf20Sopenharmony_ci 43188c2ecf20Sopenharmony_ci return vcpu->arch.ret; 43198c2ecf20Sopenharmony_ci 43208c2ecf20Sopenharmony_ci sigpend: 43218c2ecf20Sopenharmony_ci vcpu->stat.signal_exits++; 43228c2ecf20Sopenharmony_ci run->exit_reason = KVM_EXIT_INTR; 43238c2ecf20Sopenharmony_ci vcpu->arch.ret = -EINTR; 43248c2ecf20Sopenharmony_ci out: 43258c2ecf20Sopenharmony_ci local_irq_enable(); 43268c2ecf20Sopenharmony_ci preempt_enable(); 43278c2ecf20Sopenharmony_ci goto done; 43288c2ecf20Sopenharmony_ci} 43298c2ecf20Sopenharmony_ci 43308c2ecf20Sopenharmony_cistatic int kvmppc_vcpu_run_hv(struct kvm_vcpu *vcpu) 43318c2ecf20Sopenharmony_ci{ 43328c2ecf20Sopenharmony_ci struct kvm_run *run = vcpu->run; 43338c2ecf20Sopenharmony_ci int r; 43348c2ecf20Sopenharmony_ci int srcu_idx; 43358c2ecf20Sopenharmony_ci unsigned long ebb_regs[3] = {}; /* shut up GCC */ 43368c2ecf20Sopenharmony_ci unsigned long user_tar = 0; 43378c2ecf20Sopenharmony_ci unsigned int user_vrsave; 43388c2ecf20Sopenharmony_ci struct kvm *kvm; 43398c2ecf20Sopenharmony_ci 43408c2ecf20Sopenharmony_ci if (!vcpu->arch.sane) { 43418c2ecf20Sopenharmony_ci run->exit_reason = KVM_EXIT_INTERNAL_ERROR; 43428c2ecf20Sopenharmony_ci return -EINVAL; 43438c2ecf20Sopenharmony_ci } 43448c2ecf20Sopenharmony_ci 43458c2ecf20Sopenharmony_ci /* 43468c2ecf20Sopenharmony_ci * Don't allow entry with a suspended transaction, because 43478c2ecf20Sopenharmony_ci * the guest entry/exit code will lose it. 43488c2ecf20Sopenharmony_ci * If the guest has TM enabled, save away their TM-related SPRs 43498c2ecf20Sopenharmony_ci * (they will get restored by the TM unavailable interrupt). 43508c2ecf20Sopenharmony_ci */ 43518c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_TRANSACTIONAL_MEM 43528c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_TM) && current->thread.regs && 43538c2ecf20Sopenharmony_ci (current->thread.regs->msr & MSR_TM)) { 43548c2ecf20Sopenharmony_ci if (MSR_TM_ACTIVE(current->thread.regs->msr)) { 43558c2ecf20Sopenharmony_ci run->exit_reason = KVM_EXIT_FAIL_ENTRY; 43568c2ecf20Sopenharmony_ci run->fail_entry.hardware_entry_failure_reason = 0; 43578c2ecf20Sopenharmony_ci return -EINVAL; 43588c2ecf20Sopenharmony_ci } 43598c2ecf20Sopenharmony_ci /* Enable TM so we can read the TM SPRs */ 43608c2ecf20Sopenharmony_ci mtmsr(mfmsr() | MSR_TM); 43618c2ecf20Sopenharmony_ci current->thread.tm_tfhar = mfspr(SPRN_TFHAR); 43628c2ecf20Sopenharmony_ci current->thread.tm_tfiar = mfspr(SPRN_TFIAR); 43638c2ecf20Sopenharmony_ci current->thread.tm_texasr = mfspr(SPRN_TEXASR); 43648c2ecf20Sopenharmony_ci current->thread.regs->msr &= ~MSR_TM; 43658c2ecf20Sopenharmony_ci } 43668c2ecf20Sopenharmony_ci#endif 43678c2ecf20Sopenharmony_ci 43688c2ecf20Sopenharmony_ci /* 43698c2ecf20Sopenharmony_ci * Force online to 1 for the sake of old userspace which doesn't 43708c2ecf20Sopenharmony_ci * set it. 43718c2ecf20Sopenharmony_ci */ 43728c2ecf20Sopenharmony_ci if (!vcpu->arch.online) { 43738c2ecf20Sopenharmony_ci atomic_inc(&vcpu->arch.vcore->online_count); 43748c2ecf20Sopenharmony_ci vcpu->arch.online = 1; 43758c2ecf20Sopenharmony_ci } 43768c2ecf20Sopenharmony_ci 43778c2ecf20Sopenharmony_ci kvmppc_core_prepare_to_enter(vcpu); 43788c2ecf20Sopenharmony_ci 43798c2ecf20Sopenharmony_ci /* No need to go into the guest when all we'll do is come back out */ 43808c2ecf20Sopenharmony_ci if (signal_pending(current)) { 43818c2ecf20Sopenharmony_ci run->exit_reason = KVM_EXIT_INTR; 43828c2ecf20Sopenharmony_ci return -EINTR; 43838c2ecf20Sopenharmony_ci } 43848c2ecf20Sopenharmony_ci 43858c2ecf20Sopenharmony_ci kvm = vcpu->kvm; 43868c2ecf20Sopenharmony_ci atomic_inc(&kvm->arch.vcpus_running); 43878c2ecf20Sopenharmony_ci /* Order vcpus_running vs. mmu_ready, see kvmppc_alloc_reset_hpt */ 43888c2ecf20Sopenharmony_ci smp_mb(); 43898c2ecf20Sopenharmony_ci 43908c2ecf20Sopenharmony_ci flush_all_to_thread(current); 43918c2ecf20Sopenharmony_ci 43928c2ecf20Sopenharmony_ci /* Save userspace EBB and other register values */ 43938c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_207S)) { 43948c2ecf20Sopenharmony_ci ebb_regs[0] = mfspr(SPRN_EBBHR); 43958c2ecf20Sopenharmony_ci ebb_regs[1] = mfspr(SPRN_EBBRR); 43968c2ecf20Sopenharmony_ci ebb_regs[2] = mfspr(SPRN_BESCR); 43978c2ecf20Sopenharmony_ci user_tar = mfspr(SPRN_TAR); 43988c2ecf20Sopenharmony_ci } 43998c2ecf20Sopenharmony_ci user_vrsave = mfspr(SPRN_VRSAVE); 44008c2ecf20Sopenharmony_ci 44018c2ecf20Sopenharmony_ci vcpu->arch.waitp = &vcpu->arch.vcore->wait; 44028c2ecf20Sopenharmony_ci vcpu->arch.pgdir = kvm->mm->pgd; 44038c2ecf20Sopenharmony_ci vcpu->arch.state = KVMPPC_VCPU_BUSY_IN_HOST; 44048c2ecf20Sopenharmony_ci 44058c2ecf20Sopenharmony_ci do { 44068c2ecf20Sopenharmony_ci /* 44078c2ecf20Sopenharmony_ci * The early POWER9 chips that can't mix radix and HPT threads 44088c2ecf20Sopenharmony_ci * on the same core also need the workaround for the problem 44098c2ecf20Sopenharmony_ci * where the TLB would prefetch entries in the guest exit path 44108c2ecf20Sopenharmony_ci * for radix guests using the guest PIDR value and LPID 0. 44118c2ecf20Sopenharmony_ci * The workaround is in the old path (kvmppc_run_vcpu()) 44128c2ecf20Sopenharmony_ci * but not the new path (kvmhv_run_single_vcpu()). 44138c2ecf20Sopenharmony_ci */ 44148c2ecf20Sopenharmony_ci if (kvm->arch.threads_indep && kvm_is_radix(kvm) && 44158c2ecf20Sopenharmony_ci !no_mixing_hpt_and_radix) 44168c2ecf20Sopenharmony_ci r = kvmhv_run_single_vcpu(vcpu, ~(u64)0, 44178c2ecf20Sopenharmony_ci vcpu->arch.vcore->lpcr); 44188c2ecf20Sopenharmony_ci else 44198c2ecf20Sopenharmony_ci r = kvmppc_run_vcpu(vcpu); 44208c2ecf20Sopenharmony_ci 44218c2ecf20Sopenharmony_ci if (run->exit_reason == KVM_EXIT_PAPR_HCALL && 44228c2ecf20Sopenharmony_ci !(vcpu->arch.shregs.msr & MSR_PR)) { 44238c2ecf20Sopenharmony_ci trace_kvm_hcall_enter(vcpu); 44248c2ecf20Sopenharmony_ci r = kvmppc_pseries_do_hcall(vcpu); 44258c2ecf20Sopenharmony_ci trace_kvm_hcall_exit(vcpu, r); 44268c2ecf20Sopenharmony_ci kvmppc_core_prepare_to_enter(vcpu); 44278c2ecf20Sopenharmony_ci } else if (r == RESUME_PAGE_FAULT) { 44288c2ecf20Sopenharmony_ci srcu_idx = srcu_read_lock(&kvm->srcu); 44298c2ecf20Sopenharmony_ci r = kvmppc_book3s_hv_page_fault(vcpu, 44308c2ecf20Sopenharmony_ci vcpu->arch.fault_dar, vcpu->arch.fault_dsisr); 44318c2ecf20Sopenharmony_ci srcu_read_unlock(&kvm->srcu, srcu_idx); 44328c2ecf20Sopenharmony_ci } else if (r == RESUME_PASSTHROUGH) { 44338c2ecf20Sopenharmony_ci if (WARN_ON(xics_on_xive())) 44348c2ecf20Sopenharmony_ci r = H_SUCCESS; 44358c2ecf20Sopenharmony_ci else 44368c2ecf20Sopenharmony_ci r = kvmppc_xics_rm_complete(vcpu, 0); 44378c2ecf20Sopenharmony_ci } 44388c2ecf20Sopenharmony_ci } while (is_kvmppc_resume_guest(r)); 44398c2ecf20Sopenharmony_ci 44408c2ecf20Sopenharmony_ci /* Restore userspace EBB and other register values */ 44418c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_207S)) { 44428c2ecf20Sopenharmony_ci mtspr(SPRN_EBBHR, ebb_regs[0]); 44438c2ecf20Sopenharmony_ci mtspr(SPRN_EBBRR, ebb_regs[1]); 44448c2ecf20Sopenharmony_ci mtspr(SPRN_BESCR, ebb_regs[2]); 44458c2ecf20Sopenharmony_ci mtspr(SPRN_TAR, user_tar); 44468c2ecf20Sopenharmony_ci mtspr(SPRN_FSCR, current->thread.fscr); 44478c2ecf20Sopenharmony_ci } 44488c2ecf20Sopenharmony_ci mtspr(SPRN_VRSAVE, user_vrsave); 44498c2ecf20Sopenharmony_ci 44508c2ecf20Sopenharmony_ci vcpu->arch.state = KVMPPC_VCPU_NOTREADY; 44518c2ecf20Sopenharmony_ci atomic_dec(&kvm->arch.vcpus_running); 44528c2ecf20Sopenharmony_ci return r; 44538c2ecf20Sopenharmony_ci} 44548c2ecf20Sopenharmony_ci 44558c2ecf20Sopenharmony_cistatic void kvmppc_add_seg_page_size(struct kvm_ppc_one_seg_page_size **sps, 44568c2ecf20Sopenharmony_ci int shift, int sllp) 44578c2ecf20Sopenharmony_ci{ 44588c2ecf20Sopenharmony_ci (*sps)->page_shift = shift; 44598c2ecf20Sopenharmony_ci (*sps)->slb_enc = sllp; 44608c2ecf20Sopenharmony_ci (*sps)->enc[0].page_shift = shift; 44618c2ecf20Sopenharmony_ci (*sps)->enc[0].pte_enc = kvmppc_pgsize_lp_encoding(shift, shift); 44628c2ecf20Sopenharmony_ci /* 44638c2ecf20Sopenharmony_ci * Add 16MB MPSS support (may get filtered out by userspace) 44648c2ecf20Sopenharmony_ci */ 44658c2ecf20Sopenharmony_ci if (shift != 24) { 44668c2ecf20Sopenharmony_ci int penc = kvmppc_pgsize_lp_encoding(shift, 24); 44678c2ecf20Sopenharmony_ci if (penc != -1) { 44688c2ecf20Sopenharmony_ci (*sps)->enc[1].page_shift = 24; 44698c2ecf20Sopenharmony_ci (*sps)->enc[1].pte_enc = penc; 44708c2ecf20Sopenharmony_ci } 44718c2ecf20Sopenharmony_ci } 44728c2ecf20Sopenharmony_ci (*sps)++; 44738c2ecf20Sopenharmony_ci} 44748c2ecf20Sopenharmony_ci 44758c2ecf20Sopenharmony_cistatic int kvm_vm_ioctl_get_smmu_info_hv(struct kvm *kvm, 44768c2ecf20Sopenharmony_ci struct kvm_ppc_smmu_info *info) 44778c2ecf20Sopenharmony_ci{ 44788c2ecf20Sopenharmony_ci struct kvm_ppc_one_seg_page_size *sps; 44798c2ecf20Sopenharmony_ci 44808c2ecf20Sopenharmony_ci /* 44818c2ecf20Sopenharmony_ci * POWER7, POWER8 and POWER9 all support 32 storage keys for data. 44828c2ecf20Sopenharmony_ci * POWER7 doesn't support keys for instruction accesses, 44838c2ecf20Sopenharmony_ci * POWER8 and POWER9 do. 44848c2ecf20Sopenharmony_ci */ 44858c2ecf20Sopenharmony_ci info->data_keys = 32; 44868c2ecf20Sopenharmony_ci info->instr_keys = cpu_has_feature(CPU_FTR_ARCH_207S) ? 32 : 0; 44878c2ecf20Sopenharmony_ci 44888c2ecf20Sopenharmony_ci /* POWER7, 8 and 9 all have 1T segments and 32-entry SLB */ 44898c2ecf20Sopenharmony_ci info->flags = KVM_PPC_PAGE_SIZES_REAL | KVM_PPC_1T_SEGMENTS; 44908c2ecf20Sopenharmony_ci info->slb_size = 32; 44918c2ecf20Sopenharmony_ci 44928c2ecf20Sopenharmony_ci /* We only support these sizes for now, and no muti-size segments */ 44938c2ecf20Sopenharmony_ci sps = &info->sps[0]; 44948c2ecf20Sopenharmony_ci kvmppc_add_seg_page_size(&sps, 12, 0); 44958c2ecf20Sopenharmony_ci kvmppc_add_seg_page_size(&sps, 16, SLB_VSID_L | SLB_VSID_LP_01); 44968c2ecf20Sopenharmony_ci kvmppc_add_seg_page_size(&sps, 24, SLB_VSID_L); 44978c2ecf20Sopenharmony_ci 44988c2ecf20Sopenharmony_ci /* If running as a nested hypervisor, we don't support HPT guests */ 44998c2ecf20Sopenharmony_ci if (kvmhv_on_pseries()) 45008c2ecf20Sopenharmony_ci info->flags |= KVM_PPC_NO_HASH; 45018c2ecf20Sopenharmony_ci 45028c2ecf20Sopenharmony_ci return 0; 45038c2ecf20Sopenharmony_ci} 45048c2ecf20Sopenharmony_ci 45058c2ecf20Sopenharmony_ci/* 45068c2ecf20Sopenharmony_ci * Get (and clear) the dirty memory log for a memory slot. 45078c2ecf20Sopenharmony_ci */ 45088c2ecf20Sopenharmony_cistatic int kvm_vm_ioctl_get_dirty_log_hv(struct kvm *kvm, 45098c2ecf20Sopenharmony_ci struct kvm_dirty_log *log) 45108c2ecf20Sopenharmony_ci{ 45118c2ecf20Sopenharmony_ci struct kvm_memslots *slots; 45128c2ecf20Sopenharmony_ci struct kvm_memory_slot *memslot; 45138c2ecf20Sopenharmony_ci int i, r; 45148c2ecf20Sopenharmony_ci unsigned long n; 45158c2ecf20Sopenharmony_ci unsigned long *buf, *p; 45168c2ecf20Sopenharmony_ci struct kvm_vcpu *vcpu; 45178c2ecf20Sopenharmony_ci 45188c2ecf20Sopenharmony_ci mutex_lock(&kvm->slots_lock); 45198c2ecf20Sopenharmony_ci 45208c2ecf20Sopenharmony_ci r = -EINVAL; 45218c2ecf20Sopenharmony_ci if (log->slot >= KVM_USER_MEM_SLOTS) 45228c2ecf20Sopenharmony_ci goto out; 45238c2ecf20Sopenharmony_ci 45248c2ecf20Sopenharmony_ci slots = kvm_memslots(kvm); 45258c2ecf20Sopenharmony_ci memslot = id_to_memslot(slots, log->slot); 45268c2ecf20Sopenharmony_ci r = -ENOENT; 45278c2ecf20Sopenharmony_ci if (!memslot || !memslot->dirty_bitmap) 45288c2ecf20Sopenharmony_ci goto out; 45298c2ecf20Sopenharmony_ci 45308c2ecf20Sopenharmony_ci /* 45318c2ecf20Sopenharmony_ci * Use second half of bitmap area because both HPT and radix 45328c2ecf20Sopenharmony_ci * accumulate bits in the first half. 45338c2ecf20Sopenharmony_ci */ 45348c2ecf20Sopenharmony_ci n = kvm_dirty_bitmap_bytes(memslot); 45358c2ecf20Sopenharmony_ci buf = memslot->dirty_bitmap + n / sizeof(long); 45368c2ecf20Sopenharmony_ci memset(buf, 0, n); 45378c2ecf20Sopenharmony_ci 45388c2ecf20Sopenharmony_ci if (kvm_is_radix(kvm)) 45398c2ecf20Sopenharmony_ci r = kvmppc_hv_get_dirty_log_radix(kvm, memslot, buf); 45408c2ecf20Sopenharmony_ci else 45418c2ecf20Sopenharmony_ci r = kvmppc_hv_get_dirty_log_hpt(kvm, memslot, buf); 45428c2ecf20Sopenharmony_ci if (r) 45438c2ecf20Sopenharmony_ci goto out; 45448c2ecf20Sopenharmony_ci 45458c2ecf20Sopenharmony_ci /* 45468c2ecf20Sopenharmony_ci * We accumulate dirty bits in the first half of the 45478c2ecf20Sopenharmony_ci * memslot's dirty_bitmap area, for when pages are paged 45488c2ecf20Sopenharmony_ci * out or modified by the host directly. Pick up these 45498c2ecf20Sopenharmony_ci * bits and add them to the map. 45508c2ecf20Sopenharmony_ci */ 45518c2ecf20Sopenharmony_ci p = memslot->dirty_bitmap; 45528c2ecf20Sopenharmony_ci for (i = 0; i < n / sizeof(long); ++i) 45538c2ecf20Sopenharmony_ci buf[i] |= xchg(&p[i], 0); 45548c2ecf20Sopenharmony_ci 45558c2ecf20Sopenharmony_ci /* Harvest dirty bits from VPA and DTL updates */ 45568c2ecf20Sopenharmony_ci /* Note: we never modify the SLB shadow buffer areas */ 45578c2ecf20Sopenharmony_ci kvm_for_each_vcpu(i, vcpu, kvm) { 45588c2ecf20Sopenharmony_ci spin_lock(&vcpu->arch.vpa_update_lock); 45598c2ecf20Sopenharmony_ci kvmppc_harvest_vpa_dirty(&vcpu->arch.vpa, memslot, buf); 45608c2ecf20Sopenharmony_ci kvmppc_harvest_vpa_dirty(&vcpu->arch.dtl, memslot, buf); 45618c2ecf20Sopenharmony_ci spin_unlock(&vcpu->arch.vpa_update_lock); 45628c2ecf20Sopenharmony_ci } 45638c2ecf20Sopenharmony_ci 45648c2ecf20Sopenharmony_ci r = -EFAULT; 45658c2ecf20Sopenharmony_ci if (copy_to_user(log->dirty_bitmap, buf, n)) 45668c2ecf20Sopenharmony_ci goto out; 45678c2ecf20Sopenharmony_ci 45688c2ecf20Sopenharmony_ci r = 0; 45698c2ecf20Sopenharmony_ciout: 45708c2ecf20Sopenharmony_ci mutex_unlock(&kvm->slots_lock); 45718c2ecf20Sopenharmony_ci return r; 45728c2ecf20Sopenharmony_ci} 45738c2ecf20Sopenharmony_ci 45748c2ecf20Sopenharmony_cistatic void kvmppc_core_free_memslot_hv(struct kvm_memory_slot *slot) 45758c2ecf20Sopenharmony_ci{ 45768c2ecf20Sopenharmony_ci vfree(slot->arch.rmap); 45778c2ecf20Sopenharmony_ci slot->arch.rmap = NULL; 45788c2ecf20Sopenharmony_ci} 45798c2ecf20Sopenharmony_ci 45808c2ecf20Sopenharmony_cistatic int kvmppc_core_prepare_memory_region_hv(struct kvm *kvm, 45818c2ecf20Sopenharmony_ci struct kvm_memory_slot *slot, 45828c2ecf20Sopenharmony_ci const struct kvm_userspace_memory_region *mem, 45838c2ecf20Sopenharmony_ci enum kvm_mr_change change) 45848c2ecf20Sopenharmony_ci{ 45858c2ecf20Sopenharmony_ci unsigned long npages = mem->memory_size >> PAGE_SHIFT; 45868c2ecf20Sopenharmony_ci 45878c2ecf20Sopenharmony_ci if (change == KVM_MR_CREATE) { 45888c2ecf20Sopenharmony_ci unsigned long size = array_size(npages, sizeof(*slot->arch.rmap)); 45898c2ecf20Sopenharmony_ci 45908c2ecf20Sopenharmony_ci if ((size >> PAGE_SHIFT) > totalram_pages()) 45918c2ecf20Sopenharmony_ci return -ENOMEM; 45928c2ecf20Sopenharmony_ci 45938c2ecf20Sopenharmony_ci slot->arch.rmap = vzalloc(size); 45948c2ecf20Sopenharmony_ci if (!slot->arch.rmap) 45958c2ecf20Sopenharmony_ci return -ENOMEM; 45968c2ecf20Sopenharmony_ci } 45978c2ecf20Sopenharmony_ci 45988c2ecf20Sopenharmony_ci return 0; 45998c2ecf20Sopenharmony_ci} 46008c2ecf20Sopenharmony_ci 46018c2ecf20Sopenharmony_cistatic void kvmppc_core_commit_memory_region_hv(struct kvm *kvm, 46028c2ecf20Sopenharmony_ci const struct kvm_userspace_memory_region *mem, 46038c2ecf20Sopenharmony_ci const struct kvm_memory_slot *old, 46048c2ecf20Sopenharmony_ci const struct kvm_memory_slot *new, 46058c2ecf20Sopenharmony_ci enum kvm_mr_change change) 46068c2ecf20Sopenharmony_ci{ 46078c2ecf20Sopenharmony_ci unsigned long npages = mem->memory_size >> PAGE_SHIFT; 46088c2ecf20Sopenharmony_ci 46098c2ecf20Sopenharmony_ci /* 46108c2ecf20Sopenharmony_ci * If we are making a new memslot, it might make 46118c2ecf20Sopenharmony_ci * some address that was previously cached as emulated 46128c2ecf20Sopenharmony_ci * MMIO be no longer emulated MMIO, so invalidate 46138c2ecf20Sopenharmony_ci * all the caches of emulated MMIO translations. 46148c2ecf20Sopenharmony_ci */ 46158c2ecf20Sopenharmony_ci if (npages) 46168c2ecf20Sopenharmony_ci atomic64_inc(&kvm->arch.mmio_update); 46178c2ecf20Sopenharmony_ci 46188c2ecf20Sopenharmony_ci /* 46198c2ecf20Sopenharmony_ci * For change == KVM_MR_MOVE or KVM_MR_DELETE, higher levels 46208c2ecf20Sopenharmony_ci * have already called kvm_arch_flush_shadow_memslot() to 46218c2ecf20Sopenharmony_ci * flush shadow mappings. For KVM_MR_CREATE we have no 46228c2ecf20Sopenharmony_ci * previous mappings. So the only case to handle is 46238c2ecf20Sopenharmony_ci * KVM_MR_FLAGS_ONLY when the KVM_MEM_LOG_DIRTY_PAGES bit 46248c2ecf20Sopenharmony_ci * has been changed. 46258c2ecf20Sopenharmony_ci * For radix guests, we flush on setting KVM_MEM_LOG_DIRTY_PAGES 46268c2ecf20Sopenharmony_ci * to get rid of any THP PTEs in the partition-scoped page tables 46278c2ecf20Sopenharmony_ci * so we can track dirtiness at the page level; we flush when 46288c2ecf20Sopenharmony_ci * clearing KVM_MEM_LOG_DIRTY_PAGES so that we can go back to 46298c2ecf20Sopenharmony_ci * using THP PTEs. 46308c2ecf20Sopenharmony_ci */ 46318c2ecf20Sopenharmony_ci if (change == KVM_MR_FLAGS_ONLY && kvm_is_radix(kvm) && 46328c2ecf20Sopenharmony_ci ((new->flags ^ old->flags) & KVM_MEM_LOG_DIRTY_PAGES)) 46338c2ecf20Sopenharmony_ci kvmppc_radix_flush_memslot(kvm, old); 46348c2ecf20Sopenharmony_ci /* 46358c2ecf20Sopenharmony_ci * If UV hasn't yet called H_SVM_INIT_START, don't register memslots. 46368c2ecf20Sopenharmony_ci */ 46378c2ecf20Sopenharmony_ci if (!kvm->arch.secure_guest) 46388c2ecf20Sopenharmony_ci return; 46398c2ecf20Sopenharmony_ci 46408c2ecf20Sopenharmony_ci switch (change) { 46418c2ecf20Sopenharmony_ci case KVM_MR_CREATE: 46428c2ecf20Sopenharmony_ci /* 46438c2ecf20Sopenharmony_ci * @TODO kvmppc_uvmem_memslot_create() can fail and 46448c2ecf20Sopenharmony_ci * return error. Fix this. 46458c2ecf20Sopenharmony_ci */ 46468c2ecf20Sopenharmony_ci kvmppc_uvmem_memslot_create(kvm, new); 46478c2ecf20Sopenharmony_ci break; 46488c2ecf20Sopenharmony_ci case KVM_MR_DELETE: 46498c2ecf20Sopenharmony_ci kvmppc_uvmem_memslot_delete(kvm, old); 46508c2ecf20Sopenharmony_ci break; 46518c2ecf20Sopenharmony_ci default: 46528c2ecf20Sopenharmony_ci /* TODO: Handle KVM_MR_MOVE */ 46538c2ecf20Sopenharmony_ci break; 46548c2ecf20Sopenharmony_ci } 46558c2ecf20Sopenharmony_ci} 46568c2ecf20Sopenharmony_ci 46578c2ecf20Sopenharmony_ci/* 46588c2ecf20Sopenharmony_ci * Update LPCR values in kvm->arch and in vcores. 46598c2ecf20Sopenharmony_ci * Caller must hold kvm->arch.mmu_setup_lock (for mutual exclusion 46608c2ecf20Sopenharmony_ci * of kvm->arch.lpcr update). 46618c2ecf20Sopenharmony_ci */ 46628c2ecf20Sopenharmony_civoid kvmppc_update_lpcr(struct kvm *kvm, unsigned long lpcr, unsigned long mask) 46638c2ecf20Sopenharmony_ci{ 46648c2ecf20Sopenharmony_ci long int i; 46658c2ecf20Sopenharmony_ci u32 cores_done = 0; 46668c2ecf20Sopenharmony_ci 46678c2ecf20Sopenharmony_ci if ((kvm->arch.lpcr & mask) == lpcr) 46688c2ecf20Sopenharmony_ci return; 46698c2ecf20Sopenharmony_ci 46708c2ecf20Sopenharmony_ci kvm->arch.lpcr = (kvm->arch.lpcr & ~mask) | lpcr; 46718c2ecf20Sopenharmony_ci 46728c2ecf20Sopenharmony_ci for (i = 0; i < KVM_MAX_VCORES; ++i) { 46738c2ecf20Sopenharmony_ci struct kvmppc_vcore *vc = kvm->arch.vcores[i]; 46748c2ecf20Sopenharmony_ci if (!vc) 46758c2ecf20Sopenharmony_ci continue; 46768c2ecf20Sopenharmony_ci spin_lock(&vc->lock); 46778c2ecf20Sopenharmony_ci vc->lpcr = (vc->lpcr & ~mask) | lpcr; 46788c2ecf20Sopenharmony_ci spin_unlock(&vc->lock); 46798c2ecf20Sopenharmony_ci if (++cores_done >= kvm->arch.online_vcores) 46808c2ecf20Sopenharmony_ci break; 46818c2ecf20Sopenharmony_ci } 46828c2ecf20Sopenharmony_ci} 46838c2ecf20Sopenharmony_ci 46848c2ecf20Sopenharmony_civoid kvmppc_setup_partition_table(struct kvm *kvm) 46858c2ecf20Sopenharmony_ci{ 46868c2ecf20Sopenharmony_ci unsigned long dw0, dw1; 46878c2ecf20Sopenharmony_ci 46888c2ecf20Sopenharmony_ci if (!kvm_is_radix(kvm)) { 46898c2ecf20Sopenharmony_ci /* PS field - page size for VRMA */ 46908c2ecf20Sopenharmony_ci dw0 = ((kvm->arch.vrma_slb_v & SLB_VSID_L) >> 1) | 46918c2ecf20Sopenharmony_ci ((kvm->arch.vrma_slb_v & SLB_VSID_LP) << 1); 46928c2ecf20Sopenharmony_ci /* HTABSIZE and HTABORG fields */ 46938c2ecf20Sopenharmony_ci dw0 |= kvm->arch.sdr1; 46948c2ecf20Sopenharmony_ci 46958c2ecf20Sopenharmony_ci /* Second dword as set by userspace */ 46968c2ecf20Sopenharmony_ci dw1 = kvm->arch.process_table; 46978c2ecf20Sopenharmony_ci } else { 46988c2ecf20Sopenharmony_ci dw0 = PATB_HR | radix__get_tree_size() | 46998c2ecf20Sopenharmony_ci __pa(kvm->arch.pgtable) | RADIX_PGD_INDEX_SIZE; 47008c2ecf20Sopenharmony_ci dw1 = PATB_GR | kvm->arch.process_table; 47018c2ecf20Sopenharmony_ci } 47028c2ecf20Sopenharmony_ci kvmhv_set_ptbl_entry(kvm->arch.lpid, dw0, dw1); 47038c2ecf20Sopenharmony_ci} 47048c2ecf20Sopenharmony_ci 47058c2ecf20Sopenharmony_ci/* 47068c2ecf20Sopenharmony_ci * Set up HPT (hashed page table) and RMA (real-mode area). 47078c2ecf20Sopenharmony_ci * Must be called with kvm->arch.mmu_setup_lock held. 47088c2ecf20Sopenharmony_ci */ 47098c2ecf20Sopenharmony_cistatic int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu) 47108c2ecf20Sopenharmony_ci{ 47118c2ecf20Sopenharmony_ci int err = 0; 47128c2ecf20Sopenharmony_ci struct kvm *kvm = vcpu->kvm; 47138c2ecf20Sopenharmony_ci unsigned long hva; 47148c2ecf20Sopenharmony_ci struct kvm_memory_slot *memslot; 47158c2ecf20Sopenharmony_ci struct vm_area_struct *vma; 47168c2ecf20Sopenharmony_ci unsigned long lpcr = 0, senc; 47178c2ecf20Sopenharmony_ci unsigned long psize, porder; 47188c2ecf20Sopenharmony_ci int srcu_idx; 47198c2ecf20Sopenharmony_ci 47208c2ecf20Sopenharmony_ci /* Allocate hashed page table (if not done already) and reset it */ 47218c2ecf20Sopenharmony_ci if (!kvm->arch.hpt.virt) { 47228c2ecf20Sopenharmony_ci int order = KVM_DEFAULT_HPT_ORDER; 47238c2ecf20Sopenharmony_ci struct kvm_hpt_info info; 47248c2ecf20Sopenharmony_ci 47258c2ecf20Sopenharmony_ci err = kvmppc_allocate_hpt(&info, order); 47268c2ecf20Sopenharmony_ci /* If we get here, it means userspace didn't specify a 47278c2ecf20Sopenharmony_ci * size explicitly. So, try successively smaller 47288c2ecf20Sopenharmony_ci * sizes if the default failed. */ 47298c2ecf20Sopenharmony_ci while ((err == -ENOMEM) && --order >= PPC_MIN_HPT_ORDER) 47308c2ecf20Sopenharmony_ci err = kvmppc_allocate_hpt(&info, order); 47318c2ecf20Sopenharmony_ci 47328c2ecf20Sopenharmony_ci if (err < 0) { 47338c2ecf20Sopenharmony_ci pr_err("KVM: Couldn't alloc HPT\n"); 47348c2ecf20Sopenharmony_ci goto out; 47358c2ecf20Sopenharmony_ci } 47368c2ecf20Sopenharmony_ci 47378c2ecf20Sopenharmony_ci kvmppc_set_hpt(kvm, &info); 47388c2ecf20Sopenharmony_ci } 47398c2ecf20Sopenharmony_ci 47408c2ecf20Sopenharmony_ci /* Look up the memslot for guest physical address 0 */ 47418c2ecf20Sopenharmony_ci srcu_idx = srcu_read_lock(&kvm->srcu); 47428c2ecf20Sopenharmony_ci memslot = gfn_to_memslot(kvm, 0); 47438c2ecf20Sopenharmony_ci 47448c2ecf20Sopenharmony_ci /* We must have some memory at 0 by now */ 47458c2ecf20Sopenharmony_ci err = -EINVAL; 47468c2ecf20Sopenharmony_ci if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID)) 47478c2ecf20Sopenharmony_ci goto out_srcu; 47488c2ecf20Sopenharmony_ci 47498c2ecf20Sopenharmony_ci /* Look up the VMA for the start of this memory slot */ 47508c2ecf20Sopenharmony_ci hva = memslot->userspace_addr; 47518c2ecf20Sopenharmony_ci mmap_read_lock(kvm->mm); 47528c2ecf20Sopenharmony_ci vma = find_vma(kvm->mm, hva); 47538c2ecf20Sopenharmony_ci if (!vma || vma->vm_start > hva || (vma->vm_flags & VM_IO)) 47548c2ecf20Sopenharmony_ci goto up_out; 47558c2ecf20Sopenharmony_ci 47568c2ecf20Sopenharmony_ci psize = vma_kernel_pagesize(vma); 47578c2ecf20Sopenharmony_ci 47588c2ecf20Sopenharmony_ci mmap_read_unlock(kvm->mm); 47598c2ecf20Sopenharmony_ci 47608c2ecf20Sopenharmony_ci /* We can handle 4k, 64k or 16M pages in the VRMA */ 47618c2ecf20Sopenharmony_ci if (psize >= 0x1000000) 47628c2ecf20Sopenharmony_ci psize = 0x1000000; 47638c2ecf20Sopenharmony_ci else if (psize >= 0x10000) 47648c2ecf20Sopenharmony_ci psize = 0x10000; 47658c2ecf20Sopenharmony_ci else 47668c2ecf20Sopenharmony_ci psize = 0x1000; 47678c2ecf20Sopenharmony_ci porder = __ilog2(psize); 47688c2ecf20Sopenharmony_ci 47698c2ecf20Sopenharmony_ci senc = slb_pgsize_encoding(psize); 47708c2ecf20Sopenharmony_ci kvm->arch.vrma_slb_v = senc | SLB_VSID_B_1T | 47718c2ecf20Sopenharmony_ci (VRMA_VSID << SLB_VSID_SHIFT_1T); 47728c2ecf20Sopenharmony_ci /* Create HPTEs in the hash page table for the VRMA */ 47738c2ecf20Sopenharmony_ci kvmppc_map_vrma(vcpu, memslot, porder); 47748c2ecf20Sopenharmony_ci 47758c2ecf20Sopenharmony_ci /* Update VRMASD field in the LPCR */ 47768c2ecf20Sopenharmony_ci if (!cpu_has_feature(CPU_FTR_ARCH_300)) { 47778c2ecf20Sopenharmony_ci /* the -4 is to account for senc values starting at 0x10 */ 47788c2ecf20Sopenharmony_ci lpcr = senc << (LPCR_VRMASD_SH - 4); 47798c2ecf20Sopenharmony_ci kvmppc_update_lpcr(kvm, lpcr, LPCR_VRMASD); 47808c2ecf20Sopenharmony_ci } 47818c2ecf20Sopenharmony_ci 47828c2ecf20Sopenharmony_ci /* Order updates to kvm->arch.lpcr etc. vs. mmu_ready */ 47838c2ecf20Sopenharmony_ci smp_wmb(); 47848c2ecf20Sopenharmony_ci err = 0; 47858c2ecf20Sopenharmony_ci out_srcu: 47868c2ecf20Sopenharmony_ci srcu_read_unlock(&kvm->srcu, srcu_idx); 47878c2ecf20Sopenharmony_ci out: 47888c2ecf20Sopenharmony_ci return err; 47898c2ecf20Sopenharmony_ci 47908c2ecf20Sopenharmony_ci up_out: 47918c2ecf20Sopenharmony_ci mmap_read_unlock(kvm->mm); 47928c2ecf20Sopenharmony_ci goto out_srcu; 47938c2ecf20Sopenharmony_ci} 47948c2ecf20Sopenharmony_ci 47958c2ecf20Sopenharmony_ci/* 47968c2ecf20Sopenharmony_ci * Must be called with kvm->arch.mmu_setup_lock held and 47978c2ecf20Sopenharmony_ci * mmu_ready = 0 and no vcpus running. 47988c2ecf20Sopenharmony_ci */ 47998c2ecf20Sopenharmony_ciint kvmppc_switch_mmu_to_hpt(struct kvm *kvm) 48008c2ecf20Sopenharmony_ci{ 48018c2ecf20Sopenharmony_ci if (nesting_enabled(kvm)) 48028c2ecf20Sopenharmony_ci kvmhv_release_all_nested(kvm); 48038c2ecf20Sopenharmony_ci kvmppc_rmap_reset(kvm); 48048c2ecf20Sopenharmony_ci kvm->arch.process_table = 0; 48058c2ecf20Sopenharmony_ci /* Mutual exclusion with kvm_unmap_hva_range etc. */ 48068c2ecf20Sopenharmony_ci spin_lock(&kvm->mmu_lock); 48078c2ecf20Sopenharmony_ci kvm->arch.radix = 0; 48088c2ecf20Sopenharmony_ci spin_unlock(&kvm->mmu_lock); 48098c2ecf20Sopenharmony_ci kvmppc_free_radix(kvm); 48108c2ecf20Sopenharmony_ci kvmppc_update_lpcr(kvm, LPCR_VPM1, 48118c2ecf20Sopenharmony_ci LPCR_VPM1 | LPCR_UPRT | LPCR_GTSE | LPCR_HR); 48128c2ecf20Sopenharmony_ci return 0; 48138c2ecf20Sopenharmony_ci} 48148c2ecf20Sopenharmony_ci 48158c2ecf20Sopenharmony_ci/* 48168c2ecf20Sopenharmony_ci * Must be called with kvm->arch.mmu_setup_lock held and 48178c2ecf20Sopenharmony_ci * mmu_ready = 0 and no vcpus running. 48188c2ecf20Sopenharmony_ci */ 48198c2ecf20Sopenharmony_ciint kvmppc_switch_mmu_to_radix(struct kvm *kvm) 48208c2ecf20Sopenharmony_ci{ 48218c2ecf20Sopenharmony_ci int err; 48228c2ecf20Sopenharmony_ci 48238c2ecf20Sopenharmony_ci err = kvmppc_init_vm_radix(kvm); 48248c2ecf20Sopenharmony_ci if (err) 48258c2ecf20Sopenharmony_ci return err; 48268c2ecf20Sopenharmony_ci kvmppc_rmap_reset(kvm); 48278c2ecf20Sopenharmony_ci /* Mutual exclusion with kvm_unmap_hva_range etc. */ 48288c2ecf20Sopenharmony_ci spin_lock(&kvm->mmu_lock); 48298c2ecf20Sopenharmony_ci kvm->arch.radix = 1; 48308c2ecf20Sopenharmony_ci spin_unlock(&kvm->mmu_lock); 48318c2ecf20Sopenharmony_ci kvmppc_free_hpt(&kvm->arch.hpt); 48328c2ecf20Sopenharmony_ci kvmppc_update_lpcr(kvm, LPCR_UPRT | LPCR_GTSE | LPCR_HR, 48338c2ecf20Sopenharmony_ci LPCR_VPM1 | LPCR_UPRT | LPCR_GTSE | LPCR_HR); 48348c2ecf20Sopenharmony_ci return 0; 48358c2ecf20Sopenharmony_ci} 48368c2ecf20Sopenharmony_ci 48378c2ecf20Sopenharmony_ci#ifdef CONFIG_KVM_XICS 48388c2ecf20Sopenharmony_ci/* 48398c2ecf20Sopenharmony_ci * Allocate a per-core structure for managing state about which cores are 48408c2ecf20Sopenharmony_ci * running in the host versus the guest and for exchanging data between 48418c2ecf20Sopenharmony_ci * real mode KVM and CPU running in the host. 48428c2ecf20Sopenharmony_ci * This is only done for the first VM. 48438c2ecf20Sopenharmony_ci * The allocated structure stays even if all VMs have stopped. 48448c2ecf20Sopenharmony_ci * It is only freed when the kvm-hv module is unloaded. 48458c2ecf20Sopenharmony_ci * It's OK for this routine to fail, we just don't support host 48468c2ecf20Sopenharmony_ci * core operations like redirecting H_IPI wakeups. 48478c2ecf20Sopenharmony_ci */ 48488c2ecf20Sopenharmony_civoid kvmppc_alloc_host_rm_ops(void) 48498c2ecf20Sopenharmony_ci{ 48508c2ecf20Sopenharmony_ci struct kvmppc_host_rm_ops *ops; 48518c2ecf20Sopenharmony_ci unsigned long l_ops; 48528c2ecf20Sopenharmony_ci int cpu, core; 48538c2ecf20Sopenharmony_ci int size; 48548c2ecf20Sopenharmony_ci 48558c2ecf20Sopenharmony_ci /* Not the first time here ? */ 48568c2ecf20Sopenharmony_ci if (kvmppc_host_rm_ops_hv != NULL) 48578c2ecf20Sopenharmony_ci return; 48588c2ecf20Sopenharmony_ci 48598c2ecf20Sopenharmony_ci ops = kzalloc(sizeof(struct kvmppc_host_rm_ops), GFP_KERNEL); 48608c2ecf20Sopenharmony_ci if (!ops) 48618c2ecf20Sopenharmony_ci return; 48628c2ecf20Sopenharmony_ci 48638c2ecf20Sopenharmony_ci size = cpu_nr_cores() * sizeof(struct kvmppc_host_rm_core); 48648c2ecf20Sopenharmony_ci ops->rm_core = kzalloc(size, GFP_KERNEL); 48658c2ecf20Sopenharmony_ci 48668c2ecf20Sopenharmony_ci if (!ops->rm_core) { 48678c2ecf20Sopenharmony_ci kfree(ops); 48688c2ecf20Sopenharmony_ci return; 48698c2ecf20Sopenharmony_ci } 48708c2ecf20Sopenharmony_ci 48718c2ecf20Sopenharmony_ci cpus_read_lock(); 48728c2ecf20Sopenharmony_ci 48738c2ecf20Sopenharmony_ci for (cpu = 0; cpu < nr_cpu_ids; cpu += threads_per_core) { 48748c2ecf20Sopenharmony_ci if (!cpu_online(cpu)) 48758c2ecf20Sopenharmony_ci continue; 48768c2ecf20Sopenharmony_ci 48778c2ecf20Sopenharmony_ci core = cpu >> threads_shift; 48788c2ecf20Sopenharmony_ci ops->rm_core[core].rm_state.in_host = 1; 48798c2ecf20Sopenharmony_ci } 48808c2ecf20Sopenharmony_ci 48818c2ecf20Sopenharmony_ci ops->vcpu_kick = kvmppc_fast_vcpu_kick_hv; 48828c2ecf20Sopenharmony_ci 48838c2ecf20Sopenharmony_ci /* 48848c2ecf20Sopenharmony_ci * Make the contents of the kvmppc_host_rm_ops structure visible 48858c2ecf20Sopenharmony_ci * to other CPUs before we assign it to the global variable. 48868c2ecf20Sopenharmony_ci * Do an atomic assignment (no locks used here), but if someone 48878c2ecf20Sopenharmony_ci * beats us to it, just free our copy and return. 48888c2ecf20Sopenharmony_ci */ 48898c2ecf20Sopenharmony_ci smp_wmb(); 48908c2ecf20Sopenharmony_ci l_ops = (unsigned long) ops; 48918c2ecf20Sopenharmony_ci 48928c2ecf20Sopenharmony_ci if (cmpxchg64((unsigned long *)&kvmppc_host_rm_ops_hv, 0, l_ops)) { 48938c2ecf20Sopenharmony_ci cpus_read_unlock(); 48948c2ecf20Sopenharmony_ci kfree(ops->rm_core); 48958c2ecf20Sopenharmony_ci kfree(ops); 48968c2ecf20Sopenharmony_ci return; 48978c2ecf20Sopenharmony_ci } 48988c2ecf20Sopenharmony_ci 48998c2ecf20Sopenharmony_ci cpuhp_setup_state_nocalls_cpuslocked(CPUHP_KVM_PPC_BOOK3S_PREPARE, 49008c2ecf20Sopenharmony_ci "ppc/kvm_book3s:prepare", 49018c2ecf20Sopenharmony_ci kvmppc_set_host_core, 49028c2ecf20Sopenharmony_ci kvmppc_clear_host_core); 49038c2ecf20Sopenharmony_ci cpus_read_unlock(); 49048c2ecf20Sopenharmony_ci} 49058c2ecf20Sopenharmony_ci 49068c2ecf20Sopenharmony_civoid kvmppc_free_host_rm_ops(void) 49078c2ecf20Sopenharmony_ci{ 49088c2ecf20Sopenharmony_ci if (kvmppc_host_rm_ops_hv) { 49098c2ecf20Sopenharmony_ci cpuhp_remove_state_nocalls(CPUHP_KVM_PPC_BOOK3S_PREPARE); 49108c2ecf20Sopenharmony_ci kfree(kvmppc_host_rm_ops_hv->rm_core); 49118c2ecf20Sopenharmony_ci kfree(kvmppc_host_rm_ops_hv); 49128c2ecf20Sopenharmony_ci kvmppc_host_rm_ops_hv = NULL; 49138c2ecf20Sopenharmony_ci } 49148c2ecf20Sopenharmony_ci} 49158c2ecf20Sopenharmony_ci#endif 49168c2ecf20Sopenharmony_ci 49178c2ecf20Sopenharmony_cistatic int kvmppc_core_init_vm_hv(struct kvm *kvm) 49188c2ecf20Sopenharmony_ci{ 49198c2ecf20Sopenharmony_ci unsigned long lpcr, lpid; 49208c2ecf20Sopenharmony_ci char buf[32]; 49218c2ecf20Sopenharmony_ci int ret; 49228c2ecf20Sopenharmony_ci 49238c2ecf20Sopenharmony_ci mutex_init(&kvm->arch.uvmem_lock); 49248c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&kvm->arch.uvmem_pfns); 49258c2ecf20Sopenharmony_ci mutex_init(&kvm->arch.mmu_setup_lock); 49268c2ecf20Sopenharmony_ci 49278c2ecf20Sopenharmony_ci /* Allocate the guest's logical partition ID */ 49288c2ecf20Sopenharmony_ci 49298c2ecf20Sopenharmony_ci lpid = kvmppc_alloc_lpid(); 49308c2ecf20Sopenharmony_ci if ((long)lpid < 0) 49318c2ecf20Sopenharmony_ci return -ENOMEM; 49328c2ecf20Sopenharmony_ci kvm->arch.lpid = lpid; 49338c2ecf20Sopenharmony_ci 49348c2ecf20Sopenharmony_ci kvmppc_alloc_host_rm_ops(); 49358c2ecf20Sopenharmony_ci 49368c2ecf20Sopenharmony_ci kvmhv_vm_nested_init(kvm); 49378c2ecf20Sopenharmony_ci 49388c2ecf20Sopenharmony_ci /* 49398c2ecf20Sopenharmony_ci * Since we don't flush the TLB when tearing down a VM, 49408c2ecf20Sopenharmony_ci * and this lpid might have previously been used, 49418c2ecf20Sopenharmony_ci * make sure we flush on each core before running the new VM. 49428c2ecf20Sopenharmony_ci * On POWER9, the tlbie in mmu_partition_table_set_entry() 49438c2ecf20Sopenharmony_ci * does this flush for us. 49448c2ecf20Sopenharmony_ci */ 49458c2ecf20Sopenharmony_ci if (!cpu_has_feature(CPU_FTR_ARCH_300)) 49468c2ecf20Sopenharmony_ci cpumask_setall(&kvm->arch.need_tlb_flush); 49478c2ecf20Sopenharmony_ci 49488c2ecf20Sopenharmony_ci /* Start out with the default set of hcalls enabled */ 49498c2ecf20Sopenharmony_ci memcpy(kvm->arch.enabled_hcalls, default_enabled_hcalls, 49508c2ecf20Sopenharmony_ci sizeof(kvm->arch.enabled_hcalls)); 49518c2ecf20Sopenharmony_ci 49528c2ecf20Sopenharmony_ci if (!cpu_has_feature(CPU_FTR_ARCH_300)) 49538c2ecf20Sopenharmony_ci kvm->arch.host_sdr1 = mfspr(SPRN_SDR1); 49548c2ecf20Sopenharmony_ci 49558c2ecf20Sopenharmony_ci /* Init LPCR for virtual RMA mode */ 49568c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_HVMODE)) { 49578c2ecf20Sopenharmony_ci kvm->arch.host_lpid = mfspr(SPRN_LPID); 49588c2ecf20Sopenharmony_ci kvm->arch.host_lpcr = lpcr = mfspr(SPRN_LPCR); 49598c2ecf20Sopenharmony_ci lpcr &= LPCR_PECE | LPCR_LPES; 49608c2ecf20Sopenharmony_ci } else { 49618c2ecf20Sopenharmony_ci lpcr = 0; 49628c2ecf20Sopenharmony_ci } 49638c2ecf20Sopenharmony_ci lpcr |= (4UL << LPCR_DPFD_SH) | LPCR_HDICE | 49648c2ecf20Sopenharmony_ci LPCR_VPM0 | LPCR_VPM1; 49658c2ecf20Sopenharmony_ci kvm->arch.vrma_slb_v = SLB_VSID_B_1T | 49668c2ecf20Sopenharmony_ci (VRMA_VSID << SLB_VSID_SHIFT_1T); 49678c2ecf20Sopenharmony_ci /* On POWER8 turn on online bit to enable PURR/SPURR */ 49688c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_207S)) 49698c2ecf20Sopenharmony_ci lpcr |= LPCR_ONL; 49708c2ecf20Sopenharmony_ci /* 49718c2ecf20Sopenharmony_ci * On POWER9, VPM0 bit is reserved (VPM0=1 behaviour is assumed) 49728c2ecf20Sopenharmony_ci * Set HVICE bit to enable hypervisor virtualization interrupts. 49738c2ecf20Sopenharmony_ci * Set HEIC to prevent OS interrupts to go to hypervisor (should 49748c2ecf20Sopenharmony_ci * be unnecessary but better safe than sorry in case we re-enable 49758c2ecf20Sopenharmony_ci * EE in HV mode with this LPCR still set) 49768c2ecf20Sopenharmony_ci */ 49778c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_300)) { 49788c2ecf20Sopenharmony_ci lpcr &= ~LPCR_VPM0; 49798c2ecf20Sopenharmony_ci lpcr |= LPCR_HVICE | LPCR_HEIC; 49808c2ecf20Sopenharmony_ci 49818c2ecf20Sopenharmony_ci /* 49828c2ecf20Sopenharmony_ci * If xive is enabled, we route 0x500 interrupts directly 49838c2ecf20Sopenharmony_ci * to the guest. 49848c2ecf20Sopenharmony_ci */ 49858c2ecf20Sopenharmony_ci if (xics_on_xive()) 49868c2ecf20Sopenharmony_ci lpcr |= LPCR_LPES; 49878c2ecf20Sopenharmony_ci } 49888c2ecf20Sopenharmony_ci 49898c2ecf20Sopenharmony_ci /* 49908c2ecf20Sopenharmony_ci * If the host uses radix, the guest starts out as radix. 49918c2ecf20Sopenharmony_ci */ 49928c2ecf20Sopenharmony_ci if (radix_enabled()) { 49938c2ecf20Sopenharmony_ci kvm->arch.radix = 1; 49948c2ecf20Sopenharmony_ci kvm->arch.mmu_ready = 1; 49958c2ecf20Sopenharmony_ci lpcr &= ~LPCR_VPM1; 49968c2ecf20Sopenharmony_ci lpcr |= LPCR_UPRT | LPCR_GTSE | LPCR_HR; 49978c2ecf20Sopenharmony_ci ret = kvmppc_init_vm_radix(kvm); 49988c2ecf20Sopenharmony_ci if (ret) { 49998c2ecf20Sopenharmony_ci kvmppc_free_lpid(kvm->arch.lpid); 50008c2ecf20Sopenharmony_ci return ret; 50018c2ecf20Sopenharmony_ci } 50028c2ecf20Sopenharmony_ci kvmppc_setup_partition_table(kvm); 50038c2ecf20Sopenharmony_ci } 50048c2ecf20Sopenharmony_ci 50058c2ecf20Sopenharmony_ci kvm->arch.lpcr = lpcr; 50068c2ecf20Sopenharmony_ci 50078c2ecf20Sopenharmony_ci /* Initialization for future HPT resizes */ 50088c2ecf20Sopenharmony_ci kvm->arch.resize_hpt = NULL; 50098c2ecf20Sopenharmony_ci 50108c2ecf20Sopenharmony_ci /* 50118c2ecf20Sopenharmony_ci * Work out how many sets the TLB has, for the use of 50128c2ecf20Sopenharmony_ci * the TLB invalidation loop in book3s_hv_rmhandlers.S. 50138c2ecf20Sopenharmony_ci */ 50148c2ecf20Sopenharmony_ci if (radix_enabled()) 50158c2ecf20Sopenharmony_ci kvm->arch.tlb_sets = POWER9_TLB_SETS_RADIX; /* 128 */ 50168c2ecf20Sopenharmony_ci else if (cpu_has_feature(CPU_FTR_ARCH_300)) 50178c2ecf20Sopenharmony_ci kvm->arch.tlb_sets = POWER9_TLB_SETS_HASH; /* 256 */ 50188c2ecf20Sopenharmony_ci else if (cpu_has_feature(CPU_FTR_ARCH_207S)) 50198c2ecf20Sopenharmony_ci kvm->arch.tlb_sets = POWER8_TLB_SETS; /* 512 */ 50208c2ecf20Sopenharmony_ci else 50218c2ecf20Sopenharmony_ci kvm->arch.tlb_sets = POWER7_TLB_SETS; /* 128 */ 50228c2ecf20Sopenharmony_ci 50238c2ecf20Sopenharmony_ci /* 50248c2ecf20Sopenharmony_ci * Track that we now have a HV mode VM active. This blocks secondary 50258c2ecf20Sopenharmony_ci * CPU threads from coming online. 50268c2ecf20Sopenharmony_ci * On POWER9, we only need to do this if the "indep_threads_mode" 50278c2ecf20Sopenharmony_ci * module parameter has been set to N. 50288c2ecf20Sopenharmony_ci */ 50298c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_300)) { 50308c2ecf20Sopenharmony_ci if (!indep_threads_mode && !cpu_has_feature(CPU_FTR_HVMODE)) { 50318c2ecf20Sopenharmony_ci pr_warn("KVM: Ignoring indep_threads_mode=N in nested hypervisor\n"); 50328c2ecf20Sopenharmony_ci kvm->arch.threads_indep = true; 50338c2ecf20Sopenharmony_ci } else { 50348c2ecf20Sopenharmony_ci kvm->arch.threads_indep = indep_threads_mode; 50358c2ecf20Sopenharmony_ci } 50368c2ecf20Sopenharmony_ci } 50378c2ecf20Sopenharmony_ci if (!kvm->arch.threads_indep) 50388c2ecf20Sopenharmony_ci kvm_hv_vm_activated(); 50398c2ecf20Sopenharmony_ci 50408c2ecf20Sopenharmony_ci /* 50418c2ecf20Sopenharmony_ci * Initialize smt_mode depending on processor. 50428c2ecf20Sopenharmony_ci * POWER8 and earlier have to use "strict" threading, where 50438c2ecf20Sopenharmony_ci * all vCPUs in a vcore have to run on the same (sub)core, 50448c2ecf20Sopenharmony_ci * whereas on POWER9 the threads can each run a different 50458c2ecf20Sopenharmony_ci * guest. 50468c2ecf20Sopenharmony_ci */ 50478c2ecf20Sopenharmony_ci if (!cpu_has_feature(CPU_FTR_ARCH_300)) 50488c2ecf20Sopenharmony_ci kvm->arch.smt_mode = threads_per_subcore; 50498c2ecf20Sopenharmony_ci else 50508c2ecf20Sopenharmony_ci kvm->arch.smt_mode = 1; 50518c2ecf20Sopenharmony_ci kvm->arch.emul_smt_mode = 1; 50528c2ecf20Sopenharmony_ci 50538c2ecf20Sopenharmony_ci /* 50548c2ecf20Sopenharmony_ci * Create a debugfs directory for the VM 50558c2ecf20Sopenharmony_ci */ 50568c2ecf20Sopenharmony_ci snprintf(buf, sizeof(buf), "vm%d", current->pid); 50578c2ecf20Sopenharmony_ci kvm->arch.debugfs_dir = debugfs_create_dir(buf, kvm_debugfs_dir); 50588c2ecf20Sopenharmony_ci kvmppc_mmu_debugfs_init(kvm); 50598c2ecf20Sopenharmony_ci if (radix_enabled()) 50608c2ecf20Sopenharmony_ci kvmhv_radix_debugfs_init(kvm); 50618c2ecf20Sopenharmony_ci 50628c2ecf20Sopenharmony_ci return 0; 50638c2ecf20Sopenharmony_ci} 50648c2ecf20Sopenharmony_ci 50658c2ecf20Sopenharmony_cistatic void kvmppc_free_vcores(struct kvm *kvm) 50668c2ecf20Sopenharmony_ci{ 50678c2ecf20Sopenharmony_ci long int i; 50688c2ecf20Sopenharmony_ci 50698c2ecf20Sopenharmony_ci for (i = 0; i < KVM_MAX_VCORES; ++i) 50708c2ecf20Sopenharmony_ci kfree(kvm->arch.vcores[i]); 50718c2ecf20Sopenharmony_ci kvm->arch.online_vcores = 0; 50728c2ecf20Sopenharmony_ci} 50738c2ecf20Sopenharmony_ci 50748c2ecf20Sopenharmony_cistatic void kvmppc_core_destroy_vm_hv(struct kvm *kvm) 50758c2ecf20Sopenharmony_ci{ 50768c2ecf20Sopenharmony_ci debugfs_remove_recursive(kvm->arch.debugfs_dir); 50778c2ecf20Sopenharmony_ci 50788c2ecf20Sopenharmony_ci if (!kvm->arch.threads_indep) 50798c2ecf20Sopenharmony_ci kvm_hv_vm_deactivated(); 50808c2ecf20Sopenharmony_ci 50818c2ecf20Sopenharmony_ci kvmppc_free_vcores(kvm); 50828c2ecf20Sopenharmony_ci 50838c2ecf20Sopenharmony_ci 50848c2ecf20Sopenharmony_ci if (kvm_is_radix(kvm)) 50858c2ecf20Sopenharmony_ci kvmppc_free_radix(kvm); 50868c2ecf20Sopenharmony_ci else 50878c2ecf20Sopenharmony_ci kvmppc_free_hpt(&kvm->arch.hpt); 50888c2ecf20Sopenharmony_ci 50898c2ecf20Sopenharmony_ci /* Perform global invalidation and return lpid to the pool */ 50908c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_300)) { 50918c2ecf20Sopenharmony_ci if (nesting_enabled(kvm)) 50928c2ecf20Sopenharmony_ci kvmhv_release_all_nested(kvm); 50938c2ecf20Sopenharmony_ci kvm->arch.process_table = 0; 50948c2ecf20Sopenharmony_ci if (kvm->arch.secure_guest) 50958c2ecf20Sopenharmony_ci uv_svm_terminate(kvm->arch.lpid); 50968c2ecf20Sopenharmony_ci kvmhv_set_ptbl_entry(kvm->arch.lpid, 0, 0); 50978c2ecf20Sopenharmony_ci } 50988c2ecf20Sopenharmony_ci 50998c2ecf20Sopenharmony_ci kvmppc_free_lpid(kvm->arch.lpid); 51008c2ecf20Sopenharmony_ci 51018c2ecf20Sopenharmony_ci kvmppc_free_pimap(kvm); 51028c2ecf20Sopenharmony_ci} 51038c2ecf20Sopenharmony_ci 51048c2ecf20Sopenharmony_ci/* We don't need to emulate any privileged instructions or dcbz */ 51058c2ecf20Sopenharmony_cistatic int kvmppc_core_emulate_op_hv(struct kvm_vcpu *vcpu, 51068c2ecf20Sopenharmony_ci unsigned int inst, int *advance) 51078c2ecf20Sopenharmony_ci{ 51088c2ecf20Sopenharmony_ci return EMULATE_FAIL; 51098c2ecf20Sopenharmony_ci} 51108c2ecf20Sopenharmony_ci 51118c2ecf20Sopenharmony_cistatic int kvmppc_core_emulate_mtspr_hv(struct kvm_vcpu *vcpu, int sprn, 51128c2ecf20Sopenharmony_ci ulong spr_val) 51138c2ecf20Sopenharmony_ci{ 51148c2ecf20Sopenharmony_ci return EMULATE_FAIL; 51158c2ecf20Sopenharmony_ci} 51168c2ecf20Sopenharmony_ci 51178c2ecf20Sopenharmony_cistatic int kvmppc_core_emulate_mfspr_hv(struct kvm_vcpu *vcpu, int sprn, 51188c2ecf20Sopenharmony_ci ulong *spr_val) 51198c2ecf20Sopenharmony_ci{ 51208c2ecf20Sopenharmony_ci return EMULATE_FAIL; 51218c2ecf20Sopenharmony_ci} 51228c2ecf20Sopenharmony_ci 51238c2ecf20Sopenharmony_cistatic int kvmppc_core_check_processor_compat_hv(void) 51248c2ecf20Sopenharmony_ci{ 51258c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_HVMODE) && 51268c2ecf20Sopenharmony_ci cpu_has_feature(CPU_FTR_ARCH_206)) 51278c2ecf20Sopenharmony_ci return 0; 51288c2ecf20Sopenharmony_ci 51298c2ecf20Sopenharmony_ci /* POWER9 in radix mode is capable of being a nested hypervisor. */ 51308c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_300) && radix_enabled()) 51318c2ecf20Sopenharmony_ci return 0; 51328c2ecf20Sopenharmony_ci 51338c2ecf20Sopenharmony_ci return -EIO; 51348c2ecf20Sopenharmony_ci} 51358c2ecf20Sopenharmony_ci 51368c2ecf20Sopenharmony_ci#ifdef CONFIG_KVM_XICS 51378c2ecf20Sopenharmony_ci 51388c2ecf20Sopenharmony_civoid kvmppc_free_pimap(struct kvm *kvm) 51398c2ecf20Sopenharmony_ci{ 51408c2ecf20Sopenharmony_ci kfree(kvm->arch.pimap); 51418c2ecf20Sopenharmony_ci} 51428c2ecf20Sopenharmony_ci 51438c2ecf20Sopenharmony_cistatic struct kvmppc_passthru_irqmap *kvmppc_alloc_pimap(void) 51448c2ecf20Sopenharmony_ci{ 51458c2ecf20Sopenharmony_ci return kzalloc(sizeof(struct kvmppc_passthru_irqmap), GFP_KERNEL); 51468c2ecf20Sopenharmony_ci} 51478c2ecf20Sopenharmony_ci 51488c2ecf20Sopenharmony_cistatic int kvmppc_set_passthru_irq(struct kvm *kvm, int host_irq, int guest_gsi) 51498c2ecf20Sopenharmony_ci{ 51508c2ecf20Sopenharmony_ci struct irq_desc *desc; 51518c2ecf20Sopenharmony_ci struct kvmppc_irq_map *irq_map; 51528c2ecf20Sopenharmony_ci struct kvmppc_passthru_irqmap *pimap; 51538c2ecf20Sopenharmony_ci struct irq_chip *chip; 51548c2ecf20Sopenharmony_ci int i, rc = 0; 51558c2ecf20Sopenharmony_ci 51568c2ecf20Sopenharmony_ci if (!kvm_irq_bypass) 51578c2ecf20Sopenharmony_ci return 1; 51588c2ecf20Sopenharmony_ci 51598c2ecf20Sopenharmony_ci desc = irq_to_desc(host_irq); 51608c2ecf20Sopenharmony_ci if (!desc) 51618c2ecf20Sopenharmony_ci return -EIO; 51628c2ecf20Sopenharmony_ci 51638c2ecf20Sopenharmony_ci mutex_lock(&kvm->lock); 51648c2ecf20Sopenharmony_ci 51658c2ecf20Sopenharmony_ci pimap = kvm->arch.pimap; 51668c2ecf20Sopenharmony_ci if (pimap == NULL) { 51678c2ecf20Sopenharmony_ci /* First call, allocate structure to hold IRQ map */ 51688c2ecf20Sopenharmony_ci pimap = kvmppc_alloc_pimap(); 51698c2ecf20Sopenharmony_ci if (pimap == NULL) { 51708c2ecf20Sopenharmony_ci mutex_unlock(&kvm->lock); 51718c2ecf20Sopenharmony_ci return -ENOMEM; 51728c2ecf20Sopenharmony_ci } 51738c2ecf20Sopenharmony_ci kvm->arch.pimap = pimap; 51748c2ecf20Sopenharmony_ci } 51758c2ecf20Sopenharmony_ci 51768c2ecf20Sopenharmony_ci /* 51778c2ecf20Sopenharmony_ci * For now, we only support interrupts for which the EOI operation 51788c2ecf20Sopenharmony_ci * is an OPAL call followed by a write to XIRR, since that's 51798c2ecf20Sopenharmony_ci * what our real-mode EOI code does, or a XIVE interrupt 51808c2ecf20Sopenharmony_ci */ 51818c2ecf20Sopenharmony_ci chip = irq_data_get_irq_chip(&desc->irq_data); 51828c2ecf20Sopenharmony_ci if (!chip || !(is_pnv_opal_msi(chip) || is_xive_irq(chip))) { 51838c2ecf20Sopenharmony_ci pr_warn("kvmppc_set_passthru_irq_hv: Could not assign IRQ map for (%d,%d)\n", 51848c2ecf20Sopenharmony_ci host_irq, guest_gsi); 51858c2ecf20Sopenharmony_ci mutex_unlock(&kvm->lock); 51868c2ecf20Sopenharmony_ci return -ENOENT; 51878c2ecf20Sopenharmony_ci } 51888c2ecf20Sopenharmony_ci 51898c2ecf20Sopenharmony_ci /* 51908c2ecf20Sopenharmony_ci * See if we already have an entry for this guest IRQ number. 51918c2ecf20Sopenharmony_ci * If it's mapped to a hardware IRQ number, that's an error, 51928c2ecf20Sopenharmony_ci * otherwise re-use this entry. 51938c2ecf20Sopenharmony_ci */ 51948c2ecf20Sopenharmony_ci for (i = 0; i < pimap->n_mapped; i++) { 51958c2ecf20Sopenharmony_ci if (guest_gsi == pimap->mapped[i].v_hwirq) { 51968c2ecf20Sopenharmony_ci if (pimap->mapped[i].r_hwirq) { 51978c2ecf20Sopenharmony_ci mutex_unlock(&kvm->lock); 51988c2ecf20Sopenharmony_ci return -EINVAL; 51998c2ecf20Sopenharmony_ci } 52008c2ecf20Sopenharmony_ci break; 52018c2ecf20Sopenharmony_ci } 52028c2ecf20Sopenharmony_ci } 52038c2ecf20Sopenharmony_ci 52048c2ecf20Sopenharmony_ci if (i == KVMPPC_PIRQ_MAPPED) { 52058c2ecf20Sopenharmony_ci mutex_unlock(&kvm->lock); 52068c2ecf20Sopenharmony_ci return -EAGAIN; /* table is full */ 52078c2ecf20Sopenharmony_ci } 52088c2ecf20Sopenharmony_ci 52098c2ecf20Sopenharmony_ci irq_map = &pimap->mapped[i]; 52108c2ecf20Sopenharmony_ci 52118c2ecf20Sopenharmony_ci irq_map->v_hwirq = guest_gsi; 52128c2ecf20Sopenharmony_ci irq_map->desc = desc; 52138c2ecf20Sopenharmony_ci 52148c2ecf20Sopenharmony_ci /* 52158c2ecf20Sopenharmony_ci * Order the above two stores before the next to serialize with 52168c2ecf20Sopenharmony_ci * the KVM real mode handler. 52178c2ecf20Sopenharmony_ci */ 52188c2ecf20Sopenharmony_ci smp_wmb(); 52198c2ecf20Sopenharmony_ci irq_map->r_hwirq = desc->irq_data.hwirq; 52208c2ecf20Sopenharmony_ci 52218c2ecf20Sopenharmony_ci if (i == pimap->n_mapped) 52228c2ecf20Sopenharmony_ci pimap->n_mapped++; 52238c2ecf20Sopenharmony_ci 52248c2ecf20Sopenharmony_ci if (xics_on_xive()) 52258c2ecf20Sopenharmony_ci rc = kvmppc_xive_set_mapped(kvm, guest_gsi, desc); 52268c2ecf20Sopenharmony_ci else 52278c2ecf20Sopenharmony_ci kvmppc_xics_set_mapped(kvm, guest_gsi, desc->irq_data.hwirq); 52288c2ecf20Sopenharmony_ci if (rc) 52298c2ecf20Sopenharmony_ci irq_map->r_hwirq = 0; 52308c2ecf20Sopenharmony_ci 52318c2ecf20Sopenharmony_ci mutex_unlock(&kvm->lock); 52328c2ecf20Sopenharmony_ci 52338c2ecf20Sopenharmony_ci return 0; 52348c2ecf20Sopenharmony_ci} 52358c2ecf20Sopenharmony_ci 52368c2ecf20Sopenharmony_cistatic int kvmppc_clr_passthru_irq(struct kvm *kvm, int host_irq, int guest_gsi) 52378c2ecf20Sopenharmony_ci{ 52388c2ecf20Sopenharmony_ci struct irq_desc *desc; 52398c2ecf20Sopenharmony_ci struct kvmppc_passthru_irqmap *pimap; 52408c2ecf20Sopenharmony_ci int i, rc = 0; 52418c2ecf20Sopenharmony_ci 52428c2ecf20Sopenharmony_ci if (!kvm_irq_bypass) 52438c2ecf20Sopenharmony_ci return 0; 52448c2ecf20Sopenharmony_ci 52458c2ecf20Sopenharmony_ci desc = irq_to_desc(host_irq); 52468c2ecf20Sopenharmony_ci if (!desc) 52478c2ecf20Sopenharmony_ci return -EIO; 52488c2ecf20Sopenharmony_ci 52498c2ecf20Sopenharmony_ci mutex_lock(&kvm->lock); 52508c2ecf20Sopenharmony_ci if (!kvm->arch.pimap) 52518c2ecf20Sopenharmony_ci goto unlock; 52528c2ecf20Sopenharmony_ci 52538c2ecf20Sopenharmony_ci pimap = kvm->arch.pimap; 52548c2ecf20Sopenharmony_ci 52558c2ecf20Sopenharmony_ci for (i = 0; i < pimap->n_mapped; i++) { 52568c2ecf20Sopenharmony_ci if (guest_gsi == pimap->mapped[i].v_hwirq) 52578c2ecf20Sopenharmony_ci break; 52588c2ecf20Sopenharmony_ci } 52598c2ecf20Sopenharmony_ci 52608c2ecf20Sopenharmony_ci if (i == pimap->n_mapped) { 52618c2ecf20Sopenharmony_ci mutex_unlock(&kvm->lock); 52628c2ecf20Sopenharmony_ci return -ENODEV; 52638c2ecf20Sopenharmony_ci } 52648c2ecf20Sopenharmony_ci 52658c2ecf20Sopenharmony_ci if (xics_on_xive()) 52668c2ecf20Sopenharmony_ci rc = kvmppc_xive_clr_mapped(kvm, guest_gsi, pimap->mapped[i].desc); 52678c2ecf20Sopenharmony_ci else 52688c2ecf20Sopenharmony_ci kvmppc_xics_clr_mapped(kvm, guest_gsi, pimap->mapped[i].r_hwirq); 52698c2ecf20Sopenharmony_ci 52708c2ecf20Sopenharmony_ci /* invalidate the entry (what do do on error from the above ?) */ 52718c2ecf20Sopenharmony_ci pimap->mapped[i].r_hwirq = 0; 52728c2ecf20Sopenharmony_ci 52738c2ecf20Sopenharmony_ci /* 52748c2ecf20Sopenharmony_ci * We don't free this structure even when the count goes to 52758c2ecf20Sopenharmony_ci * zero. The structure is freed when we destroy the VM. 52768c2ecf20Sopenharmony_ci */ 52778c2ecf20Sopenharmony_ci unlock: 52788c2ecf20Sopenharmony_ci mutex_unlock(&kvm->lock); 52798c2ecf20Sopenharmony_ci return rc; 52808c2ecf20Sopenharmony_ci} 52818c2ecf20Sopenharmony_ci 52828c2ecf20Sopenharmony_cistatic int kvmppc_irq_bypass_add_producer_hv(struct irq_bypass_consumer *cons, 52838c2ecf20Sopenharmony_ci struct irq_bypass_producer *prod) 52848c2ecf20Sopenharmony_ci{ 52858c2ecf20Sopenharmony_ci int ret = 0; 52868c2ecf20Sopenharmony_ci struct kvm_kernel_irqfd *irqfd = 52878c2ecf20Sopenharmony_ci container_of(cons, struct kvm_kernel_irqfd, consumer); 52888c2ecf20Sopenharmony_ci 52898c2ecf20Sopenharmony_ci irqfd->producer = prod; 52908c2ecf20Sopenharmony_ci 52918c2ecf20Sopenharmony_ci ret = kvmppc_set_passthru_irq(irqfd->kvm, prod->irq, irqfd->gsi); 52928c2ecf20Sopenharmony_ci if (ret) 52938c2ecf20Sopenharmony_ci pr_info("kvmppc_set_passthru_irq (irq %d, gsi %d) fails: %d\n", 52948c2ecf20Sopenharmony_ci prod->irq, irqfd->gsi, ret); 52958c2ecf20Sopenharmony_ci 52968c2ecf20Sopenharmony_ci return ret; 52978c2ecf20Sopenharmony_ci} 52988c2ecf20Sopenharmony_ci 52998c2ecf20Sopenharmony_cistatic void kvmppc_irq_bypass_del_producer_hv(struct irq_bypass_consumer *cons, 53008c2ecf20Sopenharmony_ci struct irq_bypass_producer *prod) 53018c2ecf20Sopenharmony_ci{ 53028c2ecf20Sopenharmony_ci int ret; 53038c2ecf20Sopenharmony_ci struct kvm_kernel_irqfd *irqfd = 53048c2ecf20Sopenharmony_ci container_of(cons, struct kvm_kernel_irqfd, consumer); 53058c2ecf20Sopenharmony_ci 53068c2ecf20Sopenharmony_ci irqfd->producer = NULL; 53078c2ecf20Sopenharmony_ci 53088c2ecf20Sopenharmony_ci /* 53098c2ecf20Sopenharmony_ci * When producer of consumer is unregistered, we change back to 53108c2ecf20Sopenharmony_ci * default external interrupt handling mode - KVM real mode 53118c2ecf20Sopenharmony_ci * will switch back to host. 53128c2ecf20Sopenharmony_ci */ 53138c2ecf20Sopenharmony_ci ret = kvmppc_clr_passthru_irq(irqfd->kvm, prod->irq, irqfd->gsi); 53148c2ecf20Sopenharmony_ci if (ret) 53158c2ecf20Sopenharmony_ci pr_warn("kvmppc_clr_passthru_irq (irq %d, gsi %d) fails: %d\n", 53168c2ecf20Sopenharmony_ci prod->irq, irqfd->gsi, ret); 53178c2ecf20Sopenharmony_ci} 53188c2ecf20Sopenharmony_ci#endif 53198c2ecf20Sopenharmony_ci 53208c2ecf20Sopenharmony_cistatic long kvm_arch_vm_ioctl_hv(struct file *filp, 53218c2ecf20Sopenharmony_ci unsigned int ioctl, unsigned long arg) 53228c2ecf20Sopenharmony_ci{ 53238c2ecf20Sopenharmony_ci struct kvm *kvm __maybe_unused = filp->private_data; 53248c2ecf20Sopenharmony_ci void __user *argp = (void __user *)arg; 53258c2ecf20Sopenharmony_ci long r; 53268c2ecf20Sopenharmony_ci 53278c2ecf20Sopenharmony_ci switch (ioctl) { 53288c2ecf20Sopenharmony_ci 53298c2ecf20Sopenharmony_ci case KVM_PPC_ALLOCATE_HTAB: { 53308c2ecf20Sopenharmony_ci u32 htab_order; 53318c2ecf20Sopenharmony_ci 53328c2ecf20Sopenharmony_ci /* If we're a nested hypervisor, we currently only support radix */ 53338c2ecf20Sopenharmony_ci if (kvmhv_on_pseries()) { 53348c2ecf20Sopenharmony_ci r = -EOPNOTSUPP; 53358c2ecf20Sopenharmony_ci break; 53368c2ecf20Sopenharmony_ci } 53378c2ecf20Sopenharmony_ci 53388c2ecf20Sopenharmony_ci r = -EFAULT; 53398c2ecf20Sopenharmony_ci if (get_user(htab_order, (u32 __user *)argp)) 53408c2ecf20Sopenharmony_ci break; 53418c2ecf20Sopenharmony_ci r = kvmppc_alloc_reset_hpt(kvm, htab_order); 53428c2ecf20Sopenharmony_ci if (r) 53438c2ecf20Sopenharmony_ci break; 53448c2ecf20Sopenharmony_ci r = 0; 53458c2ecf20Sopenharmony_ci break; 53468c2ecf20Sopenharmony_ci } 53478c2ecf20Sopenharmony_ci 53488c2ecf20Sopenharmony_ci case KVM_PPC_GET_HTAB_FD: { 53498c2ecf20Sopenharmony_ci struct kvm_get_htab_fd ghf; 53508c2ecf20Sopenharmony_ci 53518c2ecf20Sopenharmony_ci r = -EFAULT; 53528c2ecf20Sopenharmony_ci if (copy_from_user(&ghf, argp, sizeof(ghf))) 53538c2ecf20Sopenharmony_ci break; 53548c2ecf20Sopenharmony_ci r = kvm_vm_ioctl_get_htab_fd(kvm, &ghf); 53558c2ecf20Sopenharmony_ci break; 53568c2ecf20Sopenharmony_ci } 53578c2ecf20Sopenharmony_ci 53588c2ecf20Sopenharmony_ci case KVM_PPC_RESIZE_HPT_PREPARE: { 53598c2ecf20Sopenharmony_ci struct kvm_ppc_resize_hpt rhpt; 53608c2ecf20Sopenharmony_ci 53618c2ecf20Sopenharmony_ci r = -EFAULT; 53628c2ecf20Sopenharmony_ci if (copy_from_user(&rhpt, argp, sizeof(rhpt))) 53638c2ecf20Sopenharmony_ci break; 53648c2ecf20Sopenharmony_ci 53658c2ecf20Sopenharmony_ci r = kvm_vm_ioctl_resize_hpt_prepare(kvm, &rhpt); 53668c2ecf20Sopenharmony_ci break; 53678c2ecf20Sopenharmony_ci } 53688c2ecf20Sopenharmony_ci 53698c2ecf20Sopenharmony_ci case KVM_PPC_RESIZE_HPT_COMMIT: { 53708c2ecf20Sopenharmony_ci struct kvm_ppc_resize_hpt rhpt; 53718c2ecf20Sopenharmony_ci 53728c2ecf20Sopenharmony_ci r = -EFAULT; 53738c2ecf20Sopenharmony_ci if (copy_from_user(&rhpt, argp, sizeof(rhpt))) 53748c2ecf20Sopenharmony_ci break; 53758c2ecf20Sopenharmony_ci 53768c2ecf20Sopenharmony_ci r = kvm_vm_ioctl_resize_hpt_commit(kvm, &rhpt); 53778c2ecf20Sopenharmony_ci break; 53788c2ecf20Sopenharmony_ci } 53798c2ecf20Sopenharmony_ci 53808c2ecf20Sopenharmony_ci default: 53818c2ecf20Sopenharmony_ci r = -ENOTTY; 53828c2ecf20Sopenharmony_ci } 53838c2ecf20Sopenharmony_ci 53848c2ecf20Sopenharmony_ci return r; 53858c2ecf20Sopenharmony_ci} 53868c2ecf20Sopenharmony_ci 53878c2ecf20Sopenharmony_ci/* 53888c2ecf20Sopenharmony_ci * List of hcall numbers to enable by default. 53898c2ecf20Sopenharmony_ci * For compatibility with old userspace, we enable by default 53908c2ecf20Sopenharmony_ci * all hcalls that were implemented before the hcall-enabling 53918c2ecf20Sopenharmony_ci * facility was added. Note this list should not include H_RTAS. 53928c2ecf20Sopenharmony_ci */ 53938c2ecf20Sopenharmony_cistatic unsigned int default_hcall_list[] = { 53948c2ecf20Sopenharmony_ci H_REMOVE, 53958c2ecf20Sopenharmony_ci H_ENTER, 53968c2ecf20Sopenharmony_ci H_READ, 53978c2ecf20Sopenharmony_ci H_PROTECT, 53988c2ecf20Sopenharmony_ci H_BULK_REMOVE, 53998c2ecf20Sopenharmony_ci H_GET_TCE, 54008c2ecf20Sopenharmony_ci H_PUT_TCE, 54018c2ecf20Sopenharmony_ci H_SET_DABR, 54028c2ecf20Sopenharmony_ci H_SET_XDABR, 54038c2ecf20Sopenharmony_ci H_CEDE, 54048c2ecf20Sopenharmony_ci H_PROD, 54058c2ecf20Sopenharmony_ci H_CONFER, 54068c2ecf20Sopenharmony_ci H_REGISTER_VPA, 54078c2ecf20Sopenharmony_ci#ifdef CONFIG_KVM_XICS 54088c2ecf20Sopenharmony_ci H_EOI, 54098c2ecf20Sopenharmony_ci H_CPPR, 54108c2ecf20Sopenharmony_ci H_IPI, 54118c2ecf20Sopenharmony_ci H_IPOLL, 54128c2ecf20Sopenharmony_ci H_XIRR, 54138c2ecf20Sopenharmony_ci H_XIRR_X, 54148c2ecf20Sopenharmony_ci#endif 54158c2ecf20Sopenharmony_ci 0 54168c2ecf20Sopenharmony_ci}; 54178c2ecf20Sopenharmony_ci 54188c2ecf20Sopenharmony_cistatic void init_default_hcalls(void) 54198c2ecf20Sopenharmony_ci{ 54208c2ecf20Sopenharmony_ci int i; 54218c2ecf20Sopenharmony_ci unsigned int hcall; 54228c2ecf20Sopenharmony_ci 54238c2ecf20Sopenharmony_ci for (i = 0; default_hcall_list[i]; ++i) { 54248c2ecf20Sopenharmony_ci hcall = default_hcall_list[i]; 54258c2ecf20Sopenharmony_ci WARN_ON(!kvmppc_hcall_impl_hv(hcall)); 54268c2ecf20Sopenharmony_ci __set_bit(hcall / 4, default_enabled_hcalls); 54278c2ecf20Sopenharmony_ci } 54288c2ecf20Sopenharmony_ci} 54298c2ecf20Sopenharmony_ci 54308c2ecf20Sopenharmony_cistatic int kvmhv_configure_mmu(struct kvm *kvm, struct kvm_ppc_mmuv3_cfg *cfg) 54318c2ecf20Sopenharmony_ci{ 54328c2ecf20Sopenharmony_ci unsigned long lpcr; 54338c2ecf20Sopenharmony_ci int radix; 54348c2ecf20Sopenharmony_ci int err; 54358c2ecf20Sopenharmony_ci 54368c2ecf20Sopenharmony_ci /* If not on a POWER9, reject it */ 54378c2ecf20Sopenharmony_ci if (!cpu_has_feature(CPU_FTR_ARCH_300)) 54388c2ecf20Sopenharmony_ci return -ENODEV; 54398c2ecf20Sopenharmony_ci 54408c2ecf20Sopenharmony_ci /* If any unknown flags set, reject it */ 54418c2ecf20Sopenharmony_ci if (cfg->flags & ~(KVM_PPC_MMUV3_RADIX | KVM_PPC_MMUV3_GTSE)) 54428c2ecf20Sopenharmony_ci return -EINVAL; 54438c2ecf20Sopenharmony_ci 54448c2ecf20Sopenharmony_ci /* GR (guest radix) bit in process_table field must match */ 54458c2ecf20Sopenharmony_ci radix = !!(cfg->flags & KVM_PPC_MMUV3_RADIX); 54468c2ecf20Sopenharmony_ci if (!!(cfg->process_table & PATB_GR) != radix) 54478c2ecf20Sopenharmony_ci return -EINVAL; 54488c2ecf20Sopenharmony_ci 54498c2ecf20Sopenharmony_ci /* Process table size field must be reasonable, i.e. <= 24 */ 54508c2ecf20Sopenharmony_ci if ((cfg->process_table & PRTS_MASK) > 24) 54518c2ecf20Sopenharmony_ci return -EINVAL; 54528c2ecf20Sopenharmony_ci 54538c2ecf20Sopenharmony_ci /* We can change a guest to/from radix now, if the host is radix */ 54548c2ecf20Sopenharmony_ci if (radix && !radix_enabled()) 54558c2ecf20Sopenharmony_ci return -EINVAL; 54568c2ecf20Sopenharmony_ci 54578c2ecf20Sopenharmony_ci /* If we're a nested hypervisor, we currently only support radix */ 54588c2ecf20Sopenharmony_ci if (kvmhv_on_pseries() && !radix) 54598c2ecf20Sopenharmony_ci return -EINVAL; 54608c2ecf20Sopenharmony_ci 54618c2ecf20Sopenharmony_ci mutex_lock(&kvm->arch.mmu_setup_lock); 54628c2ecf20Sopenharmony_ci if (radix != kvm_is_radix(kvm)) { 54638c2ecf20Sopenharmony_ci if (kvm->arch.mmu_ready) { 54648c2ecf20Sopenharmony_ci kvm->arch.mmu_ready = 0; 54658c2ecf20Sopenharmony_ci /* order mmu_ready vs. vcpus_running */ 54668c2ecf20Sopenharmony_ci smp_mb(); 54678c2ecf20Sopenharmony_ci if (atomic_read(&kvm->arch.vcpus_running)) { 54688c2ecf20Sopenharmony_ci kvm->arch.mmu_ready = 1; 54698c2ecf20Sopenharmony_ci err = -EBUSY; 54708c2ecf20Sopenharmony_ci goto out_unlock; 54718c2ecf20Sopenharmony_ci } 54728c2ecf20Sopenharmony_ci } 54738c2ecf20Sopenharmony_ci if (radix) 54748c2ecf20Sopenharmony_ci err = kvmppc_switch_mmu_to_radix(kvm); 54758c2ecf20Sopenharmony_ci else 54768c2ecf20Sopenharmony_ci err = kvmppc_switch_mmu_to_hpt(kvm); 54778c2ecf20Sopenharmony_ci if (err) 54788c2ecf20Sopenharmony_ci goto out_unlock; 54798c2ecf20Sopenharmony_ci } 54808c2ecf20Sopenharmony_ci 54818c2ecf20Sopenharmony_ci kvm->arch.process_table = cfg->process_table; 54828c2ecf20Sopenharmony_ci kvmppc_setup_partition_table(kvm); 54838c2ecf20Sopenharmony_ci 54848c2ecf20Sopenharmony_ci lpcr = (cfg->flags & KVM_PPC_MMUV3_GTSE) ? LPCR_GTSE : 0; 54858c2ecf20Sopenharmony_ci kvmppc_update_lpcr(kvm, lpcr, LPCR_GTSE); 54868c2ecf20Sopenharmony_ci err = 0; 54878c2ecf20Sopenharmony_ci 54888c2ecf20Sopenharmony_ci out_unlock: 54898c2ecf20Sopenharmony_ci mutex_unlock(&kvm->arch.mmu_setup_lock); 54908c2ecf20Sopenharmony_ci return err; 54918c2ecf20Sopenharmony_ci} 54928c2ecf20Sopenharmony_ci 54938c2ecf20Sopenharmony_cistatic int kvmhv_enable_nested(struct kvm *kvm) 54948c2ecf20Sopenharmony_ci{ 54958c2ecf20Sopenharmony_ci if (!nested) 54968c2ecf20Sopenharmony_ci return -EPERM; 54978c2ecf20Sopenharmony_ci if (!cpu_has_feature(CPU_FTR_ARCH_300) || no_mixing_hpt_and_radix) 54988c2ecf20Sopenharmony_ci return -ENODEV; 54998c2ecf20Sopenharmony_ci 55008c2ecf20Sopenharmony_ci /* kvm == NULL means the caller is testing if the capability exists */ 55018c2ecf20Sopenharmony_ci if (kvm) 55028c2ecf20Sopenharmony_ci kvm->arch.nested_enable = true; 55038c2ecf20Sopenharmony_ci return 0; 55048c2ecf20Sopenharmony_ci} 55058c2ecf20Sopenharmony_ci 55068c2ecf20Sopenharmony_cistatic int kvmhv_load_from_eaddr(struct kvm_vcpu *vcpu, ulong *eaddr, void *ptr, 55078c2ecf20Sopenharmony_ci int size) 55088c2ecf20Sopenharmony_ci{ 55098c2ecf20Sopenharmony_ci int rc = -EINVAL; 55108c2ecf20Sopenharmony_ci 55118c2ecf20Sopenharmony_ci if (kvmhv_vcpu_is_radix(vcpu)) { 55128c2ecf20Sopenharmony_ci rc = kvmhv_copy_from_guest_radix(vcpu, *eaddr, ptr, size); 55138c2ecf20Sopenharmony_ci 55148c2ecf20Sopenharmony_ci if (rc > 0) 55158c2ecf20Sopenharmony_ci rc = -EINVAL; 55168c2ecf20Sopenharmony_ci } 55178c2ecf20Sopenharmony_ci 55188c2ecf20Sopenharmony_ci /* For now quadrants are the only way to access nested guest memory */ 55198c2ecf20Sopenharmony_ci if (rc && vcpu->arch.nested) 55208c2ecf20Sopenharmony_ci rc = -EAGAIN; 55218c2ecf20Sopenharmony_ci 55228c2ecf20Sopenharmony_ci return rc; 55238c2ecf20Sopenharmony_ci} 55248c2ecf20Sopenharmony_ci 55258c2ecf20Sopenharmony_cistatic int kvmhv_store_to_eaddr(struct kvm_vcpu *vcpu, ulong *eaddr, void *ptr, 55268c2ecf20Sopenharmony_ci int size) 55278c2ecf20Sopenharmony_ci{ 55288c2ecf20Sopenharmony_ci int rc = -EINVAL; 55298c2ecf20Sopenharmony_ci 55308c2ecf20Sopenharmony_ci if (kvmhv_vcpu_is_radix(vcpu)) { 55318c2ecf20Sopenharmony_ci rc = kvmhv_copy_to_guest_radix(vcpu, *eaddr, ptr, size); 55328c2ecf20Sopenharmony_ci 55338c2ecf20Sopenharmony_ci if (rc > 0) 55348c2ecf20Sopenharmony_ci rc = -EINVAL; 55358c2ecf20Sopenharmony_ci } 55368c2ecf20Sopenharmony_ci 55378c2ecf20Sopenharmony_ci /* For now quadrants are the only way to access nested guest memory */ 55388c2ecf20Sopenharmony_ci if (rc && vcpu->arch.nested) 55398c2ecf20Sopenharmony_ci rc = -EAGAIN; 55408c2ecf20Sopenharmony_ci 55418c2ecf20Sopenharmony_ci return rc; 55428c2ecf20Sopenharmony_ci} 55438c2ecf20Sopenharmony_ci 55448c2ecf20Sopenharmony_cistatic void unpin_vpa_reset(struct kvm *kvm, struct kvmppc_vpa *vpa) 55458c2ecf20Sopenharmony_ci{ 55468c2ecf20Sopenharmony_ci unpin_vpa(kvm, vpa); 55478c2ecf20Sopenharmony_ci vpa->gpa = 0; 55488c2ecf20Sopenharmony_ci vpa->pinned_addr = NULL; 55498c2ecf20Sopenharmony_ci vpa->dirty = false; 55508c2ecf20Sopenharmony_ci vpa->update_pending = 0; 55518c2ecf20Sopenharmony_ci} 55528c2ecf20Sopenharmony_ci 55538c2ecf20Sopenharmony_ci/* 55548c2ecf20Sopenharmony_ci * Enable a guest to become a secure VM, or test whether 55558c2ecf20Sopenharmony_ci * that could be enabled. 55568c2ecf20Sopenharmony_ci * Called when the KVM_CAP_PPC_SECURE_GUEST capability is 55578c2ecf20Sopenharmony_ci * tested (kvm == NULL) or enabled (kvm != NULL). 55588c2ecf20Sopenharmony_ci */ 55598c2ecf20Sopenharmony_cistatic int kvmhv_enable_svm(struct kvm *kvm) 55608c2ecf20Sopenharmony_ci{ 55618c2ecf20Sopenharmony_ci if (!kvmppc_uvmem_available()) 55628c2ecf20Sopenharmony_ci return -EINVAL; 55638c2ecf20Sopenharmony_ci if (kvm) 55648c2ecf20Sopenharmony_ci kvm->arch.svm_enabled = 1; 55658c2ecf20Sopenharmony_ci return 0; 55668c2ecf20Sopenharmony_ci} 55678c2ecf20Sopenharmony_ci 55688c2ecf20Sopenharmony_ci/* 55698c2ecf20Sopenharmony_ci * IOCTL handler to turn off secure mode of guest 55708c2ecf20Sopenharmony_ci * 55718c2ecf20Sopenharmony_ci * - Release all device pages 55728c2ecf20Sopenharmony_ci * - Issue ucall to terminate the guest on the UV side 55738c2ecf20Sopenharmony_ci * - Unpin the VPA pages. 55748c2ecf20Sopenharmony_ci * - Reinit the partition scoped page tables 55758c2ecf20Sopenharmony_ci */ 55768c2ecf20Sopenharmony_cistatic int kvmhv_svm_off(struct kvm *kvm) 55778c2ecf20Sopenharmony_ci{ 55788c2ecf20Sopenharmony_ci struct kvm_vcpu *vcpu; 55798c2ecf20Sopenharmony_ci int mmu_was_ready; 55808c2ecf20Sopenharmony_ci int srcu_idx; 55818c2ecf20Sopenharmony_ci int ret = 0; 55828c2ecf20Sopenharmony_ci int i; 55838c2ecf20Sopenharmony_ci 55848c2ecf20Sopenharmony_ci if (!(kvm->arch.secure_guest & KVMPPC_SECURE_INIT_START)) 55858c2ecf20Sopenharmony_ci return ret; 55868c2ecf20Sopenharmony_ci 55878c2ecf20Sopenharmony_ci mutex_lock(&kvm->arch.mmu_setup_lock); 55888c2ecf20Sopenharmony_ci mmu_was_ready = kvm->arch.mmu_ready; 55898c2ecf20Sopenharmony_ci if (kvm->arch.mmu_ready) { 55908c2ecf20Sopenharmony_ci kvm->arch.mmu_ready = 0; 55918c2ecf20Sopenharmony_ci /* order mmu_ready vs. vcpus_running */ 55928c2ecf20Sopenharmony_ci smp_mb(); 55938c2ecf20Sopenharmony_ci if (atomic_read(&kvm->arch.vcpus_running)) { 55948c2ecf20Sopenharmony_ci kvm->arch.mmu_ready = 1; 55958c2ecf20Sopenharmony_ci ret = -EBUSY; 55968c2ecf20Sopenharmony_ci goto out; 55978c2ecf20Sopenharmony_ci } 55988c2ecf20Sopenharmony_ci } 55998c2ecf20Sopenharmony_ci 56008c2ecf20Sopenharmony_ci srcu_idx = srcu_read_lock(&kvm->srcu); 56018c2ecf20Sopenharmony_ci for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++) { 56028c2ecf20Sopenharmony_ci struct kvm_memory_slot *memslot; 56038c2ecf20Sopenharmony_ci struct kvm_memslots *slots = __kvm_memslots(kvm, i); 56048c2ecf20Sopenharmony_ci 56058c2ecf20Sopenharmony_ci if (!slots) 56068c2ecf20Sopenharmony_ci continue; 56078c2ecf20Sopenharmony_ci 56088c2ecf20Sopenharmony_ci kvm_for_each_memslot(memslot, slots) { 56098c2ecf20Sopenharmony_ci kvmppc_uvmem_drop_pages(memslot, kvm, true); 56108c2ecf20Sopenharmony_ci uv_unregister_mem_slot(kvm->arch.lpid, memslot->id); 56118c2ecf20Sopenharmony_ci } 56128c2ecf20Sopenharmony_ci } 56138c2ecf20Sopenharmony_ci srcu_read_unlock(&kvm->srcu, srcu_idx); 56148c2ecf20Sopenharmony_ci 56158c2ecf20Sopenharmony_ci ret = uv_svm_terminate(kvm->arch.lpid); 56168c2ecf20Sopenharmony_ci if (ret != U_SUCCESS) { 56178c2ecf20Sopenharmony_ci ret = -EINVAL; 56188c2ecf20Sopenharmony_ci goto out; 56198c2ecf20Sopenharmony_ci } 56208c2ecf20Sopenharmony_ci 56218c2ecf20Sopenharmony_ci /* 56228c2ecf20Sopenharmony_ci * When secure guest is reset, all the guest pages are sent 56238c2ecf20Sopenharmony_ci * to UV via UV_PAGE_IN before the non-boot vcpus get a 56248c2ecf20Sopenharmony_ci * chance to run and unpin their VPA pages. Unpinning of all 56258c2ecf20Sopenharmony_ci * VPA pages is done here explicitly so that VPA pages 56268c2ecf20Sopenharmony_ci * can be migrated to the secure side. 56278c2ecf20Sopenharmony_ci * 56288c2ecf20Sopenharmony_ci * This is required to for the secure SMP guest to reboot 56298c2ecf20Sopenharmony_ci * correctly. 56308c2ecf20Sopenharmony_ci */ 56318c2ecf20Sopenharmony_ci kvm_for_each_vcpu(i, vcpu, kvm) { 56328c2ecf20Sopenharmony_ci spin_lock(&vcpu->arch.vpa_update_lock); 56338c2ecf20Sopenharmony_ci unpin_vpa_reset(kvm, &vcpu->arch.dtl); 56348c2ecf20Sopenharmony_ci unpin_vpa_reset(kvm, &vcpu->arch.slb_shadow); 56358c2ecf20Sopenharmony_ci unpin_vpa_reset(kvm, &vcpu->arch.vpa); 56368c2ecf20Sopenharmony_ci spin_unlock(&vcpu->arch.vpa_update_lock); 56378c2ecf20Sopenharmony_ci } 56388c2ecf20Sopenharmony_ci 56398c2ecf20Sopenharmony_ci kvmppc_setup_partition_table(kvm); 56408c2ecf20Sopenharmony_ci kvm->arch.secure_guest = 0; 56418c2ecf20Sopenharmony_ci kvm->arch.mmu_ready = mmu_was_ready; 56428c2ecf20Sopenharmony_ciout: 56438c2ecf20Sopenharmony_ci mutex_unlock(&kvm->arch.mmu_setup_lock); 56448c2ecf20Sopenharmony_ci return ret; 56458c2ecf20Sopenharmony_ci} 56468c2ecf20Sopenharmony_ci 56478c2ecf20Sopenharmony_cistatic struct kvmppc_ops kvm_ops_hv = { 56488c2ecf20Sopenharmony_ci .get_sregs = kvm_arch_vcpu_ioctl_get_sregs_hv, 56498c2ecf20Sopenharmony_ci .set_sregs = kvm_arch_vcpu_ioctl_set_sregs_hv, 56508c2ecf20Sopenharmony_ci .get_one_reg = kvmppc_get_one_reg_hv, 56518c2ecf20Sopenharmony_ci .set_one_reg = kvmppc_set_one_reg_hv, 56528c2ecf20Sopenharmony_ci .vcpu_load = kvmppc_core_vcpu_load_hv, 56538c2ecf20Sopenharmony_ci .vcpu_put = kvmppc_core_vcpu_put_hv, 56548c2ecf20Sopenharmony_ci .inject_interrupt = kvmppc_inject_interrupt_hv, 56558c2ecf20Sopenharmony_ci .set_msr = kvmppc_set_msr_hv, 56568c2ecf20Sopenharmony_ci .vcpu_run = kvmppc_vcpu_run_hv, 56578c2ecf20Sopenharmony_ci .vcpu_create = kvmppc_core_vcpu_create_hv, 56588c2ecf20Sopenharmony_ci .vcpu_free = kvmppc_core_vcpu_free_hv, 56598c2ecf20Sopenharmony_ci .check_requests = kvmppc_core_check_requests_hv, 56608c2ecf20Sopenharmony_ci .get_dirty_log = kvm_vm_ioctl_get_dirty_log_hv, 56618c2ecf20Sopenharmony_ci .flush_memslot = kvmppc_core_flush_memslot_hv, 56628c2ecf20Sopenharmony_ci .prepare_memory_region = kvmppc_core_prepare_memory_region_hv, 56638c2ecf20Sopenharmony_ci .commit_memory_region = kvmppc_core_commit_memory_region_hv, 56648c2ecf20Sopenharmony_ci .unmap_hva_range = kvm_unmap_hva_range_hv, 56658c2ecf20Sopenharmony_ci .age_hva = kvm_age_hva_hv, 56668c2ecf20Sopenharmony_ci .test_age_hva = kvm_test_age_hva_hv, 56678c2ecf20Sopenharmony_ci .set_spte_hva = kvm_set_spte_hva_hv, 56688c2ecf20Sopenharmony_ci .free_memslot = kvmppc_core_free_memslot_hv, 56698c2ecf20Sopenharmony_ci .init_vm = kvmppc_core_init_vm_hv, 56708c2ecf20Sopenharmony_ci .destroy_vm = kvmppc_core_destroy_vm_hv, 56718c2ecf20Sopenharmony_ci .get_smmu_info = kvm_vm_ioctl_get_smmu_info_hv, 56728c2ecf20Sopenharmony_ci .emulate_op = kvmppc_core_emulate_op_hv, 56738c2ecf20Sopenharmony_ci .emulate_mtspr = kvmppc_core_emulate_mtspr_hv, 56748c2ecf20Sopenharmony_ci .emulate_mfspr = kvmppc_core_emulate_mfspr_hv, 56758c2ecf20Sopenharmony_ci .fast_vcpu_kick = kvmppc_fast_vcpu_kick_hv, 56768c2ecf20Sopenharmony_ci .arch_vm_ioctl = kvm_arch_vm_ioctl_hv, 56778c2ecf20Sopenharmony_ci .hcall_implemented = kvmppc_hcall_impl_hv, 56788c2ecf20Sopenharmony_ci#ifdef CONFIG_KVM_XICS 56798c2ecf20Sopenharmony_ci .irq_bypass_add_producer = kvmppc_irq_bypass_add_producer_hv, 56808c2ecf20Sopenharmony_ci .irq_bypass_del_producer = kvmppc_irq_bypass_del_producer_hv, 56818c2ecf20Sopenharmony_ci#endif 56828c2ecf20Sopenharmony_ci .configure_mmu = kvmhv_configure_mmu, 56838c2ecf20Sopenharmony_ci .get_rmmu_info = kvmhv_get_rmmu_info, 56848c2ecf20Sopenharmony_ci .set_smt_mode = kvmhv_set_smt_mode, 56858c2ecf20Sopenharmony_ci .enable_nested = kvmhv_enable_nested, 56868c2ecf20Sopenharmony_ci .load_from_eaddr = kvmhv_load_from_eaddr, 56878c2ecf20Sopenharmony_ci .store_to_eaddr = kvmhv_store_to_eaddr, 56888c2ecf20Sopenharmony_ci .enable_svm = kvmhv_enable_svm, 56898c2ecf20Sopenharmony_ci .svm_off = kvmhv_svm_off, 56908c2ecf20Sopenharmony_ci}; 56918c2ecf20Sopenharmony_ci 56928c2ecf20Sopenharmony_cistatic int kvm_init_subcore_bitmap(void) 56938c2ecf20Sopenharmony_ci{ 56948c2ecf20Sopenharmony_ci int i, j; 56958c2ecf20Sopenharmony_ci int nr_cores = cpu_nr_cores(); 56968c2ecf20Sopenharmony_ci struct sibling_subcore_state *sibling_subcore_state; 56978c2ecf20Sopenharmony_ci 56988c2ecf20Sopenharmony_ci for (i = 0; i < nr_cores; i++) { 56998c2ecf20Sopenharmony_ci int first_cpu = i * threads_per_core; 57008c2ecf20Sopenharmony_ci int node = cpu_to_node(first_cpu); 57018c2ecf20Sopenharmony_ci 57028c2ecf20Sopenharmony_ci /* Ignore if it is already allocated. */ 57038c2ecf20Sopenharmony_ci if (paca_ptrs[first_cpu]->sibling_subcore_state) 57048c2ecf20Sopenharmony_ci continue; 57058c2ecf20Sopenharmony_ci 57068c2ecf20Sopenharmony_ci sibling_subcore_state = 57078c2ecf20Sopenharmony_ci kzalloc_node(sizeof(struct sibling_subcore_state), 57088c2ecf20Sopenharmony_ci GFP_KERNEL, node); 57098c2ecf20Sopenharmony_ci if (!sibling_subcore_state) 57108c2ecf20Sopenharmony_ci return -ENOMEM; 57118c2ecf20Sopenharmony_ci 57128c2ecf20Sopenharmony_ci 57138c2ecf20Sopenharmony_ci for (j = 0; j < threads_per_core; j++) { 57148c2ecf20Sopenharmony_ci int cpu = first_cpu + j; 57158c2ecf20Sopenharmony_ci 57168c2ecf20Sopenharmony_ci paca_ptrs[cpu]->sibling_subcore_state = 57178c2ecf20Sopenharmony_ci sibling_subcore_state; 57188c2ecf20Sopenharmony_ci } 57198c2ecf20Sopenharmony_ci } 57208c2ecf20Sopenharmony_ci return 0; 57218c2ecf20Sopenharmony_ci} 57228c2ecf20Sopenharmony_ci 57238c2ecf20Sopenharmony_cistatic int kvmppc_radix_possible(void) 57248c2ecf20Sopenharmony_ci{ 57258c2ecf20Sopenharmony_ci return cpu_has_feature(CPU_FTR_ARCH_300) && radix_enabled(); 57268c2ecf20Sopenharmony_ci} 57278c2ecf20Sopenharmony_ci 57288c2ecf20Sopenharmony_cistatic int kvmppc_book3s_init_hv(void) 57298c2ecf20Sopenharmony_ci{ 57308c2ecf20Sopenharmony_ci int r; 57318c2ecf20Sopenharmony_ci 57328c2ecf20Sopenharmony_ci if (!tlbie_capable) { 57338c2ecf20Sopenharmony_ci pr_err("KVM-HV: Host does not support TLBIE\n"); 57348c2ecf20Sopenharmony_ci return -ENODEV; 57358c2ecf20Sopenharmony_ci } 57368c2ecf20Sopenharmony_ci 57378c2ecf20Sopenharmony_ci /* 57388c2ecf20Sopenharmony_ci * FIXME!! Do we need to check on all cpus ? 57398c2ecf20Sopenharmony_ci */ 57408c2ecf20Sopenharmony_ci r = kvmppc_core_check_processor_compat_hv(); 57418c2ecf20Sopenharmony_ci if (r < 0) 57428c2ecf20Sopenharmony_ci return -ENODEV; 57438c2ecf20Sopenharmony_ci 57448c2ecf20Sopenharmony_ci r = kvmhv_nested_init(); 57458c2ecf20Sopenharmony_ci if (r) 57468c2ecf20Sopenharmony_ci return r; 57478c2ecf20Sopenharmony_ci 57488c2ecf20Sopenharmony_ci r = kvm_init_subcore_bitmap(); 57498c2ecf20Sopenharmony_ci if (r) 57508c2ecf20Sopenharmony_ci return r; 57518c2ecf20Sopenharmony_ci 57528c2ecf20Sopenharmony_ci /* 57538c2ecf20Sopenharmony_ci * We need a way of accessing the XICS interrupt controller, 57548c2ecf20Sopenharmony_ci * either directly, via paca_ptrs[cpu]->kvm_hstate.xics_phys, or 57558c2ecf20Sopenharmony_ci * indirectly, via OPAL. 57568c2ecf20Sopenharmony_ci */ 57578c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 57588c2ecf20Sopenharmony_ci if (!xics_on_xive() && !kvmhv_on_pseries() && 57598c2ecf20Sopenharmony_ci !local_paca->kvm_hstate.xics_phys) { 57608c2ecf20Sopenharmony_ci struct device_node *np; 57618c2ecf20Sopenharmony_ci 57628c2ecf20Sopenharmony_ci np = of_find_compatible_node(NULL, NULL, "ibm,opal-intc"); 57638c2ecf20Sopenharmony_ci if (!np) { 57648c2ecf20Sopenharmony_ci pr_err("KVM-HV: Cannot determine method for accessing XICS\n"); 57658c2ecf20Sopenharmony_ci return -ENODEV; 57668c2ecf20Sopenharmony_ci } 57678c2ecf20Sopenharmony_ci /* presence of intc confirmed - node can be dropped again */ 57688c2ecf20Sopenharmony_ci of_node_put(np); 57698c2ecf20Sopenharmony_ci } 57708c2ecf20Sopenharmony_ci#endif 57718c2ecf20Sopenharmony_ci 57728c2ecf20Sopenharmony_ci kvm_ops_hv.owner = THIS_MODULE; 57738c2ecf20Sopenharmony_ci kvmppc_hv_ops = &kvm_ops_hv; 57748c2ecf20Sopenharmony_ci 57758c2ecf20Sopenharmony_ci init_default_hcalls(); 57768c2ecf20Sopenharmony_ci 57778c2ecf20Sopenharmony_ci init_vcore_lists(); 57788c2ecf20Sopenharmony_ci 57798c2ecf20Sopenharmony_ci r = kvmppc_mmu_hv_init(); 57808c2ecf20Sopenharmony_ci if (r) 57818c2ecf20Sopenharmony_ci return r; 57828c2ecf20Sopenharmony_ci 57838c2ecf20Sopenharmony_ci if (kvmppc_radix_possible()) { 57848c2ecf20Sopenharmony_ci r = kvmppc_radix_init(); 57858c2ecf20Sopenharmony_ci if (r) 57868c2ecf20Sopenharmony_ci return r; 57878c2ecf20Sopenharmony_ci } 57888c2ecf20Sopenharmony_ci 57898c2ecf20Sopenharmony_ci /* 57908c2ecf20Sopenharmony_ci * POWER9 chips before version 2.02 can't have some threads in 57918c2ecf20Sopenharmony_ci * HPT mode and some in radix mode on the same core. 57928c2ecf20Sopenharmony_ci */ 57938c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_300)) { 57948c2ecf20Sopenharmony_ci unsigned int pvr = mfspr(SPRN_PVR); 57958c2ecf20Sopenharmony_ci if ((pvr >> 16) == PVR_POWER9 && 57968c2ecf20Sopenharmony_ci (((pvr & 0xe000) == 0 && (pvr & 0xfff) < 0x202) || 57978c2ecf20Sopenharmony_ci ((pvr & 0xe000) == 0x2000 && (pvr & 0xfff) < 0x101))) 57988c2ecf20Sopenharmony_ci no_mixing_hpt_and_radix = true; 57998c2ecf20Sopenharmony_ci } 58008c2ecf20Sopenharmony_ci 58018c2ecf20Sopenharmony_ci r = kvmppc_uvmem_init(); 58028c2ecf20Sopenharmony_ci if (r < 0) 58038c2ecf20Sopenharmony_ci pr_err("KVM-HV: kvmppc_uvmem_init failed %d\n", r); 58048c2ecf20Sopenharmony_ci 58058c2ecf20Sopenharmony_ci return r; 58068c2ecf20Sopenharmony_ci} 58078c2ecf20Sopenharmony_ci 58088c2ecf20Sopenharmony_cistatic void kvmppc_book3s_exit_hv(void) 58098c2ecf20Sopenharmony_ci{ 58108c2ecf20Sopenharmony_ci kvmppc_uvmem_free(); 58118c2ecf20Sopenharmony_ci kvmppc_free_host_rm_ops(); 58128c2ecf20Sopenharmony_ci if (kvmppc_radix_possible()) 58138c2ecf20Sopenharmony_ci kvmppc_radix_exit(); 58148c2ecf20Sopenharmony_ci kvmppc_hv_ops = NULL; 58158c2ecf20Sopenharmony_ci kvmhv_nested_exit(); 58168c2ecf20Sopenharmony_ci} 58178c2ecf20Sopenharmony_ci 58188c2ecf20Sopenharmony_cimodule_init(kvmppc_book3s_init_hv); 58198c2ecf20Sopenharmony_cimodule_exit(kvmppc_book3s_exit_hv); 58208c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 58218c2ecf20Sopenharmony_ciMODULE_ALIAS_MISCDEV(KVM_MINOR); 58228c2ecf20Sopenharmony_ciMODULE_ALIAS("devname:kvm"); 5823