diff --git a/sys/dev/virtio/balloon/virtio_balloon.h b/sys/dev/virtio/balloon/virtio_balloon.h --- a/sys/dev/virtio/balloon/virtio_balloon.h +++ b/sys/dev/virtio/balloon/virtio_balloon.h @@ -36,6 +36,7 @@ /* Feature bits. */ #define VIRTIO_BALLOON_F_MUST_TELL_HOST 0x1 /* Tell before reclaiming pages */ #define VIRTIO_BALLOON_F_STATS_VQ 0x2 /* Memory stats virtqueue */ +#define VIRTIO_BALLOON_F_DEFLATE_ON_OOM 0x4 /* Deflate balloon on OOM */ /* Size of a PFN in the balloon interface. */ #define VIRTIO_BALLOON_PFN_SHIFT 12 @@ -54,8 +55,33 @@ #define VIRTIO_BALLOON_S_MINFLT 3 /* Number of minor faults */ #define VIRTIO_BALLOON_S_MEMFREE 4 /* Total amount of free memory */ #define VIRTIO_BALLOON_S_MEMTOT 5 /* Total amount of memory */ -#define VIRTIO_BALLOON_S_NR 6 +#define VIRTIO_BALLOON_S_AVAIL 6 /* Available memory as in /proc */ +#define VIRTIO_BALLOON_S_CACHES 7 /* Disk caches */ +#define VIRTIO_BALLOON_S_NR 8 +/* + * Memory statistics structure. + * Driver fills an array of these structures and passes to device. + * + * NOTE: fields are laid out in a way that would make compiler add padding + * between and after fields, so we have to use compiler-specific attributes to + * pack it, to disable this padding. This also often causes compiler to + * generate suboptimal code. + * + * We maintain this statistics structure format for backwards compatibility, + * but don't follow this example. + * + * If implementing a similar structure, do something like the below instead: + * struct virtio_balloon_stat { + * __virtio16 tag; + * __u8 reserved[6]; + * __virtio64 val; + * }; + * + * In other words, add explicit reserved fields to align field and + * structure boundaries at field size, avoiding compiler padding + * without the packed attribute. + */ struct virtio_balloon_stat { uint16_t tag; uint64_t val; diff --git a/sys/dev/virtio/balloon/virtio_balloon.c b/sys/dev/virtio/balloon/virtio_balloon.c --- a/sys/dev/virtio/balloon/virtio_balloon.c +++ b/sys/dev/virtio/balloon/virtio_balloon.c @@ -80,6 +80,8 @@ static struct virtio_feature_desc vtballoon_feature_desc[] = { { VIRTIO_BALLOON_F_MUST_TELL_HOST, "MustTellHost" }, { VIRTIO_BALLOON_F_STATS_VQ, "StatsVq" }, + { VIRTIO_BALLOON_F_DEFLATE_ON_OOM, "DeflateOnOOM" }, + { 0, NULL } }; @@ -110,8 +112,11 @@ static void vtballoon_thread(void *); static void vtballoon_add_sysctl(struct vtballoon_softc *); +#define vtballoon_modern(_sc) \ + (((_sc)->vtballoon_features & VIRTIO_F_VERSION_1) != 0) + /* Features desired/implemented by this driver. */ -#define VTBALLOON_FEATURES 0 +#define VTBALLOON_FEATURES VIRTIO_BALLOON_F_MUST_TELL_HOST /* Timeout between retries when the balloon needs inflating. */ #define VTBALLOON_LOWMEM_TIMEOUT hz @@ -278,8 +283,10 @@ uint64_t features; dev = sc->vtballoon_dev; - features = virtio_negotiate_features(dev, VTBALLOON_FEATURES); - sc->vtballoon_features = features; + features = VTBALLOON_FEATURES; + + sc->vtballoon_features = virtio_negotiate_features(dev, features); + virtio_finalize_features(dev); } static int @@ -440,7 +447,8 @@ { vm_page_t m; - m = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL | VM_ALLOC_NOOBJ); + m = vm_page_alloc(NULL, 0, + VM_ALLOC_NORMAL | VM_ALLOC_NOOBJ | VM_ALLOC_NODUMP); if (m != NULL) sc->vtballoon_current_npages++; @@ -463,16 +471,23 @@ desired = virtio_read_dev_config_4(sc->vtballoon_dev, offsetof(struct virtio_balloon_config, num_pages)); - return (le32toh(desired)); + if (vtballoon_modern(sc)) + return (desired); + else + return (le32toh(desired)); } static void vtballoon_update_size(struct vtballoon_softc *sc) { + uint32_t npages; + + npages = sc->vtballoon_current_npages; + if (!vtballoon_modern(sc)) + npages = htole32(npages); virtio_write_dev_config_4(sc->vtballoon_dev, - offsetof(struct virtio_balloon_config, actual), - htole32(sc->vtballoon_current_npages)); + offsetof(struct virtio_balloon_config, actual), npages); } static int