GNU Linux-libre 4.9.315-gnu1
[releases.git] / drivers / gpu / drm / vmwgfx / vmwgfx_msg.h
1 /*
2  * Copyright (C) 2016, VMware, Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
12  * NON INFRINGEMENT.  See the GNU General Public License for more
13  * details.
14  *
15  * Based on code from vmware.c and vmmouse.c.
16  * Author:
17  *   Sinclair Yeh <syeh@vmware.com>
18  */
19 #ifndef _VMWGFX_MSG_H
20 #define _VMWGFX_MSG_H
21
22
23 /**
24  * Hypervisor-specific bi-directional communication channel.  Should never
25  * execute on bare metal hardware.  The caller must make sure to check for
26  * supported hypervisor before using these macros.
27  *
28  * The last two parameters are both input and output and must be initialized.
29  *
30  * @cmd: [IN] Message Cmd
31  * @in_ebx: [IN] Message Len, through EBX
32  * @in_si: [IN] Input argument through SI, set to 0 if not used
33  * @in_di: [IN] Input argument through DI, set ot 0 if not used
34  * @port_num: [IN] port number + [channel id]
35  * @magic: [IN] hypervisor magic value
36  * @eax: [OUT] value of EAX register
37  * @ebx: [OUT] e.g. status from an HB message status command
38  * @ecx: [OUT] e.g. status from a non-HB message status command
39  * @edx: [OUT] e.g. channel id
40  * @si:  [OUT]
41  * @di:  [OUT]
42  */
43 #define VMW_PORT(cmd, in_ebx, in_si, in_di,     \
44                  port_num, magic,               \
45                  eax, ebx, ecx, edx, si, di)    \
46 ({                                              \
47         asm volatile ("inl %%dx, %%eax;" :      \
48                 "=a"(eax),                      \
49                 "=b"(ebx),                      \
50                 "=c"(ecx),                      \
51                 "=d"(edx),                      \
52                 "=S"(si),                       \
53                 "=D"(di) :                      \
54                 "a"(magic),                     \
55                 "b"(in_ebx),                    \
56                 "c"(cmd),                       \
57                 "d"(port_num),                  \
58                 "S"(in_si),                     \
59                 "D"(in_di) :                    \
60                 "memory");                      \
61 })
62
63
64 /**
65  * Hypervisor-specific bi-directional communication channel.  Should never
66  * execute on bare metal hardware.  The caller must make sure to check for
67  * supported hypervisor before using these macros.
68  *
69  * The last 3 parameters are both input and output and must be initialized.
70  *
71  * @cmd: [IN] Message Cmd
72  * @in_ecx: [IN] Message Len, through ECX
73  * @in_si: [IN] Input argument through SI, set to 0 if not used
74  * @in_di: [IN] Input argument through DI, set to 0 if not used
75  * @port_num: [IN] port number + [channel id]
76  * @magic: [IN] hypervisor magic value
77  * @bp:  [IN]
78  * @eax: [OUT] value of EAX register
79  * @ebx: [OUT] e.g. status from an HB message status command
80  * @ecx: [OUT] e.g. status from a non-HB message status command
81  * @edx: [OUT] e.g. channel id
82  * @si:  [OUT]
83  * @di:  [OUT]
84  */
85 #ifdef __x86_64__
86
87 #define VMW_PORT_HB_OUT(cmd, in_ecx, in_si, in_di,      \
88                         port_num, magic, bp,            \
89                         eax, ebx, ecx, edx, si, di)     \
90 ({                                                      \
91         asm volatile ("push %%rbp;"                     \
92                 "mov %12, %%rbp;"                       \
93                 "rep outsb;"                            \
94                 "pop %%rbp;" :                          \
95                 "=a"(eax),                              \
96                 "=b"(ebx),                              \
97                 "=c"(ecx),                              \
98                 "=d"(edx),                              \
99                 "=S"(si),                               \
100                 "=D"(di) :                              \
101                 "a"(magic),                             \
102                 "b"(cmd),                               \
103                 "c"(in_ecx),                            \
104                 "d"(port_num),                          \
105                 "S"(in_si),                             \
106                 "D"(in_di),                             \
107                 "r"(bp) :                               \
108                 "memory", "cc");                        \
109 })
110
111
112 #define VMW_PORT_HB_IN(cmd, in_ecx, in_si, in_di,       \
113                        port_num, magic, bp,             \
114                        eax, ebx, ecx, edx, si, di)      \
115 ({                                                      \
116         asm volatile ("push %%rbp;"                     \
117                 "mov %12, %%rbp;"                       \
118                 "rep insb;"                             \
119                 "pop %%rbp" :                           \
120                 "=a"(eax),                              \
121                 "=b"(ebx),                              \
122                 "=c"(ecx),                              \
123                 "=d"(edx),                              \
124                 "=S"(si),                               \
125                 "=D"(di) :                              \
126                 "a"(magic),                             \
127                 "b"(cmd),                               \
128                 "c"(in_ecx),                            \
129                 "d"(port_num),                          \
130                 "S"(in_si),                             \
131                 "D"(in_di),                             \
132                 "r"(bp) :                               \
133                 "memory", "cc");                        \
134 })
135
136 #else
137
138 /*
139  * In the 32-bit version of this macro, we store bp in a memory location
140  * because we've ran out of registers.
141  * Now we can't reference that memory location while we've modified
142  * %esp or %ebp, so we first push it on the stack, just before we push
143  * %ebp, and then when we need it we read it from the stack where we
144  * just pushed it.
145  */
146 #define VMW_PORT_HB_OUT(cmd, in_ecx, in_si, in_di,      \
147                         port_num, magic, bp,            \
148                         eax, ebx, ecx, edx, si, di)     \
149 ({                                                      \
150         asm volatile ("push %12;"                       \
151                 "push %%ebp;"                           \
152                 "mov 0x04(%%esp), %%ebp;"               \
153                 "rep outsb;"                            \
154                 "pop %%ebp;"                            \
155                 "add $0x04, %%esp;" :                   \
156                 "=a"(eax),                              \
157                 "=b"(ebx),                              \
158                 "=c"(ecx),                              \
159                 "=d"(edx),                              \
160                 "=S"(si),                               \
161                 "=D"(di) :                              \
162                 "a"(magic),                             \
163                 "b"(cmd),                               \
164                 "c"(in_ecx),                            \
165                 "d"(port_num),                          \
166                 "S"(in_si),                             \
167                 "D"(in_di),                             \
168                 "m"(bp) :                               \
169                 "memory", "cc");                        \
170 })
171
172
173 #define VMW_PORT_HB_IN(cmd, in_ecx, in_si, in_di,       \
174                        port_num, magic, bp,             \
175                        eax, ebx, ecx, edx, si, di)      \
176 ({                                                      \
177         asm volatile ("push %12;"                       \
178                 "push %%ebp;"                           \
179                 "mov 0x04(%%esp), %%ebp;"               \
180                 "rep insb;"                             \
181                 "pop %%ebp;"                            \
182                 "add $0x04, %%esp;" :                   \
183                 "=a"(eax),                              \
184                 "=b"(ebx),                              \
185                 "=c"(ecx),                              \
186                 "=d"(edx),                              \
187                 "=S"(si),                               \
188                 "=D"(di) :                              \
189                 "a"(magic),                             \
190                 "b"(cmd),                               \
191                 "c"(in_ecx),                            \
192                 "d"(port_num),                          \
193                 "S"(in_si),                             \
194                 "D"(in_di),                             \
195                 "m"(bp) :                               \
196                 "memory", "cc");                        \
197 })
198 #endif /* #if __x86_64__ */
199
200 #endif