mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
Michal reported that the gitlab CI is failing because of this series
[1].
This reverts commit 6f9d90ea94.
Signed-off-by: Julien Grall <jgrall@amazon.com>
353 lines
11 KiB
C
353 lines
11 KiB
C
#include <stdbool.h>
|
|
#include <syslog.h>
|
|
#include <stdio.h>
|
|
#include <err.h>
|
|
#include <stdlib.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/time.h>
|
|
#include <inttypes.h>
|
|
#include <xenstore.h>
|
|
#include <xenctrl.h>
|
|
#include <xenguest.h>
|
|
#include <libxl.h>
|
|
#include <xenevtchn.h>
|
|
#include <xenforeignmemory.h>
|
|
#include <xen/io/xs_wire.h>
|
|
|
|
#include "init-dom-json.h"
|
|
|
|
#define XENSTORE_PFN_OFFSET 1
|
|
#define STR_MAX_LENGTH 128
|
|
|
|
static int alloc_xs_page(struct xc_interface_core *xch,
|
|
libxl_dominfo *info,
|
|
uint64_t *xenstore_pfn)
|
|
{
|
|
int rc;
|
|
const xen_pfn_t base = GUEST_MAGIC_BASE >> XC_PAGE_SHIFT;
|
|
xen_pfn_t p2m = (GUEST_MAGIC_BASE >> XC_PAGE_SHIFT) + XENSTORE_PFN_OFFSET;
|
|
|
|
rc = xc_domain_setmaxmem(xch, info->domid,
|
|
info->max_memkb + (XC_PAGE_SIZE/1024));
|
|
if (rc < 0)
|
|
return rc;
|
|
|
|
rc = xc_domain_populate_physmap_exact(xch, info->domid, 1, 0, 0, &p2m);
|
|
if (rc < 0)
|
|
return rc;
|
|
|
|
*xenstore_pfn = base + XENSTORE_PFN_OFFSET;
|
|
rc = xc_clear_domain_page(xch, info->domid, *xenstore_pfn);
|
|
if (rc < 0)
|
|
return rc;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static bool do_xs_write_dom(struct xs_handle *xsh, xs_transaction_t t,
|
|
domid_t domid, char *path, char *val)
|
|
{
|
|
char full_path[STR_MAX_LENGTH];
|
|
struct xs_permissions perms[2];
|
|
int rc;
|
|
|
|
perms[0].id = domid;
|
|
perms[0].perms = XS_PERM_NONE;
|
|
perms[1].id = 0;
|
|
perms[1].perms = XS_PERM_READ;
|
|
|
|
rc = snprintf(full_path, STR_MAX_LENGTH,
|
|
"/local/domain/%u/%s", domid, path);
|
|
if (rc < 0 || rc >= STR_MAX_LENGTH)
|
|
return false;
|
|
if (!xs_write(xsh, t, full_path, val, strlen(val)))
|
|
return false;
|
|
return xs_set_permissions(xsh, t, full_path, perms, 2);
|
|
}
|
|
|
|
static bool do_xs_write_libxl(struct xs_handle *xsh, xs_transaction_t t,
|
|
domid_t domid, char *path, char *val)
|
|
{
|
|
char full_path[STR_MAX_LENGTH];
|
|
int rc;
|
|
|
|
rc = snprintf(full_path, STR_MAX_LENGTH,
|
|
"/libxl/%u/%s", domid, path);
|
|
if (rc < 0 || rc >= STR_MAX_LENGTH)
|
|
return false;
|
|
return xs_write(xsh, t, full_path, val, strlen(val));
|
|
}
|
|
|
|
static bool do_xs_write_vm(struct xs_handle *xsh, xs_transaction_t t,
|
|
libxl_uuid uuid, char *path, char *val)
|
|
{
|
|
char full_path[STR_MAX_LENGTH];
|
|
int rc;
|
|
|
|
rc = snprintf(full_path, STR_MAX_LENGTH,
|
|
"/vm/" LIBXL_UUID_FMT "/%s", LIBXL_UUID_BYTES(uuid), path);
|
|
if (rc < 0 || rc >= STR_MAX_LENGTH)
|
|
return false;
|
|
return xs_write(xsh, t, full_path, val, strlen(val));
|
|
}
|
|
|
|
/*
|
|
* The xenstore nodes are the xenstore nodes libxl writes at domain
|
|
* creation.
|
|
*
|
|
* The list was retrieved by running xenstore-ls on a corresponding
|
|
* domain started by xl/libxl.
|
|
*/
|
|
static int create_xenstore(struct xs_handle *xsh,
|
|
libxl_dominfo *info, libxl_uuid uuid,
|
|
evtchn_port_t xenstore_port)
|
|
{
|
|
domid_t domid;
|
|
unsigned int i;
|
|
char uuid_str[STR_MAX_LENGTH];
|
|
char dom_name_str[STR_MAX_LENGTH];
|
|
char vm_val_str[STR_MAX_LENGTH];
|
|
char id_str[STR_MAX_LENGTH];
|
|
char max_memkb_str[STR_MAX_LENGTH];
|
|
char target_memkb_str[STR_MAX_LENGTH];
|
|
char cpu_str[STR_MAX_LENGTH];
|
|
char xenstore_port_str[STR_MAX_LENGTH];
|
|
char ring_ref_str[STR_MAX_LENGTH];
|
|
xs_transaction_t t;
|
|
struct timeval start_time;
|
|
char start_time_str[STR_MAX_LENGTH];
|
|
int rc;
|
|
|
|
if (gettimeofday(&start_time, NULL) < 0)
|
|
return -errno;
|
|
rc = snprintf(start_time_str, STR_MAX_LENGTH, "%jd.%02d",
|
|
(intmax_t)start_time.tv_sec, (int)start_time.tv_usec / 10000);
|
|
if (rc < 0 || rc >= STR_MAX_LENGTH)
|
|
return rc;
|
|
|
|
domid = info->domid;
|
|
rc = snprintf(id_str, STR_MAX_LENGTH, "%u", domid);
|
|
if (rc < 0 || rc >= STR_MAX_LENGTH)
|
|
return rc;
|
|
rc = snprintf(dom_name_str, STR_MAX_LENGTH, "dom0less-%u", domid);
|
|
if (rc < 0 || rc >= STR_MAX_LENGTH)
|
|
return rc;
|
|
rc = snprintf(uuid_str, STR_MAX_LENGTH, LIBXL_UUID_FMT, LIBXL_UUID_BYTES(uuid));
|
|
if (rc < 0 || rc >= STR_MAX_LENGTH)
|
|
return rc;
|
|
rc = snprintf(vm_val_str, STR_MAX_LENGTH,
|
|
"vm/" LIBXL_UUID_FMT, LIBXL_UUID_BYTES(uuid));
|
|
if (rc < 0 || rc >= STR_MAX_LENGTH)
|
|
return rc;
|
|
rc = snprintf(max_memkb_str, STR_MAX_LENGTH, "%"PRIu64, info->max_memkb);
|
|
if (rc < 0 || rc >= STR_MAX_LENGTH)
|
|
return rc;
|
|
rc = snprintf(target_memkb_str, STR_MAX_LENGTH, "%"PRIu64, info->current_memkb);
|
|
if (rc < 0 || rc >= STR_MAX_LENGTH)
|
|
return rc;
|
|
rc = snprintf(ring_ref_str, STR_MAX_LENGTH, "%lld",
|
|
(GUEST_MAGIC_BASE >> XC_PAGE_SHIFT) + XENSTORE_PFN_OFFSET);
|
|
if (rc < 0 || rc >= STR_MAX_LENGTH)
|
|
return rc;
|
|
rc = snprintf(xenstore_port_str, STR_MAX_LENGTH, "%u", xenstore_port);
|
|
if (rc < 0 || rc >= STR_MAX_LENGTH)
|
|
return rc;
|
|
|
|
retry_transaction:
|
|
t = xs_transaction_start(xsh);
|
|
if (t == XBT_NULL)
|
|
return -errno;
|
|
|
|
rc = -EIO;
|
|
/* /vm */
|
|
if (!do_xs_write_vm(xsh, t, uuid, "name", dom_name_str)) goto err;
|
|
if (!do_xs_write_vm(xsh, t, uuid, "uuid", uuid_str)) goto err;
|
|
if (!do_xs_write_vm(xsh, t, uuid, "start_time", start_time_str)) goto err;
|
|
|
|
/* /domain */
|
|
if (!do_xs_write_dom(xsh, t, domid, "vm", vm_val_str)) goto err;
|
|
if (!do_xs_write_dom(xsh, t, domid, "name", dom_name_str)) goto err;
|
|
if (!do_xs_write_dom(xsh, t, domid, "cpu", "")) goto err;
|
|
for (i = 0; i < info->vcpu_max_id; i++) {
|
|
rc = snprintf(cpu_str, STR_MAX_LENGTH, "cpu/%u/availability/", i);
|
|
if (rc < 0 || rc >= STR_MAX_LENGTH)
|
|
goto err;
|
|
rc = -EIO;
|
|
if (!do_xs_write_dom(xsh, t, domid, cpu_str,
|
|
(info->cpupool & (1 << i)) ? "online" : "offline"))
|
|
goto err;
|
|
}
|
|
|
|
if (!do_xs_write_dom(xsh, t, domid, "memory", "")) goto err;
|
|
if (!do_xs_write_dom(xsh, t, domid, "memory/static-max", max_memkb_str)) goto err;
|
|
if (!do_xs_write_dom(xsh, t, domid, "memory/target", target_memkb_str)) goto err;
|
|
if (!do_xs_write_dom(xsh, t, domid, "memory/videoram", "-1")) goto err;
|
|
|
|
if (!do_xs_write_dom(xsh, t, domid, "device", "")) goto err;
|
|
if (!do_xs_write_dom(xsh, t, domid, "device/suspend", "")) goto err;
|
|
if (!do_xs_write_dom(xsh, t, domid, "device/suspend/event-channel", "")) goto err;
|
|
|
|
if (!do_xs_write_dom(xsh, t, domid, "control", "")) goto err;
|
|
if (!do_xs_write_dom(xsh, t, domid, "control/shutdown", "")) goto err;
|
|
if (!do_xs_write_dom(xsh, t, domid, "control/feature-poweroff", "1")) goto err;
|
|
if (!do_xs_write_dom(xsh, t, domid, "control/feature-reboot", "1")) goto err;
|
|
if (!do_xs_write_dom(xsh, t, domid, "control/feature-suspend", "")) goto err;
|
|
if (!do_xs_write_dom(xsh, t, domid, "control/sysrq", "")) goto err;
|
|
if (!do_xs_write_dom(xsh, t, domid, "control/platform-feature-multiprocessor-suspend", "1")) goto err;
|
|
if (!do_xs_write_dom(xsh, t, domid, "control/platform-feature-xs_reset_watches", "1")) goto err;
|
|
|
|
if (!do_xs_write_dom(xsh, t, domid, "domid", id_str)) goto err;
|
|
if (!do_xs_write_dom(xsh, t, domid, "data", "")) goto err;
|
|
if (!do_xs_write_dom(xsh, t, domid, "drivers", "")) goto err;
|
|
if (!do_xs_write_dom(xsh, t, domid, "feature", "")) goto err;
|
|
if (!do_xs_write_dom(xsh, t, domid, "attr", "")) goto err;
|
|
|
|
if (!do_xs_write_dom(xsh, t, domid, "store/port", xenstore_port_str)) goto err;
|
|
if (!do_xs_write_dom(xsh, t, domid, "store/ring-ref", ring_ref_str)) goto err;
|
|
|
|
if (!do_xs_write_libxl(xsh, t, domid, "type", "pvh")) goto err;
|
|
if (!do_xs_write_libxl(xsh, t, domid, "dm-version", "qemu_xen")) goto err;
|
|
|
|
if (!xs_transaction_end(xsh, t, false)) {
|
|
if (errno == EAGAIN)
|
|
goto retry_transaction;
|
|
else
|
|
return -errno;
|
|
}
|
|
|
|
return 0;
|
|
|
|
err:
|
|
xs_transaction_end(xsh, t, true);
|
|
return rc;
|
|
}
|
|
|
|
static int init_domain(struct xs_handle *xsh,
|
|
struct xc_interface_core *xch,
|
|
xenforeignmemory_handle *xfh,
|
|
libxl_dominfo *info)
|
|
{
|
|
libxl_uuid uuid;
|
|
uint64_t xenstore_evtchn, xenstore_pfn;
|
|
int rc;
|
|
struct xenstore_domain_interface *intf;
|
|
|
|
printf("Init dom0less domain: %u\n", info->domid);
|
|
|
|
rc = xc_hvm_param_get(xch, info->domid, HVM_PARAM_STORE_EVTCHN,
|
|
&xenstore_evtchn);
|
|
if (rc != 0) {
|
|
printf("Failed to get HVM_PARAM_STORE_EVTCHN\n");
|
|
return 1;
|
|
}
|
|
|
|
/* no xen,enhanced; nothing to do */
|
|
if (!xenstore_evtchn)
|
|
return 0;
|
|
|
|
/* Alloc xenstore page */
|
|
if (alloc_xs_page(xch, info, &xenstore_pfn) != 0) {
|
|
printf("Error on alloc magic pages\n");
|
|
return 1;
|
|
}
|
|
|
|
intf = xenforeignmemory_map(xfh, info->domid, PROT_READ | PROT_WRITE, 1,
|
|
&xenstore_pfn, NULL);
|
|
if (!intf) {
|
|
printf("Error mapping xenstore page\n");
|
|
return 1;
|
|
}
|
|
intf->connection = XENSTORE_RECONNECT;
|
|
xenforeignmemory_unmap(xfh, intf, 1);
|
|
|
|
rc = xc_dom_gnttab_seed(xch, info->domid, true,
|
|
(xen_pfn_t)-1, xenstore_pfn, 0, 0);
|
|
if (rc)
|
|
err(1, "xc_dom_gnttab_seed");
|
|
|
|
libxl_uuid_generate(&uuid);
|
|
xc_domain_sethandle(xch, info->domid, libxl_uuid_bytearray(&uuid));
|
|
|
|
rc = gen_stub_json_config(info->domid, &uuid);
|
|
if (rc)
|
|
err(1, "gen_stub_json_config");
|
|
|
|
/* Now everything is ready: set HVM_PARAM_STORE_PFN */
|
|
rc = xc_hvm_param_set(xch, info->domid, HVM_PARAM_STORE_PFN,
|
|
xenstore_pfn);
|
|
if (rc < 0)
|
|
return rc;
|
|
|
|
rc = create_xenstore(xsh, info, uuid, xenstore_evtchn);
|
|
if (rc)
|
|
err(1, "writing to xenstore");
|
|
|
|
rc = xs_introduce_domain(xsh, info->domid,
|
|
(GUEST_MAGIC_BASE >> XC_PAGE_SHIFT) + XENSTORE_PFN_OFFSET,
|
|
xenstore_evtchn);
|
|
if (!rc)
|
|
err(1, "xs_introduce_domain");
|
|
return 0;
|
|
}
|
|
|
|
/* Check if domain has been configured in XS */
|
|
static bool domain_exists(struct xs_handle *xsh, int domid)
|
|
{
|
|
return xs_is_domain_introduced(xsh, domid);
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
libxl_dominfo *info = NULL;
|
|
libxl_ctx *ctx;
|
|
int nb_vm = 0, rc = 0, i;
|
|
struct xs_handle *xsh = NULL;
|
|
struct xc_interface_core *xch = NULL;
|
|
xenforeignmemory_handle *xfh = NULL;
|
|
|
|
/* TODO reuse libxl xsh connection */
|
|
xsh = xs_open(0);
|
|
xch = xc_interface_open(0, 0, 0);
|
|
xfh = xenforeignmemory_open(0, 0);
|
|
if (xsh == NULL || xch == NULL || xfh == NULL) {
|
|
fprintf(stderr, "Cannot open xc/xs/xenforeignmemory interfaces");
|
|
rc = -errno;
|
|
goto out;
|
|
}
|
|
|
|
rc = libxl_ctx_alloc(&ctx, LIBXL_VERSION, 0, NULL);
|
|
if (rc) {
|
|
fprintf(stderr, "cannot init xl context\n");
|
|
goto out;
|
|
}
|
|
|
|
info = libxl_list_domain(ctx, &nb_vm);
|
|
if (!info) {
|
|
fprintf(stderr, "libxl_list_vm failed.\n");
|
|
rc = -1;
|
|
goto out;
|
|
}
|
|
|
|
for (i = 0; i < nb_vm; i++) {
|
|
domid_t domid = info[i].domid;
|
|
|
|
/* Don't need to check for Dom0 */
|
|
if (!domid)
|
|
continue;
|
|
|
|
printf("Checking domid: %u\n", domid);
|
|
if (!domain_exists(xsh, domid)) {
|
|
rc = init_domain(xsh, xch, xfh, &info[i]);
|
|
if (rc < 0) {
|
|
fprintf(stderr, "init_domain failed.\n");
|
|
goto out;
|
|
}
|
|
} else {
|
|
printf("Domain %u has already been initialized\n", domid);
|
|
}
|
|
}
|
|
out:
|
|
libxl_dominfo_list_free(info, nb_vm);
|
|
return rc;
|
|
}
|