diff -ur linux-2.6.15.4-orig/arch/i386/kernel/vsyscall-sigreturn.S linux-2.6.15.4-lilyvm/arch/i386/kernel/vsyscall-sigreturn.S --- linux-2.6.15.4-orig/arch/i386/kernel/vsyscall-sigreturn.S 2006-02-10 16:22:48.000000000 +0900 +++ linux-2.6.15.4-lilyvm/arch/i386/kernel/vsyscall-sigreturn.S 2006-03-08 11:50:24.000000000 +0900 @@ -22,7 +22,7 @@ .LSTART_sigreturn: popl %eax /* XXX does this mean it needs unwind info? */ movl $__NR_sigreturn, %eax - int $0x80 + .byte 0xcd,0x80 # int $0x80 .LEND_sigreturn: .size __kernel_sigreturn,.-.LSTART_sigreturn @@ -32,7 +32,7 @@ __kernel_rt_sigreturn: .LSTART_rt_sigreturn: movl $__NR_rt_sigreturn, %eax - int $0x80 + .byte 0xcd,0x80 # int $0x80 .LEND_rt_sigreturn: .size __kernel_rt_sigreturn,.-.LSTART_rt_sigreturn .balign 32 diff -ur linux-2.6.15.4-orig/drivers/block/Makefile linux-2.6.15.4-lilyvm/drivers/block/Makefile --- linux-2.6.15.4-orig/drivers/block/Makefile 2006-02-10 16:22:48.000000000 +0900 +++ linux-2.6.15.4-lilyvm/drivers/block/Makefile 2006-03-06 14:21:18.000000000 +0900 @@ -31,3 +31,5 @@ obj-$(CONFIG_BLK_DEV_SX8) += sx8.o obj-$(CONFIG_BLK_DEV_UB) += ub.o +obj-y += vmdisk.o + diff -ur linux-2.6.15.4-orig/drivers/net/Makefile linux-2.6.15.4-lilyvm/drivers/net/Makefile --- linux-2.6.15.4-orig/drivers/net/Makefile 2006-02-10 16:22:48.000000000 +0900 +++ linux-2.6.15.4-lilyvm/drivers/net/Makefile 2006-03-17 16:30:41.000000000 +0900 @@ -207,3 +207,5 @@ obj-$(CONFIG_FS_ENET) += fs_enet/ +obj-y += vmn.o + diff -ur linux-2.6.15.4-orig/include/asm-i386/fixmap.h linux-2.6.15.4-lilyvm/include/asm-i386/fixmap.h --- linux-2.6.15.4-orig/include/asm-i386/fixmap.h 2006-02-10 16:22:48.000000000 +0900 +++ linux-2.6.15.4-lilyvm/include/asm-i386/fixmap.h 2006-03-17 16:30:02.000000000 +0900 @@ -20,7 +20,7 @@ * Leave one empty page between vmalloc'ed areas and * the start of the fixmap. */ -#define __FIXADDR_TOP 0xfffff000 +#define __FIXADDR_TOP 0xbf6ff000 #ifndef __ASSEMBLY__ #include diff -ur linux-2.6.15.4-orig/include/asm-i386/page.h linux-2.6.15.4-lilyvm/include/asm-i386/page.h --- linux-2.6.15.4-orig/include/asm-i386/page.h 2006-02-10 16:22:48.000000000 +0900 +++ linux-2.6.15.4-lilyvm/include/asm-i386/page.h 2006-03-03 00:30:17.000000000 +0900 @@ -110,10 +110,10 @@ #endif /* __ASSEMBLY__ */ #ifdef __ASSEMBLY__ -#define __PAGE_OFFSET (0xC0000000) +#define __PAGE_OFFSET (0xA0000000) #define __PHYSICAL_START CONFIG_PHYSICAL_START #else -#define __PAGE_OFFSET (0xC0000000UL) +#define __PAGE_OFFSET (0xA0000000UL) #define __PHYSICAL_START ((unsigned long)CONFIG_PHYSICAL_START) #endif #define __KERNEL_START (__PAGE_OFFSET + __PHYSICAL_START) --- linux-2.6.15.4-orig/drivers/block/vmdisk.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.15.4-lilyvm/drivers/block/vmdisk.c 2006-03-06 14:47:02.000000000 +0900 @@ -0,0 +1,229 @@ +#include +#include +#include +/*#include */ +#include +#include +#include +#include + +#define DEVICE_NAME "vmdisk" +static int Major; +static int *vmdisk_sizes, *vmdisk_blksizes; +static int num_disks; + +static int device_open (struct inode *inode, struct file *file); + +static struct block_device_operations vmdisk_ops = { + .open = device_open, +}; + +static struct vmdisk_dev_t { + spinlock_t lock; + struct gendisk **d; + request_queue_t **q; + int *n; +} vmdisk; + +#define lilyvm_call_int (*(int(**)(int,...))0xbfafefac) +#define lilyvm_call_longlong (*(long long(**)(int,...))0xbfafef9c) +#define lilyvm_call lilyvm_call_int +#define LILYVM_CALL_VMDISK_NUM_DISKS 3 +#define LILYVM_CALL_VMDISK_GETSIZE 4 +#define LILYVM_CALL_VMDISK_PREAD 5 +#define LILYVM_CALL_VMDISK_PWRITE 6 + +static int +vmdisk_make_request (request_queue_t *q, struct bio *bio) +{ + unsigned int minor, len; + unsigned long long offset; + unsigned char *p; + int rw; + struct bio_vec *bvec; + int i, fail; + + rw = bio_data_dir (bio); + minor = *(int *)q->queuedata; + spin_lock_irq (&vmdisk.lock); + if (minor >= num_disks) goto fail; + if (rw == READA) rw = READ; + if (rw != READ && rw != WRITE) goto fail; + offset = bio->bi_sector << 9; + fail = 0; + bio_for_each_segment (bvec, bio, i) + { + len = bvec->bv_len; + /*if ((offset + len) >= (vmdisk_sizes[minor] << BLOCK_SIZE_BITS)) goto fail;*/ + if (((offset + len) >> BLOCK_SIZE_BITS) >= vmdisk_sizes[minor]) + fail = 1; + if (fail) + continue; + + p = page_address (bvec->bv_page) + bvec->bv_offset; + if (len > 0) + { + if (rw == READ) + { + lilyvm_call (LILYVM_CALL_VMDISK_PREAD, minor, p, len, offset); + } + else + { + lilyvm_call (LILYVM_CALL_VMDISK_PWRITE, minor, p, len, offset); + } + } + offset += len; + } + if (fail) + goto fail; + bio_endio (bio, bio->bi_size, 0); + spin_unlock_irq (&vmdisk.lock); + return 0; + fail: + spin_unlock_irq (&vmdisk.lock); + bio_io_error (bio, bio->bi_size); + return 0; +} + +static int __init +drv_init (void) +{ + int i, ret; + + Major = register_blkdev (0, DEVICE_NAME); + if (Major < 0) + { + printk (KERN_ALERT "Registering the block device failed with %d\n", + Major); + return Major; + } + + num_disks = lilyvm_call (LILYVM_CALL_VMDISK_NUM_DISKS); + vmdisk_sizes = kmalloc (sizeof (*vmdisk_sizes) * num_disks, GFP_KERNEL); + if (vmdisk_sizes == NULL) + { + ret = unregister_blkdev (Major, DEVICE_NAME); + if (ret < 0) printk (KERN_ALERT "Error in unregister_blkdev: %d\n", ret); + printk (KERN_ALERT "alloc_disk failed\n"); + return -ENOMEM; + } + + printk (KERN_ALERT "%s: major %d %d disks\n", + DEVICE_NAME, Major, num_disks); + + for (i = 0; i < num_disks; i++) + { + vmdisk_sizes[i] = (lilyvm_call_longlong (LILYVM_CALL_VMDISK_GETSIZE, i) >> 9/*BLOCK_SIZE_BITS*/) + 1; + printk (KERN_ALERT "%s: minor %d %d blocks\n", + DEVICE_NAME, i, vmdisk_sizes[i] - 1); + } + + spin_lock_init (&vmdisk.lock); + vmdisk.d = kmalloc (sizeof (*vmdisk.d) * num_disks, GFP_KERNEL); + if (vmdisk.d == NULL) + { + kfree (vmdisk_sizes); + ret = unregister_blkdev (Major, DEVICE_NAME); + if (ret < 0) printk (KERN_ALERT "Error in unregister_blkdev: %d\n", ret); + return -ENOMEM; + } + vmdisk.q = kmalloc (sizeof (*vmdisk.q) * num_disks, GFP_KERNEL); + if (vmdisk.q == NULL) + { + kfree (vmdisk.d); + kfree (vmdisk_sizes); + ret = unregister_blkdev (Major, DEVICE_NAME); + if (ret < 0) printk (KERN_ALERT "Error in unregister_blkdev: %d\n", ret); + return -ENOMEM; + } + vmdisk.n = kmalloc (sizeof (*vmdisk.n) * num_disks, GFP_KERNEL); + if (vmdisk.q == NULL) + { + kfree (vmdisk.q); + kfree (vmdisk.d); + kfree (vmdisk_sizes); + ret = unregister_blkdev (Major, DEVICE_NAME); + if (ret < 0) printk (KERN_ALERT "Error in unregister_blkdev: %d\n", ret); + return -ENOMEM; + } + for (i = 0; i < num_disks; i++) + { + vmdisk.n[i] = i; + vmdisk.d[i] = alloc_disk (num_disks); + if (!vmdisk.d[i]) + { + kfree (vmdisk_sizes); + /* FIXME: kfree vmdisk.d[0 to i-1] */ + /* FIXME: put_queue vmdisk.q[0 to i-1] */ + kfree (vmdisk.n); + kfree (vmdisk.q); + kfree (vmdisk.d); + ret = unregister_blkdev (Major, DEVICE_NAME); + if (ret < 0) printk (KERN_ALERT "Error in unregister_blkdev: %d\n", ret); + printk (KERN_ALERT "alloc_disk failed\n"); + return -ENOMEM; + } + vmdisk.d[i]->private_data = &vmdisk; + vmdisk.d[i]->major = Major; + vmdisk.d[i]->first_minor = i; + vmdisk.d[i]->minors = 1; + set_capacity (vmdisk.d[i], vmdisk_sizes[i]); + sprintf (vmdisk.d[i]->disk_name, "vmdisk%d", i); + vmdisk.d[i]->fops = &vmdisk_ops; + vmdisk.q[i] = blk_alloc_queue (GFP_KERNEL); + if (!vmdisk.q[i]) + { + kfree (vmdisk_sizes); + /* FIXME: kfree vmdisk.d[0 to i-1] */ + /* FIXME: put_queue vmdisk.q[0 to i-1] */ + ret = unregister_blkdev (Major, DEVICE_NAME); + if (ret < 0) printk (KERN_ALERT "Error in unregister_blkdev: %d\n", ret); + printk (KERN_ALERT "blk_alloc_queue failed\n"); + return -ENOMEM; + } + vmdisk.q[i]->queuedata = &vmdisk.n[i]; + vmdisk.d[i]->queue = vmdisk.q[i]; + blk_queue_make_request (vmdisk.q[i], vmdisk_make_request); + blk_queue_hardsect_size (vmdisk.q[i], 512/*BLOCK_SIZE*/); + } + for (i = 0; i < num_disks; i++) + add_disk (vmdisk.d[i]); + + return 0; +} + +static void __exit +drv_exit (void) +{ + int ret; + int i; + + for (i = 0; i < num_disks; i++) + { + del_gendisk (vmdisk.d[i]); + blk_put_queue (vmdisk.q[i]); + put_disk (vmdisk.d[i]); + } + kfree (vmdisk.n); + kfree (vmdisk.q); + kfree (vmdisk.d); + kfree (vmdisk_sizes); + ret = unregister_blkdev (Major, DEVICE_NAME); + if (ret < 0) printk (KERN_ALERT "Error in unregister_blkdev: %d\n", ret); + else printk (KERN_ALERT "%s: removed\n", DEVICE_NAME); +} + +static int +device_open (struct inode *inode, struct file *file) +{ + unsigned int minor; + + minor = MINOR (inode->i_rdev); + if (minor < num_disks) + return 0; + else + return -ENXIO; +} + +module_init (drv_init); +module_exit (drv_exit); --- linux-2.6.15.4-orig/drivers/net/vmn.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.15.4-lilyvm/drivers/net/vmn.c 2006-03-17 16:05:10.000000000 +0900 @@ -0,0 +1,179 @@ +/* + * vmn.c - LilyVM network driver + * + * Copyright 2004 Hideki EIRAKU + * Licensed under the GPL + */ + +/* + gcc -O -DMODULE -D__KERNEL__ -I linux/linux-2.4.22/include/ -Wall -c vmn.c +*/ + +#include +#include +#include /* struct net_device_stats */ +#include /* ARPHRD_PPP */ + +#define lilyvm_call_int (*(int(**)(int,...))0xbfafefac) +#define lilyvm_call_longlong (*(long long(**)(int,...))0xbfafef9c) +#define lilyvm_call lilyvm_call_int +#define LILYVM_CALL_VMN_WRITE 1 +#define LILYVM_CALL_VMN_READ 2 + +struct vmn_struct +{ + int i; + struct net_device_stats stats; +}; +static void vmn_intrpt (void *); + +static struct net_device *devs; +static int num_of_devs; +DECLARE_WORK (work, vmn_intrpt, NULL); +/* static struct tq_struct Task = { { NULL }, 0, vmn_intrpt, NULL }; */ +static volatile int intrpt = 0, incleanup = 0; + +static int +vmn_xmit (struct sk_buff *skb, struct net_device *dev) +{ + struct vmn_struct *p; + + p = dev->priv; + p->stats.tx_packets++; + p->stats.tx_bytes += skb->len; + lilyvm_call (LILYVM_CALL_VMN_WRITE, skb->data, skb->len); + dev_kfree_skb (skb); + return 0; +} + +static struct net_device_stats * +vmn_stats (struct net_device *dev) +{ + struct vmn_struct *p; + + p = dev->priv; + return &p->stats; +} + +static int __init +vmn_init (struct net_device *dev) +{ + dev->priv = kmalloc (sizeof (struct vmn_struct), GFP_KERNEL); + if (dev->priv == NULL) return -ENOMEM; + memset (dev->priv, 0, sizeof (struct vmn_struct)); + + dev->hard_start_xmit = vmn_xmit; + dev->get_stats = vmn_stats; + dev->hard_header_len = 0; + dev->addr_len = 0; + dev->mtu = 1500; + dev->type = ARPHRD_PPP; + dev->flags = IFF_NOARP; + dev->tx_queue_len = 0; + + return 0; +} + +static void +vmn_intr (void) +{ + struct sk_buff *skb; + struct vmn_struct *p; + static char buf[8192]; + static int len = 0; + + p = devs[0].priv; + if (len == 0) len = lilyvm_call (LILYVM_CALL_VMN_READ, buf, 8192); + while (len > 0) + { + skb = alloc_skb (len, GFP_ATOMIC); + if (skb == NULL) + { + intrpt = 1; + /* queue_task (&Task, &tq_timer); */ + schedule_delayed_work (&work, 1); + break; + } + memcpy (skb_put (skb, len), buf, len); + skb->dev = &devs[0]; + skb->mac.raw = skb->data; + skb->protocol = htons (ETH_P_IP); + if (netif_rx (skb) == NET_RX_DROP) + { + intrpt = 1; + /* queue_task (&Task, &tq_timer); */ + schedule_delayed_work (&work, 1); + break; + } + p->stats.rx_packets++; + p->stats.rx_bytes += len; + len = lilyvm_call (LILYVM_CALL_VMN_READ, buf, 8192); + } +} + +static void +vmn_interrupt (int irq, void *id, struct pt_regs *regs) +{ + vmn_intr (); +} + +static irqreturn_t +vmn_interrupt26 (int irq, void *id, struct pt_regs *regs) +{ + vmn_intr (); + return IRQ_HANDLED; +} + +static void +vmn_intrpt (void *p) +{ + intrpt = 0; + if (!incleanup) vmn_intr (); +} + +static int __init +vmn_init_module (void) +{ + int i; + + num_of_devs = 1; + devs = kmalloc (sizeof (*devs) * num_of_devs, GFP_KERNEL); + if (!devs) return -ENOMEM; + memset (devs, 0, sizeof (*devs) * num_of_devs); + for (i = 0; i < num_of_devs; i++) + { + devs[i].init = vmn_init; + SET_MODULE_OWNER (&devs[i]); + if (dev_alloc_name (&devs[i], "vmn%d") < 0) goto err; + /* if (register_netdevice (&devs[i]) < 0) goto err; */ + if (register_netdev (&devs[i]) < 0) goto err; + ((struct vmn_struct *)devs[i].priv)->i = i; + } + if (request_irq (1, vmn_interrupt26, SA_SHIRQ, "vmn", devs)) goto err; + return 0; + err: + printk (KERN_ERR "vmn: failed\n"); + return -EBUSY; +} + +static void __exit +vmn_cleanup_module (void) +{ + int i; + + incleanup = 1; + free_irq (1, "vmn"); + for (i = 0; i < num_of_devs; i++) + { + unregister_netdevice (&devs[i]); + kfree (devs[i].priv); + } + kfree (devs); + devs = NULL; + while (intrpt); /* :( */ + incleanup = 0; +} + +module_init (vmn_init_module); +module_exit (vmn_cleanup_module); +MODULE_LICENSE("GPL");