@@ -884,6 +884,23 @@ int xc_vcpu_getcontext(xc_interface *xch,
uint32_t domid,
uint32_t vcpu,
vcpu_guest_context_any_t *ctxt);
+/**
+ * This function initializes the vpl011 emulation and returns
+ * the event to be used by the backend for communicating with
+ * the emulation code.
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm domid the domain to get information from
+ * @parm console_domid the domid of the backend console
+ * @parm gfn the guest pfn to be used as the ring buffer
+ * @parm evtchn the event channel to be used for events
+ * @return 0 on success, negative error on failure
+ */
+int xc_dom_vpl011_init(xc_interface *xch,
+ uint32_t domid,
+ uint32_t console_domid,
+ xen_pfn_t gfn,
+ evtchn_port_t *evtchn);
/**
* This function returns information about the XSAVE state of a particular
@@ -343,6 +343,29 @@ int xc_domain_get_guest_width(xc_interface *xch, uint32_t domid,
return 0;
}
+int xc_dom_vpl011_init(xc_interface *xch,
+ uint32_t domid,
+ uint32_t console_domid,
+ xen_pfn_t gfn,
+ evtchn_port_t *evtchn)
+{
+ DECLARE_DOMCTL;
+ int rc = 0;
+
+ domctl.cmd = XEN_DOMCTL_vuart_op;
+ domctl.domain = (domid_t)domid;
+ domctl.u.vuart_op.cmd = XEN_DOMCTL_VUART_OP_INIT_VPL011;
+ domctl.u.vuart_op.console_domid = console_domid;
+ domctl.u.vuart_op.gfn = gfn;
+
+ if ( (rc = do_domctl(xch, &domctl)) < 0 )
+ return rc;
+
+ *evtchn = domctl.u.vuart_op.evtchn;
+
+ return rc;
+}
+
int xc_domain_getinfo(xc_interface *xch,
uint32_t first_domid,
unsigned int max_doms,
@@ -32,6 +32,13 @@ _hidden
int libxl__arch_domain_create(libxl__gc *gc, libxl_domain_config *d_config,
uint32_t domid);
+/* arch specific internal domain creation finish function */
+_hidden
+int libxl__arch_domain_create_finish(libxl__gc *gc,
+ libxl_domain_build_info *info,
+ uint32_t domid,
+ libxl__domain_build_state *state);
+
/* setup arch specific hardware description, i.e. DTB on ARM */
_hidden
int libxl__arch_domain_init_hw_description(libxl__gc *gc,
@@ -106,6 +106,25 @@ int libxl__arch_domain_create(libxl__gc *gc, libxl_domain_config *d_config,
return 0;
}
+int libxl__arch_domain_create_finish(libxl__gc *gc,
+ libxl_domain_build_info *info,
+ uint32_t domid,
+ libxl__domain_build_state *state)
+{
+ int ret = 0;
+
+ if ( info->arch_arm.vuart &&
+ (ret = xc_dom_vpl011_init(CTX->xch,
+ domid,
+ state->console_domid,
+ xc_get_vuart_gfn(),
+ &state->vuart_port)) != 0 ) {
+ LOG(ERROR, "xc_dom_vpl011_init failed\n");
+ }
+
+ return ret;
+}
+
int libxl__arch_extra_memory(libxl__gc *gc,
const libxl_domain_build_info *info,
uint64_t *out)
@@ -587,7 +587,10 @@ retry_transaction:
goto retry_transaction;
xs_introduce_domain(ctx->xsh, domid, state->store_mfn, state->store_port);
free(vm_path);
- return 0;
+
+ rc = libxl__arch_domain_create_finish(gc, info, domid, state);
+
+ return rc;
}
static int set_vnuma_info(libxl__gc *gc, uint32_t domid,
@@ -788,6 +791,7 @@ int libxl__build_pv(libxl__gc *gc, uint32_t domid,
if (xc_dom_translated(dom)) {
state->console_mfn = dom->console_pfn;
state->store_mfn = dom->xenstore_pfn;
+ state->vuart_gfn = dom->vuart_gfn;
} else {
state->console_mfn = xc_dom_p2m(dom, dom->console_pfn);
state->store_mfn = xc_dom_p2m(dom, dom->xenstore_pfn);
@@ -358,6 +358,14 @@ out:
return ret;
}
+int libxl__arch_domain_create_finish(libxl__gc *gc,
+ libxl_domain_build_info *info,
+ uint32_t domid,
+ libxl__domain_build_state *state)
+{
+ return 0;
+}
+
int libxl__arch_extra_memory(libxl__gc *gc,
const libxl_domain_build_info *info,
uint64_t *out)
@@ -665,6 +665,8 @@ fail:
void arch_domain_destroy(struct domain *d)
{
+ domain_vpl011_deinit(d);
+
/* IOMMU page table is shared with P2M, always call
* iommu_domain_destroy() before p2m_teardown().
*/
@@ -5,13 +5,15 @@
*/
#include <xen/types.h>
-#include <xen/lib.h>
+#include <public/domctl.h>
#include <xen/errno.h>
-#include <xen/sched.h>
+#include <xen/guest_access.h>
#include <xen/hypercall.h>
#include <xen/iocap.h>
+#include <xen/lib.h>
+#include <xen/mm.h>
+#include <xen/sched.h>
#include <xsm/xsm.h>
-#include <public/domctl.h>
void arch_get_domain_info(const struct domain *d,
struct xen_domctl_getdomaininfo *info)
@@ -119,6 +121,42 @@ long arch_do_domctl(struct xen_domctl *domctl, struct domain *d,
d->disable_migrate = domctl->u.disable_migrate.disable;
return 0;
+ case XEN_DOMCTL_vuart_op:
+ {
+ int rc;
+ struct xen_domctl_vuart_op *vuart_op = &domctl->u.vuart_op;
+
+ switch(vuart_op->cmd)
+ {
+ case XEN_DOMCTL_VUART_OP_INIT_VPL011:
+
+ if ( !d->creation_finished )
+ {
+ struct vpl011_init_info info;
+
+ info.console_domid = vuart_op->console_domid;
+ info.gfn = _gfn(vuart_op->gfn);
+
+ rc = domain_vpl011_init(d, &info);
+ if ( !rc )
+ {
+ vuart_op->evtchn = info.evtchn;
+ rc = __copy_to_guest(u_domctl, domctl, 1);
+ }
+ }
+ else
+ {
+ rc = - EPERM;
+ }
+ break;
+
+ default:
+ rc = -EINVAL;
+ break;
+ }
+
+ return rc;
+ }
default:
{
int rc;
@@ -36,6 +36,7 @@
#include "grant_table.h"
#include "hvm/save.h"
#include "memory.h"
+#include "event_channel.h"
#define XEN_DOMCTL_INTERFACE_VERSION 0x0000000d
@@ -1138,6 +1139,15 @@ struct xen_domctl_psr_cat_op {
uint32_t target; /* IN */
uint64_t data; /* IN/OUT */
};
+
+struct xen_domctl_vuart_op {
+#define XEN_DOMCTL_VUART_OP_INIT_VPL011 0
+ uint32_t cmd; /* XEN_DOMCTL_VUART_OP_* */
+ uint32_t console_domid; /* IN */
+ xen_pfn_t gfn; /* IN */
+ evtchn_port_t evtchn; /* OUT */
+};
+
typedef struct xen_domctl_psr_cat_op xen_domctl_psr_cat_op_t;
DEFINE_XEN_GUEST_HANDLE(xen_domctl_psr_cat_op_t);
@@ -1218,6 +1228,7 @@ struct xen_domctl {
#define XEN_DOMCTL_monitor_op 77
#define XEN_DOMCTL_psr_cat_op 78
#define XEN_DOMCTL_soft_reset 79
+#define XEN_DOMCTL_vuart_op 80
#define XEN_DOMCTL_gdbsx_guestmemio 1000
#define XEN_DOMCTL_gdbsx_pausevcpu 1001
#define XEN_DOMCTL_gdbsx_unpausevcpu 1002
@@ -1280,6 +1291,7 @@ struct xen_domctl {
struct xen_domctl_psr_cmt_op psr_cmt_op;
struct xen_domctl_monitor_op monitor_op;
struct xen_domctl_psr_cat_op psr_cat_op;
+ struct xen_domctl_vuart_op vuart_op;
uint8_t pad[128];
} u;
};
Add a new domctl API to initialize vpl011. It takes the GFN and console backend domid as input and returns an event channel to be used for sending and receiving events from Xen. Xen will communicate with xenconsole using GFN as the ring buffer and the event channel to transmit and receive pl011 data on the guest domain's behalf. Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org> --- Changes since v3: - Added a new arch specific function libxl__arch_domain_create_finish(), which calls the vpl011 initialization function. For x86 this function does not do anything. - domain_vpl011_init() takes a pointer to a structure which contains all the required information such as console_domid, gfn instead of passing parameters separately. - Dropped a DOMCTL API defined for de-initializing vpl011 as that should be taken care when the domain is destroyed (and not dependent on userspace libraries/applications). Changes since v2: - Replaced the DOMCTL APIs defined for get/set of event channel and GFN with a set of DOMCTL APIs for initializing and de-initializing vpl011 emulation. tools/libxc/include/xenctrl.h | 17 +++++++++++++++++ tools/libxc/xc_domain.c | 23 ++++++++++++++++++++++ tools/libxl/libxl_arch.h | 7 +++++++ tools/libxl/libxl_arm.c | 19 +++++++++++++++++++ tools/libxl/libxl_dom.c | 6 +++++- tools/libxl/libxl_x86.c | 8 ++++++++ xen/arch/arm/domain.c | 2 ++ xen/arch/arm/domctl.c | 44 ++++++++++++++++++++++++++++++++++++++++--- xen/include/public/domctl.h | 12 ++++++++++++ 9 files changed, 134 insertions(+), 4 deletions(-)