aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-04-17 13:54:07 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-04-17 13:54:07 -0400
commit88764e0a3ecf655950c4d46b323cf80e2e0ee481 (patch)
tree395682bc8b0071ccf0124c5a7b952c0ca855fef7
parent23c1a60e2e9d7d07f5f686e6413fc92bfb84366f (diff)
parenteb47f71200b7d5b4c8c1f8c75675f592d855aafd (diff)
Merge tag 'stable/for-linus-3.15-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip
Pull Xen fixes from David Vrabel: "Xen regression and bug fixes for 3.15-rc1: - fix completely broken 32-bit PV guests caused by x86 refactoring 32-bit thread_info. - only enable ticketlock slow path on Xen (not bare metal) - fix two bugs with PV guests not shutting down when requested - fix a minor memory leak in xen-pciback error path" * tag 'stable/for-linus-3.15-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip: xen/manage: Poweroff forcefully if user-space is not yet up. xen/xenbus: Avoid synchronous wait on XenBus stalling shutdown/restart. xen/spinlock: Don't enable them unconditionally. xen-pciback: silence an unwanted debug printk xen: fix memory leak in __xen_pcibk_add_pci_dev() x86/xen: Fix 32-bit PV guests's usage of kernel_stack
-rw-r--r--arch/x86/xen/smp.c3
-rw-r--r--arch/x86/xen/spinlock.c5
-rw-r--r--arch/x86/xen/xen-asm_32.S25
-rw-r--r--drivers/xen/manage.c32
-rw-r--r--drivers/xen/xen-pciback/pciback_ops.c3
-rw-r--r--drivers/xen/xen-pciback/vpci.c2
-rw-r--r--drivers/xen/xenbus/xenbus_xs.c44
7 files changed, 98 insertions, 16 deletions
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index a18eadd8bb40..7005974c3ff3 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -441,10 +441,11 @@ static int xen_cpu_up(unsigned int cpu, struct task_struct *idle)
441 irq_ctx_init(cpu); 441 irq_ctx_init(cpu);
442#else 442#else
443 clear_tsk_thread_flag(idle, TIF_FORK); 443 clear_tsk_thread_flag(idle, TIF_FORK);
444#endif
444 per_cpu(kernel_stack, cpu) = 445 per_cpu(kernel_stack, cpu) =
445 (unsigned long)task_stack_page(idle) - 446 (unsigned long)task_stack_page(idle) -
446 KERNEL_STACK_OFFSET + THREAD_SIZE; 447 KERNEL_STACK_OFFSET + THREAD_SIZE;
447#endif 448
448 xen_setup_runstate_info(cpu); 449 xen_setup_runstate_info(cpu);
449 xen_setup_timer(cpu); 450 xen_setup_timer(cpu);
450 xen_init_lock_cpu(cpu); 451 xen_init_lock_cpu(cpu);
diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c
index 4d3acc34a998..0ba5f3b967f0 100644
--- a/arch/x86/xen/spinlock.c
+++ b/arch/x86/xen/spinlock.c
@@ -274,7 +274,7 @@ void __init xen_init_spinlocks(void)
274 printk(KERN_DEBUG "xen: PV spinlocks disabled\n"); 274 printk(KERN_DEBUG "xen: PV spinlocks disabled\n");
275 return; 275 return;
276 } 276 }
277 277 printk(KERN_DEBUG "xen: PV spinlocks enabled\n");
278 pv_lock_ops.lock_spinning = PV_CALLEE_SAVE(xen_lock_spinning); 278 pv_lock_ops.lock_spinning = PV_CALLEE_SAVE(xen_lock_spinning);
279 pv_lock_ops.unlock_kick = xen_unlock_kick; 279 pv_lock_ops.unlock_kick = xen_unlock_kick;
280} 280}
@@ -290,6 +290,9 @@ static __init int xen_init_spinlocks_jump(void)
290 if (!xen_pvspin) 290 if (!xen_pvspin)
291 return 0; 291 return 0;
292 292
293 if (!xen_domain())
294 return 0;
295
293 static_key_slow_inc(&paravirt_ticketlocks_enabled); 296 static_key_slow_inc(&paravirt_ticketlocks_enabled);
294 return 0; 297 return 0;
295} 298}
diff --git a/arch/x86/xen/xen-asm_32.S b/arch/x86/xen/xen-asm_32.S
index 33ca6e42a4ca..fd92a64d748e 100644
--- a/arch/x86/xen/xen-asm_32.S
+++ b/arch/x86/xen/xen-asm_32.S
@@ -75,6 +75,17 @@ ENDPROC(xen_sysexit)
75 * stack state in whatever form its in, we keep things simple by only 75 * stack state in whatever form its in, we keep things simple by only
76 * using a single register which is pushed/popped on the stack. 76 * using a single register which is pushed/popped on the stack.
77 */ 77 */
78
79.macro POP_FS
801:
81 popw %fs
82.pushsection .fixup, "ax"
832: movw $0, (%esp)
84 jmp 1b
85.popsection
86 _ASM_EXTABLE(1b,2b)
87.endm
88
78ENTRY(xen_iret) 89ENTRY(xen_iret)
79 /* test eflags for special cases */ 90 /* test eflags for special cases */
80 testl $(X86_EFLAGS_VM | XEN_EFLAGS_NMI), 8(%esp) 91 testl $(X86_EFLAGS_VM | XEN_EFLAGS_NMI), 8(%esp)
@@ -83,15 +94,13 @@ ENTRY(xen_iret)
83 push %eax 94 push %eax
84 ESP_OFFSET=4 # bytes pushed onto stack 95 ESP_OFFSET=4 # bytes pushed onto stack
85 96
86 /* 97 /* Store vcpu_info pointer for easy access */
87 * Store vcpu_info pointer for easy access. Do it this way to
88 * avoid having to reload %fs
89 */
90#ifdef CONFIG_SMP 98#ifdef CONFIG_SMP
91 GET_THREAD_INFO(%eax) 99 pushw %fs
92 movl %ss:TI_cpu(%eax), %eax 100 movl $(__KERNEL_PERCPU), %eax
93 movl %ss:__per_cpu_offset(,%eax,4), %eax 101 movl %eax, %fs
94 mov %ss:xen_vcpu(%eax), %eax 102 movl %fs:xen_vcpu, %eax
103 POP_FS
95#else 104#else
96 movl %ss:xen_vcpu, %eax 105 movl %ss:xen_vcpu, %eax
97#endif 106#endif
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c
index fc6c94c0b436..32f9236c959f 100644
--- a/drivers/xen/manage.c
+++ b/drivers/xen/manage.c
@@ -198,10 +198,32 @@ struct shutdown_handler {
198 void (*cb)(void); 198 void (*cb)(void);
199}; 199};
200 200
201static int poweroff_nb(struct notifier_block *cb, unsigned long code, void *unused)
202{
203 switch (code) {
204 case SYS_DOWN:
205 case SYS_HALT:
206 case SYS_POWER_OFF:
207 shutting_down = SHUTDOWN_POWEROFF;
208 default:
209 break;
210 }
211 return NOTIFY_DONE;
212}
201static void do_poweroff(void) 213static void do_poweroff(void)
202{ 214{
203 shutting_down = SHUTDOWN_POWEROFF; 215 switch (system_state) {
204 orderly_poweroff(false); 216 case SYSTEM_BOOTING:
217 orderly_poweroff(true);
218 break;
219 case SYSTEM_RUNNING:
220 orderly_poweroff(false);
221 break;
222 default:
223 /* Don't do it when we are halting/rebooting. */
224 pr_info("Ignoring Xen toolstack shutdown.\n");
225 break;
226 }
205} 227}
206 228
207static void do_reboot(void) 229static void do_reboot(void)
@@ -307,6 +329,10 @@ static struct xenbus_watch shutdown_watch = {
307 .callback = shutdown_handler 329 .callback = shutdown_handler
308}; 330};
309 331
332static struct notifier_block xen_reboot_nb = {
333 .notifier_call = poweroff_nb,
334};
335
310static int setup_shutdown_watcher(void) 336static int setup_shutdown_watcher(void)
311{ 337{
312 int err; 338 int err;
@@ -317,6 +343,7 @@ static int setup_shutdown_watcher(void)
317 return err; 343 return err;
318 } 344 }
319 345
346
320#ifdef CONFIG_MAGIC_SYSRQ 347#ifdef CONFIG_MAGIC_SYSRQ
321 err = register_xenbus_watch(&sysrq_watch); 348 err = register_xenbus_watch(&sysrq_watch);
322 if (err) { 349 if (err) {
@@ -345,6 +372,7 @@ int xen_setup_shutdown_event(void)
345 if (!xen_domain()) 372 if (!xen_domain())
346 return -ENODEV; 373 return -ENODEV;
347 register_xenstore_notifier(&xenstore_notifier); 374 register_xenstore_notifier(&xenstore_notifier);
375 register_reboot_notifier(&xen_reboot_nb);
348 376
349 return 0; 377 return 0;
350} 378}
diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c
index 929dd46bb40c..607e41460c0d 100644
--- a/drivers/xen/xen-pciback/pciback_ops.c
+++ b/drivers/xen/xen-pciback/pciback_ops.c
@@ -217,7 +217,7 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev,
217 if (result == 0) { 217 if (result == 0) {
218 for (i = 0; i < op->value; i++) { 218 for (i = 0; i < op->value; i++) {
219 op->msix_entries[i].entry = entries[i].entry; 219 op->msix_entries[i].entry = entries[i].entry;
220 if (entries[i].vector) 220 if (entries[i].vector) {
221 op->msix_entries[i].vector = 221 op->msix_entries[i].vector =
222 xen_pirq_from_irq(entries[i].vector); 222 xen_pirq_from_irq(entries[i].vector);
223 if (unlikely(verbose_request)) 223 if (unlikely(verbose_request))
@@ -225,6 +225,7 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev,
225 "MSI-X[%d]: %d\n", 225 "MSI-X[%d]: %d\n",
226 pci_name(dev), i, 226 pci_name(dev), i,
227 op->msix_entries[i].vector); 227 op->msix_entries[i].vector);
228 }
228 } 229 }
229 } else 230 } else
230 pr_warn_ratelimited("%s: error enabling MSI-X for guest %u: err %d!\n", 231 pr_warn_ratelimited("%s: error enabling MSI-X for guest %u: err %d!\n",
diff --git a/drivers/xen/xen-pciback/vpci.c b/drivers/xen/xen-pciback/vpci.c
index 3165ce361b00..51afff96c515 100644
--- a/drivers/xen/xen-pciback/vpci.c
+++ b/drivers/xen/xen-pciback/vpci.c
@@ -137,6 +137,8 @@ unlock:
137 /* Publish this device. */ 137 /* Publish this device. */
138 if (!err) 138 if (!err)
139 err = publish_cb(pdev, 0, 0, PCI_DEVFN(slot, func), devid); 139 err = publish_cb(pdev, 0, 0, PCI_DEVFN(slot, func), devid);
140 else
141 kfree(dev_entry);
140 142
141out: 143out:
142 return err; 144 return err;
diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c
index b6d5fff43d16..ba804f3d8278 100644
--- a/drivers/xen/xenbus/xenbus_xs.c
+++ b/drivers/xen/xenbus/xenbus_xs.c
@@ -50,6 +50,7 @@
50#include <xen/xenbus.h> 50#include <xen/xenbus.h>
51#include <xen/xen.h> 51#include <xen/xen.h>
52#include "xenbus_comms.h" 52#include "xenbus_comms.h"
53#include "xenbus_probe.h"
53 54
54struct xs_stored_msg { 55struct xs_stored_msg {
55 struct list_head list; 56 struct list_head list;
@@ -139,6 +140,29 @@ static int get_error(const char *errorstring)
139 return xsd_errors[i].errnum; 140 return xsd_errors[i].errnum;
140} 141}
141 142
143static bool xenbus_ok(void)
144{
145 switch (xen_store_domain_type) {
146 case XS_LOCAL:
147 switch (system_state) {
148 case SYSTEM_POWER_OFF:
149 case SYSTEM_RESTART:
150 case SYSTEM_HALT:
151 return false;
152 default:
153 break;
154 }
155 return true;
156 case XS_PV:
157 case XS_HVM:
158 /* FIXME: Could check that the remote domain is alive,
159 * but it is normally initial domain. */
160 return true;
161 default:
162 break;
163 }
164 return false;
165}
142static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len) 166static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len)
143{ 167{
144 struct xs_stored_msg *msg; 168 struct xs_stored_msg *msg;
@@ -148,9 +172,20 @@ static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len)
148 172
149 while (list_empty(&xs_state.reply_list)) { 173 while (list_empty(&xs_state.reply_list)) {
150 spin_unlock(&xs_state.reply_lock); 174 spin_unlock(&xs_state.reply_lock);
151 /* XXX FIXME: Avoid synchronous wait for response here. */ 175 if (xenbus_ok())
152 wait_event(xs_state.reply_waitq, 176 /* XXX FIXME: Avoid synchronous wait for response here. */
153 !list_empty(&xs_state.reply_list)); 177 wait_event_timeout(xs_state.reply_waitq,
178 !list_empty(&xs_state.reply_list),
179 msecs_to_jiffies(500));
180 else {
181 /*
182 * If we are in the process of being shut-down there is
183 * no point of trying to contact XenBus - it is either
184 * killed (xenstored application) or the other domain
185 * has been killed or is unreachable.
186 */
187 return ERR_PTR(-EIO);
188 }
154 spin_lock(&xs_state.reply_lock); 189 spin_lock(&xs_state.reply_lock);
155 } 190 }
156 191
@@ -215,6 +250,9 @@ void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg)
215 250
216 mutex_unlock(&xs_state.request_mutex); 251 mutex_unlock(&xs_state.request_mutex);
217 252
253 if (IS_ERR(ret))
254 return ret;
255
218 if ((msg->type == XS_TRANSACTION_END) || 256 if ((msg->type == XS_TRANSACTION_END) ||
219 ((req_msg.type == XS_TRANSACTION_START) && 257 ((req_msg.type == XS_TRANSACTION_START) &&
220 (msg->type == XS_ERROR))) 258 (msg->type == XS_ERROR)))