...to control the visibility of the FIFO event channel operations
(EVTCHNOP_init_control, EVTCHNOP_expand_array, and EVTCHNOP_set_priority) to
the guest.
These operations were added to the public header in commit
d2d50c2f308f
("evtchn: add FIFO-based event channel ABI") and the first implementation
appeared in the two subsequent commits:
edc8872aeb4a ("evtchn: implement
EVTCHNOP_set_priority and add the set_priority hook") and
88910061ec61
("evtchn: add FIFO-based event channel hypercalls and port ops"). Prior to
that, a guest issuing those operations would receive a return value of
-ENOSYS (not implemented) from Xen. Guests aware of the FIFO operations but
running on an older (pre-4.4) Xen would fall back to using the 2-level event
channel interface upon seeing this return value.
Unfortunately the uncontrolable appearance of these new operations in Xen 4.4
onwards has implications for hibernation of some Linux guests. During resume
from hibernation, there are two kernels involved: the "boot" kernel and the
"resume" kernel. The guest boot kernel may default to use FIFO operations and
instruct Xen via EVTCHNOP_init_control to switch from 2-level to FIFO. On the
other hand, the resume kernel keeps assuming 2-level, because it was hibernated
on a version of Xen that did not support the FIFO operations.
To maintain compatibility it is necessary to make Xen behave as it did
before the new operations were added and hence the code in this patch ensures
that, if XEN_DOMCTL_CDF_evtchn_fifo is not set, the FIFO event channel
operations will again result in -ENOSYS being returned to the guest.
This patch also adds an extra log line into the 'e' key handler output to
call out which event channel ABI is in use by a domain.
NOTE: To maintain current behavior, until a tool-stack option is added to
control the flag, it is unconditionally set for all domains. A
subsequent patch will introduce such tool-stack control.
Signed-off-by: Paul Durrant <pdurrant@amazon.com>
Signed-off-by: Eslam Elnikety <elnikety@amazon.com>
---
Cc: Ian Jackson <iwj@xenproject.org>
Cc: Wei Liu <wl@xen.org>
Cc: Anthony PERARD <anthony.perard@citrix.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: George Dunlap <george.dunlap@citrix.com>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Julien Grall <julien@xen.org>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Christian Lindig <christian.lindig@citrix.com>
Cc: David Scott <dave@recoil.org>
Cc: Volodymyr Babchuk <Volodymyr_Babchuk@epam.com>
Cc: "Roger Pau Monné" <roger.pau@citrix.com>
v5:
- Flip the sense of the flag from disabling to enabling, as requested by
Andrew
v4:
- New in v4
.max_evtchn_port = b_info->event_channels,
.max_grant_frames = b_info->max_grant_frames,
.max_maptrack_frames = b_info->max_maptrack_frames,
+ .flags = XEN_DOMCTL_CDF_evtchn_fifo,
};
if (info->type != LIBXL_DOMAIN_TYPE_PV) {
| CDF_XS_DOMAIN
| CDF_IOMMU
| CDF_NESTED_VIRT
+ | CDF_EVTCHN_FIFO
type domain_create_iommu_opts =
| IOMMU_NO_SHAREPT
| CDF_XS_DOMAIN
| CDF_IOMMU
| CDF_NESTED_VIRT
+ | CDF_EVTCHN_FIFO
type domain_create_iommu_opts =
| IOMMU_NO_SHAREPT
unsigned int max_vcpus;
/* HVM and HAP must be set. IOMMU may or may not be */
- if ( (config->flags & ~XEN_DOMCTL_CDF_iommu) !=
+ if ( (config->flags &
+ ~(XEN_DOMCTL_CDF_iommu | XEN_DOMCTL_CDF_evtchn_fifo) !=
(XEN_DOMCTL_CDF_hvm | XEN_DOMCTL_CDF_hap) )
{
dprintk(XENLOG_INFO, "Unsupported configuration %#x\n",
struct domain *d;
struct xen_domctl_createdomain d_cfg = {
.arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE,
- .flags = XEN_DOMCTL_CDF_hvm | XEN_DOMCTL_CDF_hap,
+ .flags = XEN_DOMCTL_CDF_hvm | XEN_DOMCTL_CDF_hap |
+ XEN_DOMCTL_CDF_evtchn_fifo,
.max_evtchn_port = -1,
.max_grant_frames = 64,
.max_maptrack_frames = 1024,
struct bootmodule *xen_bootmodule;
struct domain *dom0;
struct xen_domctl_createdomain dom0_cfg = {
- .flags = XEN_DOMCTL_CDF_hvm | XEN_DOMCTL_CDF_hap,
+ .flags = XEN_DOMCTL_CDF_hvm | XEN_DOMCTL_CDF_hap |
+ XEN_DOMCTL_CDF_evtchn_fifo,
.max_evtchn_port = -1,
.max_grant_frames = gnttab_dom0_frames(),
.max_maptrack_frames = -1,
const char *loader)
{
struct xen_domctl_createdomain dom0_cfg = {
- .flags = IS_ENABLED(CONFIG_TBOOT) ? XEN_DOMCTL_CDF_s3_integrity : 0,
+ .flags = XEN_DOMCTL_CDF_evtchn_fifo |
+ (IS_ENABLED(CONFIG_TBOOT) ? XEN_DOMCTL_CDF_s3_integrity : 0),
.max_evtchn_port = -1,
.max_grant_frames = -1,
.max_maptrack_frames = -1,
~(XEN_DOMCTL_CDF_hvm | XEN_DOMCTL_CDF_hap |
XEN_DOMCTL_CDF_s3_integrity | XEN_DOMCTL_CDF_oos_off |
XEN_DOMCTL_CDF_xs_domain | XEN_DOMCTL_CDF_iommu |
- XEN_DOMCTL_CDF_nested_virt) )
+ XEN_DOMCTL_CDF_nested_virt | XEN_DOMCTL_CDF_evtchn_fifo) )
{
dprintk(XENLOG_INFO, "Unknown CDF flags %#x\n", config->flags);
return -EINVAL;
return ret;
}
+static bool is_fifo_op(int cmd)
+{
+ switch ( cmd )
+ {
+ case EVTCHNOP_init_control:
+ case EVTCHNOP_expand_array:
+ case EVTCHNOP_set_priority:
+ return true;
+ default:
+ return false;
+ }
+}
+
long do_event_channel_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
{
long rc;
+ if ( !(current->domain->options & XEN_DOMCTL_CDF_evtchn_fifo) &&
+ is_fifo_op(cmd) )
+ return -ENOSYS;
+
switch ( cmd )
{
case EVTCHNOP_alloc_unbound: {
unsigned int port;
int irq;
- printk("Event channel information for domain %d:\n"
- "Polling vCPUs: {%*pbl}\n"
- " port [p/m/s]\n", d->domain_id, d->max_vcpus, d->poll_mask);
+ printk("Event channel information for %pd:\n", d);
+ printk("ABI: %s\n", d->evtchn_fifo ? "FIFO" : "2-level");
+ printk("Polling vCPUs: {%*pbl}\n"
+ " port [p/m/s]\n", d->max_vcpus, d->poll_mask);
spin_lock(&d->event_lock);
#define XEN_DOMCTL_CDF_iommu (1U<<_XEN_DOMCTL_CDF_iommu)
#define _XEN_DOMCTL_CDF_nested_virt 6
#define XEN_DOMCTL_CDF_nested_virt (1U << _XEN_DOMCTL_CDF_nested_virt)
+#define _XEN_DOMCTL_CDF_evtchn_fifo 7
+#define XEN_DOMCTL_CDF_evtchn_fifo (1U << _XEN_DOMCTL_CDF_evtchn_fifo)
/* Max XEN_DOMCTL_CDF_* constant. Used for ABI checking. */
-#define XEN_DOMCTL_CDF_MAX XEN_DOMCTL_CDF_nested_virt
+#define XEN_DOMCTL_CDF_MAX XEN_DOMCTL_CDF_evtchn_fifo
uint32_t flags;