sync with latest
[sdk/emulator/qemu.git] / tizen / src / check_hax.c
1 /*
2  * check if hax is available. reference:target-i386/hax-all.c
3  *
4  * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  * SeokYeon Hwang <syeon.hwang@samsung.com>
8  * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
9  * Hyunjun Son
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
24  *
25  * Contributors:
26  * - S-Core Co., Ltd
27  *
28  */
29
30 #include <stdio.h>
31 #include <string.h>
32
33 #ifdef _WIN32
34 #include <stdint.h>
35 #include <errno.h>
36 #include <windows.h>
37 #include <winioctl.h>
38 #endif
39
40 #ifdef __APPLE__
41 #include <stdint.h>
42 #include <sys/types.h>
43 #include <sys/ioctl.h>
44 #include <sys/mman.h>
45 #include <stdarg.h>
46 #include <sys/stat.h>
47 #include <fcntl.h>
48 #include <errno.h>
49 #endif
50
51
52
53 #define HAX_MAX_VCPU 0x10
54
55 #define HAX_CAP_STATUS_NOTWORKING  0x0
56 #define HAX_CAP_WORKSTATUS_MASK 0x1
57 #define HAX_CAP_FAILREASON_VT   0x1
58 #define HAX_CAP_FAILREASON_NX   0x2
59
60 #define HAX_CAP_MEMQUOTA    0x2
61
62 #ifdef __APPLE__
63 #define HAX_IOCTL_CAPABILITY _IOR(0, 0x23, struct hax_capabilityinfo)
64 typedef int hax_fd;
65 #endif
66
67 #ifdef _WIN32
68 #define HAX_DEVICE_TYPE 0x4000
69 #define HAX_IOCTL_CAPABILITY    CTL_CODE(HAX_DEVICE_TYPE, 0x910, METHOD_BUFFERED, FILE_ANY_ACCESS)
70 typedef HANDLE hax_fd;
71 #endif
72
73 struct hax_vm {
74     hax_fd fd;
75     int id;
76     struct hax_vcpu_state *vcpus[HAX_MAX_VCPU];
77 };
78
79 struct hax_state {
80     hax_fd fd; /* the global hax device interface */
81     uint32_t version;
82     struct hax_vm *vm;
83     uint64_t mem_quota;
84 };
85
86 struct hax_capabilityinfo {
87     /* bit 0: 1 - working
88      *        0 - not working, possibly because NT/NX disabled
89      * bit 1: 1 - memory limitation working
90      *        0 - no memory limitation
91      */
92     uint16_t wstatus;
93     /* valid when not working
94      * bit 0: VT not enabeld
95      * bit 1: NX not enabled*/
96     uint16_t winfo;
97     uint32_t pad;
98     uint64_t mem_quota;
99 };
100 #ifdef _WIN32
101 static inline int hax_invalid_fd( hax_fd fd ) {
102     return ( fd == INVALID_HANDLE_VALUE );
103 }
104 #endif
105 #ifdef __APPLE__
106 static inline int hax_invalid_fd(hax_fd fd)
107 {
108     return fd <= 0;
109 }
110 #endif
111
112
113 static hax_fd hax_mod_open( void );
114 static int hax_open_device( hax_fd *fd );
115 static int hax_get_capability( struct hax_state *hax );
116 static int hax_capability( struct hax_state *hax, struct hax_capabilityinfo *cap );
117
118 static int check_hax( void ) {
119
120     struct hax_state hax;
121     memset( &hax, 0, sizeof( struct hax_state ) );
122
123     hax.fd = hax_mod_open();
124
125     int ret_fd = hax_invalid_fd( hax.fd );
126     if ( ret_fd ) {
127         fprintf( stderr, "Invalid fd:%d\n", ret_fd );
128         return ret_fd;
129     }
130
131     int ret_cap = hax_get_capability( &hax );
132     if ( ret_cap ) {
133         fprintf( stderr, "Not capable:%d\n", ret_cap );
134         return ret_cap;
135     }
136
137     return 0;
138
139 }
140 #ifdef _WIN32
141 static int hax_open_device( hax_fd *fd ) {
142     uint32_t errNum = 0;
143     HANDLE hDevice;
144
145     if ( !fd )
146         return -2;
147
148     hDevice = CreateFile( "\\\\.\\HAX", GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
149         NULL );
150
151     if ( hDevice == INVALID_HANDLE_VALUE ) {
152         fprintf( stderr, "Failed to open the HAX device!\n" );
153         errNum = GetLastError();
154         if ( errNum == ERROR_FILE_NOT_FOUND )
155             return -1;
156         return -2;
157     }
158     *fd = hDevice;
159     fprintf( stdout, "device fd:%d\n", *fd );
160     return 0;
161 }
162
163 static hax_fd hax_mod_open( void ) {
164     int ret;
165     hax_fd fd;
166
167     ret = hax_open_device( &fd );
168     if ( ret != 0 ) {
169         fprintf( stderr, "Open HAX device failed\n" );
170     }
171
172     return fd;
173 }
174 #else
175 static hax_fd hax_mod_open(void)
176 {
177     int fd = open("/dev/HAX", O_RDWR);
178
179     if (fd == -1)
180     {
181         fprintf(stderr, "hahFailed to open the hax module\n");
182         //return -errno;
183     }
184
185     return fd;
186 }
187
188 #endif
189
190 static int hax_get_capability( struct hax_state *hax ) {
191     int ret;
192     struct hax_capabilityinfo capinfo, *cap = &capinfo;
193
194     ret = hax_capability( hax, cap );
195     if ( ret )
196         return ret;
197
198     if ( ( ( cap->wstatus & HAX_CAP_WORKSTATUS_MASK ) == HAX_CAP_STATUS_NOTWORKING ) ) {
199         if ( cap->winfo & HAX_CAP_FAILREASON_VT )
200             fprintf( stderr, "VTX feature is not enabled. which will cause HAX driver not working.\n" );
201         else if ( cap->winfo & HAX_CAP_FAILREASON_NX )
202             fprintf( stderr, "NX feature is not enabled, which will cause HAX driver not working.\n" );
203         return -ENXIO;
204     }
205
206 /*
207     if ( cap->wstatus & HAX_CAP_MEMQUOTA ) {
208         if ( cap->mem_quota < hax->mem_quota ) {
209             fprintf( stderr, "The memory needed by this VM exceeds the driver limit.\n" );
210             return -ENOSPC;
211         }
212     }
213 */
214     return 0;
215 }
216 #ifdef _WIN32
217 static int hax_capability( struct hax_state *hax, struct hax_capabilityinfo *cap ) {
218     int ret;
219     HANDLE hDevice = hax->fd; //handle to hax module
220     DWORD dSize = 0;
221     DWORD err = 0;
222
223     if ( hax_invalid_fd( hDevice ) ) {
224         fprintf( stderr, "Invalid fd for hax device!\n" );
225         return -ENODEV;
226     }
227
228     ret = DeviceIoControl( hDevice, HAX_IOCTL_CAPABILITY, NULL, 0, cap, sizeof( *cap ), &dSize, ( LPOVERLAPPED ) NULL );
229
230     if ( !ret ) {
231         err = GetLastError();
232         if ( err == ERROR_INSUFFICIENT_BUFFER || err == ERROR_MORE_DATA )
233             fprintf( stderr, "hax capability is too long to hold.\n" );
234         fprintf( stderr, "Failed to get Hax capability:%d\n", err );
235         return -EFAULT;
236     } else
237         return 0;
238
239 }
240 #endif
241
242 #ifdef __APPLE__
243 int hax_capability(struct hax_state *hax, struct hax_capabilityinfo *cap)
244 {
245     int ret;
246
247     ret = ioctl(hax->fd, HAX_IOCTL_CAPABILITY, cap);
248     if (ret == -1)
249     {
250         fprintf(stderr, "Failed to get HAX capability\n");
251         return -errno;
252     }
253
254     return 0;
255 }
256 #endif
257
258 int main(int argc, char* argv[]) {
259     return check_hax();
260 }