1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /******************************************************************************
3  * asm-x86/guest/hyperv-hcall.h
4  *
5  * Copyright (c) 2019 Microsoft.
6  */
7 
8 #ifndef __X86_HYPERV_HCALL_H__
9 #define __X86_HYPERV_HCALL_H__
10 
11 #include <xen/lib.h>
12 #include <xen/page-size.h>
13 #include <xen/types.h>
14 
15 #include <asm/asm_defns.h>
16 #include <asm/fixmap.h>
17 #include <asm/guest/hyperv-tlfs.h>
18 
hv_do_hypercall(uint64_t control,paddr_t input_addr,paddr_t output_addr)19 static inline uint64_t hv_do_hypercall(uint64_t control, paddr_t input_addr,
20                                        paddr_t output_addr)
21 {
22     uint64_t status;
23     register unsigned long r8 asm ( "r8" ) = output_addr;
24 
25     /* See TLFS for volatile registers */
26     asm volatile ( "call hv_hcall_page"
27                    : "=a" (status), "+c" (control),
28                      "+d" (input_addr) ASM_CALL_CONSTRAINT
29                    : "r" (r8)
30                    : "memory" );
31 
32     return status;
33 }
34 
hv_do_fast_hypercall(uint16_t code,uint64_t input1,uint64_t input2)35 static inline uint64_t hv_do_fast_hypercall(uint16_t code,
36                                             uint64_t input1, uint64_t input2)
37 {
38     uint64_t status;
39     uint64_t control = code | HV_HYPERCALL_FAST_BIT;
40     register unsigned long r8 asm ( "r8" ) = input2;
41 
42     /* See TLFS for volatile registers */
43     asm volatile ( "call hv_hcall_page"
44                    : "=a" (status), "+c" (control),
45                      "+d" (input1) ASM_CALL_CONSTRAINT
46                    : "r" (r8) );
47 
48     return status;
49 }
50 
hv_do_rep_hypercall(uint16_t code,uint16_t rep_count,uint16_t varhead_size,paddr_t input,paddr_t output)51 static inline uint64_t hv_do_rep_hypercall(uint16_t code, uint16_t rep_count,
52                                            uint16_t varhead_size,
53                                            paddr_t input, paddr_t output)
54 {
55     uint64_t control = code;
56     uint64_t status;
57     uint16_t rep_comp;
58 
59     control |= (uint64_t)varhead_size << HV_HYPERCALL_VARHEAD_OFFSET;
60     control |= (uint64_t)rep_count << HV_HYPERCALL_REP_COMP_OFFSET;
61 
62     do {
63         status = hv_do_hypercall(control, input, output);
64         if ( (status & HV_HYPERCALL_RESULT_MASK) != HV_STATUS_SUCCESS )
65             break;
66 
67         rep_comp = MASK_EXTR(status, HV_HYPERCALL_REP_COMP_MASK);
68 
69         control &= ~HV_HYPERCALL_REP_START_MASK;
70         control |= MASK_INSR(rep_comp, HV_HYPERCALL_REP_START_MASK);
71     } while ( rep_comp < rep_count );
72 
73     return status;
74 }
75 
76 #endif /* __X86_HYPERV_HCALL_H__ */
77 
78 /*
79  * Local variables:
80  * mode: C
81  * c-file-style: "BSD"
82  * c-basic-offset: 4
83  * tab-width: 4
84  * indent-tabs-mode: nil
85  * End:
86  */
87