Commit 88764e0a authored by Linus Torvalds's avatar Linus Torvalds

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
parents 23c1a60e eb47f712
...@@ -441,10 +441,11 @@ static int xen_cpu_up(unsigned int cpu, struct task_struct *idle) ...@@ -441,10 +441,11 @@ static int xen_cpu_up(unsigned int cpu, struct task_struct *idle)
irq_ctx_init(cpu); irq_ctx_init(cpu);
#else #else
clear_tsk_thread_flag(idle, TIF_FORK); clear_tsk_thread_flag(idle, TIF_FORK);
#endif
per_cpu(kernel_stack, cpu) = per_cpu(kernel_stack, cpu) =
(unsigned long)task_stack_page(idle) - (unsigned long)task_stack_page(idle) -
KERNEL_STACK_OFFSET + THREAD_SIZE; KERNEL_STACK_OFFSET + THREAD_SIZE;
#endif
xen_setup_runstate_info(cpu); xen_setup_runstate_info(cpu);
xen_setup_timer(cpu); xen_setup_timer(cpu);
xen_init_lock_cpu(cpu); xen_init_lock_cpu(cpu);
......
...@@ -274,7 +274,7 @@ void __init xen_init_spinlocks(void) ...@@ -274,7 +274,7 @@ void __init xen_init_spinlocks(void)
printk(KERN_DEBUG "xen: PV spinlocks disabled\n"); printk(KERN_DEBUG "xen: PV spinlocks disabled\n");
return; return;
} }
printk(KERN_DEBUG "xen: PV spinlocks enabled\n");
pv_lock_ops.lock_spinning = PV_CALLEE_SAVE(xen_lock_spinning); pv_lock_ops.lock_spinning = PV_CALLEE_SAVE(xen_lock_spinning);
pv_lock_ops.unlock_kick = xen_unlock_kick; pv_lock_ops.unlock_kick = xen_unlock_kick;
} }
...@@ -290,6 +290,9 @@ static __init int xen_init_spinlocks_jump(void) ...@@ -290,6 +290,9 @@ static __init int xen_init_spinlocks_jump(void)
if (!xen_pvspin) if (!xen_pvspin)
return 0; return 0;
if (!xen_domain())
return 0;
static_key_slow_inc(&paravirt_ticketlocks_enabled); static_key_slow_inc(&paravirt_ticketlocks_enabled);
return 0; return 0;
} }
......
...@@ -75,6 +75,17 @@ ENDPROC(xen_sysexit) ...@@ -75,6 +75,17 @@ ENDPROC(xen_sysexit)
* stack state in whatever form its in, we keep things simple by only * stack state in whatever form its in, we keep things simple by only
* using a single register which is pushed/popped on the stack. * using a single register which is pushed/popped on the stack.
*/ */
.macro POP_FS
1:
popw %fs
.pushsection .fixup, "ax"
2: movw $0, (%esp)
jmp 1b
.popsection
_ASM_EXTABLE(1b,2b)
.endm
ENTRY(xen_iret) ENTRY(xen_iret)
/* test eflags for special cases */ /* test eflags for special cases */
testl $(X86_EFLAGS_VM | XEN_EFLAGS_NMI), 8(%esp) testl $(X86_EFLAGS_VM | XEN_EFLAGS_NMI), 8(%esp)
...@@ -83,15 +94,13 @@ ENTRY(xen_iret) ...@@ -83,15 +94,13 @@ ENTRY(xen_iret)
push %eax push %eax
ESP_OFFSET=4 # bytes pushed onto stack ESP_OFFSET=4 # bytes pushed onto stack
/* /* Store vcpu_info pointer for easy access */
* Store vcpu_info pointer for easy access. Do it this way to
* avoid having to reload %fs
*/
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
GET_THREAD_INFO(%eax) pushw %fs
movl %ss:TI_cpu(%eax), %eax movl $(__KERNEL_PERCPU), %eax
movl %ss:__per_cpu_offset(,%eax,4), %eax movl %eax, %fs
mov %ss:xen_vcpu(%eax), %eax movl %fs:xen_vcpu, %eax
POP_FS
#else #else
movl %ss:xen_vcpu, %eax movl %ss:xen_vcpu, %eax
#endif #endif
......
...@@ -198,10 +198,32 @@ struct shutdown_handler { ...@@ -198,10 +198,32 @@ struct shutdown_handler {
void (*cb)(void); void (*cb)(void);
}; };
static int poweroff_nb(struct notifier_block *cb, unsigned long code, void *unused)
{
switch (code) {
case SYS_DOWN:
case SYS_HALT:
case SYS_POWER_OFF:
shutting_down = SHUTDOWN_POWEROFF;
default:
break;
}
return NOTIFY_DONE;
}
static void do_poweroff(void) static void do_poweroff(void)
{ {
shutting_down = SHUTDOWN_POWEROFF; switch (system_state) {
orderly_poweroff(false); case SYSTEM_BOOTING:
orderly_poweroff(true);
break;
case SYSTEM_RUNNING:
orderly_poweroff(false);
break;
default:
/* Don't do it when we are halting/rebooting. */
pr_info("Ignoring Xen toolstack shutdown.\n");
break;
}
} }
static void do_reboot(void) static void do_reboot(void)
...@@ -307,6 +329,10 @@ static struct xenbus_watch shutdown_watch = { ...@@ -307,6 +329,10 @@ static struct xenbus_watch shutdown_watch = {
.callback = shutdown_handler .callback = shutdown_handler
}; };
static struct notifier_block xen_reboot_nb = {
.notifier_call = poweroff_nb,
};
static int setup_shutdown_watcher(void) static int setup_shutdown_watcher(void)
{ {
int err; int err;
...@@ -317,6 +343,7 @@ static int setup_shutdown_watcher(void) ...@@ -317,6 +343,7 @@ static int setup_shutdown_watcher(void)
return err; return err;
} }
#ifdef CONFIG_MAGIC_SYSRQ #ifdef CONFIG_MAGIC_SYSRQ
err = register_xenbus_watch(&sysrq_watch); err = register_xenbus_watch(&sysrq_watch);
if (err) { if (err) {
...@@ -345,6 +372,7 @@ int xen_setup_shutdown_event(void) ...@@ -345,6 +372,7 @@ int xen_setup_shutdown_event(void)
if (!xen_domain()) if (!xen_domain())
return -ENODEV; return -ENODEV;
register_xenstore_notifier(&xenstore_notifier); register_xenstore_notifier(&xenstore_notifier);
register_reboot_notifier(&xen_reboot_nb);
return 0; return 0;
} }
......
...@@ -217,7 +217,7 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev, ...@@ -217,7 +217,7 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev,
if (result == 0) { if (result == 0) {
for (i = 0; i < op->value; i++) { for (i = 0; i < op->value; i++) {
op->msix_entries[i].entry = entries[i].entry; op->msix_entries[i].entry = entries[i].entry;
if (entries[i].vector) if (entries[i].vector) {
op->msix_entries[i].vector = op->msix_entries[i].vector =
xen_pirq_from_irq(entries[i].vector); xen_pirq_from_irq(entries[i].vector);
if (unlikely(verbose_request)) if (unlikely(verbose_request))
...@@ -225,6 +225,7 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev, ...@@ -225,6 +225,7 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev,
"MSI-X[%d]: %d\n", "MSI-X[%d]: %d\n",
pci_name(dev), i, pci_name(dev), i,
op->msix_entries[i].vector); op->msix_entries[i].vector);
}
} }
} else } else
pr_warn_ratelimited("%s: error enabling MSI-X for guest %u: err %d!\n", pr_warn_ratelimited("%s: error enabling MSI-X for guest %u: err %d!\n",
......
...@@ -137,6 +137,8 @@ static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev, ...@@ -137,6 +137,8 @@ static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev,
/* Publish this device. */ /* Publish this device. */
if (!err) if (!err)
err = publish_cb(pdev, 0, 0, PCI_DEVFN(slot, func), devid); err = publish_cb(pdev, 0, 0, PCI_DEVFN(slot, func), devid);
else
kfree(dev_entry);
out: out:
return err; return err;
......
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
#include <xen/xenbus.h> #include <xen/xenbus.h>
#include <xen/xen.h> #include <xen/xen.h>
#include "xenbus_comms.h" #include "xenbus_comms.h"
#include "xenbus_probe.h"
struct xs_stored_msg { struct xs_stored_msg {
struct list_head list; struct list_head list;
...@@ -139,6 +140,29 @@ static int get_error(const char *errorstring) ...@@ -139,6 +140,29 @@ static int get_error(const char *errorstring)
return xsd_errors[i].errnum; return xsd_errors[i].errnum;
} }
static bool xenbus_ok(void)
{
switch (xen_store_domain_type) {
case XS_LOCAL:
switch (system_state) {
case SYSTEM_POWER_OFF:
case SYSTEM_RESTART:
case SYSTEM_HALT:
return false;
default:
break;
}
return true;
case XS_PV:
case XS_HVM:
/* FIXME: Could check that the remote domain is alive,
* but it is normally initial domain. */
return true;
default:
break;
}
return false;
}
static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len) static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len)
{ {
struct xs_stored_msg *msg; struct xs_stored_msg *msg;
...@@ -148,9 +172,20 @@ static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len) ...@@ -148,9 +172,20 @@ static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len)
while (list_empty(&xs_state.reply_list)) { while (list_empty(&xs_state.reply_list)) {
spin_unlock(&xs_state.reply_lock); spin_unlock(&xs_state.reply_lock);
/* XXX FIXME: Avoid synchronous wait for response here. */ if (xenbus_ok())
wait_event(xs_state.reply_waitq, /* XXX FIXME: Avoid synchronous wait for response here. */
!list_empty(&xs_state.reply_list)); wait_event_timeout(xs_state.reply_waitq,
!list_empty(&xs_state.reply_list),
msecs_to_jiffies(500));
else {
/*
* If we are in the process of being shut-down there is
* no point of trying to contact XenBus - it is either
* killed (xenstored application) or the other domain
* has been killed or is unreachable.
*/
return ERR_PTR(-EIO);
}
spin_lock(&xs_state.reply_lock); spin_lock(&xs_state.reply_lock);
} }
...@@ -215,6 +250,9 @@ void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg) ...@@ -215,6 +250,9 @@ void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg)
mutex_unlock(&xs_state.request_mutex); mutex_unlock(&xs_state.request_mutex);
if (IS_ERR(ret))
return ret;
if ((msg->type == XS_TRANSACTION_END) || if ((msg->type == XS_TRANSACTION_END) ||
((req_msg.type == XS_TRANSACTION_START) && ((req_msg.type == XS_TRANSACTION_START) &&
(msg->type == XS_ERROR))) (msg->type == XS_ERROR)))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment