xen_platform.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. /*
  2. * XEN platform pci device, formerly known as the event channel device
  3. *
  4. * Copyright (c) 2003-2004 Intel Corp.
  5. * Copyright (c) 2006 XenSource
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy
  8. * of this software and associated documentation files (the "Software"), to deal
  9. * in the Software without restriction, including without limitation the rights
  10. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. * THE SOFTWARE.
  24. */
  25. #include <assert.h>
  26. #include "hw.h"
  27. #include "pc.h"
  28. #include "pci.h"
  29. #include "irq.h"
  30. #include "xen_common.h"
  31. #include "net.h"
  32. #include "xen_backend.h"
  33. #include "rwhandler.h"
  34. #include "trace.h"
  35. #include <xenguest.h>
  36. //#define DEBUG_PLATFORM
  37. #ifdef DEBUG_PLATFORM
  38. #define DPRINTF(fmt, ...) do { \
  39. fprintf(stderr, "xen_platform: " fmt, ## __VA_ARGS__); \
  40. } while (0)
  41. #else
  42. #define DPRINTF(fmt, ...) do { } while (0)
  43. #endif
  44. #define PFFLAG_ROM_LOCK 1 /* Sets whether ROM memory area is RW or RO */
  45. typedef struct PCIXenPlatformState {
  46. PCIDevice pci_dev;
  47. uint8_t flags; /* used only for version_id == 2 */
  48. int drivers_blacklisted;
  49. uint16_t driver_product_version;
  50. /* Log from guest drivers */
  51. char log_buffer[4096];
  52. int log_buffer_off;
  53. } PCIXenPlatformState;
  54. #define XEN_PLATFORM_IOPORT 0x10
  55. /* Send bytes to syslog */
  56. static void log_writeb(PCIXenPlatformState *s, char val)
  57. {
  58. if (val == '\n' || s->log_buffer_off == sizeof(s->log_buffer) - 1) {
  59. /* Flush buffer */
  60. s->log_buffer[s->log_buffer_off] = 0;
  61. trace_xen_platform_log(s->log_buffer);
  62. s->log_buffer_off = 0;
  63. } else {
  64. s->log_buffer[s->log_buffer_off++] = val;
  65. }
  66. }
  67. /* Xen Platform, Fixed IOPort */
  68. static void platform_fixed_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
  69. {
  70. PCIXenPlatformState *s = opaque;
  71. switch (addr - XEN_PLATFORM_IOPORT) {
  72. case 0:
  73. /* TODO: */
  74. /* Unplug devices. Value is a bitmask of which devices to
  75. unplug, with bit 0 the IDE devices, bit 1 the network
  76. devices, and bit 2 the non-primary-master IDE devices. */
  77. break;
  78. case 2:
  79. switch (val) {
  80. case 1:
  81. DPRINTF("Citrix Windows PV drivers loaded in guest\n");
  82. break;
  83. case 0:
  84. DPRINTF("Guest claimed to be running PV product 0?\n");
  85. break;
  86. default:
  87. DPRINTF("Unknown PV product %d loaded in guest\n", val);
  88. break;
  89. }
  90. s->driver_product_version = val;
  91. break;
  92. }
  93. }
  94. static void platform_fixed_ioport_writel(void *opaque, uint32_t addr,
  95. uint32_t val)
  96. {
  97. switch (addr - XEN_PLATFORM_IOPORT) {
  98. case 0:
  99. /* PV driver version */
  100. break;
  101. }
  102. }
  103. static void platform_fixed_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
  104. {
  105. PCIXenPlatformState *s = opaque;
  106. switch (addr - XEN_PLATFORM_IOPORT) {
  107. case 0: /* Platform flags */ {
  108. hvmmem_type_t mem_type = (val & PFFLAG_ROM_LOCK) ?
  109. HVMMEM_ram_ro : HVMMEM_ram_rw;
  110. if (xc_hvm_set_mem_type(xen_xc, xen_domid, mem_type, 0xc0, 0x40)) {
  111. DPRINTF("unable to change ro/rw state of ROM memory area!\n");
  112. } else {
  113. s->flags = val & PFFLAG_ROM_LOCK;
  114. DPRINTF("changed ro/rw state of ROM memory area. now is %s state.\n",
  115. (mem_type == HVMMEM_ram_ro ? "ro":"rw"));
  116. }
  117. break;
  118. }
  119. case 2:
  120. log_writeb(s, val);
  121. break;
  122. }
  123. }
  124. static uint32_t platform_fixed_ioport_readw(void *opaque, uint32_t addr)
  125. {
  126. PCIXenPlatformState *s = opaque;
  127. switch (addr - XEN_PLATFORM_IOPORT) {
  128. case 0:
  129. if (s->drivers_blacklisted) {
  130. /* The drivers will recognise this magic number and refuse
  131. * to do anything. */
  132. return 0xd249;
  133. } else {
  134. /* Magic value so that you can identify the interface. */
  135. return 0x49d2;
  136. }
  137. default:
  138. return 0xffff;
  139. }
  140. }
  141. static uint32_t platform_fixed_ioport_readb(void *opaque, uint32_t addr)
  142. {
  143. PCIXenPlatformState *s = opaque;
  144. switch (addr - XEN_PLATFORM_IOPORT) {
  145. case 0:
  146. /* Platform flags */
  147. return s->flags;
  148. case 2:
  149. /* Version number */
  150. return 1;
  151. default:
  152. return 0xff;
  153. }
  154. }
  155. static void platform_fixed_ioport_reset(void *opaque)
  156. {
  157. PCIXenPlatformState *s = opaque;
  158. platform_fixed_ioport_writeb(s, XEN_PLATFORM_IOPORT, 0);
  159. }
  160. static void platform_fixed_ioport_init(PCIXenPlatformState* s)
  161. {
  162. register_ioport_write(XEN_PLATFORM_IOPORT, 16, 4, platform_fixed_ioport_writel, s);
  163. register_ioport_write(XEN_PLATFORM_IOPORT, 16, 2, platform_fixed_ioport_writew, s);
  164. register_ioport_write(XEN_PLATFORM_IOPORT, 16, 1, platform_fixed_ioport_writeb, s);
  165. register_ioport_read(XEN_PLATFORM_IOPORT, 16, 2, platform_fixed_ioport_readw, s);
  166. register_ioport_read(XEN_PLATFORM_IOPORT, 16, 1, platform_fixed_ioport_readb, s);
  167. }
  168. /* Xen Platform PCI Device */
  169. static uint32_t xen_platform_ioport_readb(void *opaque, uint32_t addr)
  170. {
  171. addr &= 0xff;
  172. if (addr == 0) {
  173. return platform_fixed_ioport_readb(opaque, XEN_PLATFORM_IOPORT);
  174. } else {
  175. return ~0u;
  176. }
  177. }
  178. static void xen_platform_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
  179. {
  180. PCIXenPlatformState *s = opaque;
  181. addr &= 0xff;
  182. val &= 0xff;
  183. switch (addr) {
  184. case 0: /* Platform flags */
  185. platform_fixed_ioport_writeb(opaque, XEN_PLATFORM_IOPORT, val);
  186. break;
  187. case 8:
  188. log_writeb(s, val);
  189. break;
  190. default:
  191. break;
  192. }
  193. }
  194. static void platform_ioport_map(PCIDevice *pci_dev, int region_num, pcibus_t addr, pcibus_t size, int type)
  195. {
  196. PCIXenPlatformState *d = DO_UPCAST(PCIXenPlatformState, pci_dev, pci_dev);
  197. register_ioport_write(addr, size, 1, xen_platform_ioport_writeb, d);
  198. register_ioport_read(addr, size, 1, xen_platform_ioport_readb, d);
  199. }
  200. static uint32_t platform_mmio_read(ReadWriteHandler *handler, pcibus_t addr, int len)
  201. {
  202. DPRINTF("Warning: attempted read from physical address "
  203. "0x" TARGET_FMT_plx " in xen platform mmio space\n", addr);
  204. return 0;
  205. }
  206. static void platform_mmio_write(ReadWriteHandler *handler, pcibus_t addr,
  207. uint32_t val, int len)
  208. {
  209. DPRINTF("Warning: attempted write of 0x%x to physical "
  210. "address 0x" TARGET_FMT_plx " in xen platform mmio space\n",
  211. val, addr);
  212. }
  213. static ReadWriteHandler platform_mmio_handler = {
  214. .read = &platform_mmio_read,
  215. .write = &platform_mmio_write,
  216. };
  217. static void platform_mmio_map(PCIDevice *d, int region_num,
  218. pcibus_t addr, pcibus_t size, int type)
  219. {
  220. int mmio_io_addr;
  221. mmio_io_addr = cpu_register_io_memory_simple(&platform_mmio_handler,
  222. DEVICE_NATIVE_ENDIAN);
  223. cpu_register_physical_memory(addr, size, mmio_io_addr);
  224. }
  225. static int xen_platform_post_load(void *opaque, int version_id)
  226. {
  227. PCIXenPlatformState *s = opaque;
  228. platform_fixed_ioport_writeb(s, XEN_PLATFORM_IOPORT, s->flags);
  229. return 0;
  230. }
  231. static const VMStateDescription vmstate_xen_platform = {
  232. .name = "platform",
  233. .version_id = 4,
  234. .minimum_version_id = 4,
  235. .minimum_version_id_old = 4,
  236. .post_load = xen_platform_post_load,
  237. .fields = (VMStateField []) {
  238. VMSTATE_PCI_DEVICE(pci_dev, PCIXenPlatformState),
  239. VMSTATE_UINT8(flags, PCIXenPlatformState),
  240. VMSTATE_END_OF_LIST()
  241. }
  242. };
  243. static int xen_platform_initfn(PCIDevice *dev)
  244. {
  245. PCIXenPlatformState *d = DO_UPCAST(PCIXenPlatformState, pci_dev, dev);
  246. uint8_t *pci_conf;
  247. pci_conf = d->pci_dev.config;
  248. pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
  249. pci_config_set_prog_interface(pci_conf, 0);
  250. pci_conf[PCI_INTERRUPT_PIN] = 1;
  251. pci_register_bar(&d->pci_dev, 0, 0x100,
  252. PCI_BASE_ADDRESS_SPACE_IO, platform_ioport_map);
  253. /* reserve 16MB mmio address for share memory*/
  254. pci_register_bar(&d->pci_dev, 1, 0x1000000,
  255. PCI_BASE_ADDRESS_MEM_PREFETCH, platform_mmio_map);
  256. platform_fixed_ioport_init(d);
  257. return 0;
  258. }
  259. static void platform_reset(DeviceState *dev)
  260. {
  261. PCIXenPlatformState *s = DO_UPCAST(PCIXenPlatformState, pci_dev.qdev, dev);
  262. platform_fixed_ioport_reset(s);
  263. }
  264. static PCIDeviceInfo xen_platform_info = {
  265. .init = xen_platform_initfn,
  266. .qdev.name = "xen-platform",
  267. .qdev.desc = "XEN platform pci device",
  268. .qdev.size = sizeof(PCIXenPlatformState),
  269. .qdev.vmsd = &vmstate_xen_platform,
  270. .qdev.reset = platform_reset,
  271. .vendor_id = PCI_VENDOR_ID_XEN,
  272. .device_id = PCI_DEVICE_ID_XEN_PLATFORM,
  273. .class_id = PCI_CLASS_OTHERS << 8 | 0x80,
  274. .subsystem_vendor_id = PCI_VENDOR_ID_XEN,
  275. .subsystem_id = PCI_DEVICE_ID_XEN_PLATFORM,
  276. .revision = 1,
  277. };
  278. static void xen_platform_register(void)
  279. {
  280. pci_qdev_register(&xen_platform_info);
  281. }
  282. device_init(xen_platform_register);