17995700eSShuo Liu /* SPDX-License-Identifier: GPL-2.0 */
27995700eSShuo Liu #ifndef _ASM_X86_ACRN_H
37995700eSShuo Liu #define _ASM_X86_ACRN_H
47995700eSShuo Liu
5ebbfc978SYin Fengwei /*
6ebbfc978SYin Fengwei * This CPUID returns feature bitmaps in EAX.
7ebbfc978SYin Fengwei * Guest VM uses this to detect the appropriate feature bit.
8ebbfc978SYin Fengwei */
9ebbfc978SYin Fengwei #define ACRN_CPUID_FEATURES 0x40000001
10ebbfc978SYin Fengwei /* Bit 0 indicates whether guest VM is privileged */
11ebbfc978SYin Fengwei #define ACRN_FEATURE_PRIVILEGED_VM BIT(0)
12ebbfc978SYin Fengwei
13*81a71f51SFei Li /*
14*81a71f51SFei Li * Timing Information.
15*81a71f51SFei Li * This leaf returns the current TSC frequency in kHz.
16*81a71f51SFei Li *
17*81a71f51SFei Li * EAX: (Virtual) TSC frequency in kHz.
18*81a71f51SFei Li * EBX, ECX, EDX: RESERVED (reserved fields are set to zero).
19*81a71f51SFei Li */
20*81a71f51SFei Li #define ACRN_CPUID_TIMING_INFO 0x40000010
21*81a71f51SFei Li
227995700eSShuo Liu void acrn_setup_intr_handler(void (*handler)(void));
237995700eSShuo Liu void acrn_remove_intr_handler(void);
247995700eSShuo Liu
acrn_cpuid_base(void)25ebbfc978SYin Fengwei static inline u32 acrn_cpuid_base(void)
26ebbfc978SYin Fengwei {
27ebbfc978SYin Fengwei if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
28ebbfc978SYin Fengwei return hypervisor_cpuid_base("ACRNACRNACRN", 0);
29ebbfc978SYin Fengwei
30ebbfc978SYin Fengwei return 0;
31ebbfc978SYin Fengwei }
32ebbfc978SYin Fengwei
acrn_get_tsc_khz(void)33*81a71f51SFei Li static inline unsigned long acrn_get_tsc_khz(void)
34*81a71f51SFei Li {
35*81a71f51SFei Li return cpuid_eax(ACRN_CPUID_TIMING_INFO);
36*81a71f51SFei Li }
37*81a71f51SFei Li
388a0a8719SShuo Liu /*
398a0a8719SShuo Liu * Hypercalls for ACRN
408a0a8719SShuo Liu *
418a0a8719SShuo Liu * - VMCALL instruction is used to implement ACRN hypercalls.
428a0a8719SShuo Liu * - ACRN hypercall ABI:
438a0a8719SShuo Liu * - Hypercall number is passed in R8 register.
448a0a8719SShuo Liu * - Up to 2 arguments are passed in RDI, RSI.
458a0a8719SShuo Liu * - Return value will be placed in RAX.
468a0a8719SShuo Liu *
478a0a8719SShuo Liu * Because GCC doesn't support R8 register as direct register constraints, use
488a0a8719SShuo Liu * supported constraint as input with a explicit MOV to R8 in beginning of asm.
498a0a8719SShuo Liu */
acrn_hypercall0(unsigned long hcall_id)508a0a8719SShuo Liu static inline long acrn_hypercall0(unsigned long hcall_id)
518a0a8719SShuo Liu {
528a0a8719SShuo Liu long result;
538a0a8719SShuo Liu
548a0a8719SShuo Liu asm volatile("movl %1, %%r8d\n\t"
558a0a8719SShuo Liu "vmcall\n\t"
568a0a8719SShuo Liu : "=a" (result)
578a0a8719SShuo Liu : "g" (hcall_id)
588a0a8719SShuo Liu : "r8", "memory");
598a0a8719SShuo Liu
608a0a8719SShuo Liu return result;
618a0a8719SShuo Liu }
628a0a8719SShuo Liu
acrn_hypercall1(unsigned long hcall_id,unsigned long param1)638a0a8719SShuo Liu static inline long acrn_hypercall1(unsigned long hcall_id,
648a0a8719SShuo Liu unsigned long param1)
658a0a8719SShuo Liu {
668a0a8719SShuo Liu long result;
678a0a8719SShuo Liu
688a0a8719SShuo Liu asm volatile("movl %1, %%r8d\n\t"
698a0a8719SShuo Liu "vmcall\n\t"
708a0a8719SShuo Liu : "=a" (result)
718a0a8719SShuo Liu : "g" (hcall_id), "D" (param1)
728a0a8719SShuo Liu : "r8", "memory");
738a0a8719SShuo Liu
748a0a8719SShuo Liu return result;
758a0a8719SShuo Liu }
768a0a8719SShuo Liu
acrn_hypercall2(unsigned long hcall_id,unsigned long param1,unsigned long param2)778a0a8719SShuo Liu static inline long acrn_hypercall2(unsigned long hcall_id,
788a0a8719SShuo Liu unsigned long param1,
798a0a8719SShuo Liu unsigned long param2)
808a0a8719SShuo Liu {
818a0a8719SShuo Liu long result;
828a0a8719SShuo Liu
838a0a8719SShuo Liu asm volatile("movl %1, %%r8d\n\t"
848a0a8719SShuo Liu "vmcall\n\t"
858a0a8719SShuo Liu : "=a" (result)
868a0a8719SShuo Liu : "g" (hcall_id), "D" (param1), "S" (param2)
878a0a8719SShuo Liu : "r8", "memory");
888a0a8719SShuo Liu
898a0a8719SShuo Liu return result;
908a0a8719SShuo Liu }
918a0a8719SShuo Liu
927995700eSShuo Liu #endif /* _ASM_X86_ACRN_H */
93