xen: bug fixes for 4.2-rc6
- Revert a fix from 4.2-rc5 that was causing lots of WARNING spam. - Fix a memory leak affecting backends in HVM guests. - Fix PV domU hang with certain configurations. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJVzHsAAAoJEFxbo/MsZsTR9Y0H/2j1PHt29RPcNdgGQ84AH0Wh tw1emL8rMcdhWQnsO7bNmywNNvRNQnU3ZJ8dzoq+5GPikNsbfQzYc7U2pIL4A+gB AAJsNDNzecuq4srk8vNxcmZ7ySvm9w6dccDUex2ge3sNWaq6gzSQvz6FSWiL0Sxg k3JcnemEg6JrYOTWdxKInAORMcRO6rgx9eIsdPUPOpgC5XLg6/mZOqBAWXIksDvs V9uCMqQicaUgBgKFIOSllqH6fcCNooRu3aDwNNj/2mMcJmEvMeBkHmNlQgEm2j5L ubdDyrC5y48TUPJm8i3+W2/AY+kgWzhThcqyVy6LRAAj5RItJFxMf0nMXzIEqlQ= =UgMy -----END PGP SIGNATURE----- Merge tag 'for-linus-4.2-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip Pull xen bug fixes from David Vrabel: - revert a fix from 4.2-rc5 that was causing lots of WARNING spam. - fix a memory leak affecting backends in HVM guests. - fix PV domU hang with certain configurations. * tag 'for-linus-4.2-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip: xen/xenbus: Don't leak memory when unmapping the ring on HVM backend Revert "xen/events/fifo: Handle linked events when closing a port" x86/xen: build "Xen PV" APIC driver for domU as well
This commit is contained in:
commit
6b476e1140
@ -13,13 +13,13 @@ CFLAGS_mmu.o := $(nostackp)
|
|||||||
obj-y := enlighten.o setup.o multicalls.o mmu.o irq.o \
|
obj-y := enlighten.o setup.o multicalls.o mmu.o irq.o \
|
||||||
time.o xen-asm.o xen-asm_$(BITS).o \
|
time.o xen-asm.o xen-asm_$(BITS).o \
|
||||||
grant-table.o suspend.o platform-pci-unplug.o \
|
grant-table.o suspend.o platform-pci-unplug.o \
|
||||||
p2m.o
|
p2m.o apic.o
|
||||||
|
|
||||||
obj-$(CONFIG_EVENT_TRACING) += trace.o
|
obj-$(CONFIG_EVENT_TRACING) += trace.o
|
||||||
|
|
||||||
obj-$(CONFIG_SMP) += smp.o
|
obj-$(CONFIG_SMP) += smp.o
|
||||||
obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o
|
obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o
|
||||||
obj-$(CONFIG_XEN_DEBUG_FS) += debugfs.o
|
obj-$(CONFIG_XEN_DEBUG_FS) += debugfs.o
|
||||||
obj-$(CONFIG_XEN_DOM0) += apic.o vga.o
|
obj-$(CONFIG_XEN_DOM0) += vga.o
|
||||||
obj-$(CONFIG_SWIOTLB_XEN) += pci-swiotlb-xen.o
|
obj-$(CONFIG_SWIOTLB_XEN) += pci-swiotlb-xen.o
|
||||||
obj-$(CONFIG_XEN_EFI) += efi.o
|
obj-$(CONFIG_XEN_EFI) += efi.o
|
||||||
|
@ -101,17 +101,15 @@ struct dom0_vga_console_info;
|
|||||||
|
|
||||||
#ifdef CONFIG_XEN_DOM0
|
#ifdef CONFIG_XEN_DOM0
|
||||||
void __init xen_init_vga(const struct dom0_vga_console_info *, size_t size);
|
void __init xen_init_vga(const struct dom0_vga_console_info *, size_t size);
|
||||||
void __init xen_init_apic(void);
|
|
||||||
#else
|
#else
|
||||||
static inline void __init xen_init_vga(const struct dom0_vga_console_info *info,
|
static inline void __init xen_init_vga(const struct dom0_vga_console_info *info,
|
||||||
size_t size)
|
size_t size)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
static inline void __init xen_init_apic(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void __init xen_init_apic(void);
|
||||||
|
|
||||||
#ifdef CONFIG_XEN_EFI
|
#ifdef CONFIG_XEN_EFI
|
||||||
extern void xen_efi_init(void);
|
extern void xen_efi_init(void);
|
||||||
#else
|
#else
|
||||||
|
@ -452,12 +452,10 @@ static void xen_free_irq(unsigned irq)
|
|||||||
irq_free_desc(irq);
|
irq_free_desc(irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xen_evtchn_close(unsigned int port, unsigned int cpu)
|
static void xen_evtchn_close(unsigned int port)
|
||||||
{
|
{
|
||||||
struct evtchn_close close;
|
struct evtchn_close close;
|
||||||
|
|
||||||
xen_evtchn_op_close(port, cpu);
|
|
||||||
|
|
||||||
close.port = port;
|
close.port = port;
|
||||||
if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
|
if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
|
||||||
BUG();
|
BUG();
|
||||||
@ -546,7 +544,7 @@ out:
|
|||||||
|
|
||||||
err:
|
err:
|
||||||
pr_err("irq%d: Failed to set port to irq mapping (%d)\n", irq, rc);
|
pr_err("irq%d: Failed to set port to irq mapping (%d)\n", irq, rc);
|
||||||
xen_evtchn_close(evtchn, NR_CPUS);
|
xen_evtchn_close(evtchn);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -567,7 +565,7 @@ static void shutdown_pirq(struct irq_data *data)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
mask_evtchn(evtchn);
|
mask_evtchn(evtchn);
|
||||||
xen_evtchn_close(evtchn, cpu_from_evtchn(evtchn));
|
xen_evtchn_close(evtchn);
|
||||||
xen_irq_info_cleanup(info);
|
xen_irq_info_cleanup(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -611,7 +609,7 @@ static void __unbind_from_irq(unsigned int irq)
|
|||||||
if (VALID_EVTCHN(evtchn)) {
|
if (VALID_EVTCHN(evtchn)) {
|
||||||
unsigned int cpu = cpu_from_irq(irq);
|
unsigned int cpu = cpu_from_irq(irq);
|
||||||
|
|
||||||
xen_evtchn_close(evtchn, cpu);
|
xen_evtchn_close(evtchn);
|
||||||
|
|
||||||
switch (type_from_irq(irq)) {
|
switch (type_from_irq(irq)) {
|
||||||
case IRQT_VIRQ:
|
case IRQT_VIRQ:
|
||||||
|
@ -255,12 +255,6 @@ static void evtchn_fifo_unmask(unsigned port)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool evtchn_fifo_is_linked(unsigned port)
|
|
||||||
{
|
|
||||||
event_word_t *word = event_word_from_port(port);
|
|
||||||
return sync_test_bit(EVTCHN_FIFO_BIT(LINKED, word), BM(word));
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t clear_linked(volatile event_word_t *word)
|
static uint32_t clear_linked(volatile event_word_t *word)
|
||||||
{
|
{
|
||||||
event_word_t new, old, w;
|
event_word_t new, old, w;
|
||||||
@ -287,8 +281,7 @@ static void handle_irq_for_port(unsigned port)
|
|||||||
|
|
||||||
static void consume_one_event(unsigned cpu,
|
static void consume_one_event(unsigned cpu,
|
||||||
struct evtchn_fifo_control_block *control_block,
|
struct evtchn_fifo_control_block *control_block,
|
||||||
unsigned priority, unsigned long *ready,
|
unsigned priority, unsigned long *ready)
|
||||||
bool drop)
|
|
||||||
{
|
{
|
||||||
struct evtchn_fifo_queue *q = &per_cpu(cpu_queue, cpu);
|
struct evtchn_fifo_queue *q = &per_cpu(cpu_queue, cpu);
|
||||||
uint32_t head;
|
uint32_t head;
|
||||||
@ -320,15 +313,13 @@ static void consume_one_event(unsigned cpu,
|
|||||||
if (head == 0)
|
if (head == 0)
|
||||||
clear_bit(priority, ready);
|
clear_bit(priority, ready);
|
||||||
|
|
||||||
if (evtchn_fifo_is_pending(port) && !evtchn_fifo_is_masked(port)) {
|
if (evtchn_fifo_is_pending(port) && !evtchn_fifo_is_masked(port))
|
||||||
if (likely(!drop))
|
handle_irq_for_port(port);
|
||||||
handle_irq_for_port(port);
|
|
||||||
}
|
|
||||||
|
|
||||||
q->head[priority] = head;
|
q->head[priority] = head;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __evtchn_fifo_handle_events(unsigned cpu, bool drop)
|
static void evtchn_fifo_handle_events(unsigned cpu)
|
||||||
{
|
{
|
||||||
struct evtchn_fifo_control_block *control_block;
|
struct evtchn_fifo_control_block *control_block;
|
||||||
unsigned long ready;
|
unsigned long ready;
|
||||||
@ -340,16 +331,11 @@ static void __evtchn_fifo_handle_events(unsigned cpu, bool drop)
|
|||||||
|
|
||||||
while (ready) {
|
while (ready) {
|
||||||
q = find_first_bit(&ready, EVTCHN_FIFO_MAX_QUEUES);
|
q = find_first_bit(&ready, EVTCHN_FIFO_MAX_QUEUES);
|
||||||
consume_one_event(cpu, control_block, q, &ready, drop);
|
consume_one_event(cpu, control_block, q, &ready);
|
||||||
ready |= xchg(&control_block->ready, 0);
|
ready |= xchg(&control_block->ready, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void evtchn_fifo_handle_events(unsigned cpu)
|
|
||||||
{
|
|
||||||
__evtchn_fifo_handle_events(cpu, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void evtchn_fifo_resume(void)
|
static void evtchn_fifo_resume(void)
|
||||||
{
|
{
|
||||||
unsigned cpu;
|
unsigned cpu;
|
||||||
@ -385,26 +371,6 @@ static void evtchn_fifo_resume(void)
|
|||||||
event_array_pages = 0;
|
event_array_pages = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void evtchn_fifo_close(unsigned port, unsigned int cpu)
|
|
||||||
{
|
|
||||||
if (cpu == NR_CPUS)
|
|
||||||
return;
|
|
||||||
|
|
||||||
get_online_cpus();
|
|
||||||
if (cpu_online(cpu)) {
|
|
||||||
if (WARN_ON(irqs_disabled()))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
while (evtchn_fifo_is_linked(port))
|
|
||||||
cpu_relax();
|
|
||||||
} else {
|
|
||||||
__evtchn_fifo_handle_events(cpu, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
put_online_cpus();
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct evtchn_ops evtchn_ops_fifo = {
|
static const struct evtchn_ops evtchn_ops_fifo = {
|
||||||
.max_channels = evtchn_fifo_max_channels,
|
.max_channels = evtchn_fifo_max_channels,
|
||||||
.nr_channels = evtchn_fifo_nr_channels,
|
.nr_channels = evtchn_fifo_nr_channels,
|
||||||
@ -418,7 +384,6 @@ static const struct evtchn_ops evtchn_ops_fifo = {
|
|||||||
.unmask = evtchn_fifo_unmask,
|
.unmask = evtchn_fifo_unmask,
|
||||||
.handle_events = evtchn_fifo_handle_events,
|
.handle_events = evtchn_fifo_handle_events,
|
||||||
.resume = evtchn_fifo_resume,
|
.resume = evtchn_fifo_resume,
|
||||||
.close = evtchn_fifo_close,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int evtchn_fifo_alloc_control_block(unsigned cpu)
|
static int evtchn_fifo_alloc_control_block(unsigned cpu)
|
||||||
|
@ -68,7 +68,6 @@ struct evtchn_ops {
|
|||||||
bool (*test_and_set_mask)(unsigned port);
|
bool (*test_and_set_mask)(unsigned port);
|
||||||
void (*mask)(unsigned port);
|
void (*mask)(unsigned port);
|
||||||
void (*unmask)(unsigned port);
|
void (*unmask)(unsigned port);
|
||||||
void (*close)(unsigned port, unsigned cpu);
|
|
||||||
|
|
||||||
void (*handle_events)(unsigned cpu);
|
void (*handle_events)(unsigned cpu);
|
||||||
void (*resume)(void);
|
void (*resume)(void);
|
||||||
@ -146,12 +145,6 @@ static inline void xen_evtchn_resume(void)
|
|||||||
evtchn_ops->resume();
|
evtchn_ops->resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void xen_evtchn_op_close(unsigned port, unsigned cpu)
|
|
||||||
{
|
|
||||||
if (evtchn_ops->close)
|
|
||||||
return evtchn_ops->close(port, cpu);
|
|
||||||
}
|
|
||||||
|
|
||||||
void xen_evtchn_2l_init(void);
|
void xen_evtchn_2l_init(void);
|
||||||
int xen_evtchn_fifo_init(void);
|
int xen_evtchn_fifo_init(void);
|
||||||
|
|
||||||
|
@ -814,8 +814,10 @@ static int xenbus_unmap_ring_vfree_hvm(struct xenbus_device *dev, void *vaddr)
|
|||||||
|
|
||||||
rv = xenbus_unmap_ring(dev, node->handles, node->nr_handles,
|
rv = xenbus_unmap_ring(dev, node->handles, node->nr_handles,
|
||||||
addrs);
|
addrs);
|
||||||
if (!rv)
|
if (!rv) {
|
||||||
vunmap(vaddr);
|
vunmap(vaddr);
|
||||||
|
free_xenballooned_pages(node->nr_handles, node->hvm.pages);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
WARN(1, "Leaking %p, size %u page(s)\n", vaddr,
|
WARN(1, "Leaking %p, size %u page(s)\n", vaddr,
|
||||||
node->nr_handles);
|
node->nr_handles);
|
||||||
|
Loading…
Reference in New Issue
Block a user