/*
 * QEMU Xen emulation: Primary console support
 *
 * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Authors: David Woodhouse <dwmw2@infradead.org>
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
 */

#include "qemu/osdep.h"

#include "qapi/error.h"

#include "hw/sysbus.h"
#include "hw/xen/xen.h"
#include "hw/xen/xen_backend_ops.h"
#include "xen_evtchn.h"
#include "xen_overlay.h"
#include "xen_primary_console.h"

#include "sysemu/kvm.h"
#include "sysemu/kvm_xen.h"

#include "trace.h"

#include "hw/xen/interface/event_channel.h"
#include "hw/xen/interface/grant_table.h"

#define TYPE_XEN_PRIMARY_CONSOLE "xen-primary-console"
OBJECT_DECLARE_SIMPLE_TYPE(XenPrimaryConsoleState, XEN_PRIMARY_CONSOLE)

struct XenPrimaryConsoleState {
    /*< private >*/
    SysBusDevice busdev;
    /*< public >*/

    MemoryRegion console_page;
    void *cp;

    evtchn_port_t guest_port;
    evtchn_port_t be_port;

    struct xengntdev_handle *gt;
    void *granted_xs;
};

struct XenPrimaryConsoleState *xen_primary_console_singleton;

static void xen_primary_console_realize(DeviceState *dev, Error **errp)
{
    XenPrimaryConsoleState *s = XEN_PRIMARY_CONSOLE(dev);

    if (xen_mode != XEN_EMULATE) {
        error_setg(errp, "Xen primary console support is for Xen emulation");
        return;
    }

    memory_region_init_ram(&s->console_page, OBJECT(dev), "xen:console_page",
                           XEN_PAGE_SIZE, &error_abort);
    memory_region_set_enabled(&s->console_page, true);
    s->cp = memory_region_get_ram_ptr(&s->console_page);
    memset(s->cp, 0, XEN_PAGE_SIZE);

    /* We can't map it this early as KVM isn't ready */
    xen_primary_console_singleton = s;
}

static void xen_primary_console_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);

    dc->realize = xen_primary_console_realize;
}

static const TypeInfo xen_primary_console_info = {
    .name          = TYPE_XEN_PRIMARY_CONSOLE,
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(XenPrimaryConsoleState),
    .class_init    = xen_primary_console_class_init,
};


void xen_primary_console_create(void)
{
    DeviceState *dev = sysbus_create_simple(TYPE_XEN_PRIMARY_CONSOLE, -1, NULL);

    trace_xen_primary_console_create();

    xen_primary_console_singleton = XEN_PRIMARY_CONSOLE(dev);

    /*
     * Defer the init (xen_primary_console_reset()) until KVM is set up and the
     * overlay page can be mapped.
     */
}

static void xen_primary_console_register_types(void)
{
    type_register_static(&xen_primary_console_info);
}

type_init(xen_primary_console_register_types)

uint16_t xen_primary_console_get_port(void)
{
    XenPrimaryConsoleState *s = xen_primary_console_singleton;
    if (!s) {
        return 0;
    }
    return s->guest_port;
}

void xen_primary_console_set_be_port(uint16_t port)
{
    XenPrimaryConsoleState *s = xen_primary_console_singleton;
    if (s) {
        s->be_port = port;
    }
}

uint64_t xen_primary_console_get_pfn(void)
{
    XenPrimaryConsoleState *s = xen_primary_console_singleton;
    if (!s) {
        return 0;
    }
    return XEN_SPECIAL_PFN(CONSOLE);
}

void *xen_primary_console_get_map(void)
{
    XenPrimaryConsoleState *s = xen_primary_console_singleton;
    if (!s) {
        return 0;
    }
    return s->cp;
}

static void alloc_guest_port(XenPrimaryConsoleState *s)
{
    struct evtchn_alloc_unbound alloc = {
        .dom = DOMID_SELF,
        .remote_dom = DOMID_QEMU,
    };

    if (!xen_evtchn_alloc_unbound_op(&alloc)) {
        s->guest_port = alloc.port;
    }
}

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;
    if (!s) {
        return 0;
    }

    if (!memory_region_is_mapped(&s->console_page)) {
        uint64_t gpa = XEN_SPECIAL_PFN(CONSOLE) << TARGET_PAGE_BITS;
        xen_overlay_do_map_page(&s->console_page, gpa);
    }

    if (s->be_port) {
        rebind_guest_port(s);
    } else {
        alloc_guest_port(s);
    }

    trace_xen_primary_console_reset(s->guest_port);

    s->gt = qemu_xen_gnttab_open();
    uint32_t xs_gntref = GNTTAB_RESERVED_CONSOLE;
    s->granted_xs = qemu_xen_gnttab_map_refs(s->gt, 1, xen_domid, &xs_gntref,
                                             PROT_READ | PROT_WRITE);

    return 0;
}
