xen_devconfig.c 4.9 KB
Newer Older
P
Peter Maydell 已提交
1
#include "qemu/osdep.h"
P
Paolo Bonzini 已提交
2
#include "hw/xen/xen_backend.h"
3
#include "sysemu/block-backend.h"
4
#include "sysemu/blockdev.h"
5 6 7 8 9

/* ------------------------------------------------------------- */

struct xs_dirs {
    char *xs_dir;
B
Blue Swirl 已提交
10
    QTAILQ_ENTRY(xs_dirs) list;
11
};
B
Blue Swirl 已提交
12
static QTAILQ_HEAD(xs_dirs_head, xs_dirs) xs_cleanup = QTAILQ_HEAD_INITIALIZER(xs_cleanup);
13 14 15 16 17

static void xen_config_cleanup_dir(char *dir)
{
    struct xs_dirs *d;

18
    d = g_malloc(sizeof(*d));
19
    d->xs_dir = dir;
B
Blue Swirl 已提交
20
    QTAILQ_INSERT_TAIL(&xs_cleanup, d, list);
21 22
}

23
void xen_config_cleanup(void)
24 25 26
{
    struct xs_dirs *d;

B
Blue Swirl 已提交
27
    QTAILQ_FOREACH(d, &xs_cleanup, list) {
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
	xs_rm(xenstore, 0, d->xs_dir);
    }
}

/* ------------------------------------------------------------- */

static int xen_config_dev_mkdir(char *dev, int p)
{
    struct xs_permissions perms[2] = {{
            .id    = 0, /* set owner: dom0 */
        },{
            .id    = xen_domid,
            .perms = p,
        }};

    if (!xs_mkdir(xenstore, 0, dev)) {
	xen_be_printf(NULL, 0, "xs_mkdir %s: failed\n", dev);
	return -1;
    }
47
    xen_config_cleanup_dir(g_strdup(dev));
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97

    if (!xs_set_permissions(xenstore, 0, dev, perms, 2)) {
	xen_be_printf(NULL, 0, "xs_set_permissions %s: failed\n", dev);
	return -1;
    }
    return 0;
}

static int xen_config_dev_dirs(const char *ftype, const char *btype, int vdev,
			       char *fe, char *be, int len)
{
    char *dom;

    dom = xs_get_domain_path(xenstore, xen_domid);
    snprintf(fe, len, "%s/device/%s/%d", dom, ftype, vdev);
    free(dom);

    dom = xs_get_domain_path(xenstore, 0);
    snprintf(be, len, "%s/backend/%s/%d/%d", dom, btype, xen_domid, vdev);
    free(dom);

    xen_config_dev_mkdir(fe, XS_PERM_READ | XS_PERM_WRITE);
    xen_config_dev_mkdir(be, XS_PERM_READ);
    return 0;
}

static int xen_config_dev_all(char *fe, char *be)
{
    /* frontend */
    if (xen_protocol)
        xenstore_write_str(fe, "protocol", xen_protocol);

    xenstore_write_int(fe, "state",           XenbusStateInitialising);
    xenstore_write_int(fe, "backend-id",      0);
    xenstore_write_str(fe, "backend",         be);

    /* backend */
    xenstore_write_str(be, "domain",          qemu_name ? qemu_name : "no-name");
    xenstore_write_int(be, "online",          1);
    xenstore_write_int(be, "state",           XenbusStateInitialising);
    xenstore_write_int(be, "frontend-id",     xen_domid);
    xenstore_write_str(be, "frontend",        fe);

    return 0;
}

/* ------------------------------------------------------------- */

int xen_config_dev_blk(DriveInfo *disk)
{
98
    char fe[256], be[256], device_name[32];
99
    int vdev = 202 * 256 + 16 * disk->unit;
100
    int cdrom = disk->media_cd;
101 102
    const char *devtype = cdrom ? "cdrom" : "disk";
    const char *mode    = cdrom ? "r"     : "w";
103
    const char *filename = qemu_opt_get(disk->opts, "file");
104

105
    snprintf(device_name, sizeof(device_name), "xvd%c", 'a' + disk->unit);
106
    xen_be_printf(NULL, 1, "config disk %d [%s]: %s\n",
107
                  disk->unit, device_name, filename);
108 109 110 111 112 113 114
    xen_config_dev_dirs("vbd", "qdisk", vdev, fe, be, sizeof(fe));

    /* frontend */
    xenstore_write_int(fe, "virtual-device",  vdev);
    xenstore_write_str(fe, "device-type",     devtype);

    /* backend */
115
    xenstore_write_str(be, "dev",             device_name);
116
    xenstore_write_str(be, "type",            "file");
117
    xenstore_write_str(be, "params",          filename);
118 119 120 121 122 123 124 125 126 127
    xenstore_write_str(be, "mode",            mode);

    /* common stuff */
    return xen_config_dev_all(fe, be);
}

int xen_config_dev_nic(NICInfo *nic)
{
    char fe[256], be[256];
    char mac[20];
128
    int vlan_id = -1;
129

130
    net_hub_id_for_client(nic->netdev, &vlan_id);
131
    snprintf(mac, sizeof(mac), "%02x:%02x:%02x:%02x:%02x:%02x",
132 133
             nic->macaddr.a[0], nic->macaddr.a[1], nic->macaddr.a[2],
             nic->macaddr.a[3], nic->macaddr.a[4], nic->macaddr.a[5]);
134 135
    xen_be_printf(NULL, 1, "config nic %d: mac=\"%s\"\n", vlan_id, mac);
    xen_config_dev_dirs("vif", "qnic", vlan_id, fe, be, sizeof(fe));
136 137

    /* frontend */
138
    xenstore_write_int(fe, "handle",     vlan_id);
139 140 141
    xenstore_write_str(fe, "mac",        mac);

    /* backend */
142
    xenstore_write_int(be, "handle",     vlan_id);
143 144 145 146 147
    xenstore_write_str(be, "mac",        mac);

    /* common stuff */
    return xen_config_dev_all(fe, be);
}
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176

int xen_config_dev_vfb(int vdev, const char *type)
{
    char fe[256], be[256];

    xen_config_dev_dirs("vfb", "vfb", vdev, fe, be, sizeof(fe));

    /* backend */
    xenstore_write_str(be, "type",  type);

    /* common stuff */
    return xen_config_dev_all(fe, be);
}

int xen_config_dev_vkbd(int vdev)
{
    char fe[256], be[256];

    xen_config_dev_dirs("vkbd", "vkbd", vdev, fe, be, sizeof(fe));
    return xen_config_dev_all(fe, be);
}

int xen_config_dev_console(int vdev)
{
    char fe[256], be[256];

    xen_config_dev_dirs("console", "console", vdev, fe, be, sizeof(fe));
    return xen_config_dev_all(fe, be);
}