1
1
/*
2
2
* VMware Balloon driver.
3
3
*
4
- * Copyright (C) 2000-2013 , VMware, Inc. All Rights Reserved.
4
+ * Copyright (C) 2000-2014 , VMware, Inc. All Rights Reserved.
5
5
*
6
6
* This program is free software; you can redistribute it and/or modify it
7
7
* under the terms of the GNU General Public License as published by the
43
43
#include <linux/workqueue.h>
44
44
#include <linux/debugfs.h>
45
45
#include <linux/seq_file.h>
46
+ #include <linux/vmw_vmci_defs.h>
47
+ #include <linux/vmw_vmci_api.h>
46
48
#include <asm/hypervisor.h>
47
49
48
50
MODULE_AUTHOR ("VMware, Inc." );
49
51
MODULE_DESCRIPTION ("VMware Memory Control (Balloon) Driver" );
50
- MODULE_VERSION ("1.4.1 .0-k" );
52
+ MODULE_VERSION ("1.5.0 .0-k" );
51
53
MODULE_ALIAS ("dmi:*:svnVMware*:*" );
52
54
MODULE_ALIAS ("vmware_vmmemctl" );
53
55
MODULE_LICENSE ("GPL" );
@@ -101,14 +103,16 @@ enum vmwballoon_capabilities {
101
103
/*
102
104
* Bit 0 is reserved and not associated to any capability.
103
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
110
};
108
111
109
112
#define VMW_BALLOON_CAPABILITIES (VMW_BALLOON_BASIC_CMDS \
110
113
| VMW_BALLOON_BATCHED_CMDS \
111
- | VMW_BALLOON_BATCHED_2M_CMDS)
114
+ | VMW_BALLOON_BATCHED_2M_CMDS \
115
+ | VMW_BALLOON_SIGNALLED_WAKEUP_CMD)
112
116
113
117
#define VMW_BALLOON_2M_SHIFT (9)
114
118
#define VMW_BALLOON_NUM_PAGE_SIZES (2)
@@ -123,7 +127,9 @@ enum vmwballoon_capabilities {
123
127
* VMW_BALLOON_BATCHED_CMDS:
124
128
* BATCHED_LOCK and BATCHED_UNLOCK commands.
125
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
133
*/
128
134
#define VMW_BALLOON_CMD_START 0
129
135
#define VMW_BALLOON_CMD_GET_TARGET 1
@@ -134,6 +140,7 @@ enum vmwballoon_capabilities {
134
140
#define VMW_BALLOON_CMD_BATCHED_UNLOCK 7
135
141
#define VMW_BALLOON_CMD_BATCHED_2M_LOCK 8
136
142
#define VMW_BALLOON_CMD_BATCHED_2M_UNLOCK 9
143
+ #define VMW_BALLOON_CMD_VMCI_DOORBELL_SET 10
137
144
138
145
139
146
/* error codes */
@@ -214,6 +221,7 @@ static void vmballoon_batch_set_pa(struct vmballoon_batch_page *batch, int idx,
214
221
#ifdef CONFIG_DEBUG_FS
215
222
struct vmballoon_stats {
216
223
unsigned int timer ;
224
+ unsigned int doorbell ;
217
225
218
226
/* allocation statistics */
219
227
unsigned int alloc [VMW_BALLOON_NUM_PAGE_SIZES ];
@@ -235,6 +243,8 @@ struct vmballoon_stats {
235
243
unsigned int start_fail ;
236
244
unsigned int guest_type ;
237
245
unsigned int guest_type_fail ;
246
+ unsigned int doorbell_set ;
247
+ unsigned int doorbell_unset ;
238
248
};
239
249
240
250
#define STATS_INC (stat ) (stat)++
@@ -299,6 +309,8 @@ struct vmballoon {
299
309
struct sysinfo sysinfo ;
300
310
301
311
struct delayed_work dwork ;
312
+
313
+ struct vmci_handle vmci_doorbell ;
302
314
};
303
315
304
316
static struct vmballoon balloon ;
@@ -992,13 +1004,76 @@ static bool vmballoon_init_batching(struct vmballoon *b)
992
1004
return true;
993
1005
}
994
1006
1007
+ /*
1008
+ * Receive notification and resize balloon
1009
+ */
1010
+ static 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
+ */
1022
+ static 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
+ */
1039
+ static 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
+
995
1066
/*
996
1067
* Perform standard reset sequence by popping the balloon (in case it
997
1068
* is not empty) and then restarting protocol. This operation normally
998
1069
* happens when host responds with VMW_BALLOON_ERROR_RESET to a command.
999
1070
*/
1000
1071
static void vmballoon_reset (struct vmballoon * b )
1001
1072
{
1073
+ int error ;
1074
+
1075
+ vmballoon_vmci_cleanup (b );
1076
+
1002
1077
/* free all pages, skipping monitor unlock */
1003
1078
vmballoon_pop (b );
1004
1079
@@ -1024,6 +1099,11 @@ static void vmballoon_reset(struct vmballoon *b)
1024
1099
}
1025
1100
1026
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
1107
if (!vmballoon_send_guest_id (b ))
1028
1108
pr_err ("failed to send guest ID to the host\n" );
1029
1109
}
@@ -1097,6 +1177,7 @@ static int vmballoon_debug_show(struct seq_file *f, void *offset)
1097
1177
seq_printf (f ,
1098
1178
"\n"
1099
1179
"timer: %8u\n"
1180
+ "doorbell: %8u\n"
1100
1181
"start: %8u (%4u failed)\n"
1101
1182
"guestType: %8u (%4u failed)\n"
1102
1183
"2m-lock: %8u (%4u failed)\n"
@@ -1112,8 +1193,11 @@ static int vmballoon_debug_show(struct seq_file *f, void *offset)
1112
1193
"err2mAlloc: %8u\n"
1113
1194
"errAlloc: %8u\n"
1114
1195
"err2mFree: %8u\n"
1115
- "errFree: %8u\n" ,
1196
+ "errFree: %8u\n"
1197
+ "doorbellSet: %8u\n"
1198
+ "doorbellUnset: %8u\n" ,
1116
1199
stats -> timer ,
1200
+ stats -> doorbell ,
1117
1201
stats -> start , stats -> start_fail ,
1118
1202
stats -> guest_type , stats -> guest_type_fail ,
1119
1203
stats -> lock [true], stats -> lock_fail [true],
@@ -1127,7 +1211,8 @@ static int vmballoon_debug_show(struct seq_file *f, void *offset)
1127
1211
stats -> free [true],
1128
1212
stats -> free [false],
1129
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
1216
1132
1217
return 0 ;
1133
1218
}
@@ -1204,6 +1289,7 @@ static int __init vmballoon_init(void)
1204
1289
if (error )
1205
1290
return error ;
1206
1291
1292
+ balloon .vmci_doorbell = VMCI_INVALID_HANDLE ;
1207
1293
balloon .batch_page = NULL ;
1208
1294
balloon .page = NULL ;
1209
1295
balloon .reset_required = true;
@@ -1216,6 +1302,7 @@ module_init(vmballoon_init);
1216
1302
1217
1303
static void __exit vmballoon_exit (void )
1218
1304
{
1305
+ vmballoon_vmci_cleanup (& balloon );
1219
1306
cancel_delayed_work_sync (& balloon .dwork );
1220
1307
1221
1308
vmballoon_debugfs_exit (& balloon );
0 commit comments