^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Mediated virtual PCI display host device driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Emulate enough of qemu stdvga to make bochs-drm.ko happy. That is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * basically the vram memory bar and the bochs dispi interface vbe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * registers in the mmio register bar. Specifically it does *not*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * include any legacy vga stuff. Device looks a lot like "qemu -device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * secondary-vga".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * (c) Gerd Hoffmann <kraxel@redhat.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * based on mtty driver which is:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Author: Neo Jia <cjia@nvidia.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Kirti Wankhede <kwankhede@nvidia.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * This program is free software; you can redistribute it and/or modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * it under the terms of the GNU General Public License version 2 as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * published by the Free Software Foundation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/cdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/vfio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/iommu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/mdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/dma-buf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/highmem.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <drm/drm_fourcc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <drm/drm_rect.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <drm/drm_modeset_lock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <drm/drm_property.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <drm/drm_plane.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define VBE_DISPI_INDEX_ID 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define VBE_DISPI_INDEX_XRES 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define VBE_DISPI_INDEX_YRES 0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define VBE_DISPI_INDEX_BPP 0x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define VBE_DISPI_INDEX_ENABLE 0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define VBE_DISPI_INDEX_BANK 0x5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define VBE_DISPI_INDEX_VIRT_WIDTH 0x6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define VBE_DISPI_INDEX_X_OFFSET 0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define VBE_DISPI_INDEX_Y_OFFSET 0x9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define VBE_DISPI_INDEX_COUNT 0xb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define VBE_DISPI_ID0 0xB0C0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define VBE_DISPI_ID1 0xB0C1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define VBE_DISPI_ID2 0xB0C2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define VBE_DISPI_ID3 0xB0C3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define VBE_DISPI_ID4 0xB0C4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define VBE_DISPI_ID5 0xB0C5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define VBE_DISPI_DISABLED 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define VBE_DISPI_ENABLED 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define VBE_DISPI_GETCAPS 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define VBE_DISPI_8BIT_DAC 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define VBE_DISPI_LFB_ENABLED 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define VBE_DISPI_NOCLEARMEM 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define MBOCHS_NAME "mbochs"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define MBOCHS_CLASS_NAME "mbochs"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define MBOCHS_EDID_REGION_INDEX VFIO_PCI_NUM_REGIONS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define MBOCHS_NUM_REGIONS (MBOCHS_EDID_REGION_INDEX+1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define MBOCHS_CONFIG_SPACE_SIZE 0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define MBOCHS_MMIO_BAR_OFFSET PAGE_SIZE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define MBOCHS_MMIO_BAR_SIZE PAGE_SIZE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define MBOCHS_EDID_OFFSET (MBOCHS_MMIO_BAR_OFFSET + \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) MBOCHS_MMIO_BAR_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define MBOCHS_EDID_SIZE PAGE_SIZE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define MBOCHS_MEMORY_BAR_OFFSET (MBOCHS_EDID_OFFSET + \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) MBOCHS_EDID_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define MBOCHS_EDID_BLOB_OFFSET (MBOCHS_EDID_SIZE/2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define STORE_LE16(addr, val) (*(u16 *)addr = val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define STORE_LE32(addr, val) (*(u32 *)addr = val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static int max_mbytes = 256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) module_param_named(count, max_mbytes, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) MODULE_PARM_DESC(mem, "megabytes available to " MBOCHS_NAME " devices");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define MBOCHS_TYPE_1 "small"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define MBOCHS_TYPE_2 "medium"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define MBOCHS_TYPE_3 "large"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static const struct mbochs_type {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) u32 mbytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) u32 max_x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) u32 max_y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) } mbochs_types[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) .name = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) .mbytes = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) .max_x = 800,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) .max_y = 600,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) .name = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) .mbytes = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) .max_x = 1920,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) .max_y = 1440,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) .name = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) .mbytes = 64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) .max_x = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) .max_y = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static dev_t mbochs_devt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static struct class *mbochs_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) static struct cdev mbochs_cdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static struct device mbochs_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static int mbochs_used_mbytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct vfio_region_info_ext {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) struct vfio_region_info base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) struct vfio_region_info_cap_type type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct mbochs_mode {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) u32 drm_format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) u32 bytepp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) u32 width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) u32 height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) u32 stride;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) u32 __pad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) u64 offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) u64 size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) struct mbochs_dmabuf {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) struct mbochs_mode mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) u32 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct page **pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) pgoff_t pagecount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) struct dma_buf *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct mdev_state *mdev_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) struct list_head next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) bool unlinked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) /* State of each mdev device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) struct mdev_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) u8 *vconfig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) u64 bar_mask[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) u32 memory_bar_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) struct mutex ops_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct mdev_device *mdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) const struct mbochs_type *type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) u16 vbe[VBE_DISPI_INDEX_COUNT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) u64 memsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) struct page **pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) pgoff_t pagecount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct vfio_region_gfx_edid edid_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) u8 edid_blob[0x400];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct list_head dmabufs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) u32 active_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) u32 next_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) static const char *vbe_name_list[VBE_DISPI_INDEX_COUNT] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) [VBE_DISPI_INDEX_ID] = "id",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) [VBE_DISPI_INDEX_XRES] = "xres",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) [VBE_DISPI_INDEX_YRES] = "yres",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) [VBE_DISPI_INDEX_BPP] = "bpp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) [VBE_DISPI_INDEX_ENABLE] = "enable",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) [VBE_DISPI_INDEX_BANK] = "bank",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) [VBE_DISPI_INDEX_VIRT_WIDTH] = "virt-width",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) [VBE_DISPI_INDEX_VIRT_HEIGHT] = "virt-height",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) [VBE_DISPI_INDEX_X_OFFSET] = "x-offset",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) [VBE_DISPI_INDEX_Y_OFFSET] = "y-offset",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) [VBE_DISPI_INDEX_VIDEO_MEMORY_64K] = "video-mem",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) static const char *vbe_name(u32 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (index < ARRAY_SIZE(vbe_name_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return vbe_name_list[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) return "(invalid)";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static struct page *__mbochs_get_page(struct mdev_state *mdev_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) pgoff_t pgoff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) static struct page *mbochs_get_page(struct mdev_state *mdev_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) pgoff_t pgoff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static const struct mbochs_type *mbochs_find_type(struct kobject *kobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) for (i = 0; i < ARRAY_SIZE(mbochs_types); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (strcmp(mbochs_types[i].name, kobj->name) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return mbochs_types + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static void mbochs_create_config_space(struct mdev_state *mdev_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) STORE_LE16((u16 *) &mdev_state->vconfig[PCI_VENDOR_ID],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 0x1234);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) STORE_LE16((u16 *) &mdev_state->vconfig[PCI_DEVICE_ID],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 0x1111);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) STORE_LE16((u16 *) &mdev_state->vconfig[PCI_SUBSYSTEM_VENDOR_ID],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) PCI_SUBVENDOR_ID_REDHAT_QUMRANET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) STORE_LE16((u16 *) &mdev_state->vconfig[PCI_SUBSYSTEM_ID],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) PCI_SUBDEVICE_ID_QEMU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) STORE_LE16((u16 *) &mdev_state->vconfig[PCI_COMMAND],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) STORE_LE16((u16 *) &mdev_state->vconfig[PCI_CLASS_DEVICE],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) PCI_CLASS_DISPLAY_OTHER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) mdev_state->vconfig[PCI_CLASS_REVISION] = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) STORE_LE32((u32 *) &mdev_state->vconfig[PCI_BASE_ADDRESS_0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) PCI_BASE_ADDRESS_SPACE_MEMORY |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) PCI_BASE_ADDRESS_MEM_TYPE_32 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) PCI_BASE_ADDRESS_MEM_PREFETCH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) mdev_state->bar_mask[0] = ~(mdev_state->memsize) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) STORE_LE32((u32 *) &mdev_state->vconfig[PCI_BASE_ADDRESS_2],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) PCI_BASE_ADDRESS_SPACE_MEMORY |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) PCI_BASE_ADDRESS_MEM_TYPE_32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) mdev_state->bar_mask[2] = ~(MBOCHS_MMIO_BAR_SIZE) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static int mbochs_check_framebuffer(struct mdev_state *mdev_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) struct mbochs_mode *mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) struct device *dev = mdev_dev(mdev_state->mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) u16 *vbe = mdev_state->vbe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) u32 virt_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) WARN_ON(!mutex_is_locked(&mdev_state->ops_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (!(vbe[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) goto nofb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) memset(mode, 0, sizeof(*mode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) switch (vbe[VBE_DISPI_INDEX_BPP]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) case 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) mode->drm_format = DRM_FORMAT_XRGB8888;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) mode->bytepp = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) dev_info_ratelimited(dev, "%s: bpp %d not supported\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) __func__, vbe[VBE_DISPI_INDEX_BPP]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) goto nofb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) mode->width = vbe[VBE_DISPI_INDEX_XRES];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) mode->height = vbe[VBE_DISPI_INDEX_YRES];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) virt_width = vbe[VBE_DISPI_INDEX_VIRT_WIDTH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (virt_width < mode->width)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) virt_width = mode->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) mode->stride = virt_width * mode->bytepp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) mode->size = (u64)mode->stride * mode->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) mode->offset = ((u64)vbe[VBE_DISPI_INDEX_X_OFFSET] * mode->bytepp +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) (u64)vbe[VBE_DISPI_INDEX_Y_OFFSET] * mode->stride);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (mode->width < 64 || mode->height < 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) dev_info_ratelimited(dev, "%s: invalid resolution %dx%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) __func__, mode->width, mode->height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) goto nofb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (mode->offset + mode->size > mdev_state->memsize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) dev_info_ratelimited(dev, "%s: framebuffer memory overflow\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) goto nofb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) nofb:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) memset(mode, 0, sizeof(*mode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) static bool mbochs_modes_equal(struct mbochs_mode *mode1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) struct mbochs_mode *mode2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) return memcmp(mode1, mode2, sizeof(struct mbochs_mode)) == 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) static void handle_pci_cfg_write(struct mdev_state *mdev_state, u16 offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) char *buf, u32 count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) struct device *dev = mdev_dev(mdev_state->mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) int index = (offset - PCI_BASE_ADDRESS_0) / 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) u32 cfg_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) switch (offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) case PCI_BASE_ADDRESS_0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) case PCI_BASE_ADDRESS_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) cfg_addr = *(u32 *)buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (cfg_addr == 0xffffffff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) cfg_addr = (cfg_addr & mdev_state->bar_mask[index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) cfg_addr &= PCI_BASE_ADDRESS_MEM_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (cfg_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) dev_info(dev, "BAR #%d @ 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) index, cfg_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) cfg_addr |= (mdev_state->vconfig[offset] &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) ~PCI_BASE_ADDRESS_MEM_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) STORE_LE32(&mdev_state->vconfig[offset], cfg_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) static void handle_mmio_write(struct mdev_state *mdev_state, u16 offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) char *buf, u32 count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) struct device *dev = mdev_dev(mdev_state->mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) u16 reg16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) switch (offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) case 0x400 ... 0x41f: /* vga ioports remapped */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) goto unhandled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) case 0x500 ... 0x515: /* bochs dispi interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (count != 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) goto unhandled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) index = (offset - 0x500) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) reg16 = *(u16 *)buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if (index < ARRAY_SIZE(mdev_state->vbe))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) mdev_state->vbe[index] = reg16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) dev_dbg(dev, "%s: vbe write %d = %d (%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) __func__, index, reg16, vbe_name(index));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) case 0x600 ... 0x607: /* qemu extended regs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) goto unhandled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) unhandled:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) dev_dbg(dev, "%s: @0x%03x, count %d (unhandled)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) __func__, offset, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) static void handle_mmio_read(struct mdev_state *mdev_state, u16 offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) char *buf, u32 count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) struct device *dev = mdev_dev(mdev_state->mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) struct vfio_region_gfx_edid *edid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) u16 reg16 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) switch (offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) case 0x000 ... 0x3ff: /* edid block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) edid = &mdev_state->edid_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (edid->link_state != VFIO_DEVICE_GFX_LINK_STATE_UP ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) offset >= edid->edid_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) memset(buf, 0, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) memcpy(buf, mdev_state->edid_blob + offset, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) case 0x500 ... 0x515: /* bochs dispi interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (count != 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) goto unhandled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) index = (offset - 0x500) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (index < ARRAY_SIZE(mdev_state->vbe))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) reg16 = mdev_state->vbe[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) dev_dbg(dev, "%s: vbe read %d = %d (%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) __func__, index, reg16, vbe_name(index));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) *(u16 *)buf = reg16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) unhandled:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) dev_dbg(dev, "%s: @0x%03x, count %d (unhandled)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) __func__, offset, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) memset(buf, 0, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) static void handle_edid_regs(struct mdev_state *mdev_state, u16 offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) char *buf, u32 count, bool is_write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) char *regs = (void *)&mdev_state->edid_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (offset + count > sizeof(mdev_state->edid_regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) if (count != 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (offset % 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) if (is_write) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) switch (offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) case offsetof(struct vfio_region_gfx_edid, link_state):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) case offsetof(struct vfio_region_gfx_edid, edid_size):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) memcpy(regs + offset, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) /* read-only regs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) memcpy(buf, regs + offset, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) static void handle_edid_blob(struct mdev_state *mdev_state, u16 offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) char *buf, u32 count, bool is_write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (offset + count > mdev_state->edid_regs.edid_max_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) if (is_write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) memcpy(mdev_state->edid_blob + offset, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) memcpy(buf, mdev_state->edid_blob + offset, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) static ssize_t mdev_access(struct mdev_device *mdev, char *buf, size_t count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) loff_t pos, bool is_write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) struct device *dev = mdev_dev(mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) struct page *pg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) loff_t poff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) char *map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) mutex_lock(&mdev_state->ops_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (pos < MBOCHS_CONFIG_SPACE_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) if (is_write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) handle_pci_cfg_write(mdev_state, pos, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) memcpy(buf, (mdev_state->vconfig + pos), count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) } else if (pos >= MBOCHS_MMIO_BAR_OFFSET &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) pos + count <= (MBOCHS_MMIO_BAR_OFFSET +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) MBOCHS_MMIO_BAR_SIZE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) pos -= MBOCHS_MMIO_BAR_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if (is_write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) handle_mmio_write(mdev_state, pos, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) handle_mmio_read(mdev_state, pos, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) } else if (pos >= MBOCHS_EDID_OFFSET &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) pos + count <= (MBOCHS_EDID_OFFSET +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) MBOCHS_EDID_SIZE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) pos -= MBOCHS_EDID_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) if (pos < MBOCHS_EDID_BLOB_OFFSET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) handle_edid_regs(mdev_state, pos, buf, count, is_write);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) pos -= MBOCHS_EDID_BLOB_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) handle_edid_blob(mdev_state, pos, buf, count, is_write);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) } else if (pos >= MBOCHS_MEMORY_BAR_OFFSET &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) pos + count <=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) MBOCHS_MEMORY_BAR_OFFSET + mdev_state->memsize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) pos -= MBOCHS_MMIO_BAR_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) poff = pos & ~PAGE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) pg = __mbochs_get_page(mdev_state, pos >> PAGE_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) map = kmap(pg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if (is_write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) memcpy(map + poff, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) memcpy(buf, map + poff, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) kunmap(pg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) put_page(pg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) dev_dbg(dev, "%s: %s @0x%llx (unhandled)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) __func__, is_write ? "WR" : "RD", pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) goto accessfailed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) ret = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) accessfailed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) mutex_unlock(&mdev_state->ops_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) static int mbochs_reset(struct mdev_device *mdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) u32 size64k = mdev_state->memsize / (64 * 1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) for (i = 0; i < ARRAY_SIZE(mdev_state->vbe); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) mdev_state->vbe[i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) mdev_state->vbe[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) mdev_state->vbe[VBE_DISPI_INDEX_VIDEO_MEMORY_64K] = size64k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) static int mbochs_create(struct kobject *kobj, struct mdev_device *mdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) const struct mbochs_type *type = mbochs_find_type(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) struct device *dev = mdev_dev(mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) struct mdev_state *mdev_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if (!type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) type = &mbochs_types[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) if (type->mbytes + mbochs_used_mbytes > max_mbytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) mdev_state = kzalloc(sizeof(struct mdev_state), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (mdev_state == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) mdev_state->vconfig = kzalloc(MBOCHS_CONFIG_SPACE_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) if (mdev_state->vconfig == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) goto err_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) mdev_state->memsize = type->mbytes * 1024 * 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) mdev_state->pagecount = mdev_state->memsize >> PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) mdev_state->pages = kcalloc(mdev_state->pagecount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) sizeof(struct page *),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (!mdev_state->pages)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) goto err_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) dev_info(dev, "%s: %s, %d MB, %ld pages\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) kobj->name, type->mbytes, mdev_state->pagecount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) mutex_init(&mdev_state->ops_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) mdev_state->mdev = mdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) mdev_set_drvdata(mdev, mdev_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) INIT_LIST_HEAD(&mdev_state->dmabufs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) mdev_state->next_id = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) mdev_state->type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) mdev_state->edid_regs.max_xres = type->max_x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) mdev_state->edid_regs.max_yres = type->max_y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) mdev_state->edid_regs.edid_offset = MBOCHS_EDID_BLOB_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) mdev_state->edid_regs.edid_max_size = sizeof(mdev_state->edid_blob);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) mbochs_create_config_space(mdev_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) mbochs_reset(mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) mbochs_used_mbytes += type->mbytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) err_mem:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) kfree(mdev_state->vconfig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) kfree(mdev_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) static int mbochs_remove(struct mdev_device *mdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) mbochs_used_mbytes -= mdev_state->type->mbytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) mdev_set_drvdata(mdev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) kfree(mdev_state->pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) kfree(mdev_state->vconfig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) kfree(mdev_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) static ssize_t mbochs_read(struct mdev_device *mdev, char __user *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) unsigned int done = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) while (count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) size_t filled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if (count >= 4 && !(*ppos % 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) ret = mdev_access(mdev, (char *)&val, sizeof(val),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) *ppos, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) if (ret <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) goto read_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if (copy_to_user(buf, &val, sizeof(val)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) goto read_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) filled = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) } else if (count >= 2 && !(*ppos % 2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) u16 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) ret = mdev_access(mdev, (char *)&val, sizeof(val),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) *ppos, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) if (ret <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) goto read_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (copy_to_user(buf, &val, sizeof(val)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) goto read_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) filled = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) ret = mdev_access(mdev, (char *)&val, sizeof(val),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) *ppos, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) if (ret <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) goto read_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) if (copy_to_user(buf, &val, sizeof(val)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) goto read_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) filled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) count -= filled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) done += filled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) *ppos += filled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) buf += filled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) return done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) read_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) static ssize_t mbochs_write(struct mdev_device *mdev, const char __user *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) unsigned int done = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) while (count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) size_t filled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) if (count >= 4 && !(*ppos % 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (copy_from_user(&val, buf, sizeof(val)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) goto write_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) ret = mdev_access(mdev, (char *)&val, sizeof(val),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) *ppos, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) if (ret <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) goto write_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) filled = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) } else if (count >= 2 && !(*ppos % 2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) u16 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) if (copy_from_user(&val, buf, sizeof(val)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) goto write_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) ret = mdev_access(mdev, (char *)&val, sizeof(val),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) *ppos, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) if (ret <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) goto write_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) filled = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) if (copy_from_user(&val, buf, sizeof(val)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) goto write_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) ret = mdev_access(mdev, (char *)&val, sizeof(val),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) *ppos, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if (ret <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) goto write_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) filled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) count -= filled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) done += filled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) *ppos += filled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) buf += filled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) return done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) write_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) static struct page *__mbochs_get_page(struct mdev_state *mdev_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) pgoff_t pgoff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) WARN_ON(!mutex_is_locked(&mdev_state->ops_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) if (!mdev_state->pages[pgoff]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) mdev_state->pages[pgoff] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) alloc_pages(GFP_HIGHUSER | __GFP_ZERO, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if (!mdev_state->pages[pgoff])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) get_page(mdev_state->pages[pgoff]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) return mdev_state->pages[pgoff];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) static struct page *mbochs_get_page(struct mdev_state *mdev_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) pgoff_t pgoff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) struct page *page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) if (WARN_ON(pgoff >= mdev_state->pagecount))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) mutex_lock(&mdev_state->ops_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) page = __mbochs_get_page(mdev_state, pgoff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) mutex_unlock(&mdev_state->ops_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) return page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) static void mbochs_put_pages(struct mdev_state *mdev_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) struct device *dev = mdev_dev(mdev_state->mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) int i, count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) WARN_ON(!mutex_is_locked(&mdev_state->ops_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) for (i = 0; i < mdev_state->pagecount; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) if (!mdev_state->pages[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) put_page(mdev_state->pages[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) mdev_state->pages[i] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) dev_dbg(dev, "%s: %d pages released\n", __func__, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) static vm_fault_t mbochs_region_vm_fault(struct vm_fault *vmf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) struct vm_area_struct *vma = vmf->vma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) struct mdev_state *mdev_state = vma->vm_private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) pgoff_t page_offset = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if (page_offset >= mdev_state->pagecount)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) return VM_FAULT_SIGBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) vmf->page = mbochs_get_page(mdev_state, page_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) if (!vmf->page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) return VM_FAULT_SIGBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) static const struct vm_operations_struct mbochs_region_vm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) .fault = mbochs_region_vm_fault,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) static int mbochs_mmap(struct mdev_device *mdev, struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (vma->vm_pgoff != MBOCHS_MEMORY_BAR_OFFSET >> PAGE_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) if (vma->vm_end < vma->vm_start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) if (vma->vm_end - vma->vm_start > mdev_state->memsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) if ((vma->vm_flags & VM_SHARED) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) vma->vm_ops = &mbochs_region_vm_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) vma->vm_private_data = mdev_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) static vm_fault_t mbochs_dmabuf_vm_fault(struct vm_fault *vmf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) struct vm_area_struct *vma = vmf->vma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) struct mbochs_dmabuf *dmabuf = vma->vm_private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) if (WARN_ON(vmf->pgoff >= dmabuf->pagecount))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) return VM_FAULT_SIGBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) vmf->page = dmabuf->pages[vmf->pgoff];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) get_page(vmf->page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) static const struct vm_operations_struct mbochs_dmabuf_vm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) .fault = mbochs_dmabuf_vm_fault,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) static int mbochs_mmap_dmabuf(struct dma_buf *buf, struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) struct mbochs_dmabuf *dmabuf = buf->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) struct device *dev = mdev_dev(dmabuf->mdev_state->mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) dev_dbg(dev, "%s: %d\n", __func__, dmabuf->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) if ((vma->vm_flags & VM_SHARED) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) vma->vm_ops = &mbochs_dmabuf_vm_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) vma->vm_private_data = dmabuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) static void mbochs_print_dmabuf(struct mbochs_dmabuf *dmabuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) const char *prefix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) struct device *dev = mdev_dev(dmabuf->mdev_state->mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) u32 fourcc = dmabuf->mode.drm_format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) dev_dbg(dev, "%s/%d: %c%c%c%c, %dx%d, stride %d, off 0x%llx, size 0x%llx, pages %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) prefix, dmabuf->id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) fourcc ? ((fourcc >> 0) & 0xff) : '-',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) fourcc ? ((fourcc >> 8) & 0xff) : '-',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) fourcc ? ((fourcc >> 16) & 0xff) : '-',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) fourcc ? ((fourcc >> 24) & 0xff) : '-',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) dmabuf->mode.width, dmabuf->mode.height, dmabuf->mode.stride,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) dmabuf->mode.offset, dmabuf->mode.size, dmabuf->pagecount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) static struct sg_table *mbochs_map_dmabuf(struct dma_buf_attachment *at,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) enum dma_data_direction direction)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) struct mbochs_dmabuf *dmabuf = at->dmabuf->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) struct device *dev = mdev_dev(dmabuf->mdev_state->mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) struct sg_table *sg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) dev_dbg(dev, "%s: %d\n", __func__, dmabuf->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) sg = kzalloc(sizeof(*sg), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) if (!sg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) goto err1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) if (sg_alloc_table_from_pages(sg, dmabuf->pages, dmabuf->pagecount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) 0, dmabuf->mode.size, GFP_KERNEL) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) goto err2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) if (dma_map_sgtable(at->dev, sg, direction, 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) goto err3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) return sg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) err3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) sg_free_table(sg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) err2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) kfree(sg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) err1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) static void mbochs_unmap_dmabuf(struct dma_buf_attachment *at,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) struct sg_table *sg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) enum dma_data_direction direction)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) struct mbochs_dmabuf *dmabuf = at->dmabuf->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) struct device *dev = mdev_dev(dmabuf->mdev_state->mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) dev_dbg(dev, "%s: %d\n", __func__, dmabuf->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) dma_unmap_sgtable(at->dev, sg, direction, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) sg_free_table(sg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) kfree(sg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) static void mbochs_release_dmabuf(struct dma_buf *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) struct mbochs_dmabuf *dmabuf = buf->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) struct mdev_state *mdev_state = dmabuf->mdev_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) struct device *dev = mdev_dev(mdev_state->mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) pgoff_t pg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) dev_dbg(dev, "%s: %d\n", __func__, dmabuf->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) for (pg = 0; pg < dmabuf->pagecount; pg++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) put_page(dmabuf->pages[pg]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) mutex_lock(&mdev_state->ops_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) dmabuf->buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) if (dmabuf->unlinked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) kfree(dmabuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) mutex_unlock(&mdev_state->ops_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) static struct dma_buf_ops mbochs_dmabuf_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) .map_dma_buf = mbochs_map_dmabuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) .unmap_dma_buf = mbochs_unmap_dmabuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) .release = mbochs_release_dmabuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) .mmap = mbochs_mmap_dmabuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) static struct mbochs_dmabuf *mbochs_dmabuf_alloc(struct mdev_state *mdev_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) struct mbochs_mode *mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) struct mbochs_dmabuf *dmabuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) pgoff_t page_offset, pg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) WARN_ON(!mutex_is_locked(&mdev_state->ops_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) dmabuf = kzalloc(sizeof(struct mbochs_dmabuf), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) if (!dmabuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) dmabuf->mode = *mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) dmabuf->id = mdev_state->next_id++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) dmabuf->pagecount = DIV_ROUND_UP(mode->size, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) dmabuf->pages = kcalloc(dmabuf->pagecount, sizeof(struct page *),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) if (!dmabuf->pages)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) goto err_free_dmabuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) page_offset = dmabuf->mode.offset >> PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) for (pg = 0; pg < dmabuf->pagecount; pg++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) dmabuf->pages[pg] = __mbochs_get_page(mdev_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) page_offset + pg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) if (!dmabuf->pages[pg])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) goto err_free_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) dmabuf->mdev_state = mdev_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) list_add(&dmabuf->next, &mdev_state->dmabufs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) mbochs_print_dmabuf(dmabuf, __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) return dmabuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) err_free_pages:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) while (pg > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) put_page(dmabuf->pages[--pg]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) kfree(dmabuf->pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) err_free_dmabuf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) kfree(dmabuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) static struct mbochs_dmabuf *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) mbochs_dmabuf_find_by_mode(struct mdev_state *mdev_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) struct mbochs_mode *mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) struct mbochs_dmabuf *dmabuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) WARN_ON(!mutex_is_locked(&mdev_state->ops_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) list_for_each_entry(dmabuf, &mdev_state->dmabufs, next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) if (mbochs_modes_equal(&dmabuf->mode, mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) return dmabuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) static struct mbochs_dmabuf *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) mbochs_dmabuf_find_by_id(struct mdev_state *mdev_state, u32 id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) struct mbochs_dmabuf *dmabuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) WARN_ON(!mutex_is_locked(&mdev_state->ops_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) list_for_each_entry(dmabuf, &mdev_state->dmabufs, next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) if (dmabuf->id == id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) return dmabuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) static int mbochs_dmabuf_export(struct mbochs_dmabuf *dmabuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) struct mdev_state *mdev_state = dmabuf->mdev_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) struct device *dev = mdev_dev(mdev_state->mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) struct dma_buf *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) WARN_ON(!mutex_is_locked(&mdev_state->ops_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) if (!IS_ALIGNED(dmabuf->mode.offset, PAGE_SIZE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) dev_info_ratelimited(dev, "%s: framebuffer not page-aligned\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) exp_info.ops = &mbochs_dmabuf_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) exp_info.size = dmabuf->mode.size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) exp_info.priv = dmabuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) buf = dma_buf_export(&exp_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) if (IS_ERR(buf)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) dev_info_ratelimited(dev, "%s: dma_buf_export failed: %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) __func__, PTR_ERR(buf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) return PTR_ERR(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) dmabuf->buf = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) dev_dbg(dev, "%s: %d\n", __func__, dmabuf->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) static int mbochs_get_region_info(struct mdev_device *mdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) struct vfio_region_info_ext *ext)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) struct vfio_region_info *region_info = &ext->base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) struct mdev_state *mdev_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) mdev_state = mdev_get_drvdata(mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) if (!mdev_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) if (region_info->index >= MBOCHS_NUM_REGIONS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) switch (region_info->index) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) case VFIO_PCI_CONFIG_REGION_INDEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) region_info->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) region_info->size = MBOCHS_CONFIG_SPACE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) region_info->flags = (VFIO_REGION_INFO_FLAG_READ |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) VFIO_REGION_INFO_FLAG_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) case VFIO_PCI_BAR0_REGION_INDEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) region_info->offset = MBOCHS_MEMORY_BAR_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) region_info->size = mdev_state->memsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) region_info->flags = (VFIO_REGION_INFO_FLAG_READ |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) VFIO_REGION_INFO_FLAG_WRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) VFIO_REGION_INFO_FLAG_MMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) case VFIO_PCI_BAR2_REGION_INDEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) region_info->offset = MBOCHS_MMIO_BAR_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) region_info->size = MBOCHS_MMIO_BAR_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) region_info->flags = (VFIO_REGION_INFO_FLAG_READ |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) VFIO_REGION_INFO_FLAG_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) case MBOCHS_EDID_REGION_INDEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) ext->base.argsz = sizeof(*ext);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) ext->base.offset = MBOCHS_EDID_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) ext->base.size = MBOCHS_EDID_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) ext->base.flags = (VFIO_REGION_INFO_FLAG_READ |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) VFIO_REGION_INFO_FLAG_WRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) VFIO_REGION_INFO_FLAG_CAPS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) ext->base.cap_offset = offsetof(typeof(*ext), type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) ext->type.header.id = VFIO_REGION_INFO_CAP_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) ext->type.header.version = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) ext->type.header.next = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) ext->type.type = VFIO_REGION_TYPE_GFX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) ext->type.subtype = VFIO_REGION_SUBTYPE_GFX_EDID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) region_info->size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) region_info->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) region_info->flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) static int mbochs_get_irq_info(struct mdev_device *mdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) struct vfio_irq_info *irq_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) irq_info->count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) static int mbochs_get_device_info(struct mdev_device *mdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) struct vfio_device_info *dev_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) dev_info->flags = VFIO_DEVICE_FLAGS_PCI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) dev_info->num_regions = MBOCHS_NUM_REGIONS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) dev_info->num_irqs = VFIO_PCI_NUM_IRQS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) static int mbochs_query_gfx_plane(struct mdev_device *mdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) struct vfio_device_gfx_plane_info *plane)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) struct device *dev = mdev_dev(mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) struct mbochs_dmabuf *dmabuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) struct mbochs_mode mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) if (plane->flags & VFIO_GFX_PLANE_TYPE_PROBE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) if (plane->flags == (VFIO_GFX_PLANE_TYPE_PROBE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) VFIO_GFX_PLANE_TYPE_DMABUF))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) if (plane->flags != VFIO_GFX_PLANE_TYPE_DMABUF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) plane->drm_format_mod = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) plane->x_pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) plane->y_pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) plane->x_hot = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) plane->y_hot = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) mutex_lock(&mdev_state->ops_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) if (plane->drm_plane_type == DRM_PLANE_TYPE_PRIMARY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) ret = mbochs_check_framebuffer(mdev_state, &mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) plane->drm_format = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) plane->width = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) plane->height = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) plane->stride = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) plane->size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) plane->dmabuf_id = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) dmabuf = mbochs_dmabuf_find_by_mode(mdev_state, &mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) if (!dmabuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) mbochs_dmabuf_alloc(mdev_state, &mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) if (!dmabuf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) mutex_unlock(&mdev_state->ops_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) plane->drm_format = dmabuf->mode.drm_format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) plane->width = dmabuf->mode.width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) plane->height = dmabuf->mode.height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) plane->stride = dmabuf->mode.stride;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) plane->size = dmabuf->mode.size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) plane->dmabuf_id = dmabuf->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) if (plane->drm_plane_type == DRM_PLANE_TYPE_PRIMARY &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) mdev_state->active_id != plane->dmabuf_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) dev_dbg(dev, "%s: primary: %d => %d\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) mdev_state->active_id, plane->dmabuf_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) mdev_state->active_id = plane->dmabuf_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) mutex_unlock(&mdev_state->ops_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) static int mbochs_get_gfx_dmabuf(struct mdev_device *mdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) u32 id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) struct mbochs_dmabuf *dmabuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) mutex_lock(&mdev_state->ops_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) dmabuf = mbochs_dmabuf_find_by_id(mdev_state, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) if (!dmabuf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) mutex_unlock(&mdev_state->ops_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) if (!dmabuf->buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) mbochs_dmabuf_export(dmabuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) mutex_unlock(&mdev_state->ops_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) if (!dmabuf->buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) return dma_buf_fd(dmabuf->buf, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) unsigned long minsz, outsz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) case VFIO_DEVICE_GET_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) struct vfio_device_info info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) minsz = offsetofend(struct vfio_device_info, num_irqs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) if (copy_from_user(&info, (void __user *)arg, minsz))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) if (info.argsz < minsz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) ret = mbochs_get_device_info(mdev, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) if (copy_to_user((void __user *)arg, &info, minsz))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) case VFIO_DEVICE_GET_REGION_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) struct vfio_region_info_ext info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) minsz = offsetofend(typeof(info), base.offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) if (copy_from_user(&info, (void __user *)arg, minsz))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) outsz = info.base.argsz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) if (outsz < minsz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) if (outsz > sizeof(info))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) ret = mbochs_get_region_info(mdev, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) if (copy_to_user((void __user *)arg, &info, outsz))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) case VFIO_DEVICE_GET_IRQ_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) struct vfio_irq_info info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) minsz = offsetofend(struct vfio_irq_info, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) if (copy_from_user(&info, (void __user *)arg, minsz))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) if ((info.argsz < minsz) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) (info.index >= VFIO_PCI_NUM_IRQS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) ret = mbochs_get_irq_info(mdev, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) if (copy_to_user((void __user *)arg, &info, minsz))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) case VFIO_DEVICE_QUERY_GFX_PLANE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) struct vfio_device_gfx_plane_info plane;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) minsz = offsetofend(struct vfio_device_gfx_plane_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) region_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) if (copy_from_user(&plane, (void __user *)arg, minsz))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) if (plane.argsz < minsz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) ret = mbochs_query_gfx_plane(mdev, &plane);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) if (copy_to_user((void __user *)arg, &plane, minsz))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) case VFIO_DEVICE_GET_GFX_DMABUF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) u32 dmabuf_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) if (get_user(dmabuf_id, (__u32 __user *)arg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) return mbochs_get_gfx_dmabuf(mdev, dmabuf_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) case VFIO_DEVICE_SET_IRQS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) case VFIO_DEVICE_RESET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) return mbochs_reset(mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) return -ENOTTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) static int mbochs_open(struct mdev_device *mdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) if (!try_module_get(THIS_MODULE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) static void mbochs_close(struct mdev_device *mdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) struct mbochs_dmabuf *dmabuf, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) mutex_lock(&mdev_state->ops_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) list_for_each_entry_safe(dmabuf, tmp, &mdev_state->dmabufs, next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) list_del(&dmabuf->next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) if (dmabuf->buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) /* free in mbochs_release_dmabuf() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) dmabuf->unlinked = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) kfree(dmabuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) mbochs_put_pages(mdev_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) mutex_unlock(&mdev_state->ops_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) module_put(THIS_MODULE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) memory_show(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) struct mdev_device *mdev = mdev_from_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) return sprintf(buf, "%d MB\n", mdev_state->type->mbytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) static DEVICE_ATTR_RO(memory);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) static struct attribute *mdev_dev_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) &dev_attr_memory.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) static const struct attribute_group mdev_dev_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) .name = "vendor",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) .attrs = mdev_dev_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) const struct attribute_group *mdev_dev_groups[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) &mdev_dev_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) name_show(struct kobject *kobj, struct device *dev, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) return sprintf(buf, "%s\n", kobj->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) MDEV_TYPE_ATTR_RO(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) description_show(struct kobject *kobj, struct device *dev, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) const struct mbochs_type *type = mbochs_find_type(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) return sprintf(buf, "virtual display, %d MB video memory\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) type ? type->mbytes : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) MDEV_TYPE_ATTR_RO(description);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) available_instances_show(struct kobject *kobj, struct device *dev, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) const struct mbochs_type *type = mbochs_find_type(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) int count = (max_mbytes - mbochs_used_mbytes) / type->mbytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) return sprintf(buf, "%d\n", count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) MDEV_TYPE_ATTR_RO(available_instances);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) static ssize_t device_api_show(struct kobject *kobj, struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) return sprintf(buf, "%s\n", VFIO_DEVICE_API_PCI_STRING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) MDEV_TYPE_ATTR_RO(device_api);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) static struct attribute *mdev_types_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) &mdev_type_attr_name.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) &mdev_type_attr_description.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) &mdev_type_attr_device_api.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) &mdev_type_attr_available_instances.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) static struct attribute_group mdev_type_group1 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) .name = MBOCHS_TYPE_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) .attrs = mdev_types_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) static struct attribute_group mdev_type_group2 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) .name = MBOCHS_TYPE_2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) .attrs = mdev_types_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) static struct attribute_group mdev_type_group3 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) .name = MBOCHS_TYPE_3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) .attrs = mdev_types_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) static struct attribute_group *mdev_type_groups[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) &mdev_type_group1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) &mdev_type_group2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) &mdev_type_group3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) static const struct mdev_parent_ops mdev_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) .mdev_attr_groups = mdev_dev_groups,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) .supported_type_groups = mdev_type_groups,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) .create = mbochs_create,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) .remove = mbochs_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) .open = mbochs_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) .release = mbochs_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) .read = mbochs_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) .write = mbochs_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) .ioctl = mbochs_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) .mmap = mbochs_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) static const struct file_operations vd_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) static void mbochs_device_release(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) /* nothing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) static int __init mbochs_dev_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) ret = alloc_chrdev_region(&mbochs_devt, 0, MINORMASK + 1, MBOCHS_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) pr_err("Error: failed to register mbochs_dev, err: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) cdev_init(&mbochs_cdev, &vd_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) cdev_add(&mbochs_cdev, mbochs_devt, MINORMASK + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) pr_info("%s: major %d\n", __func__, MAJOR(mbochs_devt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) mbochs_class = class_create(THIS_MODULE, MBOCHS_CLASS_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) if (IS_ERR(mbochs_class)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) pr_err("Error: failed to register mbochs_dev class\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) ret = PTR_ERR(mbochs_class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) goto failed1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) mbochs_dev.class = mbochs_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) mbochs_dev.release = mbochs_device_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) dev_set_name(&mbochs_dev, "%s", MBOCHS_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) ret = device_register(&mbochs_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) goto failed2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) ret = mdev_register_device(&mbochs_dev, &mdev_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) goto failed3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) failed3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) device_unregister(&mbochs_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) failed2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) class_destroy(mbochs_class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) failed1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) cdev_del(&mbochs_cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) unregister_chrdev_region(mbochs_devt, MINORMASK + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) static void __exit mbochs_dev_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) mbochs_dev.bus = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) mdev_unregister_device(&mbochs_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) device_unregister(&mbochs_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) cdev_del(&mbochs_cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) unregister_chrdev_region(mbochs_devt, MINORMASK + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) class_destroy(mbochs_class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) mbochs_class = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) module_init(mbochs_dev_init)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) module_exit(mbochs_dev_exit)