drivers: xen: keep track of missed events on event channels
The current implementation for events channel is using an empty callback for every unbind channel and the interrupt is clearing every event and calling the callback. However in a scenario where a domain fires a notification when another has not yet bind the channel, the event will be missed. To address this limitation, this commit is keeping track of missed event channel notification when the empty callback is used, a function to retrieve and clear the missed event is introduced. Signed-off-by: Luca Fancellu <luca.fancellu@arm.com>
This commit is contained in:
parent
847f68ae10
commit
58efbc6f4f
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 EPAM Systems
|
* Copyright (c) 2021 EPAM Systems
|
||||||
|
* Copyright (c) 2022 Arm Limited (or its affiliates). All rights reserved.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
@ -18,8 +19,15 @@ LOG_MODULE_REGISTER(xen_events);
|
||||||
extern shared_info_t *HYPERVISOR_shared_info;
|
extern shared_info_t *HYPERVISOR_shared_info;
|
||||||
|
|
||||||
static evtchn_handle_t event_channels[EVTCHN_2L_NR_CHANNELS];
|
static evtchn_handle_t event_channels[EVTCHN_2L_NR_CHANNELS];
|
||||||
|
static bool events_missed[EVTCHN_2L_NR_CHANNELS];
|
||||||
|
|
||||||
static void empty_callback(void *data) { }
|
static void empty_callback(void *data)
|
||||||
|
{
|
||||||
|
/* data is the event_channels entry, subtracting the base, it's the port */
|
||||||
|
unsigned int port = (((evtchn_handle_t *)data) - event_channels);
|
||||||
|
|
||||||
|
events_missed[port] = true;
|
||||||
|
}
|
||||||
|
|
||||||
void notify_evtchn(evtchn_port_t port)
|
void notify_evtchn(evtchn_port_t port)
|
||||||
{
|
{
|
||||||
|
@ -60,7 +68,22 @@ int unbind_event_channel(evtchn_port_t port)
|
||||||
__func__, port);
|
__func__, port);
|
||||||
|
|
||||||
event_channels[port].cb = empty_callback;
|
event_channels[port].cb = empty_callback;
|
||||||
event_channels[port].priv = NULL;
|
event_channels[port].priv = &event_channels[port];
|
||||||
|
events_missed[port] = false;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_missed_events(evtchn_port_t port)
|
||||||
|
{
|
||||||
|
__ASSERT(port < EVTCHN_2L_NR_CHANNELS,
|
||||||
|
"%s: trying to get missed event from invalid port #%u\n",
|
||||||
|
__func__, port);
|
||||||
|
|
||||||
|
if (events_missed[port]) {
|
||||||
|
events_missed[port] = false;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -170,7 +193,8 @@ int xen_events_init(void)
|
||||||
/* bind all ports with default callback */
|
/* bind all ports with default callback */
|
||||||
for (i = 0; i < EVTCHN_2L_NR_CHANNELS; i++) {
|
for (i = 0; i < EVTCHN_2L_NR_CHANNELS; i++) {
|
||||||
event_channels[i].cb = empty_callback;
|
event_channels[i].cb = empty_callback;
|
||||||
event_channels[i].priv = NULL;
|
event_channels[i].priv = &event_channels[i];
|
||||||
|
events_missed[i] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
IRQ_CONNECT(DT_IRQ_BY_IDX(DT_INST(0, xen_xen), 0, irq),
|
IRQ_CONNECT(DT_IRQ_BY_IDX(DT_INST(0, xen_xen), 0, irq),
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 EPAM Systems
|
* Copyright (c) 2021 EPAM Systems
|
||||||
|
* Copyright (c) 2022 Arm Limited (or its affiliates). All rights reserved.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
@ -22,6 +23,7 @@ typedef struct event_channel_handle evtchn_handle_t;
|
||||||
void notify_evtchn(evtchn_port_t port);
|
void notify_evtchn(evtchn_port_t port);
|
||||||
int bind_event_channel(evtchn_port_t port, evtchn_cb_t cb, void *data);
|
int bind_event_channel(evtchn_port_t port, evtchn_cb_t cb, void *data);
|
||||||
int unbind_event_channel(evtchn_port_t port);
|
int unbind_event_channel(evtchn_port_t port);
|
||||||
|
int get_missed_events(evtchn_port_t port);
|
||||||
|
|
||||||
int xen_events_init(void);
|
int xen_events_init(void);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue