xref: /qemu/accel/xen/xen-all.c (revision 0f66536a012b2d1b02818bbb2d24485205fc2f64)
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_native.h"
16  #include "hw/xen/xen-legacy-backend.h"
17  #include "hw/xen/xen_pt.h"
18  #include "hw/xen/xen_igd.h"
19  #include "chardev/char.h"
20  #include "qemu/accel.h"
21  #include "system/accel-ops.h"
22  #include "system/cpus.h"
23  #include "system/xen.h"
24  #include "system/runstate.h"
25  #include "migration/misc.h"
26  #include "migration/global_state.h"
27  #include "hw/boards.h"
28  
29  bool xen_allowed;
30  
31  xc_interface *xen_xc;
32  xenforeignmemory_handle *xen_fmem;
33  xendevicemodel_handle *xen_dmod;
34  
35  static void xenstore_record_dm_state(const char *state)
36  {
37      char path[50];
38  
39      snprintf(path, sizeof (path), "device-model/%u/state", xen_domid);
40      if (!qemu_xen_xs_write(xenstore, XBT_NULL, path, state, strlen(state))) {
41          error_report("error recording dm state");
42          exit(1);
43      }
44  }
45  
46  
47  static void xen_change_state_handler(void *opaque, bool running,
48                                       RunState state)
49  {
50      if (running) {
51          /* record state running */
52          xenstore_record_dm_state("running");
53      }
54  }
55  
56  static bool xen_get_igd_gfx_passthru(Object *obj, Error **errp)
57  {
58      return xen_igd_gfx_pt_enabled();
59  }
60  
61  static void xen_set_igd_gfx_passthru(Object *obj, bool value, Error **errp)
62  {
63      xen_igd_gfx_pt_set(value, errp);
64  }
65  
66  static void xen_setup_post(MachineState *ms, AccelState *accel)
67  {
68      int rc;
69  
70      if (xen_domid_restrict) {
71          rc = xen_restrict(xen_domid);
72          if (rc < 0) {
73              perror("xen: failed to restrict");
74              exit(1);
75          }
76      }
77  }
78  
79  static int xen_init(MachineState *ms)
80  {
81      MachineClass *mc = MACHINE_GET_CLASS(ms);
82  
83      xen_xc = xc_interface_open(0, 0, 0);
84      if (xen_xc == NULL) {
85          xen_pv_printf(NULL, 0, "can't open xen interface\n");
86          return -1;
87      }
88      xen_fmem = xenforeignmemory_open(0, 0);
89      if (xen_fmem == NULL) {
90          xen_pv_printf(NULL, 0, "can't open xen fmem interface\n");
91          xc_interface_close(xen_xc);
92          return -1;
93      }
94      xen_dmod = xendevicemodel_open(0, 0);
95      if (xen_dmod == NULL) {
96          xen_pv_printf(NULL, 0, "can't open xen devicemodel interface\n");
97          xenforeignmemory_close(xen_fmem);
98          xc_interface_close(xen_xc);
99          return -1;
100      }
101  
102      /*
103       * The XenStore write would fail when running restricted so don't attempt
104       * it in that case. Toolstacks should instead use QMP to listen for state
105       * changes.
106       */
107      if (!xen_domid_restrict) {
108          qemu_add_vm_change_state_handler(xen_change_state_handler, NULL);
109      }
110      /*
111       * opt out of system RAM being allocated by generic code
112       */
113      mc->default_ram_id = NULL;
114  
115      xen_mode = XEN_ATTACH;
116      return 0;
117  }
118  
119  static void xen_accel_class_init(ObjectClass *oc, void *data)
120  {
121      AccelClass *ac = ACCEL_CLASS(oc);
122      static GlobalProperty compat[] = {
123          { "migration", "store-global-state", "off" },
124          { "migration", "send-configuration", "off" },
125          { "migration", "send-section-footer", "off" },
126      };
127  
128      ac->name = "Xen";
129      ac->init_machine = xen_init;
130      ac->setup_post = xen_setup_post;
131      ac->allowed = &xen_allowed;
132      ac->compat_props = g_ptr_array_new();
133  
134      compat_props_add(ac->compat_props, compat, G_N_ELEMENTS(compat));
135  
136      object_class_property_add_bool(oc, "igd-passthru",
137          xen_get_igd_gfx_passthru, xen_set_igd_gfx_passthru);
138      object_class_property_set_description(oc, "igd-passthru",
139          "Set on/off to enable/disable igd passthrou");
140  }
141  
142  #define TYPE_XEN_ACCEL ACCEL_CLASS_NAME("xen")
143  
144  static const TypeInfo xen_accel_type = {
145      .name = TYPE_XEN_ACCEL,
146      .parent = TYPE_ACCEL,
147      .class_init = xen_accel_class_init,
148  };
149  
150  static void xen_accel_ops_class_init(ObjectClass *oc, void *data)
151  {
152      AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
153  
154      ops->create_vcpu_thread = dummy_start_vcpu_thread;
155  }
156  
157  static const TypeInfo xen_accel_ops_type = {
158      .name = ACCEL_OPS_NAME("xen"),
159  
160      .parent = TYPE_ACCEL_OPS,
161      .class_init = xen_accel_ops_class_init,
162      .abstract = true,
163  };
164  
165  static void xen_type_init(void)
166  {
167      type_register_static(&xen_accel_type);
168      type_register_static(&xen_accel_ops_type);
169  }
170  type_init(xen_type_init);
171