18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef _ASM_LOONGARCH_PARAVIRT_H
38c2ecf20Sopenharmony_ci#define _ASM_LOONGARCH_PARAVIRT_H
48c2ecf20Sopenharmony_ci#include <asm/kvm_para.h>
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#ifdef CONFIG_PARAVIRT
78c2ecf20Sopenharmony_cistatic inline bool kvm_para_available(void)
88c2ecf20Sopenharmony_ci{
98c2ecf20Sopenharmony_ci	return true;
108c2ecf20Sopenharmony_ci}
118c2ecf20Sopenharmony_cistruct static_key;
128c2ecf20Sopenharmony_ciextern struct static_key paravirt_steal_enabled;
138c2ecf20Sopenharmony_ciextern struct static_key paravirt_steal_rq_enabled;
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_cistruct pv_time_ops {
168c2ecf20Sopenharmony_ci	unsigned long long (*steal_clock)(int cpu);
178c2ecf20Sopenharmony_ci};
188c2ecf20Sopenharmony_cistruct kvm_steal_time {
198c2ecf20Sopenharmony_ci	__u64 steal;
208c2ecf20Sopenharmony_ci	__u32 version;
218c2ecf20Sopenharmony_ci	__u32 flags;
228c2ecf20Sopenharmony_ci	__u8  preempted;
238c2ecf20Sopenharmony_ci	__u8  pad[47];
248c2ecf20Sopenharmony_ci};
258c2ecf20Sopenharmony_ciextern struct pv_time_ops pv_time_ops;
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_cibool pv_is_native_spin_unlock(void);
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_cistatic inline u64 paravirt_steal_clock(int cpu)
308c2ecf20Sopenharmony_ci{
318c2ecf20Sopenharmony_ci	return pv_time_ops.steal_clock(cpu);
328c2ecf20Sopenharmony_ci}
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_cistatic inline bool pv_feature_support(int feature)
358c2ecf20Sopenharmony_ci{
368c2ecf20Sopenharmony_ci	return kvm_hypercall1(KVM_HC_FUNC_FEATURE, feature) == KVM_RET_SUC;
378c2ecf20Sopenharmony_ci}
388c2ecf20Sopenharmony_cistatic inline void pv_notify_host(int feature, unsigned long data)
398c2ecf20Sopenharmony_ci{
408c2ecf20Sopenharmony_ci	kvm_hypercall2(KVM_HC_FUNC_NOTIFY, feature, data);
418c2ecf20Sopenharmony_ci}
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci#if defined(CONFIG_SMP) && defined(CONFIG_PARAVIRT_SPINLOCKS)
448c2ecf20Sopenharmony_cistruct qspinlock;
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_cistruct pv_lock_ops {
478c2ecf20Sopenharmony_ci	void (*queued_spin_lock_slowpath)(struct qspinlock *lock, u32 val);
488c2ecf20Sopenharmony_ci	void (*queued_spin_unlock)(struct qspinlock *lock);
498c2ecf20Sopenharmony_ci	void (*wait)(u8 *ptr, u8 val);
508c2ecf20Sopenharmony_ci	void (*kick)(int cpu);
518c2ecf20Sopenharmony_ci	bool (*vcpu_is_preempted)(long cpu);
528c2ecf20Sopenharmony_ci};
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ciextern struct pv_lock_ops pv_lock_ops;
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_civoid __init kvm_spinlock_init(void);
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_cistatic __always_inline void pv_queued_spin_lock_slowpath(struct qspinlock *lock,
598c2ecf20Sopenharmony_ci		u32 val)
608c2ecf20Sopenharmony_ci{
618c2ecf20Sopenharmony_ci	pv_lock_ops.queued_spin_lock_slowpath(lock, val);
628c2ecf20Sopenharmony_ci}
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_cistatic __always_inline void pv_queued_spin_unlock(struct qspinlock *lock)
658c2ecf20Sopenharmony_ci{
668c2ecf20Sopenharmony_ci	pv_lock_ops.queued_spin_unlock(lock);
678c2ecf20Sopenharmony_ci}
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_cistatic __always_inline void pv_wait(u8 *ptr, u8 val)
708c2ecf20Sopenharmony_ci{
718c2ecf20Sopenharmony_ci	pv_lock_ops.wait(ptr, val);
728c2ecf20Sopenharmony_ci}
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_cistatic __always_inline void pv_kick(int cpu)
758c2ecf20Sopenharmony_ci{
768c2ecf20Sopenharmony_ci	pv_lock_ops.kick(cpu);
778c2ecf20Sopenharmony_ci}
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_cistatic __always_inline bool pv_vcpu_is_preempted(long cpu)
808c2ecf20Sopenharmony_ci{
818c2ecf20Sopenharmony_ci	return pv_lock_ops.vcpu_is_preempted(cpu);
828c2ecf20Sopenharmony_ci}
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci#endif /* SMP && PARAVIRT_SPINLOCKS */
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ciint __init pv_time_init(void);
878c2ecf20Sopenharmony_ciint __init pv_ipi_init(void);
888c2ecf20Sopenharmony_ci#else
898c2ecf20Sopenharmony_cistatic inline bool kvm_para_available(void)
908c2ecf20Sopenharmony_ci{
918c2ecf20Sopenharmony_ci	return false;
928c2ecf20Sopenharmony_ci}
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci#define pv_time_init() do {} while (0)
958c2ecf20Sopenharmony_ci#define pv_ipi_init() do {} while (0)
968c2ecf20Sopenharmony_ci#endif
978c2ecf20Sopenharmony_ci#endif /* _ASM_LOONGARCH_PARAVIRT_H */
98