1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef _ASM_LOONGARCH_PARAVIRT_H
3#define _ASM_LOONGARCH_PARAVIRT_H
4#include <asm/kvm_para.h>
5
6#ifdef CONFIG_PARAVIRT
7static inline bool kvm_para_available(void)
8{
9	return true;
10}
11struct static_key;
12extern struct static_key paravirt_steal_enabled;
13extern struct static_key paravirt_steal_rq_enabled;
14
15struct pv_time_ops {
16	unsigned long long (*steal_clock)(int cpu);
17};
18struct kvm_steal_time {
19	__u64 steal;
20	__u32 version;
21	__u32 flags;
22	__u8  preempted;
23	__u8  pad[47];
24};
25extern struct pv_time_ops pv_time_ops;
26
27bool pv_is_native_spin_unlock(void);
28
29static inline u64 paravirt_steal_clock(int cpu)
30{
31	return pv_time_ops.steal_clock(cpu);
32}
33
34static inline bool pv_feature_support(int feature)
35{
36	return kvm_hypercall1(KVM_HC_FUNC_FEATURE, feature) == KVM_RET_SUC;
37}
38static inline void pv_notify_host(int feature, unsigned long data)
39{
40	kvm_hypercall2(KVM_HC_FUNC_NOTIFY, feature, data);
41}
42
43#if defined(CONFIG_SMP) && defined(CONFIG_PARAVIRT_SPINLOCKS)
44struct qspinlock;
45
46struct pv_lock_ops {
47	void (*queued_spin_lock_slowpath)(struct qspinlock *lock, u32 val);
48	void (*queued_spin_unlock)(struct qspinlock *lock);
49	void (*wait)(u8 *ptr, u8 val);
50	void (*kick)(int cpu);
51	bool (*vcpu_is_preempted)(long cpu);
52};
53
54extern struct pv_lock_ops pv_lock_ops;
55
56void __init kvm_spinlock_init(void);
57
58static __always_inline void pv_queued_spin_lock_slowpath(struct qspinlock *lock,
59		u32 val)
60{
61	pv_lock_ops.queued_spin_lock_slowpath(lock, val);
62}
63
64static __always_inline void pv_queued_spin_unlock(struct qspinlock *lock)
65{
66	pv_lock_ops.queued_spin_unlock(lock);
67}
68
69static __always_inline void pv_wait(u8 *ptr, u8 val)
70{
71	pv_lock_ops.wait(ptr, val);
72}
73
74static __always_inline void pv_kick(int cpu)
75{
76	pv_lock_ops.kick(cpu);
77}
78
79static __always_inline bool pv_vcpu_is_preempted(long cpu)
80{
81	return pv_lock_ops.vcpu_is_preempted(cpu);
82}
83
84#endif /* SMP && PARAVIRT_SPINLOCKS */
85
86int __init pv_time_init(void);
87int __init pv_ipi_init(void);
88#else
89static inline bool kvm_para_available(void)
90{
91	return false;
92}
93
94#define pv_time_init() do {} while (0)
95#define pv_ipi_init() do {} while (0)
96#endif
97#endif /* _ASM_LOONGARCH_PARAVIRT_H */
98