@@ -2549,8 +2549,18 @@ libxl_device_pci *libxl_device_pci_list(libxl_ctx *ctx, uint32_t domid,
void libxl_device_pci_list_free(libxl_device_pci* list, int num);
#if defined(__arm__) || defined(__aarch64__)
+/* Values should keep consistent with the op from XEN_SYSCTL_dt_overlay */
+#define LIBXL_DT_OVERLAY_ADD 1
+#define LIBXL_DT_OVERLAY_REMOVE 2
int libxl_dt_overlay(libxl_ctx *ctx, void *overlay,
uint32_t overlay_size, uint8_t overlay_op);
+
+/* Values should keep consistent with the op from XEN_DOMCTL_dt_overlay */
+#define LIBXL_DT_OVERLAY_DOMAIN_ATTACH 1
+#define LIBXL_DT_OVERLAY_DOMAIN_DETACH 2
+int libxl_dt_overlay_domain(libxl_ctx *ctx, uint32_t domain_id,
+ void *overlay_dt, uint32_t overlay_dt_size,
+ uint8_t overlay_op);
#endif
/*
@@ -2657,6 +2657,9 @@ int xc_domain_cacheflush(xc_interface *xch, uint32_t domid,
#if defined(__arm__) || defined(__aarch64__)
int xc_dt_overlay(xc_interface *xch, void *overlay_fdt,
uint32_t overlay_fdt_size, uint8_t overlay_op);
+int xc_dt_overlay_domain(xc_interface *xch, void *overlay_fdt,
+ uint32_t overlay_fdt_size, uint8_t overlay_op,
+ uint32_t domain_id);
#endif
/* Compat shims */
@@ -48,3 +48,34 @@ err:
return err;
}
+
+int xc_dt_overlay_domain(xc_interface *xch, void *overlay_fdt,
+ uint32_t overlay_fdt_size, uint8_t overlay_op,
+ uint32_t domain_id)
+{
+ int err;
+ struct xen_domctl domctl = {
+ .cmd = XEN_DOMCTL_dt_overlay,
+ .domain = domain_id,
+ .u.dt_overlay = {
+ .overlay_op = overlay_op,
+ .overlay_fdt_size = overlay_fdt_size,
+ }
+ };
+
+ DECLARE_HYPERCALL_BOUNCE(overlay_fdt, overlay_fdt_size,
+ XC_HYPERCALL_BUFFER_BOUNCE_IN);
+
+ if ( (err = xc_hypercall_bounce_pre(xch, overlay_fdt)) )
+ goto err;
+
+ set_xen_guest_handle(domctl.u.dt_overlay.overlay_fdt, overlay_fdt);
+
+ if ( (err = do_domctl(xch, &domctl)) != 0 )
+ PERROR("%s failed", __func__);
+
+err:
+ xc_hypercall_bounce_post(xch, overlay_fdt);
+
+ return err;
+}
@@ -69,3 +69,31 @@ out:
return rc;
}
+int libxl_dt_overlay_domain(libxl_ctx *ctx, uint32_t domain_id,
+ void *overlay_dt, uint32_t overlay_dt_size,
+ uint8_t overlay_op)
+{
+ int rc;
+ int r;
+ GC_INIT(ctx);
+
+ if (check_overlay_fdt(gc, overlay_dt, overlay_dt_size)) {
+ LOG(ERROR, "Overlay DTB check failed");
+ rc = ERROR_FAIL;
+ goto out;
+ } else {
+ LOG(DEBUG, "Overlay DTB check passed");
+ rc = 0;
+ }
+
+ r = xc_dt_overlay_domain(ctx->xch, overlay_dt, overlay_dt_size, overlay_op,
+ domain_id);
+ if (r) {
+ LOG(ERROR, "%s: Attaching/Detaching overlay dtb failed.", __func__);
+ rc = ERROR_FAIL;
+ }
+
+out:
+ GC_FREE;
+ return rc;
+}
@@ -634,8 +634,8 @@ const struct cmd_spec cmd_table[] = {
#ifdef LIBXL_HAVE_DT_OVERLAY
{ "dt-overlay",
&main_dt_overlay, 0, 1,
- "Add/Remove a device tree overlay",
- "add/remove <.dtbo>",
+ "Add/Remove a device tree overlay to Xen device tree, attach/detach the device to a domain",
+ "<operation=add|remove> <.dtbo> OR <operation=attach|detach> <.dtbo> <Domain>",
"-h print this help\n"
},
#endif
@@ -1268,32 +1268,46 @@ int main_create(int argc, char **argv)
#ifdef LIBXL_HAVE_DT_OVERLAY
int main_dt_overlay(int argc, char **argv)
{
- const char *overlay_ops = NULL;
const char *overlay_config_file = NULL;
void *overlay_dtb = NULL;
int rc;
uint8_t op;
int overlay_dtb_size = 0;
- const int overlay_add_op = 1;
- const int overlay_remove_op = 2;
+ uint32_t domain_id = 0;
+ bool domain_op = false;
if (argc < 2) {
help("dt-overlay");
return EXIT_FAILURE;
}
- overlay_ops = argv[1];
- overlay_config_file = argv[2];
-
- if (strcmp(overlay_ops, "add") == 0)
- op = overlay_add_op;
- else if (strcmp(overlay_ops, "remove") == 0)
- op = overlay_remove_op;
- else {
+ if (strcmp(argv[optind], "add") == 0)
+ op = LIBXL_DT_OVERLAY_ADD;
+ else if (strcmp(argv[optind], "remove") == 0)
+ op = LIBXL_DT_OVERLAY_REMOVE;
+ else if (strcmp(argv[optind], "attach") == 0) {
+ op = LIBXL_DT_OVERLAY_DOMAIN_ATTACH;
+ domain_op = true;
+ } else if (strcmp(argv[optind], "detach") == 0) {
+ op = LIBXL_DT_OVERLAY_DOMAIN_DETACH;
+ domain_op = true;
+ } else {
fprintf(stderr, "Invalid dt overlay operation\n");
return EXIT_FAILURE;
}
+ overlay_config_file = argv[optind+1];
+
+ if (domain_op) {
+ if (argc <= optind + 2) {
+ fprintf(stderr, "Missing domain ID\n");
+ help("dt-overlay");
+ return EXIT_FAILURE;
+ } else {
+ domain_id = find_domain(argv[optind+2]);
+ }
+ }
+
if (overlay_config_file) {
rc = libxl_read_file_contents(ctx, overlay_config_file,
&overlay_dtb, &overlay_dtb_size);
@@ -1309,7 +1323,11 @@ int main_dt_overlay(int argc, char **argv)
return EXIT_FAILURE;
}
- rc = libxl_dt_overlay(ctx, overlay_dtb, overlay_dtb_size, op);
+ if (!domain_op)
+ rc = libxl_dt_overlay(ctx, overlay_dtb, overlay_dtb_size, op);
+ else
+ rc = libxl_dt_overlay_domain(ctx, domain_id, overlay_dtb,
+ overlay_dtb_size, op);
free(overlay_dtb);