/*
* VMware Balloon driver.
*
* Copyright (C) 2000-2014, VMware, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; version 2 of the License and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
* NON INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Maintained by: Xavier Deguillard <xdeguillard@vmware.com>
* Philip Moltmann <moltmann@vmware.com>
*/
/*
* This is VMware physical memory management driver for Linux. The driver
* acts like a "balloon" that can be inflated to reclaim physical pages by
* reserving them in the guest and invalidating them in the monitor,
* freeing up the underlying machine pages so they can be allocated to
* other guests. The balloon can also be deflated to allow the guest to
* use more physical memory. Higher level policies can control the sizes
* of balloons in VMs in order to manage physical memory resources.
*/
//#define DEBUG
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/vmalloc.h>
#include <linux/sched.h>
#include <linux/module.h>
#include <linux/workqueue.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/vmw_vmci_defs.h>
#include <linux/vmw_vmci_api.h>
#include <asm/hypervisor.h>
MODULE_AUTHOR("VMware, Inc.");
MODULE_DESCRIPTION("VMware Memory Control (Balloon) Driver");
MODULE_VERSION("1.5.0.0-k");
MODULE_ALIAS("dmi:*:svnVMware*:*");
MODULE_ALIAS("vmware_vmmemctl");
MODULE_LICENSE("GPL");
/*
* Various constants controlling rate of inflaint/deflating balloon,
* measured in pages.
*/
/*
* Rates of memory allocaton when guest experiences memory pressure
* (driver performs sleeping allocations).
*/
#define VMW_BALLOON_RATE_ALLOC_MIN 512U
#define VMW_BALLOON_RATE_ALLOC_MAX 2048U
#define VMW_BALLOON_RATE_ALLOC_INC 16U
/*
* When guest is under memory pressure, use a reduced page allocation
* rate for next several cycles.
*/
#define VMW_BALLOON_SLOW_CYCLES 4
/*
* Use __GFP_HIGHMEM to allow pages from HIGHMEM zone. We don't
* allow wait (__GFP_RECLAIM) for NOSLEEP page allocations. Use
* __GFP_NOWARN, to suppress page allocation failure warnings.
*/
#define VMW_PAGE_ALLOC_NOSLEEP (__GFP_HIGHMEM|__GFP_NOWARN)
/*
* Use GFP_HIGHUSER when executing in a separate kernel thread
* context and allocation can sleep. This is less stressful to
* the guest memory system, since it allows the thread to block
* while memory is reclaimed, and won't take pages from emergency
* low-memory pools.
*/
#define VMW_PAGE_ALLOC_CANSLEEP (GFP_HIGHUSER)
/* Maximum number of refused pages we accumulate during inflation cycle */
#define VMW_BALLOON_MAX_REFUSED 16
/*
* Hypervisor communication port definitions.
*/
#define VMW_BALLOON_HV_PORT 0x5670
#define VMW_BALLOON_HV_MAGIC 0x456c6d6f
#define VMW_BALLOON_GUEST_ID 1 /* Linux */
enum vmwballoon_capabilities {
/*
* Bit 0 is reserved and not associated to any capability.
*/
VMW_BALLOON_BASIC_CMDS = (1 << 1),
VMW_BALLOON_BATCHED_CMDS = (1 << 2),
VMW_BALLOON_BATCHED_2M_CMDS = (1 << 3),
VMW_BALLOON_SIGNALLED_WAKEUP_CMD = (1 << 4),
};
#define VMW_BALLOON_CAPABILITIES (VMW_BALLOON_BASIC_CMDS \
| VMW_BALLOON_BATCHED_CMDS \
| VMW_BALLOON_BATCHED_2M_CMDS \
| VMW_BALLOON_SIGNALLED_WAKEUP_CMD)
#define VMW_BALLOON_2M_SHIFT (9)
#define VMW_BALLOON_NUM_PAGE_SIZES (2)
/*
* Backdoor commands availability:
*
* START, GET_TARGET and GUEST_ID are always available,
*
* VMW_BALLOON_BASIC_CMDS:
* LOCK and UNLOCK commands,
* VMW_BALLOON_BATCHED_CMDS:
* BATCHED_LOCK and BATCHED_UNLOCK commands.
* VMW BALLOON_BATCHED_2M_CMDS:
* BATCHED_2M_LOCK and BATCHED_2M_UNLOCK commands,
* VMW VMW_BALLOON_SIGNALLED_WAKEUP_CMD:
* VMW_BALLOON_CMD_VMCI_DOORBELL_SET command.
*/
#define VMW_BALLOON_CMD_START 0
#define VMW_BALLOON_CMD_GET_TARGET 1
#define VMW_BALLOON_CMD_LOCK 2
#define VMW_BALLOON_CMD_UNLOCK 3
#define VMW_BALLOON_CMD_GUEST_ID 4
#define VMW_BALLOON_CMD_BATCHED_LOCK 6
#define VMW_BALLOON_CMD_BATCHED_UNLOCK 7
#define VMW_BALLOON_CMD_BATCHED_2M_LOCK 8
#define VMW_BALLOON_CMD_BATCHED_2M_UNLOCK 9
#define VMW_BALLOON_CMD_VMCI_DOORBELL_SET 10
/* error codes */
#define VMW_BALLOON_SUCCESS 0
#define VMW_BALLOON_FAILURE -1
#define VMW_BALLOON_ERROR_CMD_INVALID 1
#define VMW_BALLOON_ERROR_PPN_INVALID 2
#define VMW_BALLOON_ERROR_PPN_LOCKED 3
#define VMW_BALLOON_ERROR_PPN_UNLOCKED 4
#define VMW_BALLOON_ERROR_PPN_PINNED 5
#define VMW_BALLOON_ERROR_PPN_NOTNEEDED 6
#define VMW_BALLOON_ERROR_RESET 7
#define VMW_BALLOON_ERROR_BUSY 8
#define VMW_BALLOON_SUCCESS_WITH_CAPABILITIES (0x03000000)
/* Batch page description */
/*
* Layout of a page in the batch page:
*
* +-------------+----------+--------+
* | | | |
* | Page number | Reserved | Status |
* | | | |
* +-------------+----------+--------+
* 64 PAGE_SHIFT 6 0
*
* The reserved field should be set to 0.