diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-24 12:18:48 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-24 12:18:48 -0500 |
commit | b24e2bdde4af656bb0679a101265ebb8f8735d3c (patch) | |
tree | 4a7bcc9bb7568136615a356dcc237c6f3e7c1cc1 /drivers | |
parent | 84257ce6b798a0eed0b4637694137be941903cf7 (diff) | |
parent | 5054daa285beaf706f051fbd395dc36c9f0f907f (diff) |
Merge tag 'stable/for-linus-4.0-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip
Pull xen bugfixes from David Vrabel:
"Xen regression and bug fixes for 4.0-rc1
- Fix two regressions introduced in 4.0-rc1 affecting PV/PVH guests
in certain configurations.
- Prevent pvscsi frontends bypassing backend checks.
- Allow privcmd hypercalls to be preempted even on kernel with
voluntary preemption. This fixes soft-lockups with long running
toolstack hypercalls (e.g., when creating/destroying large
domains)"
* tag 'stable/for-linus-4.0-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip:
x86/xen: Initialize cr4 shadow for 64-bit PV(H) guests
xen-scsiback: mark pvscsi frontend request consumed only after last read
x86/xen: allow privcmd hypercalls to be preempted
x86/xen: Make sure X2APIC_ENABLE bit of MSR_IA32_APICBASE is not set
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/xen/Makefile | 2 | ||||
-rw-r--r-- | drivers/xen/preempt.c | 44 | ||||
-rw-r--r-- | drivers/xen/privcmd.c | 2 | ||||
-rw-r--r-- | drivers/xen/xen-scsiback.c | 14 |
4 files changed, 53 insertions, 9 deletions
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile index 2140398a2a8c..2ccd3592d41f 100644 --- a/drivers/xen/Makefile +++ b/drivers/xen/Makefile | |||
@@ -2,7 +2,7 @@ ifeq ($(filter y, $(CONFIG_ARM) $(CONFIG_ARM64)),) | |||
2 | obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o | 2 | obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o |
3 | endif | 3 | endif |
4 | obj-$(CONFIG_X86) += fallback.o | 4 | obj-$(CONFIG_X86) += fallback.o |
5 | obj-y += grant-table.o features.o balloon.o manage.o | 5 | obj-y += grant-table.o features.o balloon.o manage.o preempt.o |
6 | obj-y += events/ | 6 | obj-y += events/ |
7 | obj-y += xenbus/ | 7 | obj-y += xenbus/ |
8 | 8 | ||
diff --git a/drivers/xen/preempt.c b/drivers/xen/preempt.c new file mode 100644 index 000000000000..a1800c150839 --- /dev/null +++ b/drivers/xen/preempt.c | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * Preemptible hypercalls | ||
3 | * | ||
4 | * Copyright (C) 2014 Citrix Systems R&D ltd. | ||
5 | * | ||
6 | * This source code is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation; either version 2 of the | ||
9 | * License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/sched.h> | ||
13 | #include <xen/xen-ops.h> | ||
14 | |||
15 | #ifndef CONFIG_PREEMPT | ||
16 | |||
17 | /* | ||
18 | * Some hypercalls issued by the toolstack can take many 10s of | ||
19 | * seconds. Allow tasks running hypercalls via the privcmd driver to | ||
20 | * be voluntarily preempted even if full kernel preemption is | ||
21 | * disabled. | ||
22 | * | ||
23 | * Such preemptible hypercalls are bracketed by | ||
24 | * xen_preemptible_hcall_begin() and xen_preemptible_hcall_end() | ||
25 | * calls. | ||
26 | */ | ||
27 | |||
28 | DEFINE_PER_CPU(bool, xen_in_preemptible_hcall); | ||
29 | EXPORT_SYMBOL_GPL(xen_in_preemptible_hcall); | ||
30 | |||
31 | asmlinkage __visible void xen_maybe_preempt_hcall(void) | ||
32 | { | ||
33 | if (unlikely(__this_cpu_read(xen_in_preemptible_hcall) | ||
34 | && should_resched())) { | ||
35 | /* | ||
36 | * Clear flag as we may be rescheduled on a different | ||
37 | * cpu. | ||
38 | */ | ||
39 | __this_cpu_write(xen_in_preemptible_hcall, false); | ||
40 | _cond_resched(); | ||
41 | __this_cpu_write(xen_in_preemptible_hcall, true); | ||
42 | } | ||
43 | } | ||
44 | #endif /* CONFIG_PREEMPT */ | ||
diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c index 569a13b9e856..59ac71c4a043 100644 --- a/drivers/xen/privcmd.c +++ b/drivers/xen/privcmd.c | |||
@@ -56,10 +56,12 @@ static long privcmd_ioctl_hypercall(void __user *udata) | |||
56 | if (copy_from_user(&hypercall, udata, sizeof(hypercall))) | 56 | if (copy_from_user(&hypercall, udata, sizeof(hypercall))) |
57 | return -EFAULT; | 57 | return -EFAULT; |
58 | 58 | ||
59 | xen_preemptible_hcall_begin(); | ||
59 | ret = privcmd_call(hypercall.op, | 60 | ret = privcmd_call(hypercall.op, |
60 | hypercall.arg[0], hypercall.arg[1], | 61 | hypercall.arg[0], hypercall.arg[1], |
61 | hypercall.arg[2], hypercall.arg[3], | 62 | hypercall.arg[2], hypercall.arg[3], |
62 | hypercall.arg[4]); | 63 | hypercall.arg[4]); |
64 | xen_preemptible_hcall_end(); | ||
63 | 65 | ||
64 | return ret; | 66 | return ret; |
65 | } | 67 | } |
diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c index 61653a03a8f5..9faca6a60bb0 100644 --- a/drivers/xen/xen-scsiback.c +++ b/drivers/xen/xen-scsiback.c | |||
@@ -709,12 +709,11 @@ static int prepare_pending_reqs(struct vscsibk_info *info, | |||
709 | static int scsiback_do_cmd_fn(struct vscsibk_info *info) | 709 | static int scsiback_do_cmd_fn(struct vscsibk_info *info) |
710 | { | 710 | { |
711 | struct vscsiif_back_ring *ring = &info->ring; | 711 | struct vscsiif_back_ring *ring = &info->ring; |
712 | struct vscsiif_request *ring_req; | 712 | struct vscsiif_request ring_req; |
713 | struct vscsibk_pend *pending_req; | 713 | struct vscsibk_pend *pending_req; |
714 | RING_IDX rc, rp; | 714 | RING_IDX rc, rp; |
715 | int err, more_to_do; | 715 | int err, more_to_do; |
716 | uint32_t result; | 716 | uint32_t result; |
717 | uint8_t act; | ||
718 | 717 | ||
719 | rc = ring->req_cons; | 718 | rc = ring->req_cons; |
720 | rp = ring->sring->req_prod; | 719 | rp = ring->sring->req_prod; |
@@ -735,11 +734,10 @@ static int scsiback_do_cmd_fn(struct vscsibk_info *info) | |||
735 | if (!pending_req) | 734 | if (!pending_req) |
736 | return 1; | 735 | return 1; |
737 | 736 | ||
738 | ring_req = RING_GET_REQUEST(ring, rc); | 737 | ring_req = *RING_GET_REQUEST(ring, rc); |
739 | ring->req_cons = ++rc; | 738 | ring->req_cons = ++rc; |
740 | 739 | ||
741 | act = ring_req->act; | 740 | err = prepare_pending_reqs(info, &ring_req, pending_req); |
742 | err = prepare_pending_reqs(info, ring_req, pending_req); | ||
743 | if (err) { | 741 | if (err) { |
744 | switch (err) { | 742 | switch (err) { |
745 | case -ENODEV: | 743 | case -ENODEV: |
@@ -755,9 +753,9 @@ static int scsiback_do_cmd_fn(struct vscsibk_info *info) | |||
755 | return 1; | 753 | return 1; |
756 | } | 754 | } |
757 | 755 | ||
758 | switch (act) { | 756 | switch (ring_req.act) { |
759 | case VSCSIIF_ACT_SCSI_CDB: | 757 | case VSCSIIF_ACT_SCSI_CDB: |
760 | if (scsiback_gnttab_data_map(ring_req, pending_req)) { | 758 | if (scsiback_gnttab_data_map(&ring_req, pending_req)) { |
761 | scsiback_fast_flush_area(pending_req); | 759 | scsiback_fast_flush_area(pending_req); |
762 | scsiback_do_resp_with_sense(NULL, | 760 | scsiback_do_resp_with_sense(NULL, |
763 | DRIVER_ERROR << 24, 0, pending_req); | 761 | DRIVER_ERROR << 24, 0, pending_req); |
@@ -768,7 +766,7 @@ static int scsiback_do_cmd_fn(struct vscsibk_info *info) | |||
768 | break; | 766 | break; |
769 | case VSCSIIF_ACT_SCSI_ABORT: | 767 | case VSCSIIF_ACT_SCSI_ABORT: |
770 | scsiback_device_action(pending_req, TMR_ABORT_TASK, | 768 | scsiback_device_action(pending_req, TMR_ABORT_TASK, |
771 | ring_req->ref_rqid); | 769 | ring_req.ref_rqid); |
772 | break; | 770 | break; |
773 | case VSCSIIF_ACT_SCSI_RESET: | 771 | case VSCSIIF_ACT_SCSI_RESET: |
774 | scsiback_device_action(pending_req, TMR_LUN_RESET, 0); | 772 | scsiback_device_action(pending_req, TMR_LUN_RESET, 0); |