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. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) iQEcBAABAgAGBQJTT/hQAAoJEFxbo/MsZsTR6sMIAJs7mJXSqDQn3Z8O+TemRa53 p92ZomTNYALjUMglXcxJ2Zua6IsZMWdu7jcV1GoXC70V4YLmUs8KaBgZmI5ayUQy bBpK+6WIAJyBkJdNH5fK3wggJ2UZjw0/twPNgd9gACwjUiYhx8iHN/hTGvu4qPBJ MGAIlg6wdnGwRydi72uk9Am/xpebEdQy4DRD20vjwA/qUkT4uHVv/AA4hc4AK29w ToK8qFSisgAlahcmq8/T4+OBFEKz78b9dQcdsGWyAk0ofWILfwD1l53xhzUin25s JUVevWhhLCKRZBOq4Ykc5qyqnLff4m56rm/THQ6f0oRdJn/OR+SWOImda2Qqmvs= =Gxpq -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
88764e0a3e
7 changed files with 98 additions and 16 deletions
|
@ -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)
|
||||||
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)
|
||||||
if (!xen_pvspin)
|
if (!xen_pvspin)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (!xen_domain())
|
||||||
|
return 0;
|
||||||
|
|
||||||
static_key_slow_inc(¶virt_ticketlocks_enabled);
|
static_key_slow_inc(¶virt_ticketlocks_enabled);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
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 {
|
||||||
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 = {
|
||||||
.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)
|
||||||
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)
|
||||||
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,
|
||||||
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,
|
||||||
"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 @@ unlock:
|
||||||
/* 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 @@
|
||||||
#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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
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)))
|
||||||
|
|
Loading…
Reference in a new issue