diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2008-02-12 14:35:39 +0000 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2008-02-12 14:35:39 +0000 |
commit | 0243b256d6187ea610174531607366945e489605 (patch) | |
tree | fd2de9267b7493642626f8c84d7c81ebcd336bed /tools | |
parent | 67bfbd67d1311a1a590b47e568a07622d4492873 (diff) | |
download | xen-0243b256d6187ea610174531607366945e489605.tar.gz xen-0243b256d6187ea610174531607366945e489605.tar.bz2 xen-0243b256d6187ea610174531607366945e489605.zip |
Add stubdomain support. See stubdom/README for usage details.
- Move PAGE_SIZE and STACK_SIZE into __PAGE_SIZE and __STACK_SIZE in
arch_limits.h so as to permit getting them from there without
pulling all the internal Mini-OS defines.
- Setup a xen-elf cross-compilation environment in stubdom/cross-root
- Add a POSIX layer on top of Mini-OS by linking against the newlib C
library and lwIP, and implementing the Unixish part in mini-os/lib/sys.c
- Cross-compile zlib and libpci too.
- Add an xs.h-compatible layer on top of Mini-OS' xenbus.
- Cross-compile libxc with an additional xc_minios.c and a few things
disabled.
- Cross-compile ioemu with an additional block-vbd, but without sound,
tpm and other details. A few hacks are needed:
- Align ide and scsi buffers at least on sector size to permit
direct transmission to the block backend. While we are at it, just
page-align it to possibly save a segment. Also, limit the scsi
buffer size because of limitations of the block paravirtualization
protocol.
- Allocate big tables dynamically rather that letting them go to
bss: when Mini-OS gets installed in memory, bss is not lazily
allocated, and doing so during Mini-OS is unnecessarily trick while
we can simply use malloc.
- Had to change the Mini-OS compilation somehow, so as to export
Mini-OS compilation flags to the Makefiles of libxc and ioemu.
Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/ioemu/Makefile.target | 42 | ||||
-rw-r--r-- | tools/ioemu/aes.c | 2 | ||||
-rw-r--r-- | tools/ioemu/block-vbd.c | 341 | ||||
-rw-r--r-- | tools/ioemu/block.c | 3 | ||||
-rwxr-xr-x | tools/ioemu/configure | 22 | ||||
-rw-r--r-- | tools/ioemu/exec-all.h | 4 | ||||
-rw-r--r-- | tools/ioemu/hw/ide.c | 4 | ||||
-rw-r--r-- | tools/ioemu/hw/scsi-disk.c | 8 | ||||
-rw-r--r-- | tools/ioemu/hw/xen_machine_fv.c | 3 | ||||
-rw-r--r-- | tools/ioemu/vl.c | 65 | ||||
-rw-r--r-- | tools/ioemu/vl.h | 3 | ||||
-rw-r--r-- | tools/ioemu/vnc.c | 19 | ||||
-rw-r--r-- | tools/ioemu/xenstore.c | 19 | ||||
-rw-r--r-- | tools/libxc/Makefile | 23 | ||||
-rw-r--r-- | tools/libxc/ia64/Makefile | 2 | ||||
-rw-r--r-- | tools/libxc/xc_minios.c | 313 |
16 files changed, 846 insertions, 27 deletions
diff --git a/tools/ioemu/Makefile.target b/tools/ioemu/Makefile.target index 2b1bc6bb13..965d726adf 100644 --- a/tools/ioemu/Makefile.target +++ b/tools/ioemu/Makefile.target @@ -15,7 +15,7 @@ TARGET_BASE_ARCH:=sparc endif TARGET_PATH=$(SRC_PATH)/target-$(TARGET_BASE_ARCH)$(TARGET_SUB) VPATH=$(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw:$(SRC_PATH)/audio -CPPFLAGS=-I. -I.. -I$(TARGET_PATH) -I$(SRC_PATH) +CPPFLAGS+=-I. -I.. -I$(TARGET_PATH) -I$(SRC_PATH) CPPFLAGS+= -I$(XEN_ROOT)/tools/libxc CPPFLAGS+= -I$(XEN_ROOT)/tools/xenstore CPPFLAGS+= -I$(XEN_ROOT)/tools/include @@ -66,7 +66,11 @@ else QEMU_SYSTEM=qemu-fast endif +ifdef CONFIG_STUBDOM +QEMU_SYSTEM=qemu.a +else QEMU_SYSTEM=qemu-dm +endif ifdef CONFIG_USER_ONLY PROGS=$(QEMU_USER) @@ -345,14 +349,25 @@ VL_OBJS=vl.o osdep.o readline.o monitor.o pci.o console.o isa_mmio.o VL_OBJS+=cutils.o VL_OBJS+=block.o block-raw.o VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o block-qcow2.o +ifdef CONFIG_STUBDOM +VL_OBJS+=block-vbd.o +endif ifdef CONFIG_WIN32 VL_OBJS+=tap-win32.o endif -ifeq (,$(wildcard /usr/include/pci)) +ifdef CONFIG_STUBDOM +CONFIG_PASSTHROUGH=1 +else + ifeq (,$(wildcard /usr/include/pci)) $(warning *** pciutils-devl package not found - missing /usr/include/pci) $(warning *** PCI passthrough capability has been disabled) -else + else +CONFIG_PASSTHROUGH=1 + endif +endif + +ifdef CONFIG_PASSTHROUGH LIBS+=-lpci VL_OBJS+= pass-through.o CFLAGS += -DCONFIG_PASSTHROUGH @@ -404,13 +419,13 @@ VL_OBJS+= ne2000.o rtl8139.o pcnet.o e100.o ifeq ($(TARGET_BASE_ARCH), i386) # Hardware support -VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV) extboot.o +VL_OBJS+= ide.o pckbd.o ps2.o vga.o dma.o extboot.o ifeq ($(ARCH),ia64) VL_OBJS+= fdc.o mc146818rtc.o serial.o pc.o else VL_OBJS+= fdc.o serial.o pc.o endif -VL_OBJS+= cirrus_vga.o mixeng.o parallel.o acpi.o +VL_OBJS+= cirrus_vga.o parallel.o acpi.o VL_OBJS+= usb-uhci.o smbus_eeprom.o VL_OBJS+= piix4acpi.o VL_OBJS+= xenstore.o @@ -419,23 +434,32 @@ VL_OBJS+= xen_machine_fv.o VL_OBJS+= xen_machine_pv.o VL_OBJS+= xenfb.o VL_OBJS+= xen_console.o +ifndef CONFIG_STUBDOM VL_OBJS+= tpm_tis.o +VL_OBJS+= $(SOUND_HW) $(AUDIODRV) mixeng.o CPPFLAGS += -DHAS_TPM CPPFLAGS += -DHAS_AUDIO endif +endif ifeq ($(TARGET_BASE_ARCH), ppc) -VL_OBJS+= ppc.o ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV) +VL_OBJS+= ppc.o ide.o pckbd.o ps2.o vga.o dma.o VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o heathrow_pic.o mixeng.o VL_OBJS+= grackle_pci.o prep_pci.o unin_pci.o +ifndef CONFIG_STUBDOM +VL_OBJS+= $(SOUND_HW) $(AUDIODRV) CPPFLAGS += -DHAS_AUDIO endif +endif ifeq ($(TARGET_ARCH), mips) VL_OBJS+= mips_r4k.o mips_malta.o mips_timer.o mips_int.o dma.o vga.o serial.o i8254.o i8259.o VL_OBJS+= ide.o gt64xxx.o pckbd.o ps2.o fdc.o mc146818rtc.o usb-uhci.o acpi.o -VL_OBJS+= piix_pci.o parallel.o mixeng.o cirrus_vga.o $(SOUND_HW) $(AUDIODRV) +VL_OBJS+= piix_pci.o parallel.o mixeng.o cirrus_vga.o +ifndef CONFIG_STUBDOM +VL_OBJS+= $(SOUND_HW) $(AUDIODRV) DEFINES += -DHAS_AUDIO endif +endif ifeq ($(TARGET_BASE_ARCH), sparc) ifeq ($(TARGET_ARCH), sparc64) VL_OBJS+= sun4u.o ide.o pckbd.o ps2.o vga.o apb_pci.o @@ -513,7 +537,11 @@ SDL_LIBS := $(filter-out -mwindows, $(SDL_LIBS)) -mconsole endif $(QEMU_SYSTEM): $(VL_OBJS) libqemu.a +ifdef CONFIG_STUBDOM + $(AR) rcs $@ $(VL_OBJS) +else $(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(VL_LIBS) +endif cocoa.o: cocoa.m $(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $< diff --git a/tools/ioemu/aes.c b/tools/ioemu/aes.c index cd4484ff9b..e75b168a80 100644 --- a/tools/ioemu/aes.c +++ b/tools/ioemu/aes.c @@ -33,9 +33,11 @@ #define NDEBUG #include <assert.h> +#ifndef CONFIG_STUBDOM typedef uint32_t u32; typedef uint16_t u16; typedef uint8_t u8; +#endif #define MAXKC (256/32) #define MAXKB (256/8) diff --git a/tools/ioemu/block-vbd.c b/tools/ioemu/block-vbd.c new file mode 100644 index 0000000000..9cb97255e6 --- /dev/null +++ b/tools/ioemu/block-vbd.c @@ -0,0 +1,341 @@ +/* + * Block driver for Mini-os PV devices + * Based on block-raw.c + * + * Copyright (c) 2006 Fabrice Bellard, 2007 Samuel Thibault + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" +#include "block_int.h" +#include <assert.h> +#include <xenbus.h> +#include <blkfront.h> +#include <malloc.h> + +#define SECTOR_SIZE 512 + +#ifndef QEMU_TOOL +#include "exec-all.h" +#endif + +#define DEBUG_BLOCK +#ifdef DEBUG_BLOCK +#define DEBUG_BLOCK_PRINT( formatCstr, args... ) fprintf( logfile, formatCstr, ##args ); fflush( logfile ) +#else +#define DEBUG_BLOCK_PRINT( formatCstr, args... ) +#endif + +#define FTYPE_FILE 0 +#define FTYPE_CD 1 +#define FTYPE_FD 2 + +typedef struct BDRVVbdState { + struct blkfront_dev *dev; + int fd; + int type; + int mode; + uint64_t sectors; + unsigned sector_size; + QEMU_LIST_ENTRY(BDRVVbdState) list; +} BDRVVbdState; + +QEMU_LIST_HEAD(, BDRVVbdState) vbds; + +static int vbd_probe(const uint8_t *buf, int buf_size, const char *filename) +{ + char *value; + if (xenbus_read(XBT_NIL, filename, &value)) + return 0; + free(value); + return 100; +} + +static int vbd_open(BlockDriverState *bs, const char *filename, int flags) +{ + BDRVVbdState *s = bs->opaque; + + //handy to test posix access + //return -EIO; + + s->dev = init_blkfront((char *) filename, &s->sectors, &s->sector_size, &s->mode); + + if (!s->dev) + return -EIO; + + if (SECTOR_SIZE % s->sector_size) { + printf("sector size is %d, we only support sector sizes that divide %d\n", s->sector_size, SECTOR_SIZE); + return -EIO; + } + + s->fd = blkfront_open(s->dev); + + QEMU_LIST_INSERT_HEAD(&vbds, s, list); + + return 0; +} + +typedef struct VbdAIOCB { + BlockDriverAIOCB common; + struct blkfront_aiocb aiocb; +} VbdAIOCB; + +void qemu_aio_init(void) +{ +} + +void qemu_aio_poll(void) +{ + BDRVVbdState *s; + for (s = vbds.lh_first; s; s = s->list.le_next) + blkfront_aio_poll(s->dev); +} + +/* Wait for all IO requests to complete. */ +void qemu_aio_flush(void) +{ + BDRVVbdState *s; + for (s = vbds.lh_first; s; s = s->list.le_next) + blkfront_sync(s->dev); +} + +void qemu_aio_wait_start(void) +{ +} + +void qemu_aio_wait(void) +{ + int some = 0; + DEFINE_WAIT(w); + while (1) { + BDRVVbdState *s; + add_waiter(w, blkfront_queue); + for (s = vbds.lh_first; s; s = s->list.le_next) + if (blkfront_aio_poll(s->dev)) + some = 1; + if (some) + break; + schedule(); + } + remove_waiter(w); +} + +void qemu_aio_wait_end(void) +{ +} + +static void vbd_aio_callback(struct blkfront_aiocb *aiocbp, int ret) { + VbdAIOCB *acb = aiocbp->data; + + acb->common.cb(acb->common.opaque, ret); + qemu_aio_release(acb); +} + +static VbdAIOCB *vbd_aio_setup(BlockDriverState *bs, + int64_t sector_num, uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) +{ + BDRVVbdState *s = bs->opaque; + VbdAIOCB *acb; + + acb = qemu_aio_get(bs, cb, opaque); + if (!acb) + return NULL; + acb->aiocb.aio_dev = s->dev; + acb->aiocb.aio_buf = buf; + acb->aiocb.aio_nbytes = nb_sectors * SECTOR_SIZE; + acb->aiocb.aio_offset = sector_num * SECTOR_SIZE; + acb->aiocb.aio_cb = vbd_aio_callback; + acb->aiocb.data = acb; + + return acb; +} + +static BlockDriverAIOCB *vbd_aio_read(BlockDriverState *bs, + int64_t sector_num, uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) +{ + VbdAIOCB *acb; + + acb = vbd_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque); + if (!acb) + return NULL; + blkfront_aio(&acb->aiocb, 0); + return &acb->common; +} + +static BlockDriverAIOCB *vbd_aio_write(BlockDriverState *bs, + int64_t sector_num, const uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) +{ + VbdAIOCB *acb; + + acb = vbd_aio_setup(bs, sector_num, (uint8_t*) buf, nb_sectors, cb, opaque); + if (!acb) + return NULL; + blkfront_aio(&acb->aiocb, 1); + return &acb->common; +} + +static void vbd_cb(void *data, int ret) { + int *result = data; + result[0] = 1; + result[1] = ret; +} + +static int vbd_aligned_io(BlockDriverState *bs, + int64_t sector_num, uint8_t *buf, int nb_sectors, int write) +{ + VbdAIOCB *acb; + int result[2]; + result[0] = 0; + qemu_aio_wait_start(); + acb = vbd_aio_setup(bs, sector_num, (uint8_t*) buf, nb_sectors, vbd_cb, &result); + blkfront_aio(&acb->aiocb, write); + while (!result[0]) + qemu_aio_wait(); + qemu_aio_wait_end(); + return result[1]; +} + +static int vbd_read(BlockDriverState *bs, + int64_t sector_num, uint8_t *buf, int nb_sectors) +{ + uint8_t *iobuf; + int ret; + /* page alignment would be a bit better, but that's still fine compared to + * copying */ + if (!((uintptr_t)buf & (SECTOR_SIZE-1))) + return vbd_aligned_io(bs, sector_num, buf, nb_sectors, 0); + iobuf = memalign(PAGE_SIZE, nb_sectors * SECTOR_SIZE); + ret = vbd_aligned_io(bs, sector_num, iobuf, nb_sectors, 0); + memcpy(buf, iobuf, nb_sectors * SECTOR_SIZE); + free(iobuf); + if (ret < 0) + return ret; + else if (ret != nb_sectors * SECTOR_SIZE) + return -EINVAL; + else + return 0; +} + +static int vbd_write(BlockDriverState *bs, + int64_t sector_num, const uint8_t *buf, int nb_sectors) +{ + uint8_t *iobuf; + int ret; + if (!((uintptr_t)buf & (SECTOR_SIZE-1))) + return vbd_aligned_io(bs, sector_num, (uint8_t*) buf, nb_sectors, 1); + iobuf = memalign(PAGE_SIZE, nb_sectors * SECTOR_SIZE); + memcpy(iobuf, buf, nb_sectors * SECTOR_SIZE); + ret = vbd_aligned_io(bs, sector_num, iobuf, nb_sectors, 1); + free(iobuf); + if (ret < 0) + return ret; + else if (ret != nb_sectors * SECTOR_SIZE) + return -EINVAL; + else + return 0; +} + +static void vbd_aio_cancel(BlockDriverAIOCB *blockacb) +{ + /* TODO */ + //VbdAIOCB *acb = (VbdAIOCB *)blockacb; + + // Try to cancel. If can't, wait for it, drop the callback and call qemu_aio_release(acb) +} + +static void vbd_close(BlockDriverState *bs) +{ + BDRVVbdState *s = bs->opaque; + bs->total_sectors = 0; + if (s->fd >= 0) { + close(s->fd); + s->fd = -1; + } + QEMU_LIST_REMOVE(s, list); +} + +static int64_t vbd_getlength(BlockDriverState *bs) +{ + BDRVVbdState *s = bs->opaque; + return s->sectors * s->sector_size; +} + +static void vbd_flush(BlockDriverState *bs) +{ + BDRVVbdState *s = bs->opaque; + blkfront_sync(s->dev); +} + +/***********************************************/ +/* host device */ + +static int vbd_is_inserted(BlockDriverState *bs) +{ + /* TODO: monitor the backend */ + return 1; +} + +/* currently only used by fdc.c, but a CD version would be good too */ +static int vbd_media_changed(BlockDriverState *bs) +{ + /* TODO: monitor the backend */ + return -ENOTSUP; +} + +static int vbd_eject(BlockDriverState *bs, int eject_flag) +{ + /* TODO: Xen support needed */ + return -ENOTSUP; +} + +static int vbd_set_locked(BlockDriverState *bs, int locked) +{ + /* TODO: Xen support needed */ + return -ENOTSUP; +} + +BlockDriver bdrv_vbd = { + "vbd", + sizeof(BDRVVbdState), + vbd_probe, + vbd_open, + NULL, + NULL, + vbd_close, + NULL, + vbd_flush, + + .bdrv_aio_read = vbd_aio_read, + .bdrv_aio_write = vbd_aio_write, + .bdrv_aio_cancel = vbd_aio_cancel, + .aiocb_size = sizeof(VbdAIOCB), + .bdrv_read = vbd_read, + .bdrv_write = vbd_write, + .bdrv_getlength = vbd_getlength, + + /* removable device support */ + .bdrv_is_inserted = vbd_is_inserted, + .bdrv_media_changed = vbd_media_changed, + .bdrv_eject = vbd_eject, + .bdrv_set_locked = vbd_set_locked, +}; + diff --git a/tools/ioemu/block.c b/tools/ioemu/block.c index cf84e8ffbb..a43f3fe27b 100644 --- a/tools/ioemu/block.c +++ b/tools/ioemu/block.c @@ -1235,6 +1235,9 @@ void bdrv_init(void) { bdrv_register(&bdrv_raw); bdrv_register(&bdrv_host_device); +#ifdef CONFIG_STUBDOM + bdrv_register(&bdrv_vbd); +#endif #ifndef _WIN32 bdrv_register(&bdrv_cow); #endif diff --git a/tools/ioemu/configure b/tools/ioemu/configure index ef0bac1f8e..3e3b427b87 100755 --- a/tools/ioemu/configure +++ b/tools/ioemu/configure @@ -74,6 +74,7 @@ softmmu="yes" linux_user="no" darwin_user="no" build_docs="no" +stubdom="no" uname_release="" # OS specific @@ -231,6 +232,8 @@ for opt do ;; --enable-uname-release=*) uname_release="$optarg" ;; + --enable-stubdom) stubdom="yes" + ;; esac done @@ -416,7 +419,11 @@ if test -z "$target_list" ; then target_list="i386-darwin-user ppc-darwin-user $target_list" fi # the i386-dm target - target_list="i386-dm" + if test "$stubdom" = "yes"; then + target_list="i386-dm-stubdom" + else + target_list="i386-dm" + fi else target_list=`echo "$target_list" | sed -e 's/,/ /g'` fi @@ -575,6 +582,11 @@ bindir="$prefix/$libdir/xen/bin" configdir="/etc/xen" fi +if test "$stubdom" = "yes"; then + oss="no" + sdl="no" +fi + echo "Install prefix $prefix" echo "BIOS directory $datadir" echo "binary directory $bindir" @@ -943,6 +955,14 @@ if expr $target : '.*-dm' > /dev/null ; then echo "#define CONFIG_DM 1" >> $config_h fi +if test "$stubdom" = "yes" ; then + echo "CONFIG_STUBDOM=yes" >> $config_mak + echo "#define CONFIG_STUBDOM 1" >> $config_h + echo "#define NO_UNIX_SOCKETS 1" >> $config_h + echo "#define NO_DAEMONIZE 1" >> $config_h + echo "#define NO_AIO 1" >> $config_h +fi + if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" -o "$target_cpu" = "sparc" -o "$target_cpu" = "sparc64" -o "$target_cpu" = "m68k"; then echo "CONFIG_SOFTFLOAT=yes" >> $config_mak echo "#define CONFIG_SOFTFLOAT 1" >> $config_h diff --git a/tools/ioemu/exec-all.h b/tools/ioemu/exec-all.h index f6804b1a0a..28c120d4ca 100644 --- a/tools/ioemu/exec-all.h +++ b/tools/ioemu/exec-all.h @@ -481,6 +481,9 @@ static inline int testandset (int *p) } #endif +#ifdef CONFIG_STUBDOM +#include <spinlock.h> +#else typedef int spinlock_t; #define SPIN_LOCK_UNLOCKED 0 @@ -514,6 +517,7 @@ static inline int spin_trylock(spinlock_t *lock) return 1; } #endif +#endif extern spinlock_t tb_lock; diff --git a/tools/ioemu/hw/ide.c b/tools/ioemu/hw/ide.c index 0e65141ec6..cba064bd10 100644 --- a/tools/ioemu/hw/ide.c +++ b/tools/ioemu/hw/ide.c @@ -22,6 +22,7 @@ * THE SOFTWARE. */ #include "vl.h" +#include <malloc.h> /* debug IDE devices */ //#define DEBUG_IDE @@ -347,7 +348,7 @@ typedef struct IDEState { EndTransferFunc *end_transfer_func; uint8_t *data_ptr; uint8_t *data_end; - uint8_t io_buffer[MAX_MULT_SECTORS*512 + 4]; + uint8_t *io_buffer; QEMUTimer *sector_write_timer; /* only used for win2k instal hack */ uint32_t irq_count; /* counts IRQs when using win2k install hack */ } IDEState; @@ -2305,6 +2306,7 @@ static void ide_init2(IDEState *ide_state, for(i = 0; i < 2; i++) { s = ide_state + i; + s->io_buffer = memalign(getpagesize(), MAX_MULT_SECTORS*512 + 4); if (i == 0) s->bs = hd0; else diff --git a/tools/ioemu/hw/scsi-disk.c b/tools/ioemu/hw/scsi-disk.c index c6280fd559..d62d4d0d95 100644 --- a/tools/ioemu/hw/scsi-disk.c +++ b/tools/ioemu/hw/scsi-disk.c @@ -26,13 +26,18 @@ do { printf("scsi-disk: " fmt , ##args); } while (0) do { fprintf(stderr, "scsi-disk: " fmt , ##args); } while (0) #include "vl.h" +#include <malloc.h> #define SENSE_NO_SENSE 0 #define SENSE_NOT_READY 2 #define SENSE_HARDWARE_ERROR 4 #define SENSE_ILLEGAL_REQUEST 5 +#ifdef CONFIG_STUBDOM +#define SCSI_DMA_BUF_SIZE 32768 +#else #define SCSI_DMA_BUF_SIZE 65536 +#endif typedef struct SCSIRequest { SCSIDevice *dev; @@ -44,7 +49,7 @@ typedef struct SCSIRequest { int sector_count; /* The amounnt of data in the buffer. */ int buf_len; - uint8_t dma_buf[SCSI_DMA_BUF_SIZE]; + uint8_t *dma_buf; BlockDriverAIOCB *aiocb; struct SCSIRequest *next; } SCSIRequest; @@ -76,6 +81,7 @@ static SCSIRequest *scsi_new_request(SCSIDevice *s, uint32_t tag) free_requests = r->next; } else { r = qemu_malloc(sizeof(SCSIRequest)); + r->dma_buf = memalign(getpagesize(), SCSI_DMA_BUF_SIZE); } r->dev = s; r->tag = tag; diff --git a/tools/ioemu/hw/xen_machine_fv.c b/tools/ioemu/hw/xen_machine_fv.c index 22ba1dbc3f..272f67946f 100644 --- a/tools/ioemu/hw/xen_machine_fv.c +++ b/tools/ioemu/hw/xen_machine_fv.c @@ -24,6 +24,9 @@ */ #include "vl.h" +#ifdef CONFIG_STUBDOM +#include <xenbus.h> +#endif #include <xen/hvm/params.h> #include <sys/mman.h> diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c index 452bfcc555..6841f07848 100644 --- a/tools/ioemu/vl.c +++ b/tools/ioemu/vl.c @@ -36,22 +36,29 @@ #include <sys/times.h> #include <sys/wait.h> #include <termios.h> +#ifndef CONFIG_STUBDOM #include <sys/poll.h> +#endif #include <sys/mman.h> #include <sys/ioctl.h> #include <sys/resource.h> #include <sys/socket.h> #include <netinet/in.h> +#ifndef CONFIG_STUBDOM #include <net/if.h> +#endif #if defined(__NetBSD__) #include <net/if_tap.h> #endif #if defined(__linux__) || defined(__Linux__) #include <linux/if_tun.h> #endif +#ifndef CONFIG_STUBDOM #include <arpa/inet.h> #include <dirent.h> +#endif #include <netdb.h> +#ifndef CONFIG_STUBDOM #ifdef _BSD #include <sys/stat.h> #ifndef _BSD @@ -70,6 +77,7 @@ #include <stropts.h> #endif #endif +#endif #if defined(CONFIG_SLIRP) #include "libslirp.h" @@ -132,10 +140,9 @@ #define MAX_IOPORTS 65536 const char *bios_dir = CONFIG_QEMU_SHAREDIR; -char phys_ram_file[1024]; -void *ioport_opaque[MAX_IOPORTS]; -IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS]; -IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS]; +void **ioport_opaque; +IOPortReadFunc *(*ioport_read_table)[MAX_IOPORTS]; +IOPortWriteFunc *(*ioport_write_table)[MAX_IOPORTS]; /* Note: bs_table[MAX_DISKS] is a dummy block driver if none available to store the VM snapshots */ BlockDriverState *bs_table[MAX_DISKS + MAX_SCSI_DISKS + 1], *fd_table[MAX_FD]; @@ -270,6 +277,9 @@ void default_ioport_writel(void *opaque, uint32_t address, uint32_t data) void init_ioports(void) { + ioport_opaque = malloc(MAX_IOPORTS * sizeof(*ioport_opaque)); + ioport_read_table = malloc(3 * MAX_IOPORTS * sizeof(**ioport_read_table)); + ioport_write_table = malloc(3 * MAX_IOPORTS * sizeof(**ioport_write_table)); } /* size is the word size in byte */ @@ -797,9 +807,6 @@ static QEMUTimer *active_timers[2]; static MMRESULT timerID; static HANDLE host_alarm = NULL; static unsigned int period = 1; -#else -/* frequency of the times() clock tick */ -static int timer_freq; #endif QEMUClock *qemu_new_clock(int type) @@ -1137,9 +1144,6 @@ static void init_timer_alarm(void) struct itimerval itv; #endif - /* get times() syscall frequency */ - timer_freq = sysconf(_SC_CLK_TCK); - #ifndef CONFIG_DM /* timer signal */ sigfillset(&act.sa_mask); @@ -1497,6 +1501,7 @@ static CharDriverState *qemu_chr_open_file_out(const char *file_out) return qemu_chr_open_fd(-1, fd_out); } +#ifndef CONFIG_STUBDOM static CharDriverState *qemu_chr_open_pipe(const char *filename) { int fd_in, fd_out; @@ -1742,6 +1747,7 @@ static CharDriverState *qemu_chr_open_stdio(void) } return chr; } +#endif /* * Create a store entry for a device (e.g., monitor, serial/parallel lines). @@ -1751,6 +1757,9 @@ static CharDriverState *qemu_chr_open_stdio(void) static int store_dev_info(char *devName, int domid, CharDriverState *cState, char *storeString) { +#ifdef CONFIG_STUBDOM + return 0; +#else int xc_handle; struct xs_handle *xs; char *path; @@ -1826,8 +1835,10 @@ static int store_dev_info(char *devName, int domid, close(xc_handle); return 0; +#endif } +#ifndef CONFIG_STUBDOM #ifdef __sun__ /* Once Solaris has openpty(), this is going to be removed. */ int openpty(int *amaster, int *aslave, char *name, @@ -2486,6 +2497,7 @@ static CharDriverState *qemu_chr_open_win_file_out(const char *file_out) return qemu_chr_open_win_file(fd_out); } #endif +#endif /***********************************************************/ /* UDP Net console */ @@ -2978,12 +2990,14 @@ CharDriverState *qemu_chr_open(const char *filename) return qemu_chr_open_tcp(p, 0, 1); } else if (strstart(filename, "file:", &p)) { return qemu_chr_open_file_out(p); +#ifndef CONFIG_STUBDOM } else if (strstart(filename, "pipe:", &p)) { return qemu_chr_open_pipe(p); } else if (!strcmp(filename, "pty")) { return qemu_chr_open_pty(); } else if (!strcmp(filename, "stdio")) { return qemu_chr_open_stdio(); +#endif } else #endif #if defined(__linux__) @@ -3473,7 +3487,16 @@ static TAPState *net_tap_fd_init(VLANState *vlan, int fd) return s; } -#ifdef _BSD +#ifdef CONFIG_STUBDOM +#include <netfront.h> +static int tap_open(char *ifname, int ifname_size) +{ + char nodename[64]; + static int num = 1; // 0 is for our own TCP/IP networking + snprintf(nodename, sizeof(nodename), "device/vif/%d", num++); + return netfront_tap_open(nodename); +} +#elif defined(_BSD) static int tap_open(char *ifname, int ifname_size) { int fd; @@ -3561,6 +3584,7 @@ static int net_tap_init(VLANState *vlan, const char *ifname1, if (fd < 0) return -1; +#ifndef CONFIG_STUBDOM if (!setup_script || !strcmp(setup_script, "no")) setup_script = ""; if (setup_script[0] != '\0') { @@ -3593,6 +3617,7 @@ static int net_tap_init(VLANState *vlan, const char *ifname1, } } } +#endif s = net_tap_fd_init(vlan, fd); if (!s) return -1; @@ -7041,12 +7066,14 @@ int main(int argc, char **argv) char usb_devices[MAX_USB_CMDLINE][128]; int usb_devices_index; int fds[2]; +#ifndef CONFIG_STUBDOM struct rlimit rl; +#endif sigset_t set; char qemu_dm_logfilename[128]; const char *direct_pci = NULL; -#ifndef __sun__ +#if !defined(__sun__) && !defined(CONFIG_STUBDOM) /* Maximise rlimits. Needed where default constraints are tight (*BSD). */ if (getrlimit(RLIMIT_STACK, &rl) != 0) { perror("getrlimit(RLIMIT_STACK)"); @@ -7072,6 +7099,7 @@ int main(int argc, char **argv) perror("setrlimit(RLIMIT_MEMLOCK)"); #endif +#ifndef CONFIG_STUBDOM /* Ensure that SIGUSR2 is blocked by default when a new thread is created, then only the threads that use the signal unblock it -- this fixes a race condition in Qcow support where the AIO signal is misdelivered. */ @@ -7114,6 +7142,7 @@ int main(int argc, char **argv) } } #endif +#endif register_machines(); machine = first_machine; @@ -7631,7 +7660,15 @@ int main(int argc, char **argv) #ifdef CONFIG_DM bdrv_init(); xc_handle = xc_interface_open(); +#ifdef CONFIG_STUBDOM + char *domid_s, *msg; + if ((msg = xenbus_read(XBT_NIL, "domid", &domid_s))) + fprintf(stderr,"Can not read our own domid\n", msg); + else + xenstore_parse_domain_config(atoi(domid_s)); +#else /* CONFIG_STUBDOM */ xenstore_parse_domain_config(domid); +#endif /* CONFIG_STUBDOM */ #endif /* CONFIG_DM */ #ifdef USE_KQEMU @@ -7799,8 +7836,10 @@ int main(int argc, char **argv) vnc_display_password(ds, password); if ((vnc_display_port = vnc_display_open(ds, vnc_display, vncunused)) < 0) exit (0); +#ifndef CONFIG_STUBDOM if (vncviewer) vnc_start_viewer(vnc_display_port); +#endif xenstore_write_vncport(vnc_display_port); } else { #if defined(CONFIG_SDL) @@ -7928,6 +7967,7 @@ int main(int argc, char **argv) } #endif +#ifndef CONFIG_STUBDOM /* Unblock SIGTERM and SIGHUP, which may have been blocked by the caller */ signal(SIGHUP, SIG_DFL); sigemptyset(&set); @@ -7935,6 +7975,7 @@ int main(int argc, char **argv) sigaddset(&set, SIGHUP); if (sigprocmask(SIG_UNBLOCK, &set, NULL) == -1) fprintf(stderr, "Failed to unblock SIGTERM and SIGHUP\n"); +#endif main_loop(); quit_timers(); diff --git a/tools/ioemu/vl.h b/tools/ioemu/vl.h index 04d04845c5..00f5c16333 100644 --- a/tools/ioemu/vl.h +++ b/tools/ioemu/vl.h @@ -574,6 +574,9 @@ typedef struct BlockDriver BlockDriver; extern BlockDriver bdrv_raw; extern BlockDriver bdrv_host_device; +#ifdef CONFIG_STUBDOM +extern BlockDriver bdrv_vbd; +#endif extern BlockDriver bdrv_cow; extern BlockDriver bdrv_qcow; extern BlockDriver bdrv_vmdk; diff --git a/tools/ioemu/vnc.c b/tools/ioemu/vnc.c index 7b6e633f7a..f07ce8ca34 100644 --- a/tools/ioemu/vnc.c +++ b/tools/ioemu/vnc.c @@ -27,10 +27,12 @@ #include <sys/stat.h> #include <sys/socket.h> #include <netinet/in.h> -#include <arpa/inet.h> #include "vl.h" #include "qemu_socket.h" #include <assert.h> +#ifdef CONFIG_STUBDOM +#include <netfront.h> +#endif /* The refresh interval starts at BASE. If we scan the buffer and find no change, we increase by INC, up to MAX. If the mouse moves @@ -2407,7 +2409,9 @@ int vnc_display_open(DisplayState *ds, const char *display, int find_unused) #ifndef NO_UNIX_SOCKETS struct sockaddr_un uaddr; #endif +#ifndef CONFIG_STUBDOM int reuse_addr, ret; +#endif socklen_t addrlen; const char *p; VncState *vs = ds ? (VncState *)ds->opaque : vnc_state; @@ -2539,6 +2543,15 @@ int vnc_display_open(DisplayState *ds, const char *display, int find_unused) return -1; } +#ifdef CONFIG_STUBDOM + { + struct ip_addr ipaddr = { iaddr.sin_addr.s_addr }; + struct ip_addr netmask = { 0 }; + struct ip_addr gw = { 0 }; + networking_set_addr(&ipaddr, &netmask, &gw); + } +#endif + iaddr.sin_port = htons(ntohs(iaddr.sin_port) + 5900); vs->lsock = socket(PF_INET, SOCK_STREAM, 0); @@ -2549,6 +2562,7 @@ int vnc_display_open(DisplayState *ds, const char *display, int find_unused) return -1; } +#ifndef CONFIG_STUBDOM reuse_addr = 1; ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR, (const char *)&reuse_addr, sizeof(reuse_addr)); @@ -2560,6 +2574,7 @@ int vnc_display_open(DisplayState *ds, const char *display, int find_unused) vs->display = NULL; return -1; } +#endif } while (bind(vs->lsock, addr, addrlen) == -1) { @@ -2590,6 +2605,7 @@ int vnc_display_open(DisplayState *ds, const char *display, int find_unused) return ntohs(iaddr.sin_port); } +#ifndef CONFIG_STUBDOM int vnc_start_viewer(int port) { int pid, i, open_max; @@ -2617,4 +2633,5 @@ int vnc_start_viewer(int port) return pid; } } +#endif diff --git a/tools/ioemu/xenstore.c b/tools/ioemu/xenstore.c index 9d33237cb3..8cad6bda2d 100644 --- a/tools/ioemu/xenstore.c +++ b/tools/ioemu/xenstore.c @@ -11,8 +11,10 @@ #include "vl.h" #include "block_int.h" #include <unistd.h> +#ifndef CONFIG_STUBDOM #include <sys/ipc.h> #include <sys/shm.h> +#endif #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> @@ -219,10 +221,18 @@ void xenstore_parse_domain_config(int domid) } /* open device now if media present */ +#ifdef CONFIG_STUBDOM + if (pasprintf(&buf, "%s/device/vbd/%s", path, e[i]) == -1) + continue; + if (bdrv_open2(bs, buf, 0 /* snapshot */, &bdrv_vbd) == 0) { + pstrcpy(bs->filename, sizeof(bs->filename), params); + continue; + } +#endif + if (params[0]) { if (bdrv_open(bs, params, 0 /* snapshot */) < 0) - fprintf(stderr, "qemu: could not open hard disk image '%s'\n", - params); + fprintf(stderr, "qemu: could not open vbd '%s' or hard disk image '%s'\n", buf, params); } } @@ -265,6 +275,10 @@ extern int vga_ram_size, bios_size; void xenstore_process_logdirty_event(void) { +#ifdef CONFIG_STUBDOM + /* XXX we just can't use shm. */ + return; +#else char *act; static char *active_path = NULL; static char *next_active_path = NULL; @@ -367,6 +381,7 @@ void xenstore_process_logdirty_event(void) /* Ack that we've switched */ xs_write(xsh, XBT_NULL, active_path, act, len); free(act); +#endif } diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile index ffc5662052..41dcbab808 100644 --- a/tools/libxc/Makefile +++ b/tools/libxc/Makefile @@ -5,10 +5,12 @@ MAJOR = 3.2 MINOR = 0 CTRL_SRCS-y := +ifneq ($(stubdom),y) CTRL_SRCS-y += xc_core.c CTRL_SRCS-$(CONFIG_X86) += xc_core_x86.c CTRL_SRCS-$(CONFIG_IA64) += xc_core_ia64.c CTRL_SRCS-$(CONFIG_POWERPC) += xc_core_powerpc.c +endif CTRL_SRCS-y += xc_domain.c CTRL_SRCS-y += xc_evtchn.c CTRL_SRCS-y += xc_misc.c @@ -19,21 +21,29 @@ CTRL_SRCS-y += xc_private.c CTRL_SRCS-y += xc_sedf.c CTRL_SRCS-y += xc_csched.c CTRL_SRCS-y += xc_tbuf.c +ifneq ($(stubdom),y) CTRL_SRCS-y += xc_resume.c +endif CTRL_SRCS-$(CONFIG_X86) += xc_pagetab.c +ifneq ($(stubdom),y) CTRL_SRCS-$(CONFIG_Linux) += xc_linux.c CTRL_SRCS-$(CONFIG_SunOS) += xc_solaris.c CTRL_SRCS-$(CONFIG_X86_Linux) += xc_ptrace.c xc_ptrace_core.c CTRL_SRCS-$(CONFIG_NetBSD) += xc_netbsd.c +endif +CTRL_SRCS-$(stubdom) += xc_minios.c GUEST_SRCS-y := GUEST_SRCS-y += xg_private.c +ifneq ($(stubdom),y) GUEST_SRCS-$(CONFIG_MIGRATE) += xc_domain_restore.c xc_domain_save.c GUEST_SRCS-$(CONFIG_HVM) += xc_hvm_build.c +endif VPATH = ../../xen/common/libelf CFLAGS += -I../../xen/common/libelf +ifneq ($(stubdom),y) GUEST_SRCS-y += libelf-tools.c libelf-loader.c GUEST_SRCS-y += libelf-dominfo.c libelf-relocate.c @@ -46,6 +56,7 @@ GUEST_SRCS-y += xc_dom_compat_linux.c GUEST_SRCS-$(CONFIG_X86) += xc_dom_x86.c GUEST_SRCS-$(CONFIG_IA64) += xc_dom_ia64.c GUEST_SRCS-$(CONFIG_POWERPC) += xc_dom_powerpc.c +endif -include $(XEN_TARGET_ARCH)/Makefile @@ -64,6 +75,10 @@ CFLAGS += -Wp,-MD,.$(@F).d LDFLAGS += -L. DEPS = .*.d +ifneq ($(stubdom),y) +LDLIBS = -lpthread +endif + CTRL_LIB_OBJS := $(patsubst %.c,%.o,$(CTRL_SRCS-y)) CTRL_PIC_OBJS := $(patsubst %.c,%.opic,$(CTRL_SRCS-y)) @@ -71,10 +86,14 @@ GUEST_LIB_OBJS := $(patsubst %.c,%.o,$(GUEST_SRCS-y)) GUEST_PIC_OBJS := $(patsubst %.c,%.opic,$(GUEST_SRCS-y)) LIB := libxenctrl.a +ifneq ($(stubdom),y) LIB += libxenctrl.so libxenctrl.so.$(MAJOR) libxenctrl.so.$(MAJOR).$(MINOR) +endif LIB += libxenguest.a +ifneq ($(stubdom),y) LIB += libxenguest.so libxenguest.so.$(MAJOR) libxenguest.so.$(MAJOR).$(MINOR) +endif .PHONY: all all: build @@ -133,7 +152,7 @@ libxenctrl.so.$(MAJOR): libxenctrl.so.$(MAJOR).$(MINOR) ln -sf $< $@ libxenctrl.so.$(MAJOR).$(MINOR): $(CTRL_PIC_OBJS) - $(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenctrl.so.$(MAJOR) $(SHLIB_CFLAGS) -o $@ $^ -lpthread + $(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenctrl.so.$(MAJOR) $(SHLIB_CFLAGS) -o $@ $^ $(LDLIBS) # libxenguest @@ -146,7 +165,7 @@ libxenguest.so.$(MAJOR): libxenguest.so.$(MAJOR).$(MINOR) ln -sf $< $@ libxenguest.so.$(MAJOR).$(MINOR): $(GUEST_PIC_OBJS) libxenctrl.so - $(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenguest.so.$(MAJOR) $(SHLIB_CFLAGS) -o $@ $(GUEST_PIC_OBJS) -lz -lxenctrl -lpthread + $(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenguest.so.$(MAJOR) $(SHLIB_CFLAGS) -o $@ $(GUEST_PIC_OBJS) -lz -lxenctrl $(LDLIBS) -include $(DEPS) diff --git a/tools/libxc/ia64/Makefile b/tools/libxc/ia64/Makefile index 8a23024b24..4fd4fbbe86 100644 --- a/tools/libxc/ia64/Makefile +++ b/tools/libxc/ia64/Makefile @@ -1,3 +1,4 @@ +ifneq ($(stubdom),y) CTRL_SRCS-y += ia64/xc_ia64_stubs.c GUEST_SRCS-y += ia64/xc_ia64_hvm_build.c @@ -8,6 +9,7 @@ GUEST_SRCS-y += ia64/xc_dom_ia64_util.c GUEST_SRCS-y += ia64/dom_fw_acpi.c DOMFW_SRCS_BASE := dom_fw_common.c dom_fw_domu.c dom_fw_asm.S +endif DOMFW_SRCS := $(addprefix ia64/, $(DOMFW_SRCS_BASE)) $(DOMFW_SRCS): ln -sf ../$(XEN_ROOT)/xen/arch/ia64/xen/$(@F) $@ diff --git a/tools/libxc/xc_minios.c b/tools/libxc/xc_minios.c new file mode 100644 index 0000000000..53f7a148da --- /dev/null +++ b/tools/libxc/xc_minios.c @@ -0,0 +1,313 @@ +/****************************************************************************** + * + * Copyright 2007-2008 Samuel Thibault <samuel.thibault@eu.citrix.com>. + * All rights reserved. + * Use is subject to license terms. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + */ + +#undef NDEBUG +#include <types.h> +#include <os.h> +#include <mm.h> +#include <lib.h> +#include <events.h> +#include <wait.h> +#include <sys/mman.h> +#include <errno.h> + +#include <xen/memory.h> +#include <xen/sys/evtchn.h> +#include <unistd.h> +#include <fcntl.h> +#include <stdio.h> +#include <assert.h> +#include <stdint.h> +#include <inttypes.h> + +#include "xc_private.h" + +extern struct wait_queue_head event_queue; + +int xc_interface_open(void) +{ + return 0; +} + +int xc_interface_close(int xc_handle) +{ + return 0; +} + +void *xc_map_foreign_batch(int xc_handle, uint32_t dom, int prot, + xen_pfn_t *arr, int num) +{ + unsigned long pt_prot = 0; +#ifdef __ia64__ + /* TODO */ +#else + if (prot & PROT_READ) + pt_prot = L1_PROT_RO; + if (prot & PROT_WRITE) + pt_prot = L1_PROT; +#endif + return map_frames_ex(arr, num, 1, 0, 1, dom, 1, pt_prot); +} + +void *xc_map_foreign_range(int xc_handle, uint32_t dom, + int size, int prot, + unsigned long mfn) +{ + unsigned long pt_prot = 0; + printf("xc_map_foreign_range(%lx, %d)\n", mfn, size); +#ifdef __ia64__ + /* TODO */ +#else + if (prot & PROT_READ) + pt_prot = L1_PROT_RO; + if (prot & PROT_WRITE) + pt_prot = L1_PROT; +#endif + assert(!(size % getpagesize())); + return map_frames_ex(&mfn, size / getpagesize(), 0, 1, 1, dom, 0, pt_prot); +} + +int xc_map_foreign_ranges(int xc_handle, uint32_t dom, + privcmd_mmap_entry_t *entries, int nr) +{ + printf("xc_map_foreign_ranges, TODO\n"); + do_exit(); +} + +int do_xen_hypercall(int xc_handle, privcmd_hypercall_t *hypercall) +{ + multicall_entry_t call; + int i, ret; + + call.op = hypercall->op; + for (i = 0; i < sizeof(hypercall->arg) / sizeof(*hypercall->arg); i++) + call.args[i] = hypercall->arg[i]; + + ret = HYPERVISOR_multicall(&call, 1); + + if (ret < 0) { + errno = -ret; + return -1; + } + if (call.result < 0) { + errno = -call.result; + return -1; + } + return call.result; +} + +int xc_find_device_number(const char *name) +{ + printf("xc_find_device_number(%s)\n", name); + do_exit(); +} + +int xc_evtchn_open(void) +{ + int fd = alloc_fd(FTYPE_EVTCHN), i; + for (i = 0; i < MAX_EVTCHN_PORTS; i++) { + files[fd].evtchn.ports[i].port = -1; + files[fd].evtchn.ports[i].bound = 0; + } + printf("evtchn_open() -> %d\n", fd); + return fd; +} + +int xc_evtchn_close(int xce_handle) +{ + int i; + for (i = 0; i < MAX_EVTCHN_PORTS; i++) + if (files[xce_handle].evtchn.ports[i].bound) + unbind_evtchn(files[xce_handle].evtchn.ports[i].port); + files[xce_handle].type = FTYPE_NONE; + return 0; +} + +int xc_evtchn_fd(int xce_handle) +{ + return xce_handle; +} + +int xc_evtchn_notify(int xce_handle, evtchn_port_t port) +{ + int ret; + + ret = notify_remote_via_evtchn(port); + + if (ret < 0) { + errno = -ret; + ret = -1; + } + return ret; +} + +/* XXX Note: This is not threadsafe */ +static int port_alloc(int xce_handle) { + int i; + for (i= 0; i < MAX_EVTCHN_PORTS; i++) + if (files[xce_handle].evtchn.ports[i].port == -1) + break; + if (i == MAX_EVTCHN_PORTS) { + printf("Too many ports in xc handle\n"); + errno = EMFILE; + return -1; + } + files[xce_handle].evtchn.ports[i].pending = 0; + return i; +} + +static void poke_port(int xce_handle, evtchn_port_t port) +{ + shared_info_t *s = HYPERVISOR_shared_info; + printk("poking port %d\n", port); + synch_set_bit(port, &s->evtchn_pending[0]); + xc_evtchn_unmask(xce_handle, port); +} + +static void evtchn_handler(evtchn_port_t port, struct pt_regs *regs, void *data) +{ + int xce_handle = (intptr_t) data; + int i; + assert(files[xce_handle].type == FTYPE_EVTCHN); + mask_evtchn(port); + for (i= 0; i < MAX_EVTCHN_PORTS; i++) + if (files[xce_handle].evtchn.ports[i].port == port) + break; + if (i == MAX_EVTCHN_PORTS) { + printk("Unknown port for handle %d\n", xce_handle); + return; + } + files[xce_handle].evtchn.ports[i].pending++; + files[xce_handle].read = 1; + wake_up(&event_queue); +} + +evtchn_port_or_error_t xc_evtchn_bind_unbound_port(int xce_handle, int domid) +{ + int ret, i; + evtchn_port_t port; + + assert(get_current() == main_thread); + i = port_alloc(xce_handle); + if (i == -1) + return -1; + + printf("xc_evtchn_bind_unbound_port(%d)", domid); + ret = evtchn_alloc_unbound(domid, evtchn_handler, (void*)(intptr_t)xce_handle, &port); + printf(" = %d\n", ret); + + if (ret < 0) { + errno = -ret; + return -1; + } + files[xce_handle].evtchn.ports[i].bound = 1; + files[xce_handle].evtchn.ports[i].port = port; + return port; +} + +evtchn_port_or_error_t xc_evtchn_bind_interdomain(int xce_handle, int domid, + evtchn_port_t remote_port) +{ + evtchn_port_t local_port; + int ret, i; + + assert(get_current() == main_thread); + i = port_alloc(xce_handle); + if (i == -1) + return -1; + + printf("xc_evtchn_bind_interdomain(%d, %"PRId32")", domid, remote_port); + ret = evtchn_bind_interdomain(domid, remote_port, evtchn_handler, (void*)(intptr_t)xce_handle, &local_port); + printf(" = %d\n", ret); + + if (ret < 0) { + errno = -ret; + return -1; + } + files[xce_handle].evtchn.ports[i].bound = 1; + files[xce_handle].evtchn.ports[i].port = local_port; +/* Poke port on start: HVM won't send an event for the very first request since + * we were not ready yet */ + poke_port(xce_handle, local_port); + return local_port; +} + +int xc_evtchn_unbind(int xce_handle, evtchn_port_t port) +{ + int i; + for (i = 0; i < MAX_EVTCHN_PORTS; i++) + if (files[xce_handle].evtchn.ports[i].port == port) { + files[xce_handle].evtchn.ports[i].port = -1; + break; + } + if (i == MAX_EVTCHN_PORTS) + printf("Warning: couldn't find port %"PRId32" for xc handle %x\n", port, xce_handle); + files[xce_handle].evtchn.ports[i].bound = 0; + unbind_evtchn(port); + return 0; +} + +evtchn_port_or_error_t xc_evtchn_bind_virq(int xce_handle, unsigned int virq) +{ + evtchn_port_t port; + int i; + + assert(get_current() == main_thread); + i = port_alloc(xce_handle); + if (i == -1) + return -1; + + printf("xc_evtchn_bind_virq(%d)", virq); + port = bind_virq(virq, evtchn_handler, (void*)(intptr_t)xce_handle); + + if (port < 0) { + errno = -port; + return -1; + } + files[xce_handle].evtchn.ports[i].bound = 1; + files[xce_handle].evtchn.ports[i].port = port; + return port; +} + +evtchn_port_or_error_t xc_evtchn_pending(int xce_handle) +{ + int i; + unsigned long flags; + local_irq_save(flags); + for (i = 0; i < MAX_EVTCHN_PORTS; i++) { + evtchn_port_t port = files[xce_handle].evtchn.ports[i].port; + if (port != -1 && files[xce_handle].evtchn.ports[i].pending) { + files[xce_handle].evtchn.ports[i].pending--; + local_irq_restore(flags); + return port; + } + } + files[xce_handle].read = 0; + local_irq_restore(flags); + return -1; +} + +int xc_evtchn_unmask(int xce_handle, evtchn_port_t port) +{ + unmask_evtchn(port); + return 0; +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ |