diff options
Diffstat (limited to 'drivers/xen')
-rw-r--r-- | drivers/xen/Makefile | 2 | ||||
-rw-r--r-- | drivers/xen/acpi.c | 2 | ||||
-rw-r--r-- | drivers/xen/efi.c | 30 | ||||
-rw-r--r-- | drivers/xen/events/events_fifo.c | 3 | ||||
-rw-r--r-- | drivers/xen/gntdev.c | 205 | ||||
-rw-r--r-- | drivers/xen/grant-table.c | 4 | ||||
-rw-r--r-- | drivers/xen/pcpu.c | 8 | ||||
-rw-r--r-- | drivers/xen/time.c | 88 | ||||
-rw-r--r-- | drivers/xen/tmem.c | 2 | ||||
-rw-r--r-- | drivers/xen/xen-acpi-cpuhotplug.c | 2 | ||||
-rw-r--r-- | drivers/xen/xen-acpi-pad.c | 4 | ||||
-rw-r--r-- | drivers/xen/xen-acpi-processor.c | 8 | ||||
-rw-r--r-- | drivers/xen/xen-scsiback.c | 70 | ||||
-rw-r--r-- | drivers/xen/xenbus/xenbus_comms.c | 8 | ||||
-rw-r--r-- | drivers/xen/xenbus/xenbus_dev_frontend.c | 2 | ||||
-rw-r--r-- | drivers/xen/xenfs/xensyms.c | 4 |
16 files changed, 374 insertions, 68 deletions
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile index aa8a7f71f..9b7a35c9e 100644 --- a/drivers/xen/Makefile +++ b/drivers/xen/Makefile @@ -1,6 +1,6 @@ obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o obj-$(CONFIG_X86) += fallback.o -obj-y += grant-table.o features.o balloon.o manage.o preempt.o +obj-y += grant-table.o features.o balloon.o manage.o preempt.o time.o obj-y += events/ obj-y += xenbus/ diff --git a/drivers/xen/acpi.c b/drivers/xen/acpi.c index 90307c0b6..6893c79fd 100644 --- a/drivers/xen/acpi.c +++ b/drivers/xen/acpi.c @@ -58,7 +58,7 @@ static int xen_acpi_notify_hypervisor_state(u8 sleep_state, bits, val_a, val_b)) return -1; - HYPERVISOR_dom0_op(&op); + HYPERVISOR_platform_op(&op); return 1; } diff --git a/drivers/xen/efi.c b/drivers/xen/efi.c index f745db270..be7e56a33 100644 --- a/drivers/xen/efi.c +++ b/drivers/xen/efi.c @@ -42,7 +42,7 @@ static efi_status_t xen_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) { struct xen_platform_op op = INIT_EFI_OP(get_time); - if (HYPERVISOR_dom0_op(&op) < 0) + if (HYPERVISOR_platform_op(&op) < 0) return EFI_UNSUPPORTED; if (tm) { @@ -67,7 +67,7 @@ static efi_status_t xen_efi_set_time(efi_time_t *tm) BUILD_BUG_ON(sizeof(*tm) != sizeof(efi_data(op).u.set_time)); memcpy(&efi_data(op).u.set_time, tm, sizeof(*tm)); - if (HYPERVISOR_dom0_op(&op) < 0) + if (HYPERVISOR_platform_op(&op) < 0) return EFI_UNSUPPORTED; return efi_data(op).status; @@ -79,7 +79,7 @@ static efi_status_t xen_efi_get_wakeup_time(efi_bool_t *enabled, { struct xen_platform_op op = INIT_EFI_OP(get_wakeup_time); - if (HYPERVISOR_dom0_op(&op) < 0) + if (HYPERVISOR_platform_op(&op) < 0) return EFI_UNSUPPORTED; if (tm) { @@ -108,7 +108,7 @@ static efi_status_t xen_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm) else efi_data(op).misc |= XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY; - if (HYPERVISOR_dom0_op(&op) < 0) + if (HYPERVISOR_platform_op(&op) < 0) return EFI_UNSUPPORTED; return efi_data(op).status; @@ -129,7 +129,7 @@ static efi_status_t xen_efi_get_variable(efi_char16_t *name, efi_data(op).u.get_variable.size = *data_size; set_xen_guest_handle(efi_data(op).u.get_variable.data, data); - if (HYPERVISOR_dom0_op(&op) < 0) + if (HYPERVISOR_platform_op(&op) < 0) return EFI_UNSUPPORTED; *data_size = efi_data(op).u.get_variable.size; @@ -152,7 +152,7 @@ static efi_status_t xen_efi_get_next_variable(unsigned long *name_size, memcpy(&efi_data(op).u.get_next_variable_name.vendor_guid, vendor, sizeof(*vendor)); - if (HYPERVISOR_dom0_op(&op) < 0) + if (HYPERVISOR_platform_op(&op) < 0) return EFI_UNSUPPORTED; *name_size = efi_data(op).u.get_next_variable_name.size; @@ -178,7 +178,7 @@ static efi_status_t xen_efi_set_variable(efi_char16_t *name, efi_data(op).u.set_variable.size = data_size; set_xen_guest_handle(efi_data(op).u.set_variable.data, data); - if (HYPERVISOR_dom0_op(&op) < 0) + if (HYPERVISOR_platform_op(&op) < 0) return EFI_UNSUPPORTED; return efi_data(op).status; @@ -196,7 +196,7 @@ static efi_status_t xen_efi_query_variable_info(u32 attr, efi_data(op).u.query_variable_info.attr = attr; - if (HYPERVISOR_dom0_op(&op) < 0) + if (HYPERVISOR_platform_op(&op) < 0) return EFI_UNSUPPORTED; *storage_space = efi_data(op).u.query_variable_info.max_store_size; @@ -210,7 +210,7 @@ static efi_status_t xen_efi_get_next_high_mono_count(u32 *count) { struct xen_platform_op op = INIT_EFI_OP(get_next_high_monotonic_count); - if (HYPERVISOR_dom0_op(&op) < 0) + if (HYPERVISOR_platform_op(&op) < 0) return EFI_UNSUPPORTED; *count = efi_data(op).misc; @@ -232,7 +232,7 @@ static efi_status_t xen_efi_update_capsule(efi_capsule_header_t **capsules, efi_data(op).u.update_capsule.capsule_count = count; efi_data(op).u.update_capsule.sg_list = sg_list; - if (HYPERVISOR_dom0_op(&op) < 0) + if (HYPERVISOR_platform_op(&op) < 0) return EFI_UNSUPPORTED; return efi_data(op).status; @@ -252,7 +252,7 @@ static efi_status_t xen_efi_query_capsule_caps(efi_capsule_header_t **capsules, capsules); efi_data(op).u.query_capsule_capabilities.capsule_count = count; - if (HYPERVISOR_dom0_op(&op) < 0) + if (HYPERVISOR_platform_op(&op) < 0) return EFI_UNSUPPORTED; *max_size = efi_data(op).u.query_capsule_capabilities.max_capsule_size; @@ -331,7 +331,7 @@ efi_system_table_t __init *xen_efi_probe(void) }; union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info; - if (!xen_initial_domain() || HYPERVISOR_dom0_op(&op) < 0) + if (!xen_initial_domain() || HYPERVISOR_platform_op(&op) < 0) return NULL; /* Here we know that Xen runs on EFI platform. */ @@ -347,7 +347,7 @@ efi_system_table_t __init *xen_efi_probe(void) info->vendor.bufsz = sizeof(vendor); set_xen_guest_handle(info->vendor.name, vendor); - if (HYPERVISOR_dom0_op(&op) == 0) { + if (HYPERVISOR_platform_op(&op) == 0) { efi_systab_xen.fw_vendor = __pa_symbol(vendor); efi_systab_xen.fw_revision = info->vendor.revision; } else @@ -357,14 +357,14 @@ efi_system_table_t __init *xen_efi_probe(void) op.u.firmware_info.type = XEN_FW_EFI_INFO; op.u.firmware_info.index = XEN_FW_EFI_VERSION; - if (HYPERVISOR_dom0_op(&op) == 0) + if (HYPERVISOR_platform_op(&op) == 0) efi_systab_xen.hdr.revision = info->version; op.cmd = XENPF_firmware_info; op.u.firmware_info.type = XEN_FW_EFI_INFO; op.u.firmware_info.index = XEN_FW_EFI_RT_VERSION; - if (HYPERVISOR_dom0_op(&op) == 0) + if (HYPERVISOR_platform_op(&op) == 0) efi.runtime_version = info->version; return &efi_systab_xen; diff --git a/drivers/xen/events/events_fifo.c b/drivers/xen/events/events_fifo.c index 96a1b8da5..eff2b8800 100644 --- a/drivers/xen/events/events_fifo.c +++ b/drivers/xen/events/events_fifo.c @@ -41,6 +41,7 @@ #include <linux/percpu.h> #include <linux/cpu.h> +#include <asm/barrier.h> #include <asm/sync_bitops.h> #include <asm/xen/hypercall.h> #include <asm/xen/hypervisor.h> @@ -296,7 +297,7 @@ static void consume_one_event(unsigned cpu, * control block. */ if (head == 0) { - rmb(); /* Ensure word is up-to-date before reading head. */ + virt_rmb(); /* Ensure word is up-to-date before reading head. */ head = control_block->head[priority]; } diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 1be5dd048..dc495383a 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -518,7 +518,7 @@ static void mn_release(struct mmu_notifier *mn, mutex_unlock(&priv->lock); } -static struct mmu_notifier_ops gntdev_mmu_ops = { +static const struct mmu_notifier_ops gntdev_mmu_ops = { .release = mn_release, .invalidate_page = mn_invl_page, .invalidate_range_start = mn_invl_range_start, @@ -748,6 +748,206 @@ static long gntdev_ioctl_notify(struct gntdev_priv *priv, void __user *u) return rc; } +#define GNTDEV_COPY_BATCH 24 + +struct gntdev_copy_batch { + struct gnttab_copy ops[GNTDEV_COPY_BATCH]; + struct page *pages[GNTDEV_COPY_BATCH]; + s16 __user *status[GNTDEV_COPY_BATCH]; + unsigned int nr_ops; + unsigned int nr_pages; +}; + +static int gntdev_get_page(struct gntdev_copy_batch *batch, void __user *virt, + bool writeable, unsigned long *gfn) +{ + unsigned long addr = (unsigned long)virt; + struct page *page; + unsigned long xen_pfn; + int ret; + + ret = get_user_pages_fast(addr, 1, writeable, &page); + if (ret < 0) + return ret; + + batch->pages[batch->nr_pages++] = page; + + xen_pfn = page_to_xen_pfn(page) + XEN_PFN_DOWN(addr & ~PAGE_MASK); + *gfn = pfn_to_gfn(xen_pfn); + + return 0; +} + +static void gntdev_put_pages(struct gntdev_copy_batch *batch) +{ + unsigned int i; + + for (i = 0; i < batch->nr_pages; i++) + put_page(batch->pages[i]); + batch->nr_pages = 0; +} + +static int gntdev_copy(struct gntdev_copy_batch *batch) +{ + unsigned int i; + + gnttab_batch_copy(batch->ops, batch->nr_ops); + gntdev_put_pages(batch); + + /* + * For each completed op, update the status if the op failed + * and all previous ops for the segment were successful. + */ + for (i = 0; i < batch->nr_ops; i++) { + s16 status = batch->ops[i].status; + s16 old_status; + + if (status == GNTST_okay) + continue; + + if (__get_user(old_status, batch->status[i])) + return -EFAULT; + + if (old_status != GNTST_okay) + continue; + + if (__put_user(status, batch->status[i])) + return -EFAULT; + } + + batch->nr_ops = 0; + return 0; +} + +static int gntdev_grant_copy_seg(struct gntdev_copy_batch *batch, + struct gntdev_grant_copy_segment *seg, + s16 __user *status) +{ + uint16_t copied = 0; + + /* + * Disallow local -> local copies since there is only space in + * batch->pages for one page per-op and this would be a very + * expensive memcpy(). + */ + if (!(seg->flags & (GNTCOPY_source_gref | GNTCOPY_dest_gref))) + return -EINVAL; + + /* Can't cross page if source/dest is a grant ref. */ + if (seg->flags & GNTCOPY_source_gref) { + if (seg->source.foreign.offset + seg->len > XEN_PAGE_SIZE) + return -EINVAL; + } + if (seg->flags & GNTCOPY_dest_gref) { + if (seg->dest.foreign.offset + seg->len > XEN_PAGE_SIZE) + return -EINVAL; + } + + if (put_user(GNTST_okay, status)) + return -EFAULT; + + while (copied < seg->len) { + struct gnttab_copy *op; + void __user *virt; + size_t len, off; + unsigned long gfn; + int ret; + + if (batch->nr_ops >= GNTDEV_COPY_BATCH) { + ret = gntdev_copy(batch); + if (ret < 0) + return ret; + } + + len = seg->len - copied; + + op = &batch->ops[batch->nr_ops]; + op->flags = 0; + + if (seg->flags & GNTCOPY_source_gref) { + op->source.u.ref = seg->source.foreign.ref; + op->source.domid = seg->source.foreign.domid; + op->source.offset = seg->source.foreign.offset + copied; + op->flags |= GNTCOPY_source_gref; + } else { + virt = seg->source.virt + copied; + off = (unsigned long)virt & ~XEN_PAGE_MASK; + len = min(len, (size_t)XEN_PAGE_SIZE - off); + + ret = gntdev_get_page(batch, virt, false, &gfn); + if (ret < 0) + return ret; + + op->source.u.gmfn = gfn; + op->source.domid = DOMID_SELF; + op->source.offset = off; + } + + if (seg->flags & GNTCOPY_dest_gref) { + op->dest.u.ref = seg->dest.foreign.ref; + op->dest.domid = seg->dest.foreign.domid; + op->dest.offset = seg->dest.foreign.offset + copied; + op->flags |= GNTCOPY_dest_gref; + } else { + virt = seg->dest.virt + copied; + off = (unsigned long)virt & ~XEN_PAGE_MASK; + len = min(len, (size_t)XEN_PAGE_SIZE - off); + + ret = gntdev_get_page(batch, virt, true, &gfn); + if (ret < 0) + return ret; + + op->dest.u.gmfn = gfn; + op->dest.domid = DOMID_SELF; + op->dest.offset = off; + } + + op->len = len; + copied += len; + + batch->status[batch->nr_ops] = status; + batch->nr_ops++; + } + + return 0; +} + +static long gntdev_ioctl_grant_copy(struct gntdev_priv *priv, void __user *u) +{ + struct ioctl_gntdev_grant_copy copy; + struct gntdev_copy_batch batch; + unsigned int i; + int ret = 0; + + if (copy_from_user(©, u, sizeof(copy))) + return -EFAULT; + + batch.nr_ops = 0; + batch.nr_pages = 0; + + for (i = 0; i < copy.count; i++) { + struct gntdev_grant_copy_segment seg; + + if (copy_from_user(&seg, ©.segments[i], sizeof(seg))) { + ret = -EFAULT; + goto out; + } + + ret = gntdev_grant_copy_seg(&batch, &seg, ©.segments[i].status); + if (ret < 0) + goto out; + + cond_resched(); + } + if (batch.nr_ops) + ret = gntdev_copy(&batch); + return ret; + + out: + gntdev_put_pages(&batch); + return ret; +} + static long gntdev_ioctl(struct file *flip, unsigned int cmd, unsigned long arg) { @@ -767,6 +967,9 @@ static long gntdev_ioctl(struct file *flip, case IOCTL_GNTDEV_SET_UNMAP_NOTIFY: return gntdev_ioctl_notify(priv, ptr); + case IOCTL_GNTDEV_GRANT_COPY: + return gntdev_ioctl_grant_copy(priv, ptr); + default: pr_debug("priv %p, unknown cmd %x\n", priv, cmd); return -ENOIOCTLCMD; diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index c49f79ed5..effbaf917 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -128,7 +128,7 @@ struct unmap_refs_callback_data { int result; }; -static struct gnttab_ops *gnttab_interface; +static const struct gnttab_ops *gnttab_interface; static int grant_table_version; static int grefs_per_grant_frame; @@ -1013,7 +1013,7 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx) return rc; } -static struct gnttab_ops gnttab_v1_ops = { +static const struct gnttab_ops gnttab_v1_ops = { .map_frames = gnttab_map_frames_v1, .unmap_frames = gnttab_unmap_frames_v1, .update_entry = gnttab_update_entry_v1, diff --git a/drivers/xen/pcpu.c b/drivers/xen/pcpu.c index 49e88f2ce..cdc6daa7a 100644 --- a/drivers/xen/pcpu.c +++ b/drivers/xen/pcpu.c @@ -78,7 +78,7 @@ static int xen_pcpu_down(uint32_t cpu_id) .u.cpu_ol.cpuid = cpu_id, }; - return HYPERVISOR_dom0_op(&op); + return HYPERVISOR_platform_op(&op); } static int xen_pcpu_up(uint32_t cpu_id) @@ -89,7 +89,7 @@ static int xen_pcpu_up(uint32_t cpu_id) .u.cpu_ol.cpuid = cpu_id, }; - return HYPERVISOR_dom0_op(&op); + return HYPERVISOR_platform_op(&op); } static ssize_t show_online(struct device *dev, @@ -277,7 +277,7 @@ static int sync_pcpu(uint32_t cpu, uint32_t *max_cpu) .u.pcpu_info.xen_cpuid = cpu, }; - ret = HYPERVISOR_dom0_op(&op); + ret = HYPERVISOR_platform_op(&op); if (ret) return ret; @@ -364,7 +364,7 @@ int xen_pcpu_id(uint32_t acpi_id) op.cmd = XENPF_get_cpuinfo; while (cpu_id <= max_id) { op.u.pcpu_info.xen_cpuid = cpu_id; - if (HYPERVISOR_dom0_op(&op)) { + if (HYPERVISOR_platform_op(&op)) { cpu_id++; continue; } diff --git a/drivers/xen/time.c b/drivers/xen/time.c new file mode 100644 index 000000000..71078425c --- /dev/null +++ b/drivers/xen/time.c @@ -0,0 +1,88 @@ +/* + * Xen stolen ticks accounting. + */ +#include <linux/kernel.h> +#include <linux/kernel_stat.h> +#include <linux/math64.h> +#include <linux/gfp.h> + +#include <asm/xen/hypervisor.h> +#include <asm/xen/hypercall.h> + +#include <xen/events.h> +#include <xen/features.h> +#include <xen/interface/xen.h> +#include <xen/interface/vcpu.h> +#include <xen/xen-ops.h> + +/* runstate info updated by Xen */ +static DEFINE_PER_CPU(struct vcpu_runstate_info, xen_runstate); + +/* return an consistent snapshot of 64-bit time/counter value */ +static u64 get64(const u64 *p) +{ + u64 ret; + + if (BITS_PER_LONG < 64) { + u32 *p32 = (u32 *)p; + u32 h, l, h2; + + /* + * Read high then low, and then make sure high is + * still the same; this will only loop if low wraps + * and carries into high. + * XXX some clean way to make this endian-proof? + */ + do { + h = READ_ONCE(p32[1]); + l = READ_ONCE(p32[0]); + h2 = READ_ONCE(p32[1]); + } while(h2 != h); + + ret = (((u64)h) << 32) | l; + } else + ret = READ_ONCE(*p); + + return ret; +} + +/* + * Runstate accounting + */ +void xen_get_runstate_snapshot(struct vcpu_runstate_info *res) +{ + u64 state_time; + struct vcpu_runstate_info *state; + + BUG_ON(preemptible()); + + state = this_cpu_ptr(&xen_runstate); + + /* + * The runstate info is always updated by the hypervisor on + * the current CPU, so there's no need to use anything + * stronger than a compiler barrier when fetching it. + */ + do { + state_time = get64(&state->state_entry_time); + *res = READ_ONCE(*state); + } while (get64(&state->state_entry_time) != state_time); +} + +/* return true when a vcpu could run but has no real cpu to run on */ +bool xen_vcpu_stolen(int vcpu) +{ + return per_cpu(xen_runstate, vcpu).state == RUNSTATE_runnable; +} + +void xen_setup_runstate_info(int cpu) +{ + struct vcpu_register_runstate_memory_area area; + + area.addr.v = &per_cpu(xen_runstate, cpu); + + if (HYPERVISOR_vcpu_op(VCPUOP_register_runstate_memory_area, + cpu, &area)) + BUG(); +} + diff --git a/drivers/xen/tmem.c b/drivers/xen/tmem.c index 945fc4327..4ac2ca8a7 100644 --- a/drivers/xen/tmem.c +++ b/drivers/xen/tmem.c @@ -242,7 +242,7 @@ static int tmem_cleancache_init_shared_fs(char *uuid, size_t pagesize) return xen_tmem_new_pool(shared_uuid, TMEM_POOL_SHARED, pagesize); } -static struct cleancache_ops tmem_cleancache_ops = { +static const struct cleancache_ops tmem_cleancache_ops = { .put_page = tmem_cleancache_put_page, .get_page = tmem_cleancache_get_page, .invalidate_page = tmem_cleancache_flush_page, diff --git a/drivers/xen/xen-acpi-cpuhotplug.c b/drivers/xen/xen-acpi-cpuhotplug.c index f4a369429..fdc9e67b8 100644 --- a/drivers/xen/xen-acpi-cpuhotplug.c +++ b/drivers/xen/xen-acpi-cpuhotplug.c @@ -206,7 +206,7 @@ static int xen_hotadd_cpu(struct acpi_processor *pr) op.u.cpu_add.acpi_id = pr->acpi_id; op.u.cpu_add.pxm = pxm; - cpu_id = HYPERVISOR_dom0_op(&op); + cpu_id = HYPERVISOR_platform_op(&op); if (cpu_id < 0) pr_err(PREFIX "Failed to hotadd CPU for acpi_id %d\n", pr->acpi_id); diff --git a/drivers/xen/xen-acpi-pad.c b/drivers/xen/xen-acpi-pad.c index f83b75450..23d1808fe 100644 --- a/drivers/xen/xen-acpi-pad.c +++ b/drivers/xen/xen-acpi-pad.c @@ -36,7 +36,7 @@ static int xen_acpi_pad_idle_cpus(unsigned int idle_nums) op.u.core_parking.type = XEN_CORE_PARKING_SET; op.u.core_parking.idle_nums = idle_nums; - return HYPERVISOR_dom0_op(&op); + return HYPERVISOR_platform_op(&op); } static int xen_acpi_pad_idle_cpus_num(void) @@ -46,7 +46,7 @@ static int xen_acpi_pad_idle_cpus_num(void) op.cmd = XENPF_core_parking; op.u.core_parking.type = XEN_CORE_PARKING_GET; - return HYPERVISOR_dom0_op(&op) + return HYPERVISOR_platform_op(&op) ?: op.u.core_parking.idle_nums; } diff --git a/drivers/xen/xen-acpi-processor.c b/drivers/xen/xen-acpi-processor.c index 70fa43800..076970a54 100644 --- a/drivers/xen/xen-acpi-processor.c +++ b/drivers/xen/xen-acpi-processor.c @@ -116,7 +116,7 @@ static int push_cxx_to_hypervisor(struct acpi_processor *_pr) set_xen_guest_handle(op.u.set_pminfo.power.states, dst_cx_states); if (!no_hypercall) - ret = HYPERVISOR_dom0_op(&op); + ret = HYPERVISOR_platform_op(&op); if (!ret) { pr_debug("ACPI CPU%u - C-states uploaded.\n", _pr->acpi_id); @@ -244,7 +244,7 @@ static int push_pxx_to_hypervisor(struct acpi_processor *_pr) } if (!no_hypercall) - ret = HYPERVISOR_dom0_op(&op); + ret = HYPERVISOR_platform_op(&op); if (!ret) { struct acpi_processor_performance *perf; @@ -302,7 +302,7 @@ static unsigned int __init get_max_acpi_id(void) info = &op.u.pcpu_info; info->xen_cpuid = 0; - ret = HYPERVISOR_dom0_op(&op); + ret = HYPERVISOR_platform_op(&op); if (ret) return NR_CPUS; @@ -310,7 +310,7 @@ static unsigned int __init get_max_acpi_id(void) last_cpu = op.u.pcpu_info.max_present; for (i = 0; i <= last_cpu; i++) { info->xen_cpuid = i; - ret = HYPERVISOR_dom0_op(&op); + ret = HYPERVISOR_platform_op(&op); if (ret) continue; max_acpi_id = max(info->acpi_id, max_acpi_id); diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c index 51387d75c..c46ee1894 100644 --- a/drivers/xen/xen-scsiback.c +++ b/drivers/xen/xen-scsiback.c @@ -849,15 +849,31 @@ static int scsiback_map(struct vscsibk_info *info) } /* + Check for a translation entry being present +*/ +static struct v2p_entry *scsiback_chk_translation_entry( + struct vscsibk_info *info, struct ids_tuple *v) +{ + struct list_head *head = &(info->v2p_entry_lists); + struct v2p_entry *entry; + + list_for_each_entry(entry, head, l) + if ((entry->v.chn == v->chn) && + (entry->v.tgt == v->tgt) && + (entry->v.lun == v->lun)) + return entry; + + return NULL; +} + +/* Add a new translation entry */ static int scsiback_add_translation_entry(struct vscsibk_info *info, char *phy, struct ids_tuple *v) { int err = 0; - struct v2p_entry *entry; struct v2p_entry *new; - struct list_head *head = &(info->v2p_entry_lists); unsigned long flags; char *lunp; unsigned long long unpacked_lun; @@ -917,15 +933,10 @@ static int scsiback_add_translation_entry(struct vscsibk_info *info, spin_lock_irqsave(&info->v2p_lock, flags); /* Check double assignment to identical virtual ID */ - list_for_each_entry(entry, head, l) { - if ((entry->v.chn == v->chn) && - (entry->v.tgt == v->tgt) && - (entry->v.lun == v->lun)) { - pr_warn("Virtual ID is already used. Assignment was not performed.\n"); - err = -EEXIST; - goto out; - } - + if (scsiback_chk_translation_entry(info, v)) { + pr_warn("Virtual ID is already used. Assignment was not performed.\n"); + err = -EEXIST; + goto out; } /* Create a new translation entry and add to the list */ @@ -933,7 +944,7 @@ static int scsiback_add_translation_entry(struct vscsibk_info *info, new->v = *v; new->tpg = tpg; new->lun = unpacked_lun; - list_add_tail(&new->l, head); + list_add_tail(&new->l, &info->v2p_entry_lists); out: spin_unlock_irqrestore(&info->v2p_lock, flags); @@ -956,39 +967,40 @@ static void __scsiback_del_translation_entry(struct v2p_entry *entry) } /* - Delete the translation entry specfied + Delete the translation entry specified */ static int scsiback_del_translation_entry(struct vscsibk_info *info, struct ids_tuple *v) { struct v2p_entry *entry; - struct list_head *head = &(info->v2p_entry_lists); unsigned long flags; + int ret = 0; spin_lock_irqsave(&info->v2p_lock, flags); /* Find out the translation entry specified */ - list_for_each_entry(entry, head, l) { - if ((entry->v.chn == v->chn) && - (entry->v.tgt == v->tgt) && - (entry->v.lun == v->lun)) { - goto found; - } - } - - spin_unlock_irqrestore(&info->v2p_lock, flags); - return 1; - -found: - /* Delete the translation entry specfied */ - __scsiback_del_translation_entry(entry); + entry = scsiback_chk_translation_entry(info, v); + if (entry) + __scsiback_del_translation_entry(entry); + else + ret = -ENOENT; spin_unlock_irqrestore(&info->v2p_lock, flags); - return 0; + return ret; } static void scsiback_do_add_lun(struct vscsibk_info *info, const char *state, char *phy, struct ids_tuple *vir, int try) { + struct v2p_entry *entry; + unsigned long flags; + + if (try) { + spin_lock_irqsave(&info->v2p_lock, flags); + entry = scsiback_chk_translation_entry(info, vir); + spin_unlock_irqrestore(&info->v2p_lock, flags); + if (entry) + return; + } if (!scsiback_add_translation_entry(info, phy, vir)) { if (xenbus_printf(XBT_NIL, info->dev->nodename, state, "%d", XenbusStateInitialised)) { diff --git a/drivers/xen/xenbus/xenbus_comms.c b/drivers/xen/xenbus/xenbus_comms.c index fdb0f339d..ecdecce80 100644 --- a/drivers/xen/xenbus/xenbus_comms.c +++ b/drivers/xen/xenbus/xenbus_comms.c @@ -123,14 +123,14 @@ int xb_write(const void *data, unsigned len) avail = len; /* Must write data /after/ reading the consumer index. */ - mb(); + virt_mb(); memcpy(dst, data, avail); data += avail; len -= avail; /* Other side must not see new producer until data is there. */ - wmb(); + virt_wmb(); intf->req_prod += avail; /* Implies mb(): other side will see the updated producer. */ @@ -180,14 +180,14 @@ int xb_read(void *data, unsigned len) avail = len; /* Must read data /after/ reading the producer index. */ - rmb(); + virt_rmb(); memcpy(data, src, avail); data += avail; len -= avail; /* Other side must not see free space until we've copied out */ - mb(); + virt_mb(); intf->rsp_cons += avail; pr_debug("Finished read of %i bytes (%i to go)\n", avail, len); diff --git a/drivers/xen/xenbus/xenbus_dev_frontend.c b/drivers/xen/xenbus/xenbus_dev_frontend.c index 9433e4651..912b64edb 100644 --- a/drivers/xen/xenbus/xenbus_dev_frontend.c +++ b/drivers/xen/xenbus/xenbus_dev_frontend.c @@ -188,6 +188,8 @@ static int queue_reply(struct list_head *queue, const void *data, size_t len) if (len == 0) return 0; + if (len > XENSTORE_PAYLOAD_MAX) + return -EINVAL; rb = kmalloc(sizeof(*rb) + len, GFP_KERNEL); if (rb == NULL) diff --git a/drivers/xen/xenfs/xensyms.c b/drivers/xen/xenfs/xensyms.c index f8b128567..a03f261b1 100644 --- a/drivers/xen/xenfs/xensyms.c +++ b/drivers/xen/xenfs/xensyms.c @@ -31,7 +31,7 @@ static int xensyms_next_sym(struct xensyms *xs) symnum = symdata->symnum; - ret = HYPERVISOR_dom0_op(&xs->op); + ret = HYPERVISOR_platform_op(&xs->op); if (ret < 0) return ret; @@ -50,7 +50,7 @@ static int xensyms_next_sym(struct xensyms *xs) set_xen_guest_handle(symdata->name, xs->name); symdata->symnum--; /* Rewind */ - ret = HYPERVISOR_dom0_op(&xs->op); + ret = HYPERVISOR_platform_op(&xs->op); if (ret < 0) return ret; } |