head 1.2; access; symbols pkgsrc-2022Q2:1.1.0.16 pkgsrc-2022Q2-base:1.1 pkgsrc-2022Q1:1.1.0.14 pkgsrc-2022Q1-base:1.1 pkgsrc-2021Q4:1.1.0.12 pkgsrc-2021Q4-base:1.1 pkgsrc-2021Q3:1.1.0.10 pkgsrc-2021Q3-base:1.1 pkgsrc-2021Q2:1.1.0.8 pkgsrc-2021Q2-base:1.1 pkgsrc-2021Q1:1.1.0.6 pkgsrc-2021Q1-base:1.1 pkgsrc-2020Q4:1.1.0.4 pkgsrc-2020Q4-base:1.1 pkgsrc-2020Q3:1.1.0.2; locks; strict; comment @# @; 1.2 date 2022.06.28.16.33.25; author bouyer; state dead; branches; next 1.1; commitid lkljtNX5KSYPgPJD; 1.1 date 2020.10.02.13.00.48; author bouyer; state Exp; branches 1.1.2.1; next ; commitid 2MY96Iq2OdtetkqC; 1.1.2.1 date 2020.10.02.13.00.48; author bsiegert; state dead; branches; next 1.1.2.2; commitid 6fMH1kUIpq0AYCqC; 1.1.2.2 date 2020.10.04.20.44.32; author bsiegert; state Exp; branches; next ; commitid 6fMH1kUIpq0AYCqC; desc @@ 1.2 log @Remove xenkernel411 and xenkernel411, they're EOL upstream @ text @$NetBSD: patch-XSA344,v 1.1 2020/10/02 13:00:48 bouyer Exp $ From: Jan Beulich Subject: evtchn: arrange for preemption in evtchn_destroy() Especially closing of fully established interdomain channels can take quite some time, due to the locking involved. Therefore we shouldn't assume we can clean up still active ports all in one go. Besides adding the necessary preemption check, also avoid pointlessly starting from (or now really ending at) 0; 1 is the lowest numbered port which may need closing. Since we're now reducing ->valid_evtchns, free_xen_event_channel(), and (at least to be on the safe side) notify_via_xen_event_channel() need to cope with attempts to close / unbind from / send through already closed (and no longer valid, as per port_is_valid()) ports. This is part of XSA-344. Signed-off-by: Jan Beulich Acked-by: Julien Grall Reviewed-by: Stefano Stabellini --- xen/common/domain.c.orig +++ xen/common/domain.c @@@@ -646,7 +646,6 @@@@ int domain_kill(struct domain *d) if ( d->is_dying != DOMDYING_alive ) return domain_kill(d); d->is_dying = DOMDYING_dying; - evtchn_destroy(d); gnttab_release_mappings(d); tmem_destroy(d->tmem_client); vnuma_destroy(d->vnuma); @@@@ -654,6 +653,9 @@@@ int domain_kill(struct domain *d) d->tmem_client = NULL; /* fallthrough */ case DOMDYING_dying: + rc = evtchn_destroy(d); + if ( rc ) + break; rc = domain_relinquish_resources(d); if ( rc != 0 ) break; --- xen/common/event_channel.c.orig +++ xen/common/event_channel.c @@@@ -1291,7 +1291,16 @@@@ int alloc_unbound_xen_event_channel( void free_xen_event_channel(struct domain *d, int port) { - BUG_ON(!port_is_valid(d, port)); + if ( !port_is_valid(d, port) ) + { + /* + * Make sure ->is_dying is read /after/ ->valid_evtchns, pairing + * with the spin_barrier() and BUG_ON() in evtchn_destroy(). + */ + smp_rmb(); + BUG_ON(!d->is_dying); + return; + } evtchn_close(d, port, 0); } @@@@ -1303,7 +1312,17 @@@@ void notify_via_xen_event_channel(struct struct domain *rd; unsigned long flags; - ASSERT(port_is_valid(ld, lport)); + if ( !port_is_valid(ld, lport) ) + { + /* + * Make sure ->is_dying is read /after/ ->valid_evtchns, pairing + * with the spin_barrier() and BUG_ON() in evtchn_destroy(). + */ + smp_rmb(); + ASSERT(ld->is_dying); + return; + } + lchn = evtchn_from_port(ld, lport); spin_lock_irqsave(&lchn->lock, flags); @@@@ -1375,8 +1394,7 @@@@ int evtchn_init(struct domain *d) return 0; } - -void evtchn_destroy(struct domain *d) +int evtchn_destroy(struct domain *d) { unsigned int i; @@@@ -1385,14 +1403,29 @@@@ void evtchn_destroy(struct domain *d) spin_barrier(&d->event_lock); /* Close all existing event channels. */ - for ( i = 0; port_is_valid(d, i); i++ ) + for ( i = d->valid_evtchns; --i; ) + { evtchn_close(d, i, 0); + /* + * Avoid preempting when called from domain_create()'s error path, + * and don't check too often (choice of frequency is arbitrary). + */ + if ( i && !(i & 0x3f) && d->is_dying != DOMDYING_dead && + hypercall_preempt_check() ) + { + write_atomic(&d->valid_evtchns, i); + return -ERESTART; + } + } + ASSERT(!d->active_evtchns); clear_global_virq_handlers(d); evtchn_fifo_destroy(d); + + return 0; } --- xen/include/xen/sched.h.orig +++ xen/include/xen/sched.h @@@@ -135,7 +135,7 @@@@ struct evtchn } __attribute__((aligned(64))); int evtchn_init(struct domain *d); /* from domain_create */ -void evtchn_destroy(struct domain *d); /* from domain_kill */ +int evtchn_destroy(struct domain *d); /* from domain_kill */ void evtchn_destroy_final(struct domain *d); /* from complete_domain_destroy */ struct waitqueue_vcpu; From: Jan Beulich Subject: evtchn: arrange for preemption in evtchn_reset() Like for evtchn_destroy() looping over all possible event channels to close them can take a significant amount of time. Unlike done there, we can't alter domain properties (i.e. d->valid_evtchns) here. Borrow, in a lightweight form, the paging domctl continuation concept, redirecting the continuations to different sub-ops. Just like there this is to be able to allow for predictable overall results of the involved sub-ops: Racing requests should either complete or be refused. Note that a domain can't interfere with an already started (by a remote domain) reset, due to being paused. It can prevent a remote reset from happening by leaving a reset unfinished, but that's only going to affect itself. This is part of XSA-344. Signed-off-by: Jan Beulich Acked-by: Julien Grall Reviewed-by: Stefano Stabellini --- xen/common/domain.c.orig +++ xen/common/domain.c @@@@ -1105,7 +1105,7 @@@@ void domain_unpause_except_self(struct d domain_unpause(d); } -int domain_soft_reset(struct domain *d) +int domain_soft_reset(struct domain *d, bool resuming) { struct vcpu *v; int rc; @@@@ -1119,7 +1119,7 @@@@ int domain_soft_reset(struct domain *d) } spin_unlock(&d->shutdown_lock); - rc = evtchn_reset(d); + rc = evtchn_reset(d, resuming); if ( rc ) return rc; --- xen/common/domctl.c.orig +++ xen/common/domctl.c @@@@ -648,12 +648,22 @@@@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe } case XEN_DOMCTL_soft_reset: + case XEN_DOMCTL_soft_reset_cont: if ( d == current->domain ) /* no domain_pause() */ { ret = -EINVAL; break; } - ret = domain_soft_reset(d); + ret = domain_soft_reset(d, op->cmd == XEN_DOMCTL_soft_reset_cont); + if ( ret == -ERESTART ) + { + op->cmd = XEN_DOMCTL_soft_reset_cont; + if ( !__copy_field_to_guest(u_domctl, op, cmd) ) + ret = hypercall_create_continuation(__HYPERVISOR_domctl, + "h", u_domctl); + else + ret = -EFAULT; + } break; case XEN_DOMCTL_destroydomain: --- xen/common/event_channel.c.orig +++ xen/common/event_channel.c @@@@ -1051,7 +1051,7 @@@@ int evtchn_unmask(unsigned int port) return 0; } -int evtchn_reset(struct domain *d) +int evtchn_reset(struct domain *d, bool resuming) { unsigned int i; int rc = 0; @@@@ -1059,11 +1059,40 @@@@ int evtchn_reset(struct domain *d) if ( d != current->domain && !d->controller_pause_count ) return -EINVAL; - for ( i = 0; port_is_valid(d, i); i++ ) + spin_lock(&d->event_lock); + + /* + * If we are resuming, then start where we stopped. Otherwise, check + * that a reset operation is not already in progress, and if none is, + * record that this is now the case. + */ + i = resuming ? d->next_evtchn : !d->next_evtchn; + if ( i > d->next_evtchn ) + d->next_evtchn = i; + + spin_unlock(&d->event_lock); + + if ( !i ) + return -EBUSY; + + for ( ; port_is_valid(d, i); i++ ) + { evtchn_close(d, i, 1); + /* NB: Choice of frequency is arbitrary. */ + if ( !(i & 0x3f) && hypercall_preempt_check() ) + { + spin_lock(&d->event_lock); + d->next_evtchn = i; + spin_unlock(&d->event_lock); + return -ERESTART; + } + } + spin_lock(&d->event_lock); + d->next_evtchn = 0; + if ( d->active_evtchns > d->xen_evtchns ) rc = -EAGAIN; else if ( d->evtchn_fifo ) @@@@ -1198,7 +1227,8 @@@@ long do_event_channel_op(int cmd, XEN_GU break; } - case EVTCHNOP_reset: { + case EVTCHNOP_reset: + case EVTCHNOP_reset_cont: { struct evtchn_reset reset; struct domain *d; @@@@ -1211,9 +1241,13 @@@@ long do_event_channel_op(int cmd, XEN_GU rc = xsm_evtchn_reset(XSM_TARGET, current->domain, d); if ( !rc ) - rc = evtchn_reset(d); + rc = evtchn_reset(d, cmd == EVTCHNOP_reset_cont); rcu_unlock_domain(d); + + if ( rc == -ERESTART ) + rc = hypercall_create_continuation(__HYPERVISOR_event_channel_op, + "ih", EVTCHNOP_reset_cont, arg); break; } --- xen/include/public/domctl.h.orig +++ xen/include/public/domctl.h @@@@ -1121,7 +1121,10 @@@@ struct xen_domctl { #define XEN_DOMCTL_iomem_permission 20 #define XEN_DOMCTL_ioport_permission 21 #define XEN_DOMCTL_hypercall_init 22 -#define XEN_DOMCTL_arch_setup 23 /* Obsolete IA64 only */ +#ifdef __XEN__ +/* #define XEN_DOMCTL_arch_setup 23 Obsolete IA64 only */ +#define XEN_DOMCTL_soft_reset_cont 23 +#endif #define XEN_DOMCTL_settimeoffset 24 #define XEN_DOMCTL_getvcpuaffinity 25 #define XEN_DOMCTL_real_mode_area 26 /* Obsolete PPC only */ --- xen/include/public/event_channel.h.orig +++ xen/include/public/event_channel.h @@@@ -74,6 +74,9 @@@@ #define EVTCHNOP_init_control 11 #define EVTCHNOP_expand_array 12 #define EVTCHNOP_set_priority 13 +#ifdef __XEN__ +#define EVTCHNOP_reset_cont 14 +#endif /* ` } */ typedef uint32_t evtchn_port_t; --- xen/include/xen/event.h.orig +++ xen/include/xen/event.h @@@@ -163,7 +163,7 @@@@ void evtchn_check_pollers(struct domain void evtchn_2l_init(struct domain *d); /* Close all event channels and reset to 2-level ABI. */ -int evtchn_reset(struct domain *d); +int evtchn_reset(struct domain *d, bool resuming); /* * Low-level event channel port ops. --- xen/include/xen/sched.h.orig +++ xen/include/xen/sched.h @@@@ -355,6 +355,8 @@@@ struct domain * EVTCHNOP_reset). Read/write access like for active_evtchns. */ unsigned int xen_evtchns; + /* Port to resume from in evtchn_reset(), when in a continuation. */ + unsigned int next_evtchn; spinlock_t event_lock; const struct evtchn_port_ops *evtchn_port_ops; struct evtchn_fifo_domain *evtchn_fifo; @@@@ -608,7 +610,7 @@@@ int domain_shutdown(struct domain *d, u8 void domain_resume(struct domain *d); void domain_pause_for_debugger(void); -int domain_soft_reset(struct domain *d); +int domain_soft_reset(struct domain *d, bool resuming); int vcpu_start_shutdown_deferral(struct vcpu *v); void vcpu_end_shutdown_deferral(struct vcpu *v); @ 1.1 log @dd uptream fixes for XSA333, XSA336, XSA337, XSA338, XSA339, XSA340, XSA342, XSA343, XSA344 bump PKGREVISION @ text @d1 1 a1 1 $NetBSD: $ @ 1.1.2.1 log @file patch-XSA344 was added on branch pkgsrc-2020Q3 on 2020-10-04 20:44:32 +0000 @ text @d1 337 @ 1.1.2.2 log @Pullup ticket #6332 - requested by bouyer sysutils/xenkernel411: security fix sysutils/xenkernel413: security fix Revisions pulled up: - sysutils/xenkernel411/Makefile 1.16 - sysutils/xenkernel411/distinfo 1.14 - sysutils/xenkernel411/patches/patch-XSA333 1.1 - sysutils/xenkernel411/patches/patch-XSA336 1.1 - sysutils/xenkernel411/patches/patch-XSA337 1.1 - sysutils/xenkernel411/patches/patch-XSA338 1.1 - sysutils/xenkernel411/patches/patch-XSA339 1.1 - sysutils/xenkernel411/patches/patch-XSA340 1.1 - sysutils/xenkernel411/patches/patch-XSA342 1.1 - sysutils/xenkernel411/patches/patch-XSA343 1.1 - sysutils/xenkernel411/patches/patch-XSA344 1.1 - sysutils/xenkernel413/Makefile 1.5 - sysutils/xenkernel413/distinfo 1.3 - sysutils/xenkernel413/patches/patch-XSA333 1.1 - sysutils/xenkernel413/patches/patch-XSA334 1.1 - sysutils/xenkernel413/patches/patch-XSA336 1.1 - sysutils/xenkernel413/patches/patch-XSA337 1.1 - sysutils/xenkernel413/patches/patch-XSA338 1.1 - sysutils/xenkernel413/patches/patch-XSA339 1.1 - sysutils/xenkernel413/patches/patch-XSA340 1.1 - sysutils/xenkernel413/patches/patch-XSA342 1.1 - sysutils/xenkernel413/patches/patch-XSA343 1.1 - sysutils/xenkernel413/patches/patch-XSA344 1.1 --- Module Name: pkgsrc Committed By: bouyer Date: Thu Oct 1 12:41:19 UTC 2020 Modified Files: pkgsrc/sysutils/xenkernel413: Makefile distinfo Added Files: pkgsrc/sysutils/xenkernel413/patches: patch-XSA333 patch-XSA334 patch-XSA336 patch-XSA337 patch-XSA338 patch-XSA339 patch-XSA340 patch-XSA342 patch-XSA343 patch-XSA344 Log Message: Add uptream fixes for XSA333, XSA334, XSA336, XSA337, XSA338, XSA339, XSA340, XSA342, XSA343, XSA344 bump PKGREVISION --- Module Name: pkgsrc Committed By: bouyer Date: Fri Oct 2 13:00:48 UTC 2020 Modified Files: pkgsrc/sysutils/xenkernel411: Makefile distinfo Added Files: pkgsrc/sysutils/xenkernel411/patches: patch-XSA333 patch-XSA336 patch-XSA337 patch-XSA338 patch-XSA339 patch-XSA340 patch-XSA342 patch-XSA343 patch-XSA344 Log Message: dd uptream fixes for XSA333, XSA336, XSA337, XSA338, XSA339, XSA340, XSA342, XSA343, XSA344 bump PKGREVISION @ text @a0 337 $NetBSD: patch-XSA344,v 1.1 2020/10/02 13:00:48 bouyer Exp $ From: Jan Beulich Subject: evtchn: arrange for preemption in evtchn_destroy() Especially closing of fully established interdomain channels can take quite some time, due to the locking involved. Therefore we shouldn't assume we can clean up still active ports all in one go. Besides adding the necessary preemption check, also avoid pointlessly starting from (or now really ending at) 0; 1 is the lowest numbered port which may need closing. Since we're now reducing ->valid_evtchns, free_xen_event_channel(), and (at least to be on the safe side) notify_via_xen_event_channel() need to cope with attempts to close / unbind from / send through already closed (and no longer valid, as per port_is_valid()) ports. This is part of XSA-344. Signed-off-by: Jan Beulich Acked-by: Julien Grall Reviewed-by: Stefano Stabellini --- xen/common/domain.c.orig +++ xen/common/domain.c @@@@ -646,7 +646,6 @@@@ int domain_kill(struct domain *d) if ( d->is_dying != DOMDYING_alive ) return domain_kill(d); d->is_dying = DOMDYING_dying; - evtchn_destroy(d); gnttab_release_mappings(d); tmem_destroy(d->tmem_client); vnuma_destroy(d->vnuma); @@@@ -654,6 +653,9 @@@@ int domain_kill(struct domain *d) d->tmem_client = NULL; /* fallthrough */ case DOMDYING_dying: + rc = evtchn_destroy(d); + if ( rc ) + break; rc = domain_relinquish_resources(d); if ( rc != 0 ) break; --- xen/common/event_channel.c.orig +++ xen/common/event_channel.c @@@@ -1291,7 +1291,16 @@@@ int alloc_unbound_xen_event_channel( void free_xen_event_channel(struct domain *d, int port) { - BUG_ON(!port_is_valid(d, port)); + if ( !port_is_valid(d, port) ) + { + /* + * Make sure ->is_dying is read /after/ ->valid_evtchns, pairing + * with the spin_barrier() and BUG_ON() in evtchn_destroy(). + */ + smp_rmb(); + BUG_ON(!d->is_dying); + return; + } evtchn_close(d, port, 0); } @@@@ -1303,7 +1312,17 @@@@ void notify_via_xen_event_channel(struct struct domain *rd; unsigned long flags; - ASSERT(port_is_valid(ld, lport)); + if ( !port_is_valid(ld, lport) ) + { + /* + * Make sure ->is_dying is read /after/ ->valid_evtchns, pairing + * with the spin_barrier() and BUG_ON() in evtchn_destroy(). + */ + smp_rmb(); + ASSERT(ld->is_dying); + return; + } + lchn = evtchn_from_port(ld, lport); spin_lock_irqsave(&lchn->lock, flags); @@@@ -1375,8 +1394,7 @@@@ int evtchn_init(struct domain *d) return 0; } - -void evtchn_destroy(struct domain *d) +int evtchn_destroy(struct domain *d) { unsigned int i; @@@@ -1385,14 +1403,29 @@@@ void evtchn_destroy(struct domain *d) spin_barrier(&d->event_lock); /* Close all existing event channels. */ - for ( i = 0; port_is_valid(d, i); i++ ) + for ( i = d->valid_evtchns; --i; ) + { evtchn_close(d, i, 0); + /* + * Avoid preempting when called from domain_create()'s error path, + * and don't check too often (choice of frequency is arbitrary). + */ + if ( i && !(i & 0x3f) && d->is_dying != DOMDYING_dead && + hypercall_preempt_check() ) + { + write_atomic(&d->valid_evtchns, i); + return -ERESTART; + } + } + ASSERT(!d->active_evtchns); clear_global_virq_handlers(d); evtchn_fifo_destroy(d); + + return 0; } --- xen/include/xen/sched.h.orig +++ xen/include/xen/sched.h @@@@ -135,7 +135,7 @@@@ struct evtchn } __attribute__((aligned(64))); int evtchn_init(struct domain *d); /* from domain_create */ -void evtchn_destroy(struct domain *d); /* from domain_kill */ +int evtchn_destroy(struct domain *d); /* from domain_kill */ void evtchn_destroy_final(struct domain *d); /* from complete_domain_destroy */ struct waitqueue_vcpu; From: Jan Beulich Subject: evtchn: arrange for preemption in evtchn_reset() Like for evtchn_destroy() looping over all possible event channels to close them can take a significant amount of time. Unlike done there, we can't alter domain properties (i.e. d->valid_evtchns) here. Borrow, in a lightweight form, the paging domctl continuation concept, redirecting the continuations to different sub-ops. Just like there this is to be able to allow for predictable overall results of the involved sub-ops: Racing requests should either complete or be refused. Note that a domain can't interfere with an already started (by a remote domain) reset, due to being paused. It can prevent a remote reset from happening by leaving a reset unfinished, but that's only going to affect itself. This is part of XSA-344. Signed-off-by: Jan Beulich Acked-by: Julien Grall Reviewed-by: Stefano Stabellini --- xen/common/domain.c.orig +++ xen/common/domain.c @@@@ -1105,7 +1105,7 @@@@ void domain_unpause_except_self(struct d domain_unpause(d); } -int domain_soft_reset(struct domain *d) +int domain_soft_reset(struct domain *d, bool resuming) { struct vcpu *v; int rc; @@@@ -1119,7 +1119,7 @@@@ int domain_soft_reset(struct domain *d) } spin_unlock(&d->shutdown_lock); - rc = evtchn_reset(d); + rc = evtchn_reset(d, resuming); if ( rc ) return rc; --- xen/common/domctl.c.orig +++ xen/common/domctl.c @@@@ -648,12 +648,22 @@@@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe } case XEN_DOMCTL_soft_reset: + case XEN_DOMCTL_soft_reset_cont: if ( d == current->domain ) /* no domain_pause() */ { ret = -EINVAL; break; } - ret = domain_soft_reset(d); + ret = domain_soft_reset(d, op->cmd == XEN_DOMCTL_soft_reset_cont); + if ( ret == -ERESTART ) + { + op->cmd = XEN_DOMCTL_soft_reset_cont; + if ( !__copy_field_to_guest(u_domctl, op, cmd) ) + ret = hypercall_create_continuation(__HYPERVISOR_domctl, + "h", u_domctl); + else + ret = -EFAULT; + } break; case XEN_DOMCTL_destroydomain: --- xen/common/event_channel.c.orig +++ xen/common/event_channel.c @@@@ -1051,7 +1051,7 @@@@ int evtchn_unmask(unsigned int port) return 0; } -int evtchn_reset(struct domain *d) +int evtchn_reset(struct domain *d, bool resuming) { unsigned int i; int rc = 0; @@@@ -1059,11 +1059,40 @@@@ int evtchn_reset(struct domain *d) if ( d != current->domain && !d->controller_pause_count ) return -EINVAL; - for ( i = 0; port_is_valid(d, i); i++ ) + spin_lock(&d->event_lock); + + /* + * If we are resuming, then start where we stopped. Otherwise, check + * that a reset operation is not already in progress, and if none is, + * record that this is now the case. + */ + i = resuming ? d->next_evtchn : !d->next_evtchn; + if ( i > d->next_evtchn ) + d->next_evtchn = i; + + spin_unlock(&d->event_lock); + + if ( !i ) + return -EBUSY; + + for ( ; port_is_valid(d, i); i++ ) + { evtchn_close(d, i, 1); + /* NB: Choice of frequency is arbitrary. */ + if ( !(i & 0x3f) && hypercall_preempt_check() ) + { + spin_lock(&d->event_lock); + d->next_evtchn = i; + spin_unlock(&d->event_lock); + return -ERESTART; + } + } + spin_lock(&d->event_lock); + d->next_evtchn = 0; + if ( d->active_evtchns > d->xen_evtchns ) rc = -EAGAIN; else if ( d->evtchn_fifo ) @@@@ -1198,7 +1227,8 @@@@ long do_event_channel_op(int cmd, XEN_GU break; } - case EVTCHNOP_reset: { + case EVTCHNOP_reset: + case EVTCHNOP_reset_cont: { struct evtchn_reset reset; struct domain *d; @@@@ -1211,9 +1241,13 @@@@ long do_event_channel_op(int cmd, XEN_GU rc = xsm_evtchn_reset(XSM_TARGET, current->domain, d); if ( !rc ) - rc = evtchn_reset(d); + rc = evtchn_reset(d, cmd == EVTCHNOP_reset_cont); rcu_unlock_domain(d); + + if ( rc == -ERESTART ) + rc = hypercall_create_continuation(__HYPERVISOR_event_channel_op, + "ih", EVTCHNOP_reset_cont, arg); break; } --- xen/include/public/domctl.h.orig +++ xen/include/public/domctl.h @@@@ -1121,7 +1121,10 @@@@ struct xen_domctl { #define XEN_DOMCTL_iomem_permission 20 #define XEN_DOMCTL_ioport_permission 21 #define XEN_DOMCTL_hypercall_init 22 -#define XEN_DOMCTL_arch_setup 23 /* Obsolete IA64 only */ +#ifdef __XEN__ +/* #define XEN_DOMCTL_arch_setup 23 Obsolete IA64 only */ +#define XEN_DOMCTL_soft_reset_cont 23 +#endif #define XEN_DOMCTL_settimeoffset 24 #define XEN_DOMCTL_getvcpuaffinity 25 #define XEN_DOMCTL_real_mode_area 26 /* Obsolete PPC only */ --- xen/include/public/event_channel.h.orig +++ xen/include/public/event_channel.h @@@@ -74,6 +74,9 @@@@ #define EVTCHNOP_init_control 11 #define EVTCHNOP_expand_array 12 #define EVTCHNOP_set_priority 13 +#ifdef __XEN__ +#define EVTCHNOP_reset_cont 14 +#endif /* ` } */ typedef uint32_t evtchn_port_t; --- xen/include/xen/event.h.orig +++ xen/include/xen/event.h @@@@ -163,7 +163,7 @@@@ void evtchn_check_pollers(struct domain void evtchn_2l_init(struct domain *d); /* Close all event channels and reset to 2-level ABI. */ -int evtchn_reset(struct domain *d); +int evtchn_reset(struct domain *d, bool resuming); /* * Low-level event channel port ops. --- xen/include/xen/sched.h.orig +++ xen/include/xen/sched.h @@@@ -355,6 +355,8 @@@@ struct domain * EVTCHNOP_reset). Read/write access like for active_evtchns. */ unsigned int xen_evtchns; + /* Port to resume from in evtchn_reset(), when in a continuation. */ + unsigned int next_evtchn; spinlock_t event_lock; const struct evtchn_port_ops *evtchn_port_ops; struct evtchn_fifo_domain *evtchn_fifo; @@@@ -608,7 +610,7 @@@@ int domain_shutdown(struct domain *d, u8 void domain_resume(struct domain *d); void domain_pause_for_debugger(void); -int domain_soft_reset(struct domain *d); +int domain_soft_reset(struct domain *d, bool resuming); int vcpu_start_shutdown_deferral(struct vcpu *v); void vcpu_end_shutdown_deferral(struct vcpu *v); @