Project

General

Profile

0002-Adapt-to-DragonFlyBSD.patch

ddegroot, 10/02/2018 05:19 PM

View differences:

share/man/man4/virtio.4
74 74
An emulated SCSI HBA is provided by the
75 75
.Xr virtio_scsi 4
76 76
device driver.
77
.\".It Nm Balloon
78
.\"A pseudo-device to allow the VM to release memory back to the hypervisor is
79
.\"provided by the
80
.\".Xr virtio_balloon 4
81
.\"device driver.
77
.It Nm Balloon
78
A pseudo-device to allow the VM to release memory back to the hypervisor is
79
provided by the
80
.Xr virtio_balloon 4
81
device driver.
82 82
.El
83 83
.Sh LOADER TUNABLES
84 84
Tunables can be set at the
......
91 91
The default value is 0 (use MSI-X interrupts if available).
92 92
.El
93 93
.Sh SEE ALSO
94
.\".Xr virtio_balloon 4 ,
94
.Xr virtio_balloon 4 ,
95 95
.Xr virtio_blk 4 ,
96 96
.\".Xr virtio_console 4 ,
97 97
.Xr virtio_random 4 ,
......
105 105
.Fx
106 106
support for VirtIO was first added by
107 107
.An Bryan Venteicher Aq Mt bryanv@FreeBSD.org .
108
.Pp
109
.Dx support for Virtio Memory Balloon adapted by
110
.An Diederik de Groot Aq Mt info@talon.nl .
share/man/man4/virtio_balloon.4
22 22
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 23
.\" SUCH DAMAGE.
24 24
.\"
25
.Dd January 22, 2012
25
.Dd October 2, 2018
26 26
.Dt VIRTIO_BALLOON 4
27 27
.Os
28 28
.Sh NAME
......
40 40
module at boot time, place the following line in
41 41
.Xr loader.conf 5 :
42 42
.Bd -literal -offset indent
43
virtio_balloon_load="YES"
43
.Cd virtio_balloon_load="YES"
44 44
.Ed
45 45
.Sh DESCRIPTION
46 46
The
......
51 51
hypervisor, return memory allocated to the hypervisor so it can
52 52
be made available to other guests.
53 53
The hypervisor can later signal the balloon to return the memory.
54
.Sh EXAMPLE:
55
.Cd (vmguest) # kldload virtio_balloon
56
.Pp
57
.Cd (vmguest) # sysctl dev.vtballoon.desired
58
.Pp
59
dev.vtballoon.0.desired: 0
60
.Pp
61
.Cd (vmguest) # sysctl dev.vtballoon.current
62
.Pp
63
dev.vtballoon.0.current: 0
64

  
65
.Pp
66
.Cd (vmhost) # virsh qemu-monitor-command --domain <vmguest> --hmp 'balloon 2000'
67
.Pp
68
.Cd (vmguest) # sysctl dev.vtballoon.desired
69
.Pp
70
dev.vtballoon.0.desired: 536576
71
.Pp
72
.Cd (vmguest) # sysctl dev.vtballoon.current
73
.Pp
74
dev.vtballoon.0.current: 536576
75

  
54 76
.Sh SEE ALSO
55 77
.Xr virtio 4
56 78
.Sh HISTORY
sys/dev/virtual/virtio/balloon/Makefile
5 5
SRCS+=	bus_if.h device_if.h
6 6

  
7 7
.include <bsd.kmod.mk>
8
#CFLAGS+= -Wno-unused-function -Wno-unused-variable
sys/dev/virtual/virtio/balloon/virtio_balloon.c
27 27
/* Driver for VirtIO memory balloon devices. */
28 28

  
29 29
#include <sys/cdefs.h>
30
__FBSDID("$FreeBSD$");
31

  
32 30
#include <sys/param.h>
33 31
#include <sys/systm.h>
34 32
#include <sys/kernel.h>
......
44 42

  
45 43
#include <vm/vm.h>
46 44
#include <vm/vm_page.h>
47

  
48
#include <machine/bus.h>
49
#include <machine/resource.h>
50 45
#include <sys/bus.h>
51 46
#include <sys/rman.h>
52 47

  
53
#include <dev/virtio/virtio.h>
54
#include <dev/virtio/virtqueue.h>
55
#include <dev/virtio/balloon/virtio_balloon.h>
56

  
57
#include "virtio_if.h"
48
#include <dev/virtual/virtio/virtio/virtio.h>
49
#include <dev/virtual/virtio/virtio/virtqueue.h>
50
#include <dev/virtual/virtio/balloon/virtio_balloon.h>
58 51

  
59 52
struct vtballoon_softc {
60 53
	device_t		 vtballoon_dev;
61
	struct mtx		 vtballoon_mtx;
54
	struct lwkt_serialize    vtballoon_slz;
62 55
	uint64_t		 vtballoon_features;
63 56
	uint32_t		 vtballoon_flags;
64 57
#define VTBALLOON_FLAG_DETACH	 0x01
......
72 65

  
73 66
	struct thread		*vtballoon_td;
74 67
	uint32_t		*vtballoon_page_frames;
68
	int			 vtballoon_pagereq;
75 69
	int			 vtballoon_timeout;
70
	int			 vtballoon_nintr;
71
	int			 vtballoon_debug;
72
#define VTBALLOON_INFO     	 0x01
73
#define VTBALLOON_ERROR    	 0x02
74
#define VTBALLOON_TRACE    	 0x04
76 75
};
77 76

  
78 77
static struct virtio_feature_desc vtballoon_feature_desc[] = {
79
	{ VIRTIO_BALLOON_F_MUST_TELL_HOST,	"MustTellHost"	},
80
	{ VIRTIO_BALLOON_F_STATS_VQ,		"StatsVq"	},
81

  
78
	{ VIRTIO_BALLOON_F_MUST_TELL_HOST,	"MustTellHost"		},
79
	{ VIRTIO_BALLOON_F_STATS_VQ,		"StatsVq"		},
80
	{ VIRTIO_BALLOON_F_DEFLATE_ON_OOM,	"DeflateOnOutOfMemory"	},
82 81
	{ 0, NULL }
83 82
};
84 83

  
85
static int	vtballoon_probe(device_t);
86
static int	vtballoon_attach(device_t);
87
static int	vtballoon_detach(device_t);
88
static int	vtballoon_config_change(device_t);
84
#define vtballoon_dprintf(_sc, _level, _msg, _args ...) do {            \
85
        if ((_sc)->vtballoon_debug & (_level))                          \
86
                device_printf((_sc)->vtballoon_dev, "%s:%d: "_msg,      \
87
                  __FUNCTION__, __LINE__, ##_args);                     \
88
} while (0)
89 89

  
90
static void	vtballoon_negotiate_features(struct vtballoon_softc *);
91
static int	vtballoon_alloc_virtqueues(struct vtballoon_softc *);
90
static int		vtballoon_probe(device_t);
91
static int		vtballoon_attach(device_t);
92
static int		vtballoon_detach(device_t);
92 93

  
93
static void	vtballoon_vq_intr(void *);
94
static int		vtballoon_alloc_intrs(struct vtballoon_softc *sc);
94 95

  
95
static void	vtballoon_inflate(struct vtballoon_softc *, int);
96
static void	vtballoon_deflate(struct vtballoon_softc *, int);
96
static void		vtballoon_negotiate_features(struct vtballoon_softc *);
97
static int		vtballoon_alloc_virtqueues(struct vtballoon_softc *);
97 98

  
98
static void	vtballoon_send_page_frames(struct vtballoon_softc *,
99
		    struct virtqueue *, int);
99
static void		vtballoon_inflate_vq_intr(void *);
100
static void		vtballoon_deflate_vq_intr(void *);
101
static void 		vtballoon_config_change_intr(void *);
100 102

  
101
static void	vtballoon_pop(struct vtballoon_softc *);
102
static void	vtballoon_stop(struct vtballoon_softc *);
103
static void		vtballoon_inflate(struct vtballoon_softc *, int);
104
static void		vtballoon_deflate(struct vtballoon_softc *, int);
103 105

  
104
static vm_page_t
105
		vtballoon_alloc_page(struct vtballoon_softc *);
106
static void	vtballoon_free_page(struct vtballoon_softc *, vm_page_t);
106
static void		vtballoon_send_page_frames(struct vtballoon_softc *,
107
			    struct virtqueue *, int);
108

  
109
static void		vtballoon_pop(struct vtballoon_softc *);
110
static void		vtballoon_stop(struct vtballoon_softc *);
107 111

  
108
static int	vtballoon_sleep(struct vtballoon_softc *);
109
static void	vtballoon_thread(void *);
110
static void	vtballoon_add_sysctl(struct vtballoon_softc *);
112
static vm_page_t	vtballoon_alloc_page(struct vtballoon_softc *);
113
static void		vtballoon_free_page(struct vtballoon_softc *, vm_page_t);
114

  
115
static int		vtballoon_sleep(struct vtballoon_softc *);
116
static void		vtballoon_thread(void *);
117
static void		vtballoon_get_tunables(struct vtballoon_softc *);
118
static void		vtballoon_add_sysctl(struct vtballoon_softc *);
111 119

  
112 120
/* Features desired/implemented by this driver. */
113 121
#define VTBALLOON_FEATURES		0
114 122

  
115 123
/* Timeout between retries when the balloon needs inflating. */
116
#define VTBALLOON_LOWMEM_TIMEOUT	hz
124
//#define VTBALLOON_LOWMEM_TIMEOUT	hz
125
#define VTBALLOON_LOWMEM_TIMEOUT	hz * 1000
126

  
127
/* vm_page_alloc flags */
128
#define VTBALLOON_REGULAR_ALLOC		VM_ALLOC_NORMAL | VM_ALLOC_INTERRUPT
129
#define VTBALLOON_LOWMEM_ALLOC		VM_ALLOC_SYSTEM | VM_ALLOC_INTERRUPT
117 130

  
118 131
/*
119 132
 * Maximum number of pages we'll request to inflate or deflate
......
122 135
 */
123 136
#define VTBALLOON_PAGES_PER_REQUEST	256
124 137

  
138
#define VTBALLOON_DEFAULT_DEBUG_LEVEL   VTBALLOON_INFO | VTBALLOON_ERROR
139

  
125 140
/* Must be able to fix all pages frames in one page (segment). */
126 141
CTASSERT(VTBALLOON_PAGES_PER_REQUEST * sizeof(uint32_t) <= PAGE_SIZE);
127 142

  
128
#define VTBALLOON_MTX(_sc)		&(_sc)->vtballoon_mtx
129
#define VTBALLOON_LOCK_INIT(_sc, _name)	mtx_init(VTBALLOON_MTX((_sc)), _name, \
130
					    "VirtIO Balloon Lock", MTX_DEF)
131
#define VTBALLOON_LOCK(_sc)		mtx_lock(VTBALLOON_MTX((_sc)))
132
#define VTBALLOON_UNLOCK(_sc)		mtx_unlock(VTBALLOON_MTX((_sc)))
133
#define VTBALLOON_LOCK_DESTROY(_sc)	mtx_destroy(VTBALLOON_MTX((_sc)))
143
#define VTBALLOON_SLZ(_sc)              &(_sc)->vtballoon_slz
144
#define VTBALLOON_ENTER_SLZ(_sc)	lwkt_serialize_enter(VTBALLOON_SLZ(sc));
145
#define VTBALLOON_EXIT_SLZ(_sc)		lwkt_serialize_exit(VTBALLOON_SLZ(sc));
134 146

  
135 147
static device_method_t vtballoon_methods[] = {
136 148
	/* Device methods. */
......
138 150
	DEVMETHOD(device_attach,	vtballoon_attach),
139 151
	DEVMETHOD(device_detach,	vtballoon_detach),
140 152

  
141
	/* VirtIO methods. */
142
	DEVMETHOD(virtio_config_change, vtballoon_config_change),
143

  
144 153
	DEVMETHOD_END
145 154
};
146 155

  
......
152 161
static devclass_t vtballoon_devclass;
153 162

  
154 163
DRIVER_MODULE(virtio_balloon, virtio_pci, vtballoon_driver,
155
    vtballoon_devclass, 0, 0);
164
	vtballoon_devclass, 0, 0);
156 165
MODULE_VERSION(virtio_balloon, 1);
157 166
MODULE_DEPEND(virtio_balloon, virtio, 1, 1, 1);
158 167

  
159 168
static int
160 169
vtballoon_probe(device_t dev)
161 170
{
162

  
171
	struct vtballoon_softc *sc = device_get_softc(dev);
172
	vtballoon_dprintf(sc, VTBALLOON_TRACE, "\n");
163 173
	if (virtio_get_device_type(dev) != VIRTIO_ID_BALLOON)
164 174
		return (ENXIO);
165 175

  
......
168 178
	return (BUS_PROBE_DEFAULT);
169 179
}
170 180

  
181
struct irqmap {
182
	int irq;
183
	int idx;
184
	driver_intr_t *handler;
185
	const char * handler_name;
186
};
187

  
171 188
static int
172 189
vtballoon_attach(device_t dev)
173 190
{
174 191
	struct vtballoon_softc *sc;
175
	int error;
192
	int error, i;
176 193

  
177 194
	sc = device_get_softc(dev);
195
	sc->vtballoon_debug = VTBALLOON_DEFAULT_DEBUG_LEVEL;
196
	vtballoon_dprintf(sc, VTBALLOON_TRACE, "\n");
178 197
	sc->vtballoon_dev = dev;
179 198

  
180
	VTBALLOON_LOCK_INIT(sc, device_get_nameunit(dev));
199
	lwkt_serialize_init(VTBALLOON_SLZ(sc));
181 200
	TAILQ_INIT(&sc->vtballoon_pages);
182 201

  
202
	vtballoon_get_tunables(sc);
183 203
	vtballoon_add_sysctl(sc);
184 204

  
185 205
	virtio_set_feature_desc(dev, vtballoon_feature_desc);
186 206
	vtballoon_negotiate_features(sc);
187 207

  
188
	sc->vtballoon_page_frames = malloc(VTBALLOON_PAGES_PER_REQUEST *
189
	    sizeof(uint32_t), M_DEVBUF, M_NOWAIT | M_ZERO);
208
	sc->vtballoon_page_frames = contigmalloc(VTBALLOON_PAGES_PER_REQUEST *
209
	    sizeof(uint32_t), M_DEVBUF, M_NOWAIT | M_ZERO, 0, BUS_SPACE_MAXADDR, 16, 0);
190 210
	if (sc->vtballoon_page_frames == NULL) {
191 211
		error = ENOMEM;
192
		device_printf(dev,
193
		    "cannot allocate page frame request array\n");
212
		vtballoon_dprintf(sc, VTBALLOON_ERROR, "cannot allocate page frame request array (error:%d)\n", error);
213
		goto fail;
214
	}
215
	error = vtballoon_alloc_intrs(sc);
216
	if (error) {
217
		vtballoon_dprintf(sc, VTBALLOON_ERROR, "cannot allocate interrupts (error:%d)\n", error);
194 218
		goto fail;
195 219
	}
196 220

  
197 221
	error = vtballoon_alloc_virtqueues(sc);
198 222
	if (error) {
199
		device_printf(dev, "cannot allocate virtqueues\n");
223
		vtballoon_dprintf(sc, VTBALLOON_ERROR, "cannot allocate virtqueues (error:%d)\n", error);
200 224
		goto fail;
201 225
	}
202 226

  
203
	error = virtio_setup_intr(dev, INTR_TYPE_MISC);
204
	if (error) {
205
		device_printf(dev, "cannot setup virtqueue interrupts\n");
227
	struct irqmap info[3];
228

  
229
	/* Possible "Virtqueue <-> IRQ" configurations */
230
	switch (sc->vtballoon_nintr) {
231
	case 1:
232
		info[0] = (struct irqmap){0, 0, vtballoon_inflate_vq_intr, "inflate"};
233
		info[1] = (struct irqmap){0, 1, vtballoon_deflate_vq_intr, "deflate"};
234
		info[2] = (struct irqmap){0, -1, vtballoon_config_change_intr, "config"};
235
		break;
236
	case 2:
237
		info[0] = (struct irqmap){0, 0, vtballoon_inflate_vq_intr, "inflate"};
238
		info[1] = (struct irqmap){0, 1, vtballoon_deflate_vq_intr, "deflate"};
239
		info[2] = (struct irqmap){1, -1, vtballoon_config_change_intr, "config"};
240
		break;
241
	case 3:
242
		info[0] = (struct irqmap){0, 0, vtballoon_inflate_vq_intr, "inflate"};
243
		info[1] = (struct irqmap){1, 1, vtballoon_deflate_vq_intr, "deflate"};
244
		info[2] = (struct irqmap){2, -1, vtballoon_config_change_intr, "config"};
245
		break;
246
	default:
247
		vtballoon_dprintf(sc, VTBALLOON_ERROR, "Invalid interrupt vector count: %d\n", sc->vtballoon_nintr);
206 248
		goto fail;
207 249
	}
250
	for (i = 0; i < 3; i++) {
251
		error = virtio_bind_intr(sc->vtballoon_dev, info[i].irq, info[i].idx,
252
		    info[i].handler, sc);
253
		if (error) {
254
			vtballoon_dprintf(sc, VTBALLOON_ERROR, "cannot bind virtqueue '%s' handler to IRQ:%d/%d\n", info[i].handler_name, info[i].irq, sc->vtballoon_nintr);
255
			goto fail;
256
		}
257
	}
208 258

  
209
	error = kthread_add(vtballoon_thread, sc, NULL, &sc->vtballoon_td,
210
	    0, 0, "virtio_balloon");
259
	for (i = 0; i < sc->vtballoon_nintr; i++) {
260
		error = virtio_setup_intr(dev, i, VTBALLOON_SLZ(sc));
261
		if (error) {
262
			vtballoon_dprintf(sc, VTBALLOON_ERROR, "cannot setup virtqueue interrupt:%d (error:%d)\n", i, error);
263
			goto fail;
264
		}
265
	}
266

  
267
	error = kthread_create(vtballoon_thread, sc, &sc->vtballoon_td, "virtio_balloon");
211 268
	if (error) {
212
		device_printf(dev, "cannot create balloon kthread\n");
269
		vtballoon_dprintf(sc, VTBALLOON_ERROR, "cannot create balloon kthread (error:%d)\n", error);
213 270
		goto fail;
214 271
	}
215 272

  
......
227 284
vtballoon_detach(device_t dev)
228 285
{
229 286
	struct vtballoon_softc *sc;
287
	int i;
230 288

  
231 289
	sc = device_get_softc(dev);
290
	vtballoon_dprintf(sc, VTBALLOON_TRACE, "\n");
232 291

  
233 292
	if (sc->vtballoon_td != NULL) {
234
		VTBALLOON_LOCK(sc);
293
		VTBALLOON_ENTER_SLZ(sc);
235 294
		sc->vtballoon_flags |= VTBALLOON_FLAG_DETACH;
236
		wakeup_one(sc);
237
		msleep(sc->vtballoon_td, VTBALLOON_MTX(sc), 0, "vtbdth", 0);
238
		VTBALLOON_UNLOCK(sc);
239 295

  
296
		/* drain */
297
		wakeup_one(sc);
298
		zsleep(sc->vtballoon_td, VTBALLOON_SLZ(sc), 0, "vtbdth", 0);
299
		VTBALLOON_EXIT_SLZ(sc);
240 300
		sc->vtballoon_td = NULL;
241 301
	}
242 302

  
303
	lwkt_serialize_handler_disable(VTBALLOON_SLZ(sc));
304

  
305
        for (i = 0; i < sc->vtballoon_nintr; i++)
306
                virtio_teardown_intr(dev, i);
307

  
243 308
	if (device_is_attached(dev)) {
244 309
		vtballoon_pop(sc);
245 310
		vtballoon_stop(sc);
246 311
	}
247 312

  
248 313
	if (sc->vtballoon_page_frames != NULL) {
249
		free(sc->vtballoon_page_frames, M_DEVBUF);
314
		contigfree(sc->vtballoon_page_frames, VTBALLOON_PAGES_PER_REQUEST *
315
			sizeof(uint32_t), M_DEVBUF);
250 316
		sc->vtballoon_page_frames = NULL;
251 317
	}
252

  
253
	VTBALLOON_LOCK_DESTROY(sc);
254

  
255 318
	return (0);
256 319
}
257 320

  
258
static int
259
vtballoon_config_change(device_t dev)
321
static void
322
vtballoon_config_change_intr(void *arg)
260 323
{
261
	struct vtballoon_softc *sc;
262

  
263
	sc = device_get_softc(dev);
264

  
265
	VTBALLOON_LOCK(sc);
324
	struct vtballoon_softc *sc = arg;
325
	vtballoon_dprintf(sc, VTBALLOON_TRACE, "\n");
266 326
	wakeup_one(sc);
267
	VTBALLOON_UNLOCK(sc);
268

  
269
	return (1);
270 327
}
271 328

  
272 329
static void
......
276 333
	uint64_t features;
277 334

  
278 335
	dev = sc->vtballoon_dev;
336
	vtballoon_dprintf(sc, VTBALLOON_TRACE, "\n");
279 337
	features = virtio_negotiate_features(dev, VTBALLOON_FEATURES);
280 338
	sc->vtballoon_features = features;
281 339
}
282 340

  
341
static int vtballoon_alloc_intrs(struct vtballoon_softc *sc)
342
{
343
	vtballoon_dprintf(sc, VTBALLOON_TRACE, "\n");
344
	int cnt, error;
345
	int intrcount = virtio_intr_count(sc->vtballoon_dev);
346
	int use_config = 1;
347

  
348
        intrcount = imin(intrcount, 3);
349
	if (intrcount < 1)
350
	        return (ENXIO);
351

  
352
	cnt = intrcount;
353
	error = virtio_intr_alloc(sc->vtballoon_dev, &cnt, use_config, NULL);
354
	if (error != 0) {
355
	        virtio_intr_release(sc->vtballoon_dev);
356
	        return (error);
357
	}
358
	sc->vtballoon_nintr = cnt;
359
	return (0);
360
}
361

  
283 362
static int
284 363
vtballoon_alloc_virtqueues(struct vtballoon_softc *sc)
285 364
{
......
288 367
	int nvqs;
289 368

  
290 369
	dev = sc->vtballoon_dev;
370
	vtballoon_dprintf(sc, VTBALLOON_TRACE, "\n");
291 371
	nvqs = 2;
292 372

  
293
	VQ_ALLOC_INFO_INIT(&vq_info[0], 0, vtballoon_vq_intr, sc,
294
	    &sc->vtballoon_inflate_vq, "%s inflate", device_get_nameunit(dev));
373
	VQ_ALLOC_INFO_INIT(&vq_info[0], 0, &sc->vtballoon_inflate_vq,
374
		"%s inflate", device_get_nameunit(dev));
295 375

  
296
	VQ_ALLOC_INFO_INIT(&vq_info[1], 0, vtballoon_vq_intr, sc,
297
	    &sc->vtballoon_deflate_vq, "%s deflate", device_get_nameunit(dev));
376
	VQ_ALLOC_INFO_INIT(&vq_info[1], 0, &sc->vtballoon_deflate_vq,
377
		"%s deflate", device_get_nameunit(dev));
298 378

  
299
	return (virtio_alloc_virtqueues(dev, 0, nvqs, vq_info));
379
	return (virtio_alloc_virtqueues(dev, nvqs, vq_info));
300 380
}
301 381

  
302 382
static void
303
vtballoon_vq_intr(void *xsc)
383
vtballoon_inflate_vq_intr(void *arg)
304 384
{
305
	struct vtballoon_softc *sc;
306

  
307
	sc = xsc;
385
	struct vtballoon_softc *sc = arg;
386
	ASSERT_SERIALIZED(VTBALLOON_SLZ(sc));
387
	wakeup_one(sc);
388
}
308 389

  
309
	VTBALLOON_LOCK(sc);
390
static void
391
vtballoon_deflate_vq_intr(void *arg)
392
{
393
	struct vtballoon_softc *sc = arg;
394
	ASSERT_SERIALIZED(VTBALLOON_SLZ(sc));
310 395
	wakeup_one(sc);
311
	VTBALLOON_UNLOCK(sc);
312 396
}
313 397

  
314 398
static void
315 399
vtballoon_inflate(struct vtballoon_softc *sc, int npages)
316 400
{
317 401
	struct virtqueue *vq;
402

  
318 403
	vm_page_t m;
319 404
	int i;
320 405

  
......
325 410

  
326 411
	for (i = 0; i < npages; i++) {
327 412
		if ((m = vtballoon_alloc_page(sc)) == NULL) {
413
			/* First allocate usign VTBALLOON_REGULAR_ALLOC and fall back to VTBALLOON_LOWMEM_ALLOC
414
			 * when the guest is under severe memory pressure. Quickly decrease the
415
			 * allocation rate, allowing the system to swap out pages.
416
			 */
417
			sc->vtballoon_pagereq = VM_ALLOC_SYSTEM | VM_ALLOC_INTERRUPT;
328 418
			sc->vtballoon_timeout = VTBALLOON_LOWMEM_TIMEOUT;
329 419
			break;
330 420
		}
......
334 424

  
335 425
		KASSERT(m->queue == PQ_NONE,
336 426
		    ("%s: allocated page %p on queue", __func__, m));
337
		TAILQ_INSERT_TAIL(&sc->vtballoon_pages, m, plinks.q);
427
		TAILQ_INSERT_TAIL(&sc->vtballoon_pages, m, pageq);
338 428
	}
339 429

  
340 430
	if (i > 0)
......
362 452
		sc->vtballoon_page_frames[i] =
363 453
		    VM_PAGE_TO_PHYS(m) >> VIRTIO_BALLOON_PFN_SHIFT;
364 454

  
365
		TAILQ_REMOVE(&sc->vtballoon_pages, m, plinks.q);
366
		TAILQ_INSERT_TAIL(&free_pages, m, plinks.q);
455
		TAILQ_REMOVE(&sc->vtballoon_pages, m, pageq);
456
		TAILQ_INSERT_TAIL(&free_pages, m, pageq);
367 457
	}
368 458

  
369 459
	if (i > 0) {
......
371 461
		vtballoon_send_page_frames(sc, vq, i);
372 462

  
373 463
		while ((m = TAILQ_FIRST(&free_pages)) != NULL) {
374
			TAILQ_REMOVE(&free_pages, m, plinks.q);
464
			TAILQ_REMOVE(&free_pages, m, pageq);
375 465
			vtballoon_free_page(sc, m);
376 466
		}
377 467
	}
......
401 491

  
402 492
	error = virtqueue_enqueue(vq, vq, &sg, 1, 0);
403 493
	KASSERT(error == 0, ("error enqueuing page frames to virtqueue"));
404
	virtqueue_notify(vq);
494
	virtqueue_notify(vq, NULL);			// ?
405 495

  
406 496
	/*
407 497
	 * Inflate and deflate operations are done synchronously. The
408 498
	 * interrupt handler will wake us up.
409 499
	 */
410
	VTBALLOON_LOCK(sc);
411
	while ((c = virtqueue_dequeue(vq, NULL)) == NULL)
412
		msleep(sc, VTBALLOON_MTX(sc), 0, "vtbspf", 0);
413
	VTBALLOON_UNLOCK(sc);
500
	VTBALLOON_ENTER_SLZ(sc);
501
	while ((c = virtqueue_dequeue(vq, NULL)) == NULL) {
502
		zsleep(sc, VTBALLOON_SLZ(sc), 0, "vtbspf", 0);
503
	}
504
	VTBALLOON_EXIT_SLZ(sc);
414 505

  
415 506
	KASSERT(c == vq, ("unexpected balloon operation response"));
416 507
}
......
418 509
static void
419 510
vtballoon_pop(struct vtballoon_softc *sc)
420 511
{
512
	vtballoon_dprintf(sc, VTBALLOON_TRACE, "Popping\n");
421 513

  
422 514
	while (!TAILQ_EMPTY(&sc->vtballoon_pages))
423 515
		vtballoon_deflate(sc, sc->vtballoon_current_npages);
......
426 518
static void
427 519
vtballoon_stop(struct vtballoon_softc *sc)
428 520
{
521
	vtballoon_dprintf(sc, VTBALLOON_TRACE, "Stopping\n");
429 522

  
430 523
	virtqueue_disable_intr(sc->vtballoon_inflate_vq);
431 524
	virtqueue_disable_intr(sc->vtballoon_deflate_vq);
......
438 531
{
439 532
	vm_page_t m;
440 533

  
441
	m = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL | VM_ALLOC_NOOBJ);
534
	m = vm_page_alloc(NULL, 0, sc->vtballoon_pagereq);
535
	/*m = vm_page_alloc_contig(vm_paddr_t low, vm_paddr_t high,
536
	             unsigned long alignment, unsigned long boundary,
537
	             unsigned long size, vm_memattr_t memattr)*/		// ? Would alloc_contig be a better match for balloon ?
442 538
	if (m != NULL)
443 539
		sc->vtballoon_current_npages++;
444 540

  
......
448 544
static void
449 545
vtballoon_free_page(struct vtballoon_softc *sc, vm_page_t m)
450 546
{
451

  
452
	vm_page_free(m);
547
	//vm_page_free(m);							// ? orig fbsd.
548
	vm_page_free_toq(m);							// ? Is this a good translation ?
549
	//vm_page_free_contig(m, unsigned long size); 				// ?
453 550
	sc->vtballoon_current_npages--;
454 551
}
455 552

  
......
467 564
static void
468 565
vtballoon_update_size(struct vtballoon_softc *sc)
469 566
{
470

  
471 567
	virtio_write_dev_config_4(sc->vtballoon_dev,
472 568
	    offsetof(struct virtio_balloon_config, actual),
473 569
	    htole32(sc->vtballoon_current_npages));
......
481 577

  
482 578
	rc = 0;
483 579
	current = sc->vtballoon_current_npages;
580
	sc->vtballoon_pagereq = VM_ALLOC_NORMAL | VM_ALLOC_INTERRUPT;
484 581

  
485
	VTBALLOON_LOCK(sc);
582
	VTBALLOON_ENTER_SLZ(sc);
486 583
	for (;;) {
487 584
		if (sc->vtballoon_flags & VTBALLOON_FLAG_DETACH) {
488 585
			rc = 1;
......
506 603
		if (current < desired && timeout == 0)
507 604
			break;
508 605

  
509
		msleep(sc, VTBALLOON_MTX(sc), 0, "vtbslp", timeout);
606
		if (!timeout)
607
			vtballoon_dprintf(sc, VTBALLOON_INFO, "thread woke up, adjust size, desired:%d, current:%d\n", desired, current);
608
		zsleep(sc, VTBALLOON_SLZ(sc), 0, "vtbslp", timeout);
510 609
	}
511
	VTBALLOON_UNLOCK(sc);
610
	VTBALLOON_EXIT_SLZ(sc);
512 611

  
513 612
	return (rc);
514 613
}
515 614

  
516 615
static void
517
vtballoon_thread(void *xsc)
616
vtballoon_thread(void *arg)
518 617
{
519
	struct vtballoon_softc *sc;
520
	uint32_t current, desired;
521

  
522
	sc = xsc;
618
	struct vtballoon_softc *sc = arg;
619
	vtballoon_dprintf(sc, VTBALLOON_TRACE, "Thread started.\n");
523 620

  
621
	uint32_t current, desired;
524 622
	for (;;) {
525 623
		if (vtballoon_sleep(sc) != 0)
526 624
			break;
......
541 639
	kthread_exit();
542 640
}
543 641

  
642
static void
643
vtballoon_get_tunables(struct vtballoon_softc *sc)
644
{
645
	char tmpstr[64];
646
	vtballoon_dprintf(sc, VTBALLOON_TRACE, "\n");
647

  
648
	TUNABLE_INT_FETCH("hw.vtballoon.debug_level", &sc->vtballoon_debug);
649

  
650
	ksnprintf(tmpstr, sizeof(tmpstr), "dev.vtballoon.%d.debug_level",
651
	    device_get_unit(sc->vtballoon_dev));
652
	TUNABLE_INT_FETCH(tmpstr, &sc->vtballoon_debug);
653
}
654

  
544 655
static void
545 656
vtballoon_add_sysctl(struct vtballoon_softc *sc)
546 657
{
......
550 661
	struct sysctl_oid_list *child;
551 662

  
552 663
	dev = sc->vtballoon_dev;
664
	vtballoon_dprintf(sc, VTBALLOON_TRACE, "\n");
665

  
553 666
	ctx = device_get_sysctl_ctx(dev);
554 667
	tree = device_get_sysctl_tree(dev);
555 668
	child = SYSCTL_CHILDREN(tree);
556 669

  
670
	SYSCTL_ADD_INT(ctx, child, OID_AUTO, "debug_level",
671
	    CTLFLAG_RW, &sc->vtballoon_debug, 0,
672
	    "Debug level");
673

  
557 674
	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "desired",
558 675
	    CTLFLAG_RD, &sc->vtballoon_desired_npages, sizeof(uint32_t),
559 676
	    "Desired balloon size in pages");
sys/dev/virtual/virtio/balloon/virtio_balloon.h
34 34
/* Feature bits. */
35 35
#define VIRTIO_BALLOON_F_MUST_TELL_HOST	0x1 /* Tell before reclaiming pages */
36 36
#define VIRTIO_BALLOON_F_STATS_VQ	0x2 /* Memory stats virtqueue */
37
#define VIRTIO_BALLOON_F_DEFLATE_ON_OOM 0x3 /* Deflate on Out Of Memory */
37 38

  
38 39
/* Size of a PFN in the balloon interface. */
39 40
#define VIRTIO_BALLOON_PFN_SHIFT 12
40
-