vmw_balloon.c (d7568c130d0d0ff1fc5b364fc879b91f108a3d54) vmw_balloon.c (48e3d668b7902cca3c61e9e2098e7f76b5646c28)
1/*
2 * VMware Balloon driver.
3 *
1/*
2 * VMware Balloon driver.
3 *
4 * Copyright (C) 2000-2013, VMware, Inc. All Rights Reserved.
4 * Copyright (C) 2000-2014, VMware, Inc. All Rights Reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; version 2 of the License and no later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or

--- 25 unchanged lines hidden (view full) ---

38#include <linux/kernel.h>
39#include <linux/mm.h>
40#include <linux/vmalloc.h>
41#include <linux/sched.h>
42#include <linux/module.h>
43#include <linux/workqueue.h>
44#include <linux/debugfs.h>
45#include <linux/seq_file.h>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; version 2 of the License and no later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or

--- 25 unchanged lines hidden (view full) ---

38#include <linux/kernel.h>
39#include <linux/mm.h>
40#include <linux/vmalloc.h>
41#include <linux/sched.h>
42#include <linux/module.h>
43#include <linux/workqueue.h>
44#include <linux/debugfs.h>
45#include <linux/seq_file.h>
46#include <linux/vmw_vmci_defs.h>
47#include <linux/vmw_vmci_api.h>
46#include <asm/hypervisor.h>
47
48MODULE_AUTHOR("VMware, Inc.");
49MODULE_DESCRIPTION("VMware Memory Control (Balloon) Driver");
48#include <asm/hypervisor.h>
49
50MODULE_AUTHOR("VMware, Inc.");
51MODULE_DESCRIPTION("VMware Memory Control (Balloon) Driver");
50MODULE_VERSION("1.4.1.0-k");
52MODULE_VERSION("1.5.0.0-k");
51MODULE_ALIAS("dmi:*:svnVMware*:*");
52MODULE_ALIAS("vmware_vmmemctl");
53MODULE_LICENSE("GPL");
54
55/*
56 * Various constants controlling rate of inflaint/deflating balloon,
57 * measured in pages.
58 */

--- 37 unchanged lines hidden (view full) ---

96#define VMW_BALLOON_HV_PORT 0x5670
97#define VMW_BALLOON_HV_MAGIC 0x456c6d6f
98#define VMW_BALLOON_GUEST_ID 1 /* Linux */
99
100enum vmwballoon_capabilities {
101 /*
102 * Bit 0 is reserved and not associated to any capability.
103 */
53MODULE_ALIAS("dmi:*:svnVMware*:*");
54MODULE_ALIAS("vmware_vmmemctl");
55MODULE_LICENSE("GPL");
56
57/*
58 * Various constants controlling rate of inflaint/deflating balloon,
59 * measured in pages.
60 */

--- 37 unchanged lines hidden (view full) ---

98#define VMW_BALLOON_HV_PORT 0x5670
99#define VMW_BALLOON_HV_MAGIC 0x456c6d6f
100#define VMW_BALLOON_GUEST_ID 1 /* Linux */
101
102enum vmwballoon_capabilities {
103 /*
104 * Bit 0 is reserved and not associated to any capability.
105 */
104 VMW_BALLOON_BASIC_CMDS = (1 << 1),
105 VMW_BALLOON_BATCHED_CMDS = (1 << 2),
106 VMW_BALLOON_BATCHED_2M_CMDS = (1 << 3),
106 VMW_BALLOON_BASIC_CMDS = (1 << 1),
107 VMW_BALLOON_BATCHED_CMDS = (1 << 2),
108 VMW_BALLOON_BATCHED_2M_CMDS = (1 << 3),
109 VMW_BALLOON_SIGNALLED_WAKEUP_CMD = (1 << 4),
107};
108
109#define VMW_BALLOON_CAPABILITIES (VMW_BALLOON_BASIC_CMDS \
110 | VMW_BALLOON_BATCHED_CMDS \
110};
111
112#define VMW_BALLOON_CAPABILITIES (VMW_BALLOON_BASIC_CMDS \
113 | VMW_BALLOON_BATCHED_CMDS \
111 | VMW_BALLOON_BATCHED_2M_CMDS)
114 | VMW_BALLOON_BATCHED_2M_CMDS \
115 | VMW_BALLOON_SIGNALLED_WAKEUP_CMD)
112
113#define VMW_BALLOON_2M_SHIFT (9)
114#define VMW_BALLOON_NUM_PAGE_SIZES (2)
115
116/*
117 * Backdoor commands availability:
118 *
119 * START, GET_TARGET and GUEST_ID are always available,
120 *
121 * VMW_BALLOON_BASIC_CMDS:
122 * LOCK and UNLOCK commands,
123 * VMW_BALLOON_BATCHED_CMDS:
124 * BATCHED_LOCK and BATCHED_UNLOCK commands.
125 * VMW BALLOON_BATCHED_2M_CMDS:
116
117#define VMW_BALLOON_2M_SHIFT (9)
118#define VMW_BALLOON_NUM_PAGE_SIZES (2)
119
120/*
121 * Backdoor commands availability:
122 *
123 * START, GET_TARGET and GUEST_ID are always available,
124 *
125 * VMW_BALLOON_BASIC_CMDS:
126 * LOCK and UNLOCK commands,
127 * VMW_BALLOON_BATCHED_CMDS:
128 * BATCHED_LOCK and BATCHED_UNLOCK commands.
129 * VMW BALLOON_BATCHED_2M_CMDS:
126 * BATCHED_2M_LOCK and BATCHED_2M_UNLOCK commands.
130 * BATCHED_2M_LOCK and BATCHED_2M_UNLOCK commands,
131 * VMW VMW_BALLOON_SIGNALLED_WAKEUP_CMD:
132 * VMW_BALLOON_CMD_VMCI_DOORBELL_SET command.
127 */
128#define VMW_BALLOON_CMD_START 0
129#define VMW_BALLOON_CMD_GET_TARGET 1
130#define VMW_BALLOON_CMD_LOCK 2
131#define VMW_BALLOON_CMD_UNLOCK 3
132#define VMW_BALLOON_CMD_GUEST_ID 4
133#define VMW_BALLOON_CMD_BATCHED_LOCK 6
134#define VMW_BALLOON_CMD_BATCHED_UNLOCK 7
135#define VMW_BALLOON_CMD_BATCHED_2M_LOCK 8
136#define VMW_BALLOON_CMD_BATCHED_2M_UNLOCK 9
133 */
134#define VMW_BALLOON_CMD_START 0
135#define VMW_BALLOON_CMD_GET_TARGET 1
136#define VMW_BALLOON_CMD_LOCK 2
137#define VMW_BALLOON_CMD_UNLOCK 3
138#define VMW_BALLOON_CMD_GUEST_ID 4
139#define VMW_BALLOON_CMD_BATCHED_LOCK 6
140#define VMW_BALLOON_CMD_BATCHED_UNLOCK 7
141#define VMW_BALLOON_CMD_BATCHED_2M_LOCK 8
142#define VMW_BALLOON_CMD_BATCHED_2M_UNLOCK 9
143#define VMW_BALLOON_CMD_VMCI_DOORBELL_SET 10
137
138
139/* error codes */
140#define VMW_BALLOON_SUCCESS 0
141#define VMW_BALLOON_FAILURE -1
142#define VMW_BALLOON_ERROR_CMD_INVALID 1
143#define VMW_BALLOON_ERROR_PPN_INVALID 2
144#define VMW_BALLOON_ERROR_PPN_LOCKED 3

--- 64 unchanged lines hidden (view full) ---

209 result = __dummy1; \
210 result &= -1UL; \
211 __status & -1UL; \
212})
213
214#ifdef CONFIG_DEBUG_FS
215struct vmballoon_stats {
216 unsigned int timer;
144
145
146/* error codes */
147#define VMW_BALLOON_SUCCESS 0
148#define VMW_BALLOON_FAILURE -1
149#define VMW_BALLOON_ERROR_CMD_INVALID 1
150#define VMW_BALLOON_ERROR_PPN_INVALID 2
151#define VMW_BALLOON_ERROR_PPN_LOCKED 3

--- 64 unchanged lines hidden (view full) ---

216 result = __dummy1; \
217 result &= -1UL; \
218 __status & -1UL; \
219})
220
221#ifdef CONFIG_DEBUG_FS
222struct vmballoon_stats {
223 unsigned int timer;
224 unsigned int doorbell;
217
218 /* allocation statistics */
219 unsigned int alloc[VMW_BALLOON_NUM_PAGE_SIZES];
220 unsigned int alloc_fail[VMW_BALLOON_NUM_PAGE_SIZES];
221 unsigned int sleep_alloc;
222 unsigned int sleep_alloc_fail;
223 unsigned int refused_alloc[VMW_BALLOON_NUM_PAGE_SIZES];
224 unsigned int refused_free[VMW_BALLOON_NUM_PAGE_SIZES];

--- 5 unchanged lines hidden (view full) ---

230 unsigned int unlock[VMW_BALLOON_NUM_PAGE_SIZES];
231 unsigned int unlock_fail[VMW_BALLOON_NUM_PAGE_SIZES];
232 unsigned int target;
233 unsigned int target_fail;
234 unsigned int start;
235 unsigned int start_fail;
236 unsigned int guest_type;
237 unsigned int guest_type_fail;
225
226 /* allocation statistics */
227 unsigned int alloc[VMW_BALLOON_NUM_PAGE_SIZES];
228 unsigned int alloc_fail[VMW_BALLOON_NUM_PAGE_SIZES];
229 unsigned int sleep_alloc;
230 unsigned int sleep_alloc_fail;
231 unsigned int refused_alloc[VMW_BALLOON_NUM_PAGE_SIZES];
232 unsigned int refused_free[VMW_BALLOON_NUM_PAGE_SIZES];

--- 5 unchanged lines hidden (view full) ---

238 unsigned int unlock[VMW_BALLOON_NUM_PAGE_SIZES];
239 unsigned int unlock_fail[VMW_BALLOON_NUM_PAGE_SIZES];
240 unsigned int target;
241 unsigned int target_fail;
242 unsigned int start;
243 unsigned int start_fail;
244 unsigned int guest_type;
245 unsigned int guest_type_fail;
246 unsigned int doorbell_set;
247 unsigned int doorbell_unset;
238};
239
240#define STATS_INC(stat) (stat)++
241#else
242#define STATS_INC(stat)
243#endif
244
245struct vmballoon;

--- 48 unchanged lines hidden (view full) ---

294
295 /* debugfs file exporting statistics */
296 struct dentry *dbg_entry;
297#endif
298
299 struct sysinfo sysinfo;
300
301 struct delayed_work dwork;
248};
249
250#define STATS_INC(stat) (stat)++
251#else
252#define STATS_INC(stat)
253#endif
254
255struct vmballoon;

--- 48 unchanged lines hidden (view full) ---

304
305 /* debugfs file exporting statistics */
306 struct dentry *dbg_entry;
307#endif
308
309 struct sysinfo sysinfo;
310
311 struct delayed_work dwork;
312
313 struct vmci_handle vmci_doorbell;
302};
303
304static struct vmballoon balloon;
305
306/*
307 * Send "start" command to the host, communicating supported version
308 * of the protocol.
309 */

--- 678 unchanged lines hidden (view full) ---

988 __free_page(b->page);
989 return false;
990 }
991
992 return true;
993}
994
995/*
314};
315
316static struct vmballoon balloon;
317
318/*
319 * Send "start" command to the host, communicating supported version
320 * of the protocol.
321 */

--- 678 unchanged lines hidden (view full) ---

1000 __free_page(b->page);
1001 return false;
1002 }
1003
1004 return true;
1005}
1006
1007/*
1008 * Receive notification and resize balloon
1009 */
1010static void vmballoon_doorbell(void *client_data)
1011{
1012 struct vmballoon *b = client_data;
1013
1014 STATS_INC(b->stats.doorbell);
1015
1016 mod_delayed_work(system_freezable_wq, &b->dwork, 0);
1017}
1018
1019/*
1020 * Clean up vmci doorbell
1021 */
1022static void vmballoon_vmci_cleanup(struct vmballoon *b)
1023{
1024 int error;
1025
1026 VMWARE_BALLOON_CMD(VMCI_DOORBELL_SET, VMCI_INVALID_ID,
1027 VMCI_INVALID_ID, error);
1028 STATS_INC(b->stats.doorbell_unset);
1029
1030 if (!vmci_handle_is_invalid(b->vmci_doorbell)) {
1031 vmci_doorbell_destroy(b->vmci_doorbell);
1032 b->vmci_doorbell = VMCI_INVALID_HANDLE;
1033 }
1034}
1035
1036/*
1037 * Initialize vmci doorbell, to get notified as soon as balloon changes
1038 */
1039static int vmballoon_vmci_init(struct vmballoon *b)
1040{
1041 int error = 0;
1042
1043 if ((b->capabilities & VMW_BALLOON_SIGNALLED_WAKEUP_CMD) != 0) {
1044 error = vmci_doorbell_create(&b->vmci_doorbell,
1045 VMCI_FLAG_DELAYED_CB,
1046 VMCI_PRIVILEGE_FLAG_RESTRICTED,
1047 vmballoon_doorbell, b);
1048
1049 if (error == VMCI_SUCCESS) {
1050 VMWARE_BALLOON_CMD(VMCI_DOORBELL_SET,
1051 b->vmci_doorbell.context,
1052 b->vmci_doorbell.resource, error);
1053 STATS_INC(b->stats.doorbell_set);
1054 }
1055 }
1056
1057 if (error != 0) {
1058 vmballoon_vmci_cleanup(b);
1059
1060 return -EIO;
1061 }
1062
1063 return 0;
1064}
1065
1066/*
996 * Perform standard reset sequence by popping the balloon (in case it
997 * is not empty) and then restarting protocol. This operation normally
998 * happens when host responds with VMW_BALLOON_ERROR_RESET to a command.
999 */
1000static void vmballoon_reset(struct vmballoon *b)
1001{
1067 * Perform standard reset sequence by popping the balloon (in case it
1068 * is not empty) and then restarting protocol. This operation normally
1069 * happens when host responds with VMW_BALLOON_ERROR_RESET to a command.
1070 */
1071static void vmballoon_reset(struct vmballoon *b)
1072{
1073 int error;
1074
1075 vmballoon_vmci_cleanup(b);
1076
1002 /* free all pages, skipping monitor unlock */
1003 vmballoon_pop(b);
1004
1005 if (!vmballoon_send_start(b, VMW_BALLOON_CAPABILITIES))
1006 return;
1007
1008 if ((b->capabilities & VMW_BALLOON_BATCHED_CMDS) != 0) {
1009 b->ops = &vmballoon_batched_ops;

--- 9 unchanged lines hidden (view full) ---

1019 return;
1020 }
1021 } else if ((b->capabilities & VMW_BALLOON_BASIC_CMDS) != 0) {
1022 b->ops = &vmballoon_basic_ops;
1023 b->batch_max_pages = 1;
1024 }
1025
1026 b->reset_required = false;
1077 /* free all pages, skipping monitor unlock */
1078 vmballoon_pop(b);
1079
1080 if (!vmballoon_send_start(b, VMW_BALLOON_CAPABILITIES))
1081 return;
1082
1083 if ((b->capabilities & VMW_BALLOON_BATCHED_CMDS) != 0) {
1084 b->ops = &vmballoon_batched_ops;

--- 9 unchanged lines hidden (view full) ---

1094 return;
1095 }
1096 } else if ((b->capabilities & VMW_BALLOON_BASIC_CMDS) != 0) {
1097 b->ops = &vmballoon_basic_ops;
1098 b->batch_max_pages = 1;
1099 }
1100
1101 b->reset_required = false;
1102
1103 error = vmballoon_vmci_init(b);
1104 if (error)
1105 pr_err("failed to initialize vmci doorbell\n");
1106
1027 if (!vmballoon_send_guest_id(b))
1028 pr_err("failed to send guest ID to the host\n");
1029}
1030
1031/*
1032 * Balloon work function: reset protocol, if needed, get the new size and
1033 * adjust balloon as needed. Repeat in 1 sec.
1034 */

--- 57 unchanged lines hidden (view full) ---

1092 /* format rate info */
1093 seq_printf(f,
1094 "rateSleepAlloc: %8d pages/sec\n",
1095 b->rate_alloc);
1096
1097 seq_printf(f,
1098 "\n"
1099 "timer: %8u\n"
1107 if (!vmballoon_send_guest_id(b))
1108 pr_err("failed to send guest ID to the host\n");
1109}
1110
1111/*
1112 * Balloon work function: reset protocol, if needed, get the new size and
1113 * adjust balloon as needed. Repeat in 1 sec.
1114 */

--- 57 unchanged lines hidden (view full) ---

1172 /* format rate info */
1173 seq_printf(f,
1174 "rateSleepAlloc: %8d pages/sec\n",
1175 b->rate_alloc);
1176
1177 seq_printf(f,
1178 "\n"
1179 "timer: %8u\n"
1180 "doorbell: %8u\n"
1100 "start: %8u (%4u failed)\n"
1101 "guestType: %8u (%4u failed)\n"
1102 "2m-lock: %8u (%4u failed)\n"
1103 "lock: %8u (%4u failed)\n"
1104 "2m-unlock: %8u (%4u failed)\n"
1105 "unlock: %8u (%4u failed)\n"
1106 "target: %8u (%4u failed)\n"
1107 "prim2mAlloc: %8u (%4u failed)\n"
1108 "primNoSleepAlloc: %8u (%4u failed)\n"
1109 "primCanSleepAlloc: %8u (%4u failed)\n"
1110 "prim2mFree: %8u\n"
1111 "primFree: %8u\n"
1112 "err2mAlloc: %8u\n"
1113 "errAlloc: %8u\n"
1114 "err2mFree: %8u\n"
1181 "start: %8u (%4u failed)\n"
1182 "guestType: %8u (%4u failed)\n"
1183 "2m-lock: %8u (%4u failed)\n"
1184 "lock: %8u (%4u failed)\n"
1185 "2m-unlock: %8u (%4u failed)\n"
1186 "unlock: %8u (%4u failed)\n"
1187 "target: %8u (%4u failed)\n"
1188 "prim2mAlloc: %8u (%4u failed)\n"
1189 "primNoSleepAlloc: %8u (%4u failed)\n"
1190 "primCanSleepAlloc: %8u (%4u failed)\n"
1191 "prim2mFree: %8u\n"
1192 "primFree: %8u\n"
1193 "err2mAlloc: %8u\n"
1194 "errAlloc: %8u\n"
1195 "err2mFree: %8u\n"
1115 "errFree: %8u\n",
1196 "errFree: %8u\n"
1197 "doorbellSet: %8u\n"
1198 "doorbellUnset: %8u\n",
1116 stats->timer,
1199 stats->timer,
1200 stats->doorbell,
1117 stats->start, stats->start_fail,
1118 stats->guest_type, stats->guest_type_fail,
1119 stats->lock[true], stats->lock_fail[true],
1120 stats->lock[false], stats->lock_fail[false],
1121 stats->unlock[true], stats->unlock_fail[true],
1122 stats->unlock[false], stats->unlock_fail[false],
1123 stats->target, stats->target_fail,
1124 stats->alloc[true], stats->alloc_fail[true],
1125 stats->alloc[false], stats->alloc_fail[false],
1126 stats->sleep_alloc, stats->sleep_alloc_fail,
1127 stats->free[true],
1128 stats->free[false],
1129 stats->refused_alloc[true], stats->refused_alloc[false],
1201 stats->start, stats->start_fail,
1202 stats->guest_type, stats->guest_type_fail,
1203 stats->lock[true], stats->lock_fail[true],
1204 stats->lock[false], stats->lock_fail[false],
1205 stats->unlock[true], stats->unlock_fail[true],
1206 stats->unlock[false], stats->unlock_fail[false],
1207 stats->target, stats->target_fail,
1208 stats->alloc[true], stats->alloc_fail[true],
1209 stats->alloc[false], stats->alloc_fail[false],
1210 stats->sleep_alloc, stats->sleep_alloc_fail,
1211 stats->free[true],
1212 stats->free[false],
1213 stats->refused_alloc[true], stats->refused_alloc[false],
1130 stats->refused_free[true], stats->refused_free[false]);
1214 stats->refused_free[true], stats->refused_free[false],
1215 stats->doorbell_set, stats->doorbell_unset);
1131
1132 return 0;
1133}
1134
1135static int vmballoon_debug_open(struct inode *inode, struct file *file)
1136{
1137 return single_open(file, vmballoon_debug_show, inode->i_private);
1138}

--- 60 unchanged lines hidden (view full) ---

1199 balloon.rate_alloc = VMW_BALLOON_RATE_ALLOC_MAX;
1200
1201 INIT_DELAYED_WORK(&balloon.dwork, vmballoon_work);
1202
1203 error = vmballoon_debugfs_init(&balloon);
1204 if (error)
1205 return error;
1206
1216
1217 return 0;
1218}
1219
1220static int vmballoon_debug_open(struct inode *inode, struct file *file)
1221{
1222 return single_open(file, vmballoon_debug_show, inode->i_private);
1223}

--- 60 unchanged lines hidden (view full) ---

1284 balloon.rate_alloc = VMW_BALLOON_RATE_ALLOC_MAX;
1285
1286 INIT_DELAYED_WORK(&balloon.dwork, vmballoon_work);
1287
1288 error = vmballoon_debugfs_init(&balloon);
1289 if (error)
1290 return error;
1291
1292 balloon.vmci_doorbell = VMCI_INVALID_HANDLE;
1207 balloon.batch_page = NULL;
1208 balloon.page = NULL;
1209 balloon.reset_required = true;
1210
1211 queue_delayed_work(system_freezable_wq, &balloon.dwork, 0);
1212
1213 return 0;
1214}
1215module_init(vmballoon_init);
1216
1217static void __exit vmballoon_exit(void)
1218{
1293 balloon.batch_page = NULL;
1294 balloon.page = NULL;
1295 balloon.reset_required = true;
1296
1297 queue_delayed_work(system_freezable_wq, &balloon.dwork, 0);
1298
1299 return 0;
1300}
1301module_init(vmballoon_init);
1302
1303static void __exit vmballoon_exit(void)
1304{
1305 vmballoon_vmci_cleanup(&balloon);
1219 cancel_delayed_work_sync(&balloon.dwork);
1220
1221 vmballoon_debugfs_exit(&balloon);
1222
1223 /*
1224 * Deallocate all reserved memory, and reset connection with monitor.
1225 * Reset connection before deallocating memory to avoid potential for
1226 * additional spurious resets from guest touching deallocated pages.
1227 */
1228 vmballoon_send_start(&balloon, 0);
1229 vmballoon_pop(&balloon);
1230}
1231module_exit(vmballoon_exit);
1306 cancel_delayed_work_sync(&balloon.dwork);
1307
1308 vmballoon_debugfs_exit(&balloon);
1309
1310 /*
1311 * Deallocate all reserved memory, and reset connection with monitor.
1312 * Reset connection before deallocating memory to avoid potential for
1313 * additional spurious resets from guest touching deallocated pages.
1314 */
1315 vmballoon_send_start(&balloon, 0);
1316 vmballoon_pop(&balloon);
1317}
1318module_exit(vmballoon_exit);