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