Commit 9e77d96b authored by Juergen Gross's avatar Juergen Gross Committed by Boris Ostrovsky

xen/events: reset affinity of 2-level event when tearing it down

When creating a new event channel with 2-level events the affinity
needs to be reset initially in order to avoid using an old affinity
from earlier usage of the event channel port. So when tearing an event
channel down reset all affinity bits.

The same applies to the affinity when onlining a vcpu: all old
affinity settings for this vcpu must be reset. As percpu events get
initialized before the percpu event channel hook is called,
resetting of the affinities happens after offlining a vcpu (this is
working, as initial percpu memory is zeroed out).

Cc: stable@vger.kernel.org
Reported-by: default avatarJulien Grall <julien@xen.org>
Signed-off-by: default avatarJuergen Gross <jgross@suse.com>
Reviewed-by: default avatarJulien Grall <jgrall@amazon.com>
Link: https://lore.kernel.org/r/20210306161833.4552-2-jgross@suse.comSigned-off-by: default avatarBoris Ostrovsky <boris.ostrovsky@oracle.com>
parent 88221399
...@@ -47,6 +47,11 @@ static unsigned evtchn_2l_max_channels(void) ...@@ -47,6 +47,11 @@ static unsigned evtchn_2l_max_channels(void)
return EVTCHN_2L_NR_CHANNELS; return EVTCHN_2L_NR_CHANNELS;
} }
static void evtchn_2l_remove(evtchn_port_t evtchn, unsigned int cpu)
{
clear_bit(evtchn, BM(per_cpu(cpu_evtchn_mask, cpu)));
}
static void evtchn_2l_bind_to_cpu(evtchn_port_t evtchn, unsigned int cpu, static void evtchn_2l_bind_to_cpu(evtchn_port_t evtchn, unsigned int cpu,
unsigned int old_cpu) unsigned int old_cpu)
{ {
...@@ -355,9 +360,18 @@ static void evtchn_2l_resume(void) ...@@ -355,9 +360,18 @@ static void evtchn_2l_resume(void)
EVTCHN_2L_NR_CHANNELS/BITS_PER_EVTCHN_WORD); EVTCHN_2L_NR_CHANNELS/BITS_PER_EVTCHN_WORD);
} }
static int evtchn_2l_percpu_deinit(unsigned int cpu)
{
memset(per_cpu(cpu_evtchn_mask, cpu), 0, sizeof(xen_ulong_t) *
EVTCHN_2L_NR_CHANNELS/BITS_PER_EVTCHN_WORD);
return 0;
}
static const struct evtchn_ops evtchn_ops_2l = { static const struct evtchn_ops evtchn_ops_2l = {
.max_channels = evtchn_2l_max_channels, .max_channels = evtchn_2l_max_channels,
.nr_channels = evtchn_2l_max_channels, .nr_channels = evtchn_2l_max_channels,
.remove = evtchn_2l_remove,
.bind_to_cpu = evtchn_2l_bind_to_cpu, .bind_to_cpu = evtchn_2l_bind_to_cpu,
.clear_pending = evtchn_2l_clear_pending, .clear_pending = evtchn_2l_clear_pending,
.set_pending = evtchn_2l_set_pending, .set_pending = evtchn_2l_set_pending,
...@@ -367,6 +381,7 @@ static const struct evtchn_ops evtchn_ops_2l = { ...@@ -367,6 +381,7 @@ static const struct evtchn_ops evtchn_ops_2l = {
.unmask = evtchn_2l_unmask, .unmask = evtchn_2l_unmask,
.handle_events = evtchn_2l_handle_events, .handle_events = evtchn_2l_handle_events,
.resume = evtchn_2l_resume, .resume = evtchn_2l_resume,
.percpu_deinit = evtchn_2l_percpu_deinit,
}; };
void __init xen_evtchn_2l_init(void) void __init xen_evtchn_2l_init(void)
......
...@@ -377,6 +377,7 @@ static int xen_irq_info_pirq_setup(unsigned irq, ...@@ -377,6 +377,7 @@ static int xen_irq_info_pirq_setup(unsigned irq,
static void xen_irq_info_cleanup(struct irq_info *info) static void xen_irq_info_cleanup(struct irq_info *info)
{ {
set_evtchn_to_irq(info->evtchn, -1); set_evtchn_to_irq(info->evtchn, -1);
xen_evtchn_port_remove(info->evtchn, info->cpu);
info->evtchn = 0; info->evtchn = 0;
channels_on_cpu_dec(info); channels_on_cpu_dec(info);
} }
......
...@@ -14,6 +14,7 @@ struct evtchn_ops { ...@@ -14,6 +14,7 @@ struct evtchn_ops {
unsigned (*nr_channels)(void); unsigned (*nr_channels)(void);
int (*setup)(evtchn_port_t port); int (*setup)(evtchn_port_t port);
void (*remove)(evtchn_port_t port, unsigned int cpu);
void (*bind_to_cpu)(evtchn_port_t evtchn, unsigned int cpu, void (*bind_to_cpu)(evtchn_port_t evtchn, unsigned int cpu,
unsigned int old_cpu); unsigned int old_cpu);
...@@ -54,6 +55,13 @@ static inline int xen_evtchn_port_setup(evtchn_port_t evtchn) ...@@ -54,6 +55,13 @@ static inline int xen_evtchn_port_setup(evtchn_port_t evtchn)
return 0; return 0;
} }
static inline void xen_evtchn_port_remove(evtchn_port_t evtchn,
unsigned int cpu)
{
if (evtchn_ops->remove)
evtchn_ops->remove(evtchn, cpu);
}
static inline void xen_evtchn_port_bind_to_cpu(evtchn_port_t evtchn, static inline void xen_evtchn_port_bind_to_cpu(evtchn_port_t evtchn,
unsigned int cpu, unsigned int cpu,
unsigned int old_cpu) unsigned int old_cpu)
......
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