Annotation of qemu/hw/xen_platform.c, revision 1.1.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