1f76b348eSCornelia Huck /* SPDX-License-Identifier: BSD-3-Clause */ 2f76b348eSCornelia Huck /* 3f76b348eSCornelia Huck * Virtio Mem Device 4f76b348eSCornelia Huck * 5f76b348eSCornelia Huck * Copyright Red Hat, Inc. 2020 6f76b348eSCornelia Huck * 7f76b348eSCornelia Huck * Authors: 8f76b348eSCornelia Huck * David Hildenbrand <david@redhat.com> 9f76b348eSCornelia Huck * 10f76b348eSCornelia Huck * This header is BSD licensed so anyone can use the definitions 11f76b348eSCornelia Huck * to implement compatible drivers/servers: 12f76b348eSCornelia Huck * 13f76b348eSCornelia Huck * Redistribution and use in source and binary forms, with or without 14f76b348eSCornelia Huck * modification, are permitted provided that the following conditions 15f76b348eSCornelia Huck * are met: 16f76b348eSCornelia Huck * 1. Redistributions of source code must retain the above copyright 17f76b348eSCornelia Huck * notice, this list of conditions and the following disclaimer. 18f76b348eSCornelia Huck * 2. Redistributions in binary form must reproduce the above copyright 19f76b348eSCornelia Huck * notice, this list of conditions and the following disclaimer in the 20f76b348eSCornelia Huck * documentation and/or other materials provided with the distribution. 21f76b348eSCornelia Huck * 3. Neither the name of IBM nor the names of its contributors 22f76b348eSCornelia Huck * may be used to endorse or promote products derived from this software 23f76b348eSCornelia Huck * without specific prior written permission. 24f76b348eSCornelia Huck * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25f76b348eSCornelia Huck * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26f76b348eSCornelia Huck * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 27f76b348eSCornelia Huck * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IBM OR 28f76b348eSCornelia Huck * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29f76b348eSCornelia Huck * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 30f76b348eSCornelia Huck * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 31f76b348eSCornelia Huck * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 32f76b348eSCornelia Huck * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 33f76b348eSCornelia Huck * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 34f76b348eSCornelia Huck * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35f76b348eSCornelia Huck * SUCH DAMAGE. 36f76b348eSCornelia Huck */ 37f76b348eSCornelia Huck 38f76b348eSCornelia Huck #ifndef _LINUX_VIRTIO_MEM_H 39f76b348eSCornelia Huck #define _LINUX_VIRTIO_MEM_H 40f76b348eSCornelia Huck 41f76b348eSCornelia Huck #include "standard-headers/linux/types.h" 42f76b348eSCornelia Huck #include "standard-headers/linux/virtio_types.h" 43f76b348eSCornelia Huck #include "standard-headers/linux/virtio_ids.h" 44f76b348eSCornelia Huck #include "standard-headers/linux/virtio_config.h" 45f76b348eSCornelia Huck 46f76b348eSCornelia Huck /* 47f76b348eSCornelia Huck * Each virtio-mem device manages a dedicated region in physical address 48f76b348eSCornelia Huck * space. Each device can belong to a single NUMA node, multiple devices 49f76b348eSCornelia Huck * for a single NUMA node are possible. A virtio-mem device is like a 50f76b348eSCornelia Huck * "resizable DIMM" consisting of small memory blocks that can be plugged 51f76b348eSCornelia Huck * or unplugged. The device driver is responsible for (un)plugging memory 52f76b348eSCornelia Huck * blocks on demand. 53f76b348eSCornelia Huck * 54f76b348eSCornelia Huck * Virtio-mem devices can only operate on their assigned memory region in 55f76b348eSCornelia Huck * order to (un)plug memory. A device cannot (un)plug memory belonging to 56f76b348eSCornelia Huck * other devices. 57f76b348eSCornelia Huck * 58f76b348eSCornelia Huck * The "region_size" corresponds to the maximum amount of memory that can 59f76b348eSCornelia Huck * be provided by a device. The "size" corresponds to the amount of memory 60f76b348eSCornelia Huck * that is currently plugged. "requested_size" corresponds to a request 61f76b348eSCornelia Huck * from the device to the device driver to (un)plug blocks. The 62f76b348eSCornelia Huck * device driver should try to (un)plug blocks in order to reach the 63f76b348eSCornelia Huck * "requested_size". It is impossible to plug more memory than requested. 64f76b348eSCornelia Huck * 65f76b348eSCornelia Huck * The "usable_region_size" represents the memory region that can actually 66f76b348eSCornelia Huck * be used to (un)plug memory. It is always at least as big as the 67f76b348eSCornelia Huck * "requested_size" and will grow dynamically. It will only shrink when 68f76b348eSCornelia Huck * explicitly triggered (VIRTIO_MEM_REQ_UNPLUG). 69f76b348eSCornelia Huck * 70f76b348eSCornelia Huck * There are no guarantees what will happen if unplugged memory is 71*3ff9b192SDavid Hildenbrand * read/written. In general, unplugged memory should not be touched, because 72*3ff9b192SDavid Hildenbrand * the resulting action is undefined. There is one exception: without 73*3ff9b192SDavid Hildenbrand * VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE, unplugged memory inside the usable 74*3ff9b192SDavid Hildenbrand * region can be read, to simplify creation of memory dumps. 75f76b348eSCornelia Huck * 76f76b348eSCornelia Huck * It can happen that the device cannot process a request, because it is 77f76b348eSCornelia Huck * busy. The device driver has to retry later. 78f76b348eSCornelia Huck * 79f76b348eSCornelia Huck * Usually, during system resets all memory will get unplugged, so the 80f76b348eSCornelia Huck * device driver can start with a clean state. However, in specific 81f76b348eSCornelia Huck * scenarios (if the device is busy) it can happen that the device still 82f76b348eSCornelia Huck * has memory plugged. The device driver can request to unplug all memory 83f76b348eSCornelia Huck * (VIRTIO_MEM_REQ_UNPLUG) - which might take a while to succeed if the 84f76b348eSCornelia Huck * device is busy. 85f76b348eSCornelia Huck */ 86f76b348eSCornelia Huck 87f76b348eSCornelia Huck /* --- virtio-mem: feature bits --- */ 88f76b348eSCornelia Huck 89f76b348eSCornelia Huck /* node_id is an ACPI PXM and is valid */ 90f76b348eSCornelia Huck #define VIRTIO_MEM_F_ACPI_PXM 0 91*3ff9b192SDavid Hildenbrand /* unplugged memory must not be accessed */ 92*3ff9b192SDavid Hildenbrand #define VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE 1 93f76b348eSCornelia Huck 94f76b348eSCornelia Huck 95f76b348eSCornelia Huck /* --- virtio-mem: guest -> host requests --- */ 96f76b348eSCornelia Huck 97f76b348eSCornelia Huck /* request to plug memory blocks */ 98f76b348eSCornelia Huck #define VIRTIO_MEM_REQ_PLUG 0 99f76b348eSCornelia Huck /* request to unplug memory blocks */ 100f76b348eSCornelia Huck #define VIRTIO_MEM_REQ_UNPLUG 1 101f76b348eSCornelia Huck /* request to unplug all blocks and shrink the usable size */ 102f76b348eSCornelia Huck #define VIRTIO_MEM_REQ_UNPLUG_ALL 2 103f76b348eSCornelia Huck /* request information about the plugged state of memory blocks */ 104f76b348eSCornelia Huck #define VIRTIO_MEM_REQ_STATE 3 105f76b348eSCornelia Huck 106f76b348eSCornelia Huck struct virtio_mem_req_plug { 107f76b348eSCornelia Huck __virtio64 addr; 108f76b348eSCornelia Huck __virtio16 nb_blocks; 109f76b348eSCornelia Huck __virtio16 padding[3]; 110f76b348eSCornelia Huck }; 111f76b348eSCornelia Huck 112f76b348eSCornelia Huck struct virtio_mem_req_unplug { 113f76b348eSCornelia Huck __virtio64 addr; 114f76b348eSCornelia Huck __virtio16 nb_blocks; 115f76b348eSCornelia Huck __virtio16 padding[3]; 116f76b348eSCornelia Huck }; 117f76b348eSCornelia Huck 118f76b348eSCornelia Huck struct virtio_mem_req_state { 119f76b348eSCornelia Huck __virtio64 addr; 120f76b348eSCornelia Huck __virtio16 nb_blocks; 121f76b348eSCornelia Huck __virtio16 padding[3]; 122f76b348eSCornelia Huck }; 123f76b348eSCornelia Huck 124f76b348eSCornelia Huck struct virtio_mem_req { 125f76b348eSCornelia Huck __virtio16 type; 126f76b348eSCornelia Huck __virtio16 padding[3]; 127f76b348eSCornelia Huck 128f76b348eSCornelia Huck union { 129f76b348eSCornelia Huck struct virtio_mem_req_plug plug; 130f76b348eSCornelia Huck struct virtio_mem_req_unplug unplug; 131f76b348eSCornelia Huck struct virtio_mem_req_state state; 132f76b348eSCornelia Huck } u; 133f76b348eSCornelia Huck }; 134f76b348eSCornelia Huck 135f76b348eSCornelia Huck 136f76b348eSCornelia Huck /* --- virtio-mem: host -> guest response --- */ 137f76b348eSCornelia Huck 138f76b348eSCornelia Huck /* 139f76b348eSCornelia Huck * Request processed successfully, applicable for 140f76b348eSCornelia Huck * - VIRTIO_MEM_REQ_PLUG 141f76b348eSCornelia Huck * - VIRTIO_MEM_REQ_UNPLUG 142f76b348eSCornelia Huck * - VIRTIO_MEM_REQ_UNPLUG_ALL 143f76b348eSCornelia Huck * - VIRTIO_MEM_REQ_STATE 144f76b348eSCornelia Huck */ 145f76b348eSCornelia Huck #define VIRTIO_MEM_RESP_ACK 0 146f76b348eSCornelia Huck /* 147f76b348eSCornelia Huck * Request denied - e.g. trying to plug more than requested, applicable for 148f76b348eSCornelia Huck * - VIRTIO_MEM_REQ_PLUG 149f76b348eSCornelia Huck */ 150f76b348eSCornelia Huck #define VIRTIO_MEM_RESP_NACK 1 151f76b348eSCornelia Huck /* 152f76b348eSCornelia Huck * Request cannot be processed right now, try again later, applicable for 153f76b348eSCornelia Huck * - VIRTIO_MEM_REQ_PLUG 154f76b348eSCornelia Huck * - VIRTIO_MEM_REQ_UNPLUG 155f76b348eSCornelia Huck * - VIRTIO_MEM_REQ_UNPLUG_ALL 156f76b348eSCornelia Huck */ 157f76b348eSCornelia Huck #define VIRTIO_MEM_RESP_BUSY 2 158f76b348eSCornelia Huck /* 159f76b348eSCornelia Huck * Error in request (e.g. addresses/alignment), applicable for 160f76b348eSCornelia Huck * - VIRTIO_MEM_REQ_PLUG 161f76b348eSCornelia Huck * - VIRTIO_MEM_REQ_UNPLUG 162f76b348eSCornelia Huck * - VIRTIO_MEM_REQ_STATE 163f76b348eSCornelia Huck */ 164f76b348eSCornelia Huck #define VIRTIO_MEM_RESP_ERROR 3 165f76b348eSCornelia Huck 166f76b348eSCornelia Huck 167f76b348eSCornelia Huck /* State of memory blocks is "plugged" */ 168f76b348eSCornelia Huck #define VIRTIO_MEM_STATE_PLUGGED 0 169f76b348eSCornelia Huck /* State of memory blocks is "unplugged" */ 170f76b348eSCornelia Huck #define VIRTIO_MEM_STATE_UNPLUGGED 1 171f76b348eSCornelia Huck /* State of memory blocks is "mixed" */ 172f76b348eSCornelia Huck #define VIRTIO_MEM_STATE_MIXED 2 173f76b348eSCornelia Huck 174f76b348eSCornelia Huck struct virtio_mem_resp_state { 175f76b348eSCornelia Huck __virtio16 state; 176f76b348eSCornelia Huck }; 177f76b348eSCornelia Huck 178f76b348eSCornelia Huck struct virtio_mem_resp { 179f76b348eSCornelia Huck __virtio16 type; 180f76b348eSCornelia Huck __virtio16 padding[3]; 181f76b348eSCornelia Huck 182f76b348eSCornelia Huck union { 183f76b348eSCornelia Huck struct virtio_mem_resp_state state; 184f76b348eSCornelia Huck } u; 185f76b348eSCornelia Huck }; 186f76b348eSCornelia Huck 187f76b348eSCornelia Huck /* --- virtio-mem: configuration --- */ 188f76b348eSCornelia Huck 189f76b348eSCornelia Huck struct virtio_mem_config { 190f76b348eSCornelia Huck /* Block size and alignment. Cannot change. */ 191f76b348eSCornelia Huck uint64_t block_size; 192f76b348eSCornelia Huck /* Valid with VIRTIO_MEM_F_ACPI_PXM. Cannot change. */ 193f76b348eSCornelia Huck uint16_t node_id; 194f76b348eSCornelia Huck uint8_t padding[6]; 195f76b348eSCornelia Huck /* Start address of the memory region. Cannot change. */ 196f76b348eSCornelia Huck uint64_t addr; 197f76b348eSCornelia Huck /* Region size (maximum). Cannot change. */ 198f76b348eSCornelia Huck uint64_t region_size; 199f76b348eSCornelia Huck /* 200f76b348eSCornelia Huck * Currently usable region size. Can grow up to region_size. Can 201f76b348eSCornelia Huck * shrink due to VIRTIO_MEM_REQ_UNPLUG_ALL (in which case no config 202f76b348eSCornelia Huck * update will be sent). 203f76b348eSCornelia Huck */ 204f76b348eSCornelia Huck uint64_t usable_region_size; 205f76b348eSCornelia Huck /* 206f76b348eSCornelia Huck * Currently used size. Changes due to plug/unplug requests, but no 207f76b348eSCornelia Huck * config updates will be sent. 208f76b348eSCornelia Huck */ 209f76b348eSCornelia Huck uint64_t plugged_size; 210f76b348eSCornelia Huck /* Requested size. New plug requests cannot exceed it. Can change. */ 211f76b348eSCornelia Huck uint64_t requested_size; 212f76b348eSCornelia Huck }; 213f76b348eSCornelia Huck 214f76b348eSCornelia Huck #endif /* _LINUX_VIRTIO_MEM_H */ 215