qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

xen-all.c (6145B)


      1 /*
      2  * Copyright (C) 2014       Citrix Systems UK Ltd.
      3  *
      4  * This work is licensed under the terms of the GNU GPL, version 2.  See
      5  * the COPYING file in the top-level directory.
      6  *
      7  * Contributions after 2012-01-13 are licensed under the terms of the
      8  * GNU GPL, version 2 or (at your option) any later version.
      9  */
     10 
     11 #include "qemu/osdep.h"
     12 #include "qemu/error-report.h"
     13 #include "qemu/module.h"
     14 #include "qapi/error.h"
     15 #include "hw/xen/xen-legacy-backend.h"
     16 #include "hw/xen/xen_pt.h"
     17 #include "chardev/char.h"
     18 #include "qemu/accel.h"
     19 #include "sysemu/cpus.h"
     20 #include "sysemu/xen.h"
     21 #include "sysemu/runstate.h"
     22 #include "migration/misc.h"
     23 #include "migration/global_state.h"
     24 #include "hw/boards.h"
     25 
     26 //#define DEBUG_XEN
     27 
     28 #ifdef DEBUG_XEN
     29 #define DPRINTF(fmt, ...) \
     30     do { fprintf(stderr, "xen: " fmt, ## __VA_ARGS__); } while (0)
     31 #else
     32 #define DPRINTF(fmt, ...) \
     33     do { } while (0)
     34 #endif
     35 
     36 bool xen_allowed;
     37 
     38 xc_interface *xen_xc;
     39 xenforeignmemory_handle *xen_fmem;
     40 xendevicemodel_handle *xen_dmod;
     41 
     42 static int store_dev_info(int domid, Chardev *cs, const char *string)
     43 {
     44     struct xs_handle *xs = NULL;
     45     char *path = NULL;
     46     char *newpath = NULL;
     47     char *pts = NULL;
     48     int ret = -1;
     49 
     50     /* Only continue if we're talking to a pty. */
     51     if (!CHARDEV_IS_PTY(cs)) {
     52         return 0;
     53     }
     54     pts = cs->filename + 4;
     55 
     56     /* We now have everything we need to set the xenstore entry. */
     57     xs = xs_open(0);
     58     if (xs == NULL) {
     59         fprintf(stderr, "Could not contact XenStore\n");
     60         goto out;
     61     }
     62 
     63     path = xs_get_domain_path(xs, domid);
     64     if (path == NULL) {
     65         fprintf(stderr, "xs_get_domain_path() error\n");
     66         goto out;
     67     }
     68     newpath = realloc(path, (strlen(path) + strlen(string) +
     69                 strlen("/tty") + 1));
     70     if (newpath == NULL) {
     71         fprintf(stderr, "realloc error\n");
     72         goto out;
     73     }
     74     path = newpath;
     75 
     76     strcat(path, string);
     77     strcat(path, "/tty");
     78     if (!xs_write(xs, XBT_NULL, path, pts, strlen(pts))) {
     79         fprintf(stderr, "xs_write for '%s' fail", string);
     80         goto out;
     81     }
     82     ret = 0;
     83 
     84 out:
     85     free(path);
     86     xs_close(xs);
     87 
     88     return ret;
     89 }
     90 
     91 void xenstore_store_pv_console_info(int i, Chardev *chr)
     92 {
     93     if (i == 0) {
     94         store_dev_info(xen_domid, chr, "/console");
     95     } else {
     96         char buf[32];
     97         snprintf(buf, sizeof(buf), "/device/console/%d", i);
     98         store_dev_info(xen_domid, chr, buf);
     99     }
    100 }
    101 
    102 
    103 static void xenstore_record_dm_state(struct xs_handle *xs, const char *state)
    104 {
    105     char path[50];
    106 
    107     if (xs == NULL) {
    108         error_report("xenstore connection not initialized");
    109         exit(1);
    110     }
    111 
    112     snprintf(path, sizeof (path), "device-model/%u/state", xen_domid);
    113     /*
    114      * This call may fail when running restricted so don't make it fatal in
    115      * that case. Toolstacks should instead use QMP to listen for state changes.
    116      */
    117     if (!xs_write(xs, XBT_NULL, path, state, strlen(state)) &&
    118             !xen_domid_restrict) {
    119         error_report("error recording dm state");
    120         exit(1);
    121     }
    122 }
    123 
    124 
    125 static void xen_change_state_handler(void *opaque, bool running,
    126                                      RunState state)
    127 {
    128     if (running) {
    129         /* record state running */
    130         xenstore_record_dm_state(xenstore, "running");
    131     }
    132 }
    133 
    134 static bool xen_get_igd_gfx_passthru(Object *obj, Error **errp)
    135 {
    136     return xen_igd_gfx_pt_enabled();
    137 }
    138 
    139 static void xen_set_igd_gfx_passthru(Object *obj, bool value, Error **errp)
    140 {
    141     xen_igd_gfx_pt_set(value, errp);
    142 }
    143 
    144 static void xen_setup_post(MachineState *ms, AccelState *accel)
    145 {
    146     int rc;
    147 
    148     if (xen_domid_restrict) {
    149         rc = xen_restrict(xen_domid);
    150         if (rc < 0) {
    151             perror("xen: failed to restrict");
    152             exit(1);
    153         }
    154     }
    155 }
    156 
    157 static int xen_init(MachineState *ms)
    158 {
    159     MachineClass *mc = MACHINE_GET_CLASS(ms);
    160 
    161     xen_xc = xc_interface_open(0, 0, 0);
    162     if (xen_xc == NULL) {
    163         xen_pv_printf(NULL, 0, "can't open xen interface\n");
    164         return -1;
    165     }
    166     xen_fmem = xenforeignmemory_open(0, 0);
    167     if (xen_fmem == NULL) {
    168         xen_pv_printf(NULL, 0, "can't open xen fmem interface\n");
    169         xc_interface_close(xen_xc);
    170         return -1;
    171     }
    172     xen_dmod = xendevicemodel_open(0, 0);
    173     if (xen_dmod == NULL) {
    174         xen_pv_printf(NULL, 0, "can't open xen devicemodel interface\n");
    175         xenforeignmemory_close(xen_fmem);
    176         xc_interface_close(xen_xc);
    177         return -1;
    178     }
    179     qemu_add_vm_change_state_handler(xen_change_state_handler, NULL);
    180     /*
    181      * opt out of system RAM being allocated by generic code
    182      */
    183     mc->default_ram_id = NULL;
    184     return 0;
    185 }
    186 
    187 static void xen_accel_class_init(ObjectClass *oc, void *data)
    188 {
    189     AccelClass *ac = ACCEL_CLASS(oc);
    190     static GlobalProperty compat[] = {
    191         { "migration", "store-global-state", "off" },
    192         { "migration", "send-configuration", "off" },
    193         { "migration", "send-section-footer", "off" },
    194     };
    195 
    196     ac->name = "Xen";
    197     ac->init_machine = xen_init;
    198     ac->setup_post = xen_setup_post;
    199     ac->allowed = &xen_allowed;
    200     ac->compat_props = g_ptr_array_new();
    201 
    202     compat_props_add(ac->compat_props, compat, G_N_ELEMENTS(compat));
    203 
    204     object_class_property_add_bool(oc, "igd-passthru",
    205         xen_get_igd_gfx_passthru, xen_set_igd_gfx_passthru);
    206     object_class_property_set_description(oc, "igd-passthru",
    207         "Set on/off to enable/disable igd passthrou");
    208 }
    209 
    210 #define TYPE_XEN_ACCEL ACCEL_CLASS_NAME("xen")
    211 
    212 static const TypeInfo xen_accel_type = {
    213     .name = TYPE_XEN_ACCEL,
    214     .parent = TYPE_ACCEL,
    215     .class_init = xen_accel_class_init,
    216 };
    217 
    218 static void xen_accel_ops_class_init(ObjectClass *oc, void *data)
    219 {
    220     AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
    221 
    222     ops->create_vcpu_thread = dummy_start_vcpu_thread;
    223 }
    224 
    225 static const TypeInfo xen_accel_ops_type = {
    226     .name = ACCEL_OPS_NAME("xen"),
    227 
    228     .parent = TYPE_ACCEL_OPS,
    229     .class_init = xen_accel_ops_class_init,
    230     .abstract = true,
    231 };
    232 
    233 static void xen_type_init(void)
    234 {
    235     type_register_static(&xen_accel_type);
    236     type_register_static(&xen_accel_ops_type);
    237 }
    238 type_init(xen_type_init);