On 19/10/2023 16:40, David Woodhouse wrote:
> From: David Woodhouse <dwmw@amazon.co.uk>
>
> On soft reset, the prinary console event channel needs to be rebound to
> the backend port (in the xen-console driver). We could put that into the
> xen-console driver itself, but it's slightly less ugly to keep it within
> the KVM/Xen code, by stashing the backend port# on event channel reset
> and then rebinding in the primary console reset when it has to recreate
> the guest port anyway.
Does Xen re-bind the primary console on EVTCHNOP_reset? That's news to
me. I go check.
Paul
>
> Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
> ---
> hw/i386/kvm/xen_evtchn.c | 9 +++++++++
> hw/i386/kvm/xen_primary_console.c | 29 ++++++++++++++++++++++++++++-
> hw/i386/kvm/xen_primary_console.h | 1 +
> 3 files changed, 38 insertions(+), 1 deletion(-)
>
> diff --git a/hw/i386/kvm/xen_evtchn.c b/hw/i386/kvm/xen_evtchn.c
> index d72dca6591..ce4da6d37a 100644
> --- a/hw/i386/kvm/xen_evtchn.c
> +++ b/hw/i386/kvm/xen_evtchn.c
> @@ -40,6 +40,7 @@
> #include "xen_evtchn.h"
> #include "xen_overlay.h"
> #include "xen_xenstore.h"
> +#include "xen_primary_console.h"
>
> #include "sysemu/kvm.h"
> #include "sysemu/kvm_xen.h"
> @@ -1098,6 +1099,7 @@ int xen_evtchn_soft_reset(void)
> {
> XenEvtchnState *s = xen_evtchn_singleton;
> bool flush_kvm_routes;
> + uint16_t con_port = xen_primary_console_get_port();
> int i;
>
> if (!s) {
> @@ -1108,6 +1110,13 @@ int xen_evtchn_soft_reset(void)
>
> qemu_mutex_lock(&s->port_lock);
>
> + if (con_port) {
> + XenEvtchnPort *p = &s->port_table[con_port];
> + if (p->type == EVTCHNSTAT_interdomain) {
> + xen_primary_console_set_be_port(p->u.interdomain.port);
> + }
> + }
> +
> for (i = 0; i < s->nr_ports; i++) {
> close_port(s, i, &flush_kvm_routes);
> }
> diff --git a/hw/i386/kvm/xen_primary_console.c b/hw/i386/kvm/xen_primary_console.c
> index 0aa1c16ad6..5e6e085ac7 100644
> --- a/hw/i386/kvm/xen_primary_console.c
> +++ b/hw/i386/kvm/xen_primary_console.c
> @@ -112,6 +112,15 @@ uint16_t xen_primary_console_get_port(void)
> return s->guest_port;
> }
>
> +void xen_primary_console_set_be_port(uint16_t port)
> +{
> + XenPrimaryConsoleState *s = xen_primary_console_singleton;
> + if (s) {
> + printf("be port set to %d\n", port);
> + s->be_port = port;
> + }
> +}
> +
> uint64_t xen_primary_console_get_pfn(void)
> {
> XenPrimaryConsoleState *s = xen_primary_console_singleton;
> @@ -142,6 +151,20 @@ static void alloc_guest_port(XenPrimaryConsoleState *s)
> }
> }
>
> +static void rebind_guest_port(XenPrimaryConsoleState *s)
> +{
> + struct evtchn_bind_interdomain inter = {
> + .remote_dom = DOMID_QEMU,
> + .remote_port = s->be_port,
> + };
> +
> + if (!xen_evtchn_bind_interdomain_op(&inter)) {
> + s->guest_port = inter.local_port;
> + }
> +
> + s->be_port = 0;
> +}
> +
> int xen_primary_console_reset(void)
> {
> XenPrimaryConsoleState *s = xen_primary_console_singleton;
> @@ -154,7 +177,11 @@ int xen_primary_console_reset(void)
> xen_overlay_do_map_page(&s->console_page, gpa);
> }
>
> - alloc_guest_port(s);
> + if (s->be_port) {
> + rebind_guest_port(s);
> + } else {
> + alloc_guest_port(s);
> + }
>
> trace_xen_primary_console_reset(s->guest_port);
>
> diff --git a/hw/i386/kvm/xen_primary_console.h b/hw/i386/kvm/xen_primary_console.h
> index dd4922f3f4..7e2989ea0d 100644
> --- a/hw/i386/kvm/xen_primary_console.h
> +++ b/hw/i386/kvm/xen_primary_console.h
> @@ -16,6 +16,7 @@ void xen_primary_console_create(void);
> int xen_primary_console_reset(void);
>
> uint16_t xen_primary_console_get_port(void);
> +void xen_primary_console_set_be_port(uint16_t port);
> uint64_t xen_primary_console_get_pfn(void);
> void *xen_primary_console_get_map(void);
>