Annotation of qemu/hw/xen_platform.c, revision 1.1

1.1     ! root        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: 
        !            26: #include <assert.h>
        !            27: 
        !            28: #include "hw.h"
        !            29: #include "pc.h"
        !            30: #include "pci.h"
        !            31: #include "irq.h"
        !            32: #include "xen_common.h"
        !            33: #include "net.h"
        !            34: #include "xen_backend.h"
        !            35: #include "rwhandler.h"
        !            36: #include "trace.h"
        !            37: 
        !            38: #include <xenguest.h>
        !            39: 
        !            40: //#define DEBUG_PLATFORM
        !            41: 
        !            42: #ifdef DEBUG_PLATFORM
        !            43: #define DPRINTF(fmt, ...) do { \
        !            44:     fprintf(stderr, "xen_platform: " fmt, ## __VA_ARGS__); \
        !            45: } while (0)
        !            46: #else
        !            47: #define DPRINTF(fmt, ...) do { } while (0)
        !            48: #endif
        !            49: 
        !            50: #define PFFLAG_ROM_LOCK 1 /* Sets whether ROM memory area is RW or RO */
        !            51: 
        !            52: typedef struct PCIXenPlatformState {
        !            53:     PCIDevice  pci_dev;
        !            54:     uint8_t flags; /* used only for version_id == 2 */
        !            55:     int drivers_blacklisted;
        !            56:     uint16_t driver_product_version;
        !            57: 
        !            58:     /* Log from guest drivers */
        !            59:     char log_buffer[4096];
        !            60:     int log_buffer_off;
        !            61: } PCIXenPlatformState;
        !            62: 
        !            63: #define XEN_PLATFORM_IOPORT 0x10
        !            64: 
        !            65: /* Send bytes to syslog */
        !            66: static void log_writeb(PCIXenPlatformState *s, char val)
        !            67: {
        !            68:     if (val == '\n' || s->log_buffer_off == sizeof(s->log_buffer) - 1) {
        !            69:         /* Flush buffer */
        !            70:         s->log_buffer[s->log_buffer_off] = 0;
        !            71:         trace_xen_platform_log(s->log_buffer);
        !            72:         s->log_buffer_off = 0;
        !            73:     } else {
        !            74:         s->log_buffer[s->log_buffer_off++] = val;
        !            75:     }
        !            76: }
        !            77: 
        !            78: /* Xen Platform, Fixed IOPort */
        !            79: 
        !            80: static void platform_fixed_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
        !            81: {
        !            82:     PCIXenPlatformState *s = opaque;
        !            83: 
        !            84:     switch (addr - XEN_PLATFORM_IOPORT) {
        !            85:     case 0:
        !            86:         /* TODO: */
        !            87:         /* Unplug devices.  Value is a bitmask of which devices to
        !            88:            unplug, with bit 0 the IDE devices, bit 1 the network
        !            89:            devices, and bit 2 the non-primary-master IDE devices. */
        !            90:         break;
        !            91:     case 2:
        !            92:         switch (val) {
        !            93:         case 1:
        !            94:             DPRINTF("Citrix Windows PV drivers loaded in guest\n");
        !            95:             break;
        !            96:         case 0:
        !            97:             DPRINTF("Guest claimed to be running PV product 0?\n");
        !            98:             break;
        !            99:         default:
        !           100:             DPRINTF("Unknown PV product %d loaded in guest\n", val);
        !           101:             break;
        !           102:         }
        !           103:         s->driver_product_version = val;
        !           104:         break;
        !           105:     }
        !           106: }
        !           107: 
        !           108: static void platform_fixed_ioport_writel(void *opaque, uint32_t addr,
        !           109:                                          uint32_t val)
        !           110: {
        !           111:     switch (addr - XEN_PLATFORM_IOPORT) {
        !           112:     case 0:
        !           113:         /* PV driver version */
        !           114:         break;
        !           115:     }
        !           116: }
        !           117: 
        !           118: static void platform_fixed_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
        !           119: {
        !           120:     PCIXenPlatformState *s = opaque;
        !           121: 
        !           122:     switch (addr - XEN_PLATFORM_IOPORT) {
        !           123:     case 0: /* Platform flags */ {
        !           124:         hvmmem_type_t mem_type = (val & PFFLAG_ROM_LOCK) ?
        !           125:             HVMMEM_ram_ro : HVMMEM_ram_rw;
        !           126:         if (xc_hvm_set_mem_type(xen_xc, xen_domid, mem_type, 0xc0, 0x40)) {
        !           127:             DPRINTF("unable to change ro/rw state of ROM memory area!\n");
        !           128:         } else {
        !           129:             s->flags = val & PFFLAG_ROM_LOCK;
        !           130:             DPRINTF("changed ro/rw state of ROM memory area. now is %s state.\n",
        !           131:                     (mem_type == HVMMEM_ram_ro ? "ro":"rw"));
        !           132:         }
        !           133:         break;
        !           134:     }
        !           135:     case 2:
        !           136:         log_writeb(s, val);
        !           137:         break;
        !           138:     }
        !           139: }
        !           140: 
        !           141: static uint32_t platform_fixed_ioport_readw(void *opaque, uint32_t addr)
        !           142: {
        !           143:     PCIXenPlatformState *s = opaque;
        !           144: 
        !           145:     switch (addr - XEN_PLATFORM_IOPORT) {
        !           146:     case 0:
        !           147:         if (s->drivers_blacklisted) {
        !           148:             /* The drivers will recognise this magic number and refuse
        !           149:              * to do anything. */
        !           150:             return 0xd249;
        !           151:         } else {
        !           152:             /* Magic value so that you can identify the interface. */
        !           153:             return 0x49d2;
        !           154:         }
        !           155:     default:
        !           156:         return 0xffff;
        !           157:     }
        !           158: }
        !           159: 
        !           160: static uint32_t platform_fixed_ioport_readb(void *opaque, uint32_t addr)
        !           161: {
        !           162:     PCIXenPlatformState *s = opaque;
        !           163: 
        !           164:     switch (addr - XEN_PLATFORM_IOPORT) {
        !           165:     case 0:
        !           166:         /* Platform flags */
        !           167:         return s->flags;
        !           168:     case 2:
        !           169:         /* Version number */
        !           170:         return 1;
        !           171:     default:
        !           172:         return 0xff;
        !           173:     }
        !           174: }
        !           175: 
        !           176: static void platform_fixed_ioport_reset(void *opaque)
        !           177: {
        !           178:     PCIXenPlatformState *s = opaque;
        !           179: 
        !           180:     platform_fixed_ioport_writeb(s, XEN_PLATFORM_IOPORT, 0);
        !           181: }
        !           182: 
        !           183: static void platform_fixed_ioport_init(PCIXenPlatformState* s)
        !           184: {
        !           185:     register_ioport_write(XEN_PLATFORM_IOPORT, 16, 4, platform_fixed_ioport_writel, s);
        !           186:     register_ioport_write(XEN_PLATFORM_IOPORT, 16, 2, platform_fixed_ioport_writew, s);
        !           187:     register_ioport_write(XEN_PLATFORM_IOPORT, 16, 1, platform_fixed_ioport_writeb, s);
        !           188:     register_ioport_read(XEN_PLATFORM_IOPORT, 16, 2, platform_fixed_ioport_readw, s);
        !           189:     register_ioport_read(XEN_PLATFORM_IOPORT, 16, 1, platform_fixed_ioport_readb, s);
        !           190: }
        !           191: 
        !           192: /* Xen Platform PCI Device */
        !           193: 
        !           194: static uint32_t xen_platform_ioport_readb(void *opaque, uint32_t addr)
        !           195: {
        !           196:     addr &= 0xff;
        !           197: 
        !           198:     if (addr == 0) {
        !           199:         return platform_fixed_ioport_readb(opaque, XEN_PLATFORM_IOPORT);
        !           200:     } else {
        !           201:         return ~0u;
        !           202:     }
        !           203: }
        !           204: 
        !           205: static void xen_platform_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
        !           206: {
        !           207:     PCIXenPlatformState *s = opaque;
        !           208: 
        !           209:     addr &= 0xff;
        !           210:     val  &= 0xff;
        !           211: 
        !           212:     switch (addr) {
        !           213:     case 0: /* Platform flags */
        !           214:         platform_fixed_ioport_writeb(opaque, XEN_PLATFORM_IOPORT, val);
        !           215:         break;
        !           216:     case 8:
        !           217:         log_writeb(s, val);
        !           218:         break;
        !           219:     default:
        !           220:         break;
        !           221:     }
        !           222: }
        !           223: 
        !           224: static void platform_ioport_map(PCIDevice *pci_dev, int region_num, pcibus_t addr, pcibus_t size, int type)
        !           225: {
        !           226:     PCIXenPlatformState *d = DO_UPCAST(PCIXenPlatformState, pci_dev, pci_dev);
        !           227: 
        !           228:     register_ioport_write(addr, size, 1, xen_platform_ioport_writeb, d);
        !           229:     register_ioport_read(addr, size, 1, xen_platform_ioport_readb, d);
        !           230: }
        !           231: 
        !           232: static uint32_t platform_mmio_read(ReadWriteHandler *handler, pcibus_t addr, int len)
        !           233: {
        !           234:     DPRINTF("Warning: attempted read from physical address "
        !           235:             "0x" TARGET_FMT_plx " in xen platform mmio space\n", addr);
        !           236: 
        !           237:     return 0;
        !           238: }
        !           239: 
        !           240: static void platform_mmio_write(ReadWriteHandler *handler, pcibus_t addr,
        !           241:                                 uint32_t val, int len)
        !           242: {
        !           243:     DPRINTF("Warning: attempted write of 0x%x to physical "
        !           244:             "address 0x" TARGET_FMT_plx " in xen platform mmio space\n",
        !           245:             val, addr);
        !           246: }
        !           247: 
        !           248: static ReadWriteHandler platform_mmio_handler = {
        !           249:     .read = &platform_mmio_read,
        !           250:     .write = &platform_mmio_write,
        !           251: };
        !           252: 
        !           253: static void platform_mmio_map(PCIDevice *d, int region_num,
        !           254:                               pcibus_t addr, pcibus_t size, int type)
        !           255: {
        !           256:     int mmio_io_addr;
        !           257: 
        !           258:     mmio_io_addr = cpu_register_io_memory_simple(&platform_mmio_handler,
        !           259:                                                  DEVICE_NATIVE_ENDIAN);
        !           260: 
        !           261:     cpu_register_physical_memory(addr, size, mmio_io_addr);
        !           262: }
        !           263: 
        !           264: static int xen_platform_post_load(void *opaque, int version_id)
        !           265: {
        !           266:     PCIXenPlatformState *s = opaque;
        !           267: 
        !           268:     platform_fixed_ioport_writeb(s, XEN_PLATFORM_IOPORT, s->flags);
        !           269: 
        !           270:     return 0;
        !           271: }
        !           272: 
        !           273: static const VMStateDescription vmstate_xen_platform = {
        !           274:     .name = "platform",
        !           275:     .version_id = 4,
        !           276:     .minimum_version_id = 4,
        !           277:     .minimum_version_id_old = 4,
        !           278:     .post_load = xen_platform_post_load,
        !           279:     .fields = (VMStateField []) {
        !           280:         VMSTATE_PCI_DEVICE(pci_dev, PCIXenPlatformState),
        !           281:         VMSTATE_UINT8(flags, PCIXenPlatformState),
        !           282:         VMSTATE_END_OF_LIST()
        !           283:     }
        !           284: };
        !           285: 
        !           286: static int xen_platform_initfn(PCIDevice *dev)
        !           287: {
        !           288:     PCIXenPlatformState *d = DO_UPCAST(PCIXenPlatformState, pci_dev, dev);
        !           289:     uint8_t *pci_conf;
        !           290: 
        !           291:     pci_conf = d->pci_dev.config;
        !           292: 
        !           293:     pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
        !           294: 
        !           295:     pci_config_set_prog_interface(pci_conf, 0);
        !           296: 
        !           297:     pci_conf[PCI_INTERRUPT_PIN] = 1;
        !           298: 
        !           299:     pci_register_bar(&d->pci_dev, 0, 0x100,
        !           300:             PCI_BASE_ADDRESS_SPACE_IO, platform_ioport_map);
        !           301: 
        !           302:     /* reserve 16MB mmio address for share memory*/
        !           303:     pci_register_bar(&d->pci_dev, 1, 0x1000000,
        !           304:             PCI_BASE_ADDRESS_MEM_PREFETCH, platform_mmio_map);
        !           305: 
        !           306:     platform_fixed_ioport_init(d);
        !           307: 
        !           308:     return 0;
        !           309: }
        !           310: 
        !           311: static void platform_reset(DeviceState *dev)
        !           312: {
        !           313:     PCIXenPlatformState *s = DO_UPCAST(PCIXenPlatformState, pci_dev.qdev, dev);
        !           314: 
        !           315:     platform_fixed_ioport_reset(s);
        !           316: }
        !           317: 
        !           318: static PCIDeviceInfo xen_platform_info = {
        !           319:     .init = xen_platform_initfn,
        !           320:     .qdev.name = "xen-platform",
        !           321:     .qdev.desc = "XEN platform pci device",
        !           322:     .qdev.size = sizeof(PCIXenPlatformState),
        !           323:     .qdev.vmsd = &vmstate_xen_platform,
        !           324:     .qdev.reset = platform_reset,
        !           325: 
        !           326:     .vendor_id    =  PCI_VENDOR_ID_XEN,
        !           327:     .device_id    = PCI_DEVICE_ID_XEN_PLATFORM,
        !           328:     .class_id     = PCI_CLASS_OTHERS << 8 | 0x80,
        !           329:     .subsystem_vendor_id = PCI_VENDOR_ID_XEN,
        !           330:     .subsystem_id = PCI_DEVICE_ID_XEN_PLATFORM,
        !           331:     .revision = 1,
        !           332: };
        !           333: 
        !           334: static void xen_platform_register(void)
        !           335: {
        !           336:     pci_qdev_register(&xen_platform_info);
        !           337: }
        !           338: 
        !           339: device_init(xen_platform_register);

unix.superglobalmegacorp.com