diff options
-rw-r--r-- | MAINTAINERS | 1 | ||||
-rw-r--r-- | drivers/firmware/qemu_fw_cfg.c | 291 | ||||
-rw-r--r-- | drivers/vhost/vhost.c | 2 | ||||
-rw-r--r-- | drivers/vhost/vhost.h | 4 | ||||
-rw-r--r-- | drivers/vhost/vsock.c | 11 | ||||
-rw-r--r-- | include/uapi/linux/qemu_fw_cfg.h | 97 | ||||
-rw-r--r-- | kernel/crash_core.c | 1 | ||||
-rw-r--r-- | tools/virtio/ringtest/ptr_ring.c | 5 |
8 files changed, 348 insertions, 64 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 5e929acb5a82..83f5a6fd7de3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11464,6 +11464,7 @@ M: "Michael S. Tsirkin" <mst@redhat.com> L: qemu-devel@nongnu.org S: Maintained F: drivers/firmware/qemu_fw_cfg.c +F: include/uapi/linux/qemu_fw_cfg.h QIB DRIVER M: Dennis Dalessandro <dennis.dalessandro@intel.com> diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c index a41b572eeeb1..14fedbeca724 100644 --- a/drivers/firmware/qemu_fw_cfg.c +++ b/drivers/firmware/qemu_fw_cfg.c @@ -10,20 +10,21 @@ * and select subsets of aarch64), a Device Tree node (on arm), or using * a kernel module (or command line) parameter with the following syntax: * - * [qemu_fw_cfg.]ioport=<size>@<base>[:<ctrl_off>:<data_off>] + * [qemu_fw_cfg.]ioport=<size>@<base>[:<ctrl_off>:<data_off>[:<dma_off>]] * or - * [qemu_fw_cfg.]mmio=<size>@<base>[:<ctrl_off>:<data_off>] + * [qemu_fw_cfg.]mmio=<size>@<base>[:<ctrl_off>:<data_off>[:<dma_off>]] * * where: * <size> := size of ioport or mmio range * <base> := physical base address of ioport or mmio range * <ctrl_off> := (optional) offset of control register * <data_off> := (optional) offset of data register + * <dma_off> := (optional) offset of dma register * * e.g.: - * qemu_fw_cfg.ioport=2@0x510:0:1 (the default on x86) + * qemu_fw_cfg.ioport=12@0x510:0:1:4 (the default on x86) * or - * qemu_fw_cfg.mmio=0xA@0x9020000:8:0 (the default on arm) + * qemu_fw_cfg.mmio=16@0x9020000:8:0:16 (the default on arm) */ #include <linux/module.h> @@ -32,29 +33,17 @@ #include <linux/slab.h> #include <linux/io.h> #include <linux/ioport.h> +#include <uapi/linux/qemu_fw_cfg.h> +#include <linux/delay.h> +#include <linux/crash_dump.h> +#include <linux/crash_core.h> MODULE_AUTHOR("Gabriel L. Somlo <somlo@cmu.edu>"); MODULE_DESCRIPTION("QEMU fw_cfg sysfs support"); MODULE_LICENSE("GPL"); -/* selector key values for "well-known" fw_cfg entries */ -#define FW_CFG_SIGNATURE 0x00 -#define FW_CFG_ID 0x01 -#define FW_CFG_FILE_DIR 0x19 - -/* size in bytes of fw_cfg signature */ -#define FW_CFG_SIG_SIZE 4 - -/* fw_cfg "file name" is up to 56 characters (including terminating nul) */ -#define FW_CFG_MAX_FILE_PATH 56 - -/* fw_cfg file directory entry type */ -struct fw_cfg_file { - u32 size; - u16 select; - u16 reserved; - char name[FW_CFG_MAX_FILE_PATH]; -}; +/* fw_cfg revision attribute, in /sys/firmware/qemu_fw_cfg top-level dir. */ +static u32 fw_cfg_rev; /* fw_cfg device i/o register addresses */ static bool fw_cfg_is_mmio; @@ -63,19 +52,83 @@ static resource_size_t fw_cfg_p_size; static void __iomem *fw_cfg_dev_base; static void __iomem *fw_cfg_reg_ctrl; static void __iomem *fw_cfg_reg_data; +static void __iomem *fw_cfg_reg_dma; /* atomic access to fw_cfg device (potentially slow i/o, so using mutex) */ static DEFINE_MUTEX(fw_cfg_dev_lock); /* pick appropriate endianness for selector key */ -static inline u16 fw_cfg_sel_endianness(u16 key) +static void fw_cfg_sel_endianness(u16 key) +{ + if (fw_cfg_is_mmio) + iowrite16be(key, fw_cfg_reg_ctrl); + else + iowrite16(key, fw_cfg_reg_ctrl); +} + +#ifdef CONFIG_CRASH_CORE +static inline bool fw_cfg_dma_enabled(void) +{ + return (fw_cfg_rev & FW_CFG_VERSION_DMA) && fw_cfg_reg_dma; +} + +/* qemu fw_cfg device is sync today, but spec says it may become async */ +static void fw_cfg_wait_for_control(struct fw_cfg_dma_access *d) { - return fw_cfg_is_mmio ? cpu_to_be16(key) : cpu_to_le16(key); + for (;;) { + u32 ctrl = be32_to_cpu(READ_ONCE(d->control)); + + /* do not reorder the read to d->control */ + rmb(); + if ((ctrl & ~FW_CFG_DMA_CTL_ERROR) == 0) + return; + + cpu_relax(); + } +} + +static ssize_t fw_cfg_dma_transfer(void *address, u32 length, u32 control) +{ + phys_addr_t dma; + struct fw_cfg_dma_access *d = NULL; + ssize_t ret = length; + + d = kmalloc(sizeof(*d), GFP_KERNEL); + if (!d) { + ret = -ENOMEM; + goto end; + } + + /* fw_cfg device does not need IOMMU protection, so use physical addresses */ + *d = (struct fw_cfg_dma_access) { + .address = cpu_to_be64(address ? virt_to_phys(address) : 0), + .length = cpu_to_be32(length), + .control = cpu_to_be32(control) + }; + + dma = virt_to_phys(d); + + iowrite32be((u64)dma >> 32, fw_cfg_reg_dma); + /* force memory to sync before notifying device via MMIO */ + wmb(); + iowrite32be(dma, fw_cfg_reg_dma + 4); + + fw_cfg_wait_for_control(d); + + if (be32_to_cpu(READ_ONCE(d->control)) & FW_CFG_DMA_CTL_ERROR) { + ret = -EIO; + } + +end: + kfree(d); + + return ret; } +#endif /* read chunk of given fw_cfg blob (caller responsible for sanity-check) */ -static inline void fw_cfg_read_blob(u16 key, - void *buf, loff_t pos, size_t count) +static ssize_t fw_cfg_read_blob(u16 key, + void *buf, loff_t pos, size_t count) { u32 glk = -1U; acpi_status status; @@ -88,18 +141,60 @@ static inline void fw_cfg_read_blob(u16 key, /* Should never get here */ WARN(1, "fw_cfg_read_blob: Failed to lock ACPI!\n"); memset(buf, 0, count); - return; + return -EINVAL; } mutex_lock(&fw_cfg_dev_lock); - iowrite16(fw_cfg_sel_endianness(key), fw_cfg_reg_ctrl); + fw_cfg_sel_endianness(key); while (pos-- > 0) ioread8(fw_cfg_reg_data); ioread8_rep(fw_cfg_reg_data, buf, count); mutex_unlock(&fw_cfg_dev_lock); acpi_release_global_lock(glk); + return count; +} + +#ifdef CONFIG_CRASH_CORE +/* write chunk of given fw_cfg blob (caller responsible for sanity-check) */ +static ssize_t fw_cfg_write_blob(u16 key, + void *buf, loff_t pos, size_t count) +{ + u32 glk = -1U; + acpi_status status; + ssize_t ret = count; + + /* If we have ACPI, ensure mutual exclusion against any potential + * device access by the firmware, e.g. via AML methods: + */ + status = acpi_acquire_global_lock(ACPI_WAIT_FOREVER, &glk); + if (ACPI_FAILURE(status) && status != AE_NOT_CONFIGURED) { + /* Should never get here */ + WARN(1, "%s: Failed to lock ACPI!\n", __func__); + return -EINVAL; + } + + mutex_lock(&fw_cfg_dev_lock); + if (pos == 0) { + ret = fw_cfg_dma_transfer(buf, count, key << 16 + | FW_CFG_DMA_CTL_SELECT + | FW_CFG_DMA_CTL_WRITE); + } else { + fw_cfg_sel_endianness(key); + ret = fw_cfg_dma_transfer(NULL, pos, FW_CFG_DMA_CTL_SKIP); + if (ret < 0) + goto end; + ret = fw_cfg_dma_transfer(buf, count, FW_CFG_DMA_CTL_WRITE); + } + +end: + mutex_unlock(&fw_cfg_dev_lock); + + acpi_release_global_lock(glk); + + return ret; } +#endif /* CONFIG_CRASH_CORE */ /* clean up fw_cfg device i/o */ static void fw_cfg_io_cleanup(void) @@ -118,12 +213,14 @@ static void fw_cfg_io_cleanup(void) # if (defined(CONFIG_ARM) || defined(CONFIG_ARM64)) # define FW_CFG_CTRL_OFF 0x08 # define FW_CFG_DATA_OFF 0x00 +# define FW_CFG_DMA_OFF 0x10 # elif (defined(CONFIG_PPC_PMAC) || defined(CONFIG_SPARC32)) /* ppc/mac,sun4m */ # define FW_CFG_CTRL_OFF 0x00 # define FW_CFG_DATA_OFF 0x02 # elif (defined(CONFIG_X86) || defined(CONFIG_SPARC64)) /* x86, sun4u */ # define FW_CFG_CTRL_OFF 0x00 # define FW_CFG_DATA_OFF 0x01 +# define FW_CFG_DMA_OFF 0x04 # else # error "QEMU FW_CFG not available on this architecture!" # endif @@ -133,7 +230,7 @@ static void fw_cfg_io_cleanup(void) static int fw_cfg_do_platform_probe(struct platform_device *pdev) { char sig[FW_CFG_SIG_SIZE]; - struct resource *range, *ctrl, *data; + struct resource *range, *ctrl, *data, *dma; /* acquire i/o range details */ fw_cfg_is_mmio = false; @@ -170,6 +267,7 @@ static int fw_cfg_do_platform_probe(struct platform_device *pdev) /* were custom register offsets provided (e.g. on the command line)? */ ctrl = platform_get_resource_byname(pdev, IORESOURCE_REG, "ctrl"); data = platform_get_resource_byname(pdev, IORESOURCE_REG, "data"); + dma = platform_get_resource_byname(pdev, IORESOURCE_REG, "dma"); if (ctrl && data) { fw_cfg_reg_ctrl = fw_cfg_dev_base + ctrl->start; fw_cfg_reg_data = fw_cfg_dev_base + data->start; @@ -179,9 +277,17 @@ static int fw_cfg_do_platform_probe(struct platform_device *pdev) fw_cfg_reg_data = fw_cfg_dev_base + FW_CFG_DATA_OFF; } + if (dma) + fw_cfg_reg_dma = fw_cfg_dev_base + dma->start; +#ifdef FW_CFG_DMA_OFF + else + fw_cfg_reg_dma = fw_cfg_dev_base + FW_CFG_DMA_OFF; +#endif + /* verify fw_cfg device signature */ - fw_cfg_read_blob(FW_CFG_SIGNATURE, sig, 0, FW_CFG_SIG_SIZE); - if (memcmp(sig, "QEMU", FW_CFG_SIG_SIZE) != 0) { + if (fw_cfg_read_blob(FW_CFG_SIGNATURE, sig, + 0, FW_CFG_SIG_SIZE) < 0 || + memcmp(sig, "QEMU", FW_CFG_SIG_SIZE) != 0) { fw_cfg_io_cleanup(); return -ENODEV; } @@ -189,9 +295,6 @@ static int fw_cfg_do_platform_probe(struct platform_device *pdev) return 0; } -/* fw_cfg revision attribute, in /sys/firmware/qemu_fw_cfg top-level dir. */ -static u32 fw_cfg_rev; - static ssize_t fw_cfg_showrev(struct kobject *k, struct attribute *a, char *buf) { return sprintf(buf, "%u\n", fw_cfg_rev); @@ -208,10 +311,38 @@ static const struct { /* fw_cfg_sysfs_entry type */ struct fw_cfg_sysfs_entry { struct kobject kobj; - struct fw_cfg_file f; + u32 size; + u16 select; + char name[FW_CFG_MAX_FILE_PATH]; struct list_head list; }; +#ifdef CONFIG_CRASH_CORE +static ssize_t fw_cfg_write_vmcoreinfo(const struct fw_cfg_file *f) +{ + static struct fw_cfg_vmcoreinfo *data; + ssize_t ret; + + data = kmalloc(sizeof(struct fw_cfg_vmcoreinfo), GFP_KERNEL); + if (!data) + return -ENOMEM; + + *data = (struct fw_cfg_vmcoreinfo) { + .guest_format = cpu_to_le16(FW_CFG_VMCOREINFO_FORMAT_ELF), + .size = cpu_to_le32(VMCOREINFO_NOTE_SIZE), + .paddr = cpu_to_le64(paddr_vmcoreinfo_note()) + }; + /* spare ourself reading host format support for now since we + * don't know what else to format - host may ignore ours + */ + ret = fw_cfg_write_blob(be16_to_cpu(f->select), data, + 0, sizeof(struct fw_cfg_vmcoreinfo)); + + kfree(data); + return ret; +} +#endif /* CONFIG_CRASH_CORE */ + /* get fw_cfg_sysfs_entry from kobject member */ static inline struct fw_cfg_sysfs_entry *to_entry(struct kobject *kobj) { @@ -272,17 +403,17 @@ struct fw_cfg_sysfs_attribute fw_cfg_sysfs_attr_##_attr = { \ static ssize_t fw_cfg_sysfs_show_size(struct fw_cfg_sysfs_entry *e, char *buf) { - return sprintf(buf, "%u\n", e->f.size); + return sprintf(buf, "%u\n", e->size); } static ssize_t fw_cfg_sysfs_show_key(struct fw_cfg_sysfs_entry *e, char *buf) { - return sprintf(buf, "%u\n", e->f.select); + return sprintf(buf, "%u\n", e->select); } static ssize_t fw_cfg_sysfs_show_name(struct fw_cfg_sysfs_entry *e, char *buf) { - return sprintf(buf, "%s\n", e->f.name); + return sprintf(buf, "%s\n", e->name); } static FW_CFG_SYSFS_ATTR(size); @@ -333,14 +464,13 @@ static ssize_t fw_cfg_sysfs_read_raw(struct file *filp, struct kobject *kobj, { struct fw_cfg_sysfs_entry *entry = to_entry(kobj); - if (pos > entry->f.size) + if (pos > entry->size) return -EINVAL; - if (count > entry->f.size - pos) - count = entry->f.size - pos; + if (count > entry->size - pos) + count = entry->size - pos; - fw_cfg_read_blob(entry->f.select, buf, pos, count); - return count; + return fw_cfg_read_blob(entry->select, buf, pos, count); } static struct bin_attribute fw_cfg_sysfs_attr_raw = { @@ -452,17 +582,28 @@ static int fw_cfg_register_file(const struct fw_cfg_file *f) int err; struct fw_cfg_sysfs_entry *entry; +#ifdef CONFIG_CRASH_CORE + if (fw_cfg_dma_enabled() && + strcmp(f->name, FW_CFG_VMCOREINFO_FILENAME) == 0 && + !is_kdump_kernel()) { + if (fw_cfg_write_vmcoreinfo(f) < 0) + pr_warn("fw_cfg: failed to write vmcoreinfo"); + } +#endif + /* allocate new entry */ entry = kzalloc(sizeof(*entry), GFP_KERNEL); if (!entry) return -ENOMEM; /* set file entry information */ - memcpy(&entry->f, f, sizeof(struct fw_cfg_file)); + entry->size = be32_to_cpu(f->size); + entry->select = be16_to_cpu(f->select); + memcpy(entry->name, f->name, FW_CFG_MAX_FILE_PATH); /* register entry under "/sys/firmware/qemu_fw_cfg/by_key/" */ err = kobject_init_and_add(&entry->kobj, &fw_cfg_sysfs_entry_ktype, - fw_cfg_sel_ko, "%d", entry->f.select); + fw_cfg_sel_ko, "%d", entry->select); if (err) goto err_register; @@ -472,7 +613,7 @@ static int fw_cfg_register_file(const struct fw_cfg_file *f) goto err_add_raw; /* try adding "/sys/firmware/qemu_fw_cfg/by_name/" symlink */ - fw_cfg_build_symlink(fw_cfg_fname_kset, &entry->kobj, entry->f.name); + fw_cfg_build_symlink(fw_cfg_fname_kset, &entry->kobj, entry->name); /* success, add entry to global cache */ fw_cfg_sysfs_cache_enlist(entry); @@ -489,28 +630,35 @@ err_register: static int fw_cfg_register_dir_entries(void) { int ret = 0; + __be32 files_count; u32 count, i; struct fw_cfg_file *dir; size_t dir_size; - fw_cfg_read_blob(FW_CFG_FILE_DIR, &count, 0, sizeof(count)); - count = be32_to_cpu(count); + ret = fw_cfg_read_blob(FW_CFG_FILE_DIR, &files_count, + 0, sizeof(files_count)); + if (ret < 0) + return ret; + + count = be32_to_cpu(files_count); dir_size = count * sizeof(struct fw_cfg_file); dir = kmalloc(dir_size, GFP_KERNEL); if (!dir) return -ENOMEM; - fw_cfg_read_blob(FW_CFG_FILE_DIR, dir, sizeof(count), dir_size); + ret = fw_cfg_read_blob(FW_CFG_FILE_DIR, dir, + sizeof(files_count), dir_size); + if (ret < 0) + goto end; for (i = 0; i < count; i++) { - dir[i].size = be32_to_cpu(dir[i].size); - dir[i].select = be16_to_cpu(dir[i].select); ret = fw_cfg_register_file(&dir[i]); if (ret) break; } +end: kfree(dir); return ret; } @@ -525,6 +673,7 @@ static inline void fw_cfg_kobj_cleanup(struct kobject *kobj) static int fw_cfg_sysfs_probe(struct platform_device *pdev) { int err; + __le32 rev; /* NOTE: If we supported multiple fw_cfg devices, we'd first create * a subdirectory named after e.g. pdev->id, then hang per-device @@ -550,8 +699,11 @@ static int fw_cfg_sysfs_probe(struct platform_device *pdev) goto err_probe; /* get revision number, add matching top-level attribute */ - fw_cfg_read_blob(FW_CFG_ID, &fw_cfg_rev, 0, sizeof(fw_cfg_rev)); - fw_cfg_rev = le32_to_cpu(fw_cfg_rev); + err = fw_cfg_read_blob(FW_CFG_ID, &rev, 0, sizeof(rev)); + if (err < 0) + goto err_probe; + + fw_cfg_rev = le32_to_cpu(rev); err = sysfs_create_file(fw_cfg_top_ko, &fw_cfg_rev_attr.attr); if (err) goto err_rev; @@ -597,7 +749,7 @@ MODULE_DEVICE_TABLE(of, fw_cfg_sysfs_mmio_match); #ifdef CONFIG_ACPI static const struct acpi_device_id fw_cfg_sysfs_acpi_match[] = { - { "QEMU0002", }, + { FW_CFG_ACPI_DEVICE_ID, }, {}, }; MODULE_DEVICE_TABLE(acpi, fw_cfg_sysfs_acpi_match); @@ -629,6 +781,7 @@ static struct platform_device *fw_cfg_cmdline_dev; /* use special scanf/printf modifier for phys_addr_t, resource_size_t */ #define PH_ADDR_SCAN_FMT "@%" __PHYS_ADDR_PREFIX "i%n" \ ":%" __PHYS_ADDR_PREFIX "i" \ + ":%" __PHYS_ADDR_PREFIX "i%n" \ ":%" __PHYS_ADDR_PREFIX "i%n" #define PH_ADDR_PR_1_FMT "0x%" __PHYS_ADDR_PREFIX "x@" \ @@ -638,12 +791,15 @@ static struct platform_device *fw_cfg_cmdline_dev; ":%" __PHYS_ADDR_PREFIX "u" \ ":%" __PHYS_ADDR_PREFIX "u" +#define PH_ADDR_PR_4_FMT PH_ADDR_PR_3_FMT \ + ":%" __PHYS_ADDR_PREFIX "u" + static int fw_cfg_cmdline_set(const char *arg, const struct kernel_param *kp) { - struct resource res[3] = {}; + struct resource res[4] = {}; char *str; phys_addr_t base; - resource_size_t size, ctrl_off, data_off; + resource_size_t size, ctrl_off, data_off, dma_off; int processed, consumed = 0; /* only one fw_cfg device can exist system-wide, so if one @@ -659,19 +815,20 @@ static int fw_cfg_cmdline_set(const char *arg, const struct kernel_param *kp) /* consume "<size>" portion of command line argument */ size = memparse(arg, &str); - /* get "@<base>[:<ctrl_off>:<data_off>]" chunks */ + /* get "@<base>[:<ctrl_off>:<data_off>[:<dma_off>]]" chunks */ processed = sscanf(str, PH_ADDR_SCAN_FMT, &base, &consumed, - &ctrl_off, &data_off, &consumed); + &ctrl_off, &data_off, &consumed, + &dma_off, &consumed); - /* sscanf() must process precisely 1 or 3 chunks: + /* sscanf() must process precisely 1, 3 or 4 chunks: * <base> is mandatory, optionally followed by <ctrl_off> - * and <data_off>; + * and <data_off>, and <dma_off>; * there must be no extra characters after the last chunk, * so str[consumed] must be '\0'. */ if (str[consumed] || - (processed != 1 && processed != 3)) + (processed != 1 && processed != 3 && processed != 4)) return -EINVAL; res[0].start = base; @@ -688,6 +845,11 @@ static int fw_cfg_cmdline_set(const char *arg, const struct kernel_param *kp) res[2].start = data_off; res[2].flags = IORESOURCE_REG; } + if (processed > 3) { + res[3].name = "dma"; + res[3].start = dma_off; + res[3].flags = IORESOURCE_REG; + } /* "processed" happens to nicely match the number of resources * we need to pass in to this platform device. @@ -720,6 +882,13 @@ static int fw_cfg_cmdline_get(char *buf, const struct kernel_param *kp) fw_cfg_cmdline_dev->resource[0].start, fw_cfg_cmdline_dev->resource[1].start, fw_cfg_cmdline_dev->resource[2].start); + case 4: + return snprintf(buf, PAGE_SIZE, PH_ADDR_PR_4_FMT, + resource_size(&fw_cfg_cmdline_dev->resource[0]), + fw_cfg_cmdline_dev->resource[0].start, + fw_cfg_cmdline_dev->resource[1].start, + fw_cfg_cmdline_dev->resource[2].start, + fw_cfg_cmdline_dev->resource[3].start); } /* Should never get here */ diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 5320039671b7..bec722e41f58 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -1334,7 +1334,7 @@ err: return -EFAULT; } -long vhost_vring_ioctl(struct vhost_dev *d, int ioctl, void __user *argp) +long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp) { struct file *eventfp, *filep = NULL; bool pollstart = false, pollstop = false; diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h index ac4b6056f19a..d8ee85ae8fdc 100644 --- a/drivers/vhost/vhost.h +++ b/drivers/vhost/vhost.h @@ -45,7 +45,7 @@ void vhost_poll_stop(struct vhost_poll *poll); void vhost_poll_flush(struct vhost_poll *poll); void vhost_poll_queue(struct vhost_poll *poll); void vhost_work_flush(struct vhost_dev *dev, struct vhost_work *work); -long vhost_vring_ioctl(struct vhost_dev *d, int ioctl, void __user *argp); +long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp); struct vhost_log { u64 addr; @@ -177,7 +177,7 @@ void vhost_dev_reset_owner(struct vhost_dev *, struct vhost_umem *); void vhost_dev_cleanup(struct vhost_dev *); void vhost_dev_stop(struct vhost_dev *); long vhost_dev_ioctl(struct vhost_dev *, unsigned int ioctl, void __user *argp); -long vhost_vring_ioctl(struct vhost_dev *d, int ioctl, void __user *argp); +long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp); int vhost_vq_access_ok(struct vhost_virtqueue *vq); int vhost_log_access_ok(struct vhost_dev *); diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c index 0898dbdbf955..34bc3ab40c6d 100644 --- a/drivers/vhost/vsock.c +++ b/drivers/vhost/vsock.c @@ -699,12 +699,23 @@ static long vhost_vsock_dev_ioctl(struct file *f, unsigned int ioctl, } } +#ifdef CONFIG_COMPAT +static long vhost_vsock_dev_compat_ioctl(struct file *f, unsigned int ioctl, + unsigned long arg) +{ + return vhost_vsock_dev_ioctl(f, ioctl, (unsigned long)compat_ptr(arg)); +} +#endif + static const struct file_operations vhost_vsock_fops = { .owner = THIS_MODULE, .open = vhost_vsock_dev_open, .release = vhost_vsock_dev_release, .llseek = noop_llseek, .unlocked_ioctl = vhost_vsock_dev_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = vhost_vsock_dev_compat_ioctl, +#endif }; static struct miscdevice vhost_vsock_misc = { diff --git a/include/uapi/linux/qemu_fw_cfg.h b/include/uapi/linux/qemu_fw_cfg.h new file mode 100644 index 000000000000..e089c0159ec2 --- /dev/null +++ b/include/uapi/linux/qemu_fw_cfg.h @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +#ifndef _LINUX_FW_CFG_H +#define _LINUX_FW_CFG_H + +#include <linux/types.h> + +#define FW_CFG_ACPI_DEVICE_ID "QEMU0002" + +/* selector key values for "well-known" fw_cfg entries */ +#define FW_CFG_SIGNATURE 0x00 +#define FW_CFG_ID 0x01 +#define FW_CFG_UUID 0x02 +#define FW_CFG_RAM_SIZE 0x03 +#define FW_CFG_NOGRAPHIC 0x04 +#define FW_CFG_NB_CPUS 0x05 +#define FW_CFG_MACHINE_ID 0x06 +#define FW_CFG_KERNEL_ADDR 0x07 +#define FW_CFG_KERNEL_SIZE 0x08 +#define FW_CFG_KERNEL_CMDLINE 0x09 +#define FW_CFG_INITRD_ADDR 0x0a +#define FW_CFG_INITRD_SIZE 0x0b +#define FW_CFG_BOOT_DEVICE 0x0c +#define FW_CFG_NUMA 0x0d +#define FW_CFG_BOOT_MENU 0x0e +#define FW_CFG_MAX_CPUS 0x0f +#define FW_CFG_KERNEL_ENTRY 0x10 +#define FW_CFG_KERNEL_DATA 0x11 +#define FW_CFG_INITRD_DATA 0x12 +#define FW_CFG_CMDLINE_ADDR 0x13 +#define FW_CFG_CMDLINE_SIZE 0x14 +#define FW_CFG_CMDLINE_DATA 0x15 +#define FW_CFG_SETUP_ADDR 0x16 +#define FW_CFG_SETUP_SIZE 0x17 +#define FW_CFG_SETUP_DATA 0x18 +#define FW_CFG_FILE_DIR 0x19 + +#define FW_CFG_FILE_FIRST 0x20 +#define FW_CFG_FILE_SLOTS_MIN 0x10 + +#define FW_CFG_WRITE_CHANNEL 0x4000 +#define FW_CFG_ARCH_LOCAL 0x8000 +#define FW_CFG_ENTRY_MASK (~(FW_CFG_WRITE_CHANNEL | FW_CFG_ARCH_LOCAL)) + +#define FW_CFG_INVALID 0xffff + +/* width in bytes of fw_cfg control register */ +#define FW_CFG_CTL_SIZE 0x02 + +/* fw_cfg "file name" is up to 56 characters (including terminating nul) */ +#define FW_CFG_MAX_FILE_PATH 56 + +/* size in bytes of fw_cfg signature */ +#define FW_CFG_SIG_SIZE 4 + +/* FW_CFG_ID bits */ +#define FW_CFG_VERSION 0x01 +#define FW_CFG_VERSION_DMA 0x02 + +/* fw_cfg file directory entry type */ +struct fw_cfg_file { + __be32 size; + __be16 select; + __u16 reserved; + char name[FW_CFG_MAX_FILE_PATH]; +}; + +/* FW_CFG_DMA_CONTROL bits */ +#define FW_CFG_DMA_CTL_ERROR 0x01 +#define FW_CFG_DMA_CTL_READ 0x02 +#define FW_CFG_DMA_CTL_SKIP 0x04 +#define FW_CFG_DMA_CTL_SELECT 0x08 +#define FW_CFG_DMA_CTL_WRITE 0x10 + +#define FW_CFG_DMA_SIGNATURE 0x51454d5520434647ULL /* "QEMU CFG" */ + +/* Control as first field allows for different structures selected by this + * field, which might be useful in the future + */ +struct fw_cfg_dma_access { + __be32 control; + __be32 length; + __be64 address; +}; + +#define FW_CFG_VMCOREINFO_FILENAME "etc/vmcoreinfo" + +#define FW_CFG_VMCOREINFO_FORMAT_NONE 0x0 +#define FW_CFG_VMCOREINFO_FORMAT_ELF 0x1 + +struct fw_cfg_vmcoreinfo { + __le16 host_format; + __le16 guest_format; + __le32 size; + __le64 paddr; +}; + +#endif diff --git a/kernel/crash_core.c b/kernel/crash_core.c index 4f63597c824d..a93590cdd9e1 100644 --- a/kernel/crash_core.c +++ b/kernel/crash_core.c @@ -376,6 +376,7 @@ phys_addr_t __weak paddr_vmcoreinfo_note(void) { return __pa(vmcoreinfo_note); } +EXPORT_SYMBOL(paddr_vmcoreinfo_note); static int __init crash_save_vmcoreinfo_init(void) { diff --git a/tools/virtio/ringtest/ptr_ring.c b/tools/virtio/ringtest/ptr_ring.c index 477899c12c51..2d566fbd236b 100644 --- a/tools/virtio/ringtest/ptr_ring.c +++ b/tools/virtio/ringtest/ptr_ring.c @@ -17,6 +17,8 @@ #define likely(x) (__builtin_expect(!!(x), 1)) #define ALIGN(x, a) (((x) + (a) - 1) / (a) * (a)) #define SIZE_MAX (~(size_t)0) +#define KMALLOC_MAX_SIZE SIZE_MAX +#define BUG_ON(x) assert(x) typedef pthread_spinlock_t spinlock_t; @@ -57,6 +59,9 @@ static void kfree(void *p) free(p); } +#define kvmalloc_array kmalloc_array +#define kvfree kfree + static void spin_lock_init(spinlock_t *lock) { int r = pthread_spin_init(lock, 0); |