diff -urNpB kernel-2.6.23-v2/Kbuild contrib/Kbuild --- kernel-2.6.23-v2/Kbuild +++ contrib/Kbuild @@ -57,4 +57,5 @@ quiet_cmd_syscalls = CALL $< PHONY += missing-syscalls missing-syscalls: scripts/checksyscalls.sh FORCE - $(call cmd,syscalls) + @echo Ignoring $@ +# $(call cmd,syscalls) diff -urNpB kernel-2.6.23-v2/arch/l4/Kconfig contrib/arch/l4/Kconfig --- kernel-2.6.23-v2/arch/l4/Kconfig +++ contrib/arch/l4/Kconfig @@ -1,3 +1,5 @@ +mainmenu "OKLinux Kernel Configuration" + config L4 bool default y @@ -23,7 +25,7 @@ config RWSEM_GENERIC_SPINLOCK bool default y -mainmenu "L4/Linux Kernel Configuration" +#mainmenu "L4/Linux Kernel Configuration" menu "L4/Linux-specific options" @@ -33,19 +35,19 @@ config L4KDB_CONSOLE config IG_SERIAL bool "Compile Iguana virtual serial driver" - default y + default n config IG_INPUT bool "Compile Iguana virtual input driver" - default y + default n config IG_MMC bool "Compile Iguana virtual mmc/sd driver" - default y + default n config IG_NET bool "Compile Iguana virtual net driver" - default y + default n config MTD_IGMTD tristate "Iguana virtual MTD device" @@ -69,13 +71,30 @@ config IG_AUDIO config IG_TOUCH bool "Compile Iguana virtual touch screen driver" depends on INPUT && INPUT_TOUCHSCREEN - default y + default n config FB_IGVIRTUAL tristate "Iguana Virtual Frame buffer support (ONLY FOR TESTING!)" depends on FB default n +config SCREEN_GENODE + bool + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + default y + +config BLOCK_GENODE + bool + select BLOCK + default y + +config NET_GENODE + bool + select NET + default y + endmenu config GENERIC_HWEIGHT @@ -212,12 +231,12 @@ bool "Support for PLEB2 platform" endchoice config NODES_SHIFT - int - default 4 + int "NODES_SHIFT" + default 5 # default "7" if MPENTIUM4 || X86_GENERIC config L4_ZONE_SIZE - int + int "L4_ZONE_SIZE" default 22 # default "7" if MPENTIUM4 || X86_GENERIC @@ -273,7 +292,7 @@ config CPU_HAS_LLDSCD config GENERIC_CALIBRATE_DELAY bool - default y + default n config ISA bool @@ -311,7 +330,7 @@ source "net/Kconfig" source "fs/Kconfig" config OKL4FS bool - default m + default n source "drivers/mmc/Kconfig" @@ -360,17 +379,17 @@ source "drivers/mca/Kconfig" endmenu -source "drivers/scsi/Kconfig" +source "drivers/parport/Kconfig" -source "drivers/ata/Kconfig" +source "drivers/pnp/Kconfig" -#source "security/Kconfig" +source "drivers/misc/Kconfig" -#source "crypto/Kconfig" +source "drivers/scsi/Kconfig" -source "lib/Kconfig" +source "drivers/ata/Kconfig" -#source "drivers/md/Kconfig" +source "drivers/md/Kconfig" source "drivers/mtd/Kconfig" @@ -384,12 +403,24 @@ source "drivers/net/Kconfig" source "drivers/hid/Kconfig" +source "drivers/hwmon/Kconfig" + +source "drivers/media/Kconfig" + source "drivers/usb/Kconfig" +source "drivers/leds/Kconfig" + source "sound/Kconfig" source "drivers/i2c/Kconfig" +source "security/Kconfig" + +source "crypto/Kconfig" + +source "lib/Kconfig" + menu "Kernel hacking" source "lib/Kconfig.debug" @@ -397,7 +428,7 @@ source "lib/Kconfig.debug" config EARLY_PRINTK bool "Early printk" if EMBEDDED depends on L4KDB_CONSOLE - default n + default y help Write kernel log output directly to L4 KDB. diff -urNpB kernel-2.6.23-v2/arch/l4/Makefile contrib/arch/l4/Makefile --- kernel-2.6.23-v2/arch/l4/Makefile +++ contrib/arch/l4/Makefile @@ -105,12 +105,21 @@ CFLAGS += -DCONFIG_HYBRID_MUTEXES core-y += $(ARCH_DIR)/kernel/ \ $(ARCH_DIR)/mm/ \ $(ARCH_DIR)/lib/ \ - $(ARCH_DIR)/sys-$(SYSTEM)/ \ - $(ARCH_DIR)/kernel/fs/okl4fs/ + $(ARCH_DIR)/sys-$(SYSTEM)/ + +# $(ARCH_DIR)/kernel/fs/okl4fs drivers-y += $(ARCH_DIR)/drivers/ -libs-y += -lvtimer -lvserial -ll4e -lll -liguana -ll4 -lgcc -lmutex -lcircular_buffer -lc -latomic_ops -lfs +#libs-y += -lvtimer -lvserial -ll4e -lll -liguana -ll4 -lgcc -lmutex -lcircular_buffer -lc -latomic_ops -lfs + +GENODE_LIBS = base base-common cxx startup \ + oklx + +libs-y += $(addprefix $(GENODE_LIBS_DIR)/,$(foreach l,$(GENODE_LIBS),$l/$l.lib.a)) + +# link libgcc +libs-y += $(shell $(CC) $(WOMBAT_CFLAGS) -print-libgcc-file-name) #libs-$(CONFIG_ARCH_PXA) += -lpxa @@ -128,7 +137,7 @@ AFLAGS += -D__arch_l4__ -D__SYSTEM__=$(S CFLAGS += -Iarch/l4/include -Iinclude/asm-l4 CFLAGS += -I../include -CFLAGS += -I../../../tools/magpie/include +#CFLAGS += -I../../../tools/magpie/include CFLAGS += $(WOMBAT_CFLAGS) AFLAGS += -Iarch/l4/include diff -urNpB kernel-2.6.23-v2/arch/l4/drivers/Makefile contrib/arch/l4/drivers/Makefile --- kernel-2.6.23-v2/arch/l4/drivers/Makefile +++ contrib/arch/l4/drivers/Makefile @@ -1,4 +1,6 @@ -obj-y := ig_ramdisk.o +obj-$(CONFIG_SCREEN_GENODE) += genode_fb.o +obj-$(CONFIG_BLOCK_GENODE) += genode_block.o +obj-$(CONFIG_NET_GENODE) += genode_net.o obj-$(CONFIG_FB_IGVIRTUAL) += ig_fb.o cfbcopyarea.o cfbfillrect.o cfbimgblt.o obj-$(CONFIG_L4KDB_CONSOLE) += l4kdb_console.o obj-$(CONFIG_IG_SERIAL) += ig_serial.o diff -urNpB kernel-2.6.23-v2/arch/l4/drivers/genode_block.c contrib/arch/l4/drivers/genode_block.c --- kernel-2.6.23-v2/arch/l4/drivers/genode_block.c +++ contrib/arch/l4/drivers/genode_block.c @@ -0,0 +1,273 @@ +/* + * \brief Block driver to access Genode's block service + * \author Stefan Kalkowski + * \date 2010-07-08 + * + * This file is based on the sbull block driver from + * Linux Device Drivers, 3rd edition chapter 16 "Block Drivers". + */ + +/* + * Copyright (C) 2006-2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/* Linux includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Genode support library includes */ +#include +#include + +enum Geometry { + KERNEL_SECTOR_SIZE = 512, /* sector size used by kernel */ + GENODE_BLK_MINORS = 16 /* number of minor numbers */ +}; + + +/* + * The internal representation of our device. + */ +static struct genode_blk_device { + unsigned blk_cnt; /* Total block count */ + unsigned long blk_sz; /* Single block size */ + spinlock_t lock; /* For mutual exclusion */ + struct gendisk *gd; /* Generic disk structure */ + struct request_queue *queue; /* The device request queue */ + struct semaphore queue_wait; /* Used to block, when queue is full */ + short stopped; /* Indicates queue availability */ +} blk_dev; + + +/* + * Handle an I/O request. + */ +static void genode_blk_request(struct request_queue *q) +{ + struct request *req; + unsigned long queue_offset; + + while ((req = elv_next_request(q)) != NULL) { + void *buf = 0; + unsigned long offset = req->sector * KERNEL_SECTOR_SIZE; + unsigned long nbytes = req->nr_sectors * KERNEL_SECTOR_SIZE; + short write = rq_data_dir(req); + + if (!blk_fs_request(req)) { + printk (KERN_NOTICE "Skip non-fs request\n"); + end_request(req, 0); + continue; + } + + blkdev_dequeue_request(req); + + while (!buf) { + if ((buf = genode_block_request(nbytes, req, &queue_offset))) + break; + + /* stop_queue needs disabled interrupts */ + isr_irq_disable(); + blk_stop_queue(q); + isr_irq_enable(); + + /* block until new responses are available */ + blk_dev.stopped = 1; + down(&blk_dev.queue_wait); + + /* start_queue needs disabled interrupts */ + isr_irq_disable(); + blk_start_queue(q); + isr_irq_enable(); + } + + if (write) { + struct bio *bio; + struct bio_vec *bvec; + int idx; + char *ptr = (char*) buf; + + rq_for_each_bio(bio, req) { + bio_for_each_segment(bvec, bio, idx) { + void *buffer = __bio_kmap_atomic(bio, idx, KM_USER0); + unsigned long sz = bio_cur_sectors(bio) * KERNEL_SECTOR_SIZE; + memcpy((void*)ptr, buffer, sz); + __bio_kunmap_atomic(buffer, KM_USER0); + } + } + } + + genode_block_submit(queue_offset, nbytes, offset, write); + } +} + + +static void genode_end_request(void *request, short write, + void *buf, unsigned long sz) { + struct request *req = (struct request*) request; + char *ptr = (char*) buf; + + if (!write) { + struct bio *bio; + struct bio_vec *bvec; + int idx; + rq_for_each_bio(bio, req) { + bio_for_each_segment(bvec, bio, idx) { + void *buffer = __bio_kmap_atomic(bio, idx, KM_USER0); + unsigned long nbytes = bio_cur_sectors(bio) * KERNEL_SECTOR_SIZE; + memcpy(buffer, (void*)ptr, nbytes); + ptr += nbytes; + __bio_kunmap_atomic(buffer, KM_USER0); + } + } + } + + if (!end_that_request_first(req, 1, req->nr_sectors)) + end_that_request_last(req, 1); + + if (blk_dev.stopped) { + blk_dev.stopped = 0; + up(&blk_dev.queue_wait); + } +} + + +/* + * Ioctl method. + */ +int genode_blk_ioctl (struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + struct hd_geometry geo; + struct genode_blk_device *dev = inode->i_bdev->bd_disk->private_data; + + switch(cmd) { + case HDIO_GETGEO: + { + /* + * Get geometry: since we cannot access the real geometry of the + * device, we have to make up something plausible. So we claim + * 16 sectors, four heads, and calculate the corresponding number + * of cylinders. We set the start of data at sector four. + */ + unsigned long size = dev->blk_cnt * dev->blk_sz * + (dev->blk_sz / KERNEL_SECTOR_SIZE); + geo.cylinders = (size & ~0x3f) >> 6; + geo.heads = 4; + geo.sectors = 16; + geo.start = 4; + if (copy_to_user((void *) arg, &geo, sizeof(geo))) + return -EFAULT; + return 0; + } + } + return -ENOTTY; /* unknown command */ +} + + +/* + * The device operations structure. + */ +static struct block_device_operations genode_blk_ops = { + .owner = THIS_MODULE, + .ioctl = genode_blk_ioctl +}; + +static int __init genode_blk_init(void) +{ + int major_num; + int writeable = 0; + unsigned long req_queue_sz = 0; + + if (!genode_config_block()) + return 0; + + /* Initialize device structure */ + memset (&blk_dev, 0, sizeof (struct genode_blk_device)); + spin_lock_init(&blk_dev.lock); + + genode_block_geometry((unsigned long*)&blk_dev.blk_cnt, + &blk_dev.blk_sz, &writeable, &req_queue_sz); + + genode_block_register_callback(genode_end_request); + + /* + * Get a request queue. + */ + if(!(blk_dev.queue = blk_init_queue(genode_blk_request, &blk_dev.lock))) + return -ENOMEM; + + /* + * Align queue requests to hardware sector size. + */ + blk_queue_hardsect_size(blk_dev.queue, blk_dev.blk_sz); + + /* + * Important, limit number of sectors per request, + * as Genode's block-session has a limited request-transmit-queue. + */ + blk_queue_max_sectors(blk_dev.queue, req_queue_sz / KERNEL_SECTOR_SIZE); + blk_dev.queue->queuedata = &blk_dev; + + sema_init(&blk_dev.queue_wait, 0); + blk_dev.stopped = 0; + + /* + * Register block device and gain major number. + */ + if((major_num = register_blkdev(0, "genode_blk")) < 0) { + printk(KERN_WARNING "genode_blk: unable to get major number\n"); + return -EBUSY; + } + + /* + * Allocate and setup generic disk structure. + */ + if(!(blk_dev.gd = alloc_disk(GENODE_BLK_MINORS))) { + unregister_blkdev(major_num, "genode_blk"); + return -ENOMEM; + } + blk_dev.gd->major = major_num; + blk_dev.gd->first_minor = 0; + blk_dev.gd->fops = &genode_blk_ops; + blk_dev.gd->private_data = &blk_dev; + blk_dev.gd->queue = blk_dev.queue; + strncpy(blk_dev.gd->disk_name, "sda", sizeof(blk_dev.gd->disk_name)); + set_capacity(blk_dev.gd, blk_dev.blk_cnt * + (blk_dev.blk_sz / KERNEL_SECTOR_SIZE)); + + /* Set it read-only or writeable */ + if(!writeable) + set_disk_ro(blk_dev.gd, 1); + + /* Make the block device available to the system */ + add_disk(blk_dev.gd); + printk("Genode blk-file driver initialized\n"); + return 0; +} + + +static void __exit +genode_blk_exit(void) +{ + del_gendisk(blk_dev.gd); + put_disk(blk_dev.gd); + unregister_blkdev(blk_dev.gd->major, "genode_blk"); + blk_cleanup_queue(blk_dev.queue); +} + +module_init(genode_blk_init); +module_exit(genode_blk_exit); + +MODULE_LICENSE("GPL"); diff -urNpB kernel-2.6.23-v2/arch/l4/drivers/genode_fb.c contrib/arch/l4/drivers/genode_fb.c --- kernel-2.6.23-v2/arch/l4/drivers/genode_fb.c +++ contrib/arch/l4/drivers/genode_fb.c @@ -0,0 +1,511 @@ +/* + * \brief Genode screen driver + * \author Stefan Kalkowski + * \date 2010-04-20 + * + * This driver enables usage of any of Genode's framebuffer, input + * and nitpicker sessions, as defined in Linux corresponding XML config stub. + * The implementation is based on virtual (vfb.c) and + * L4 (l4fb.c) framebuffer driver of L4Linux from TU-Dresden. + */ + +/* + * Copyright (C) 2010-2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/* Linux includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Platform includes */ +#include + +/* Genode support lib includes */ +#include +#include +#include + + +/********************************** + ** Datastructure declarations ** + **********************************/ + +/** + * List of available framebuffers (used by device->driver_data) + */ +struct genodefb_infolist { + struct fb_info *info; + struct genodefb_infolist *next; +}; + + +/********************** + ** Global variables ** + **********************/ + +static const char GENODEFB_DRV_NAME[] = "genodefb"; + +static struct fb_var_screeninfo genodefb_var __initdata = { + .activate = FB_ACTIVATE_NOW, + .height = -1, + .width = -1, + .right_margin = 32, + .upper_margin = 16, + .lower_margin = 4, + .vsync_len = 4, + .vmode = FB_VMODE_NONINTERLACED, + .bits_per_pixel = 16, // Genode only supports RGB565 by now */ + .red.length = 5, + .red.offset = 11, + .green.length = 6, + .green.offset = 5, + .blue.length = 5, + .blue.offset = 0, + .transp.length = 0, + .transp.offset = 0, +}; + +static struct fb_fix_screeninfo genodefb_fix __initdata = { + .id = "genode_fb", + .type = FB_TYPE_PACKED_PIXELS, + .accel = FB_ACCEL_NONE, + .visual = FB_VISUAL_TRUECOLOR, + .ypanstep = 0, + .ywrapstep = 0, +}; + +static u32 pseudo_palette[17]; + + +/************************* + ** Device operations ** + *************************/ + +/* + * Set a single color register. The values supplied are + * already rounded down to the hardware's capabilities + * (according to the entries in the `var' structure). Return + * != 0 for invalid regno and pixel formats. + */ +static int genodefb_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, + struct fb_info *info) +{ + if (regno >= info->cmap.len || info->var.bits_per_pixel != 16) + return 1; + + if (regno < 16) + ((u32*) (info->pseudo_palette))[regno] = + ((red >> (16 - info->var.red.length)) << info->var.red.offset) | + ((green >> (16 - info->var.green.length)) << info->var.green.offset) | + ((blue >> (16 - info->var.blue.length)) << info->var.blue.offset); + return 0; +} + + +/** + * Pan or Wrap the Display + * + * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag + */ +static int genodefb_pan_display(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + if (var->vmode & FB_VMODE_YWRAP) { + if (var->yoffset < 0 + || var->yoffset >= info->var.yres_virtual + || var->xoffset) + return -EINVAL; + } else { + if (var->xoffset + var->xres > info->var.xres_virtual || + var->yoffset + var->yres > info->var.yres_virtual) + return -EINVAL; + } + info->var.xoffset = var->xoffset; + info->var.yoffset = var->yoffset; + if (var->vmode & FB_VMODE_YWRAP) + info->var.vmode |= FB_VMODE_YWRAP; + else + info->var.vmode &= ~FB_VMODE_YWRAP; + return 0; +} + + +static void genodefb_copyarea(struct fb_info *info, + const struct fb_copyarea *region) +{ + cfb_copyarea(info, region); + genode_fb_refresh(info->node, region->dx, region->dy, + region->width, region->height); +} + + +static void genodefb_fillrect(struct fb_info *info, + const struct fb_fillrect *rect) +{ + cfb_fillrect(info, rect); + genode_fb_refresh(info->node, rect->dx, rect->dy, + rect->width, rect->height); +} + + +static void genodefb_imageblit(struct fb_info *info, + const struct fb_image *image) +{ + cfb_imageblit(info, image); + genode_fb_refresh(info->node, image->dx, image->dy, + image->width, image->height); +} + + +static int genodefb_open(struct fb_info *info, int user) +{ + return 0; +} + + +static int genodefb_release(struct fb_info *info, int user) +{ + genode_nit_close_all_views(info->node); + return 0; +} + + +static int genodefb_ioctl(struct fb_info *info, unsigned int cmd, + unsigned long arg) +{ + void __user *argp = (void __user *)arg; + switch (cmd) { + case NITPICKER_IOCTL_CREATE_VIEW: + { + genode_nit_view_create(info->node, (int)arg); + break; + } + case NITPICKER_IOCTL_DESTROY_VIEW: + { + genode_nit_view_destroy(info->node, (int)arg); + break; + } + case NITPICKER_IOCTL_BACK_VIEW: + { + genode_nit_view_back(info->node, (int)arg); + break; + } + case NITPICKER_IOCTL_PLACE_VIEW: + { + struct genode_view_place val; + if (copy_from_user(&val, argp, sizeof(val))) + return -EFAULT; + genode_nit_view_place(info->node, val.view, val.reg.x, + val.reg.y, val.reg.w, val.reg.h); + break; + } + case NITPICKER_IOCTL_STACK_VIEW: + { + struct genode_view_stack val; + if (copy_from_user(&val, argp, sizeof(val))) + return -EFAULT; + genode_nit_view_stack(info->node, val.view, + val.neighbor, val.behind); + break; + } + case FRAMEBUFFER_IOCTL_REFRESH: + { + struct genode_screen_region val; + if (copy_from_user(&val, argp, sizeof(val))) + return -EFAULT; + genode_fb_refresh(info->node, val.x, val.y, val.w, val.h); + break; + } + default: + printk(KERN_INFO "Unknown ioctl command: %d\n", cmd); + } + return 0; +} + + +static struct fb_ops genodefb_ops = { + .owner = THIS_MODULE, + .fb_open = genodefb_open, + .fb_release = genodefb_release, + .fb_setcolreg = genodefb_setcolreg, + .fb_pan_display = genodefb_pan_display, + .fb_fillrect = genodefb_fillrect, + .fb_ioctl = genodefb_ioctl, + .fb_copyarea = genodefb_copyarea, + .fb_imageblit = genodefb_imageblit, +}; + + +/*********************** + ** Input callbacks ** + ***********************/ + +void input_event_callback (void *dev, unsigned int type, + unsigned int code, int value) +{ + struct input_dev *input_dev = (struct input_dev*) dev; + input_event(input_dev, type, code, value); + input_sync(input_dev); +} + + +/*************************************** + ** Device initialization / removal ** + ***************************************/ + +static int __init genodefb_register_input_devices(unsigned int idx, + unsigned int xres, + unsigned int yres) +{ + int i; + struct input_dev *mouse_dev = input_allocate_device(); + struct input_dev *keyb_dev = input_allocate_device(); + if (!keyb_dev || !mouse_dev) + return -ENOMEM; + + + /**************** + ** Keyboard ** + ****************/ + + keyb_dev->name = "Genode input key"; + keyb_dev->phys = "Genode fb key"; + keyb_dev->id.bustype = BUS_USB; + keyb_dev->id.vendor = 0; + keyb_dev->id.product = 0; + keyb_dev->id.version = 0; + + /* We generate key events */ + set_bit(EV_KEY, keyb_dev->evbit); + set_bit(EV_REP, keyb_dev->evbit); + + /* We can generate every key */ + for (i = 0; i < 0x100; i++) + set_bit(i, keyb_dev->keybit); + + /* Register keyboard device */ + input_register_device(keyb_dev); + genode_input_register_keyb(idx, (void*) keyb_dev); + + + /************* + ** Mouse ** + *************/ + + mouse_dev->name = "Genode input mouse"; + mouse_dev->phys = "Genode mouse"; + mouse_dev->id.bustype = BUS_USB; + mouse_dev->id.vendor = 0; + mouse_dev->id.product = 0; + mouse_dev->id.version = 0; + + /* We generate key and relative mouse events */ + set_bit(EV_KEY, mouse_dev->evbit); + set_bit(EV_REP, mouse_dev->evbit); + set_bit(EV_REL, mouse_dev->evbit); + set_bit(EV_ABS, mouse_dev->evbit); + + /* Buttons */ + set_bit(BTN_0, mouse_dev->keybit); + set_bit(BTN_1, mouse_dev->keybit); + set_bit(BTN_2, mouse_dev->keybit); + set_bit(BTN_3, mouse_dev->keybit); + set_bit(BTN_4, mouse_dev->keybit); + set_bit(BTN_LEFT, mouse_dev->keybit); + set_bit(BTN_RIGHT, mouse_dev->keybit); + set_bit(BTN_MIDDLE, mouse_dev->keybit); + + /* Movements */ + set_bit(REL_X, mouse_dev->relbit); + set_bit(REL_Y, mouse_dev->relbit); + set_bit(ABS_X, mouse_dev->absbit); + set_bit(ABS_Y, mouse_dev->absbit); + + /* Coordinates are 1:1 pixel in frame buffer */ + mouse_dev->absmax[ABS_X] = xres; + mouse_dev->absmax[ABS_Y] = yres; + mouse_dev->absmin[ABS_X] = 0; + mouse_dev->absmin[ABS_Y] = 0; + + /* We are precise */ + mouse_dev->absfuzz[ABS_X] = 0; + mouse_dev->absfuzz[ABS_Y] = 0; + mouse_dev->absflat[ABS_X] = 0; + mouse_dev->absflat[ABS_Y] = 0; + + /* Register mouse device */ + input_register_device(mouse_dev); + genode_input_register_mouse(idx, (void*) mouse_dev); + return 0; +} + + +static int __init genodefb_probe(struct platform_device *dev) +{ + struct genodefb_infolist *pred=0, *succ; + int i, ret, cnt = genode_screen_count(); + + /* + * Iterate through all available framebuffers + */ + for (i=0; i < cnt; i++) { + + /* Allocate new framebuffer list entry */ + if(!(succ = kmalloc(sizeof(struct genodefb_infolist), GFP_KERNEL))) + return -ENOMEM; + succ->next = 0; + + /* Set first entry as driver's private data, else concatenate it */ + if (!i) + platform_set_drvdata(dev, succ); + else + pred->next = succ; + pred = succ; + + /* Allocate new framebuffer info struct */ + pred->info = framebuffer_alloc(0, &dev->dev); + if (!pred->info) + return -ENOMEM; + + /* Copy default values */ + pred->info->var = genodefb_var; + pred->info->fix = genodefb_fix; + + /* Get framebuffer dimensions from Genode's support lib */ + pred->info->screen_base = genode_fb_attach(i); + pred->info->screen_size = genode_fb_size(i); + pred->info->fix.smem_start = (unsigned long) pred->info->screen_base; + pred->info->fix.smem_len = pred->info->screen_size; + if (!pred->info->screen_base || !pred->info->screen_size) { + printk(KERN_ERR "genode_fb: abort, could not be initialized.\n"); + framebuffer_release(pred->info); + return -EIO; + } + + /* Get framebuffer resolution from Genode's support lib */ + genode_fb_info(i, &pred->info->var.xres, &pred->info->var.yres); + + /* We only support 16-Bit Pixel, so line length is xres*2 */ + pred->info->fix.line_length = pred->info->var.xres * 2; + + /* Set virtual resolution to visible resolution */ + pred->info->var.xres_virtual = pred->info->var.xres; + pred->info->var.yres_virtual = pred->info->screen_size + / pred->info->fix.line_length; + + /* Some dummy values for timing to make fbset happy */ + pred->info->var.pixclock = 10000000 / pred->info->var.xres + * 1000 / pred->info->var.yres; + pred->info->var.left_margin = (pred->info->var.xres / 8) & 0xf8; + pred->info->var.hsync_len = (pred->info->var.xres / 8) & 0xf8; + + pred->info->fbops = &genodefb_ops; + pred->info->pseudo_palette = pseudo_palette; + pred->info->flags = FBINFO_FLAG_DEFAULT; + + printk(KERN_INFO "genode_fb:framebuffer at 0x%p, size %dk\n", + pred->info->screen_base, (int)(pred->info->screen_size >> 10)); + printk(KERN_INFO "genode_fb: mode is %dx%dx%d\n", + pred->info->var.xres, pred->info->var.yres, + pred->info->var.bits_per_pixel); + + /* Allocate 16-Bit colormap */ + ret = fb_alloc_cmap(&pred->info->cmap, 16, 0); + if (ret < 0) { + framebuffer_release(pred->info); + return ret; + } + + /* Register framebuffer info structure */ + if (register_framebuffer(pred->info) < 0) { + fb_dealloc_cmap(&pred->info->cmap); + framebuffer_release(pred->info); + return -EINVAL; + } + + ret = genodefb_register_input_devices(i, pred->info->var.xres, + pred->info->var.yres); + if (ret) { + fb_dealloc_cmap(&pred->info->cmap); + framebuffer_release(pred->info); + return ret; + } + } + return 0; +} + + +static int genodefb_remove(struct platform_device *device) +{ + struct genodefb_infolist *succ = platform_get_drvdata(device); + + while (succ && succ->info) { + struct genodefb_infolist *pred = succ; + succ = succ->next; + genode_fb_close(pred->info->node); + unregister_framebuffer(pred->info); + framebuffer_release(pred->info); + kfree(pred); + } + platform_set_drvdata(device, 0); + return 0; +} + + +/*************************************** + ** Module initialization / removal ** + ***************************************/ + +static struct platform_driver genodefb_driver = { + .probe = genodefb_probe, + .remove = genodefb_remove, + .driver.name = GENODEFB_DRV_NAME, +}; + +static struct platform_device genodefb_device = { + .name = GENODEFB_DRV_NAME, +}; + + +static int __init genodefb_init(void) +{ + int ret = platform_driver_register(&genodefb_driver); + if (!ret) { + ret = platform_device_register(&genodefb_device); + if (ret) + platform_driver_unregister(&genodefb_driver); + } + genode_input_register_callback(&input_event_callback); + return ret; +} +module_init(genodefb_init); + + +static void __exit genodefb_exit(void) +{ + platform_device_unregister(&genodefb_device); + platform_driver_unregister(&genodefb_driver); + genode_input_unregister_callback(); +} +module_exit(genodefb_exit); + + +MODULE_AUTHOR("Stefan Kalkowski "); +MODULE_DESCRIPTION("Frame buffer driver for OKLinux on Genode"); +MODULE_LICENSE("GPL v2"); diff -urNpB kernel-2.6.23-v2/arch/l4/drivers/genode_net.c contrib/arch/l4/drivers/genode_net.c --- kernel-2.6.23-v2/arch/l4/drivers/genode_net.c +++ contrib/arch/l4/drivers/genode_net.c @@ -0,0 +1,165 @@ +/* + * \brief NIC driver to access Genode's nic service + * \author Stefan Kalkowski + * \date 2010-09-09 + */ + +/* + * Copyright (C) 2006-2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/* Linux includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static struct net_device *net_dev; + + +static void genode_net_receive_packet(void* dev_addr, void *addr, + unsigned long size) +{ + struct net_device *dev = (struct net_device *) dev_addr; + struct net_device_stats *stats = (struct net_device_stats*) netdev_priv(dev); + + /* allocate skb */ + struct sk_buff *skb = dev_alloc_skb(size + 2); + if (!skb) { + if (printk_ratelimit()) + printk(KERN_NOTICE "genode_net_rx: low on mem - packet dropped!\n"); + stats->rx_dropped++; + return; + } + + /* copy packet */ + memcpy(skb_put(skb, size), addr, size); + + skb->dev = dev; + skb->protocol = eth_type_trans(skb, dev); + skb->ip_summed = CHECKSUM_NONE; + netif_rx(skb); + + stats->rx_packets++; + stats->rx_bytes += size; +} + + +/******************************** + ** Network driver functions ** + ********************************/ + +int genode_net_open(struct net_device *dev) +{ + genode_net_start(dev, genode_net_receive_packet); + netif_start_queue(dev); + return 0; +} + + +int genode_net_close(struct net_device *dev) +{ + netif_stop_queue(dev); + genode_net_stop(); + return 0; +} + + +int genode_net_xmit_frame(struct sk_buff *skb, struct net_device *dev) +{ + struct net_device_stats *stats = (struct net_device_stats*) netdev_priv(dev); + int len = skb->len; + void* addr = skb->data; + + /* collect acknowledgements of old packets */ + while (genode_net_tx_ack_avail()) + dev_kfree_skb((struct sk_buff *)genode_net_tx_ack()); + + /* transmit to nic-session */ + if (genode_net_tx(addr, len, skb)) { + /* tx queue is full, could not enqueue packet */ + netif_stop_queue(dev); + return 1; + } + + /* save timestamp */ + dev->trans_start = jiffies; + + stats->tx_packets++; + stats->tx_bytes += len; + return 0; +} + + +struct net_device_stats* genode_net_get_stats(struct net_device *dev) +{ + return (struct net_device_stats*) netdev_priv(dev); +} + + +void genode_net_tx_timeout(struct net_device *dev) +{ +} + + +/************************** + ** De-/Initialization ** + **************************/ + +/* Setup and register the device. */ +static int __init genode_net_init(void) +{ + int err = 0; + + if (!genode_net_ready()) + return 0; + + /* allocate network device */ + if (!(net_dev = alloc_etherdev(sizeof(struct net_device_stats)))) + goto out; + + net_dev->open = genode_net_open; + net_dev->stop = genode_net_close; + net_dev->hard_start_xmit = genode_net_xmit_frame; + net_dev->get_stats = genode_net_get_stats; + net_dev->tx_timeout = genode_net_tx_timeout; + net_dev->watchdog_timeo = 20 * HZ; + + /* set MAC address */ + genode_net_mac(net_dev->dev_addr, ETH_ALEN); + + /* register network device */ + if ((err = register_netdev(net_dev))) { + panic("loopback: Failed to register netdevice: %d\n", err); + goto out_free; + } + + return 0; + +out_free: + free_netdev(net_dev); +out: + return err; +}; + + +static void __exit genode_net_exit(void) +{ + unregister_netdev(net_dev); + free_netdev(net_dev); +} + + +module_init(genode_net_init); +module_exit(genode_net_exit); diff -urNpB kernel-2.6.23-v2/arch/l4/drivers/l4kdb_console.c contrib/arch/l4/drivers/l4kdb_console.c --- kernel-2.6.23-v2/arch/l4/drivers/l4kdb_console.c +++ contrib/arch/l4/drivers/l4kdb_console.c @@ -4,28 +4,25 @@ #include +#include + static void l4kdb_cons_write(struct console *co, const char *p, unsigned count) { - while (count-- > 0) { - L4_KDB_PrintChar(*p++); - } + char buf[count+1]; + int i; + for(i=0; i #include -#define STACK_SIZE 0x2000 +#define STACK_SIZE 0x4000 extern cap_t *first_cap; extern bootmem_area_t bootmem_area[MAX_PHYSMEM_RANGES]; diff -urNpB kernel-2.6.23-v2/arch/l4/kernel/Makefile contrib/arch/l4/kernel/Makefile --- kernel-2.6.23-v2/arch/l4/kernel/Makefile +++ contrib/arch/l4/kernel/Makefile @@ -3,7 +3,11 @@ core-y += arch/l4/kernel/fs/ obj-y := reboot.o glue.o main.o init_task.o time.o memcpy_user.o \ syscalls.o proc.o process.o syscall_impl.o setup.o \ signal.o sys_iguana.o cache.o exit.o syscall_loop.o \ - mmap.o irq.o intervm_loop.o + mmap.o irq.o intervm_loop.o calibrate.o + +# Genode specific +obj-y := $(filter-out intervm_loop.o sys_iguana.o,$(obj-y)) +obj-y += sys_genode.o obj-$(CONFIG_MODULES) += syms.o obj-$(CONFIG_ARCH_ARM) += memcpy_user_armshared.o diff -urNpB kernel-2.6.23-v2/arch/l4/kernel/calibrate.c contrib/arch/l4/kernel/calibrate.c --- kernel-2.6.23-v2/arch/l4/kernel/calibrate.c +++ contrib/arch/l4/kernel/calibrate.c @@ -0,0 +1,179 @@ +/* calibrate.c: default delay calibration + * + * Excised from init/main.c + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +#include +#include +#include + +#include + +#include + +extern void* timer_main_kernel_lock; + +static unsigned long preset_lpj; +static int __init lpj_setup(char *str) +{ + preset_lpj = simple_strtoul(str,NULL,0); + return 1; +} + +__setup("lpj=", lpj_setup); + +#ifdef ARCH_HAS_READ_CURRENT_TIMER + +/* This routine uses the read_current_timer() routine and gets the + * loops per jiffy directly, instead of guessing it using delay(). + * Also, this code tries to handle non-maskable asynchronous events + * (like SMIs) + */ +#define DELAY_CALIBRATION_TICKS ((HZ < 100) ? 1 : (HZ/100)) +#define MAX_DIRECT_CALIBRATION_RETRIES 5 + +static unsigned long __devinit calibrate_delay_direct(void) +{ + unsigned long pre_start, start, post_start; + unsigned long pre_end, end, post_end; + unsigned long start_jiffies; + unsigned long tsc_rate_min, tsc_rate_max; + unsigned long good_tsc_sum = 0; + unsigned long good_tsc_count = 0; + int i; + + if (read_current_timer(&pre_start) < 0 ) + return 0; + + /* + * A simple loop like + * while ( jiffies < start_jiffies+1) + * start = read_current_timer(); + * will not do. As we don't really know whether jiffy switch + * happened first or timer_value was read first. And some asynchronous + * event can happen between these two events introducing errors in lpj. + * + * So, we do + * 1. pre_start <- When we are sure that jiffy switch hasn't happened + * 2. check jiffy switch + * 3. start <- timer value before or after jiffy switch + * 4. post_start <- When we are sure that jiffy switch has happened + * + * Note, we don't know anything about order of 2 and 3. + * Now, by looking at post_start and pre_start difference, we can + * check whether any asynchronous event happened or not + */ + + for (i = 0; i < MAX_DIRECT_CALIBRATION_RETRIES; i++) { + pre_start = 0; + read_current_timer(&start); + start_jiffies = jiffies; + while (jiffies <= (start_jiffies + 1)) { + pre_start = start; + read_current_timer(&start); + } + read_current_timer(&post_start); + + pre_end = 0; + end = post_start; + while (jiffies <= + (start_jiffies + 1 + DELAY_CALIBRATION_TICKS)) { + pre_end = end; + read_current_timer(&end); + } + read_current_timer(&post_end); + + tsc_rate_max = (post_end - pre_start) / DELAY_CALIBRATION_TICKS; + tsc_rate_min = (pre_end - post_start) / DELAY_CALIBRATION_TICKS; + + /* + * If the upper limit and lower limit of the tsc_rate is + * >= 12.5% apart, redo calibration. + */ + if (pre_start != 0 && pre_end != 0 && + (tsc_rate_max - tsc_rate_min) < (tsc_rate_max >> 3)) { + good_tsc_count++; + good_tsc_sum += tsc_rate_max; + } + } + + if (good_tsc_count) + return (good_tsc_sum/good_tsc_count); + + printk(KERN_WARNING "calibrate_delay_direct() failed to get a good " + "estimate for loops_per_jiffy.\nProbably due to long platform interrupts. Consider using \"lpj=\" boot option.\n"); + return 0; +} +#else +static unsigned long __devinit calibrate_delay_direct(void) {return 0;} +#endif + +/* + * This is the number of bits of precision for the loops_per_jiffy. Each + * bit takes on average 1.5/HZ seconds. This (like the original) is a little + * better than 1% + */ +#define LPS_PREC 8 + +void __devinit calibrate_delay(void) +{ + unsigned long ticks, loopbit; + int lps_precision = LPS_PREC; + + genode_unlock(timer_main_kernel_lock); + + if (preset_lpj) { + loops_per_jiffy = preset_lpj; + printk("Calibrating delay loop (skipped)... " + "%lu.%02lu BogoMIPS preset\n", + loops_per_jiffy/(500000/HZ), + (loops_per_jiffy/(5000/HZ)) % 100); + } else if ((loops_per_jiffy = calibrate_delay_direct()) != 0) { + printk("Calibrating delay using timer specific routine.. "); + printk("%lu.%02lu BogoMIPS (lpj=%lu)\n", + loops_per_jiffy/(500000/HZ), + (loops_per_jiffy/(5000/HZ)) % 100, + loops_per_jiffy); + } else { + loops_per_jiffy = (1<<12); + + printk(KERN_DEBUG "Calibrating delay loop... "); + while ((loops_per_jiffy <<= 1) != 0) { + /* wait for "start of" clock tick */ + ticks = jiffies; + while (ticks == jiffies) + /* nothing */; + /* Go .. */ + ticks = jiffies; + __delay(loops_per_jiffy); + ticks = jiffies - ticks; + if (ticks) + break; + } + + /* + * Do a binary approximation to get loops_per_jiffy set to + * equal one clock (up to lps_precision bits) + */ + loops_per_jiffy >>= 1; + loopbit = loops_per_jiffy; + while (lps_precision-- && (loopbit >>= 1)) { + loops_per_jiffy |= loopbit; + ticks = jiffies; + while (ticks == jiffies) + /* nothing */; + ticks = jiffies; + __delay(loops_per_jiffy); + if (jiffies != ticks) /* longer than 1 tick */ + loops_per_jiffy &= ~loopbit; + } + + /* Round the value and print it */ + printk("%lu.%02lu BogoMIPS (lpj=%lu)\n", + loops_per_jiffy/(500000/HZ), + (loops_per_jiffy/(5000/HZ)) % 100, + loops_per_jiffy); + } + genode_lock(timer_main_kernel_lock); +} diff -urNpB kernel-2.6.23-v2/arch/l4/kernel/exit.c contrib/arch/l4/kernel/exit.c --- kernel-2.6.23-v2/arch/l4/kernel/exit.c +++ contrib/arch/l4/kernel/exit.c @@ -9,7 +9,7 @@ #include #include -#include +#include /* * Called when Linux startup fails / exit server @@ -18,10 +18,8 @@ void _Exit(int status) { - pd_delete(pd_myself()); - - assert(!"We have exitted -- sholdn't reach here"); - while(1); + genode_exit(status); + while(1) ; } void __div0(void) diff -urNpB kernel-2.6.23-v2/arch/l4/kernel/fs/okl4fs/inode.c contrib/arch/l4/kernel/fs/okl4fs/inode.c --- kernel-2.6.23-v2/arch/l4/kernel/fs/okl4fs/inode.c +++ contrib/arch/l4/kernel/fs/okl4fs/inode.c @@ -17,8 +17,8 @@ #include #include "internal.h" -#include -#include +//#include +//#include #include diff -urNpB kernel-2.6.23-v2/arch/l4/kernel/glue.c contrib/arch/l4/kernel/glue.c --- kernel-2.6.23-v2/arch/l4/kernel/glue.c +++ contrib/arch/l4/kernel/glue.c @@ -4,9 +4,12 @@ #include #include +#include /* needed by 'asm/tlb.h' */ + #define __KERNEL_SYSCALLS__ -#include /* execve */ +#include /* execve */ +#include /* 'struct mmu_gather' */ int kernel_execve(const char *filename, char *const argv[], char *const envp[]) @@ -40,7 +43,8 @@ const char *get_system_type(void) return "L4 Default arch"; } -void per_cpu__mmu_gathers (void) { printk("per_cpu__mmu_gathers called\n"); } +DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); + void ptrace_disable (void) { printk("ptrace_disable called\n"); } //void search_extable (void) { printk("search_extable called\n"); } void show_stack(struct task_struct *task, unsigned long *sp) { printk("show_stack called\n"); } diff -urNpB kernel-2.6.23-v2/arch/l4/kernel/irq.c contrib/arch/l4/kernel/irq.c --- kernel-2.6.23-v2/arch/l4/kernel/irq.c +++ contrib/arch/l4/kernel/irq.c @@ -78,12 +78,12 @@ show_interrupts(struct seq_file *p, void #endif seq_printf(p, " %14s", irq_desc[i].chip->name); seq_printf(p, " %c%s", - (action->flags & SA_INTERRUPT)?'+':' ', + (action->flags & IRQF_DISABLED)?'+':' ', action->name); for (action=action->next; action; action = action->next) { seq_printf(p, ", %c%s", - (action->flags & SA_INTERRUPT)?'+':' ', + (action->flags & IRQF_DISABLED)?'+':' ', action->name); } diff -urNpB kernel-2.6.23-v2/arch/l4/kernel/main.c contrib/arch/l4/kernel/main.c --- kernel-2.6.23-v2/arch/l4/kernel/main.c +++ contrib/arch/l4/kernel/main.c @@ -24,12 +24,13 @@ #include #include -#include #include #include -#include -void *__callback_buffer; +#include +#include +#include +#include uintptr_t temp_cap_slot; uintptr_t temp_cap_used; @@ -39,17 +40,20 @@ uintptr_t temp_cap_addr; uintptr_t dma_heap_base, dma_heap_phys_base; static uintptr_t main_stack[STACK_SIZE]; -static uintptr_t intervm_stack[STACK_SIZE]; +static uintptr_t timer_stack[STACK_SIZE]; + +void* timer_main_kernel_lock; extern void interrupt_loop(void); void *main_tls_area[KERNEL_THREADS][32]; extern void start_kernel(void); -extern void intervm_loop(void); void *console_out, *console_in; +extern void enable_early_printk(void); + /* Our per cpu irq enable/disable. Where should this go? */ DEFINE_PER_CPU(irq_info_t, _l4_irq_state) = { 0 }; EXPORT_PER_CPU_SYMBOL(_l4_irq_state); @@ -59,7 +63,6 @@ L4_Word_t start_phys_mem, end_phys_mem; L4_ThreadId_t main_thread; L4_ThreadId_t timer_thread; L4_ThreadId_t timer_handle; -L4_ThreadId_t intervm_thread; unsigned long get_instr(unsigned long addr) { @@ -96,67 +99,13 @@ unsigned long set_instr(unsigned long ad return 0; } -/* -Malloc -*/ -void * -malloc(size_t size) -{ - void *ret; - //printk("malloc: %d\n", (int)size); - ret = kmalloc(size, GFP_ATOMIC); - //printk("malloc returned: %p\n", ret); - return ret; -} - -void * -calloc(size_t nmemb, size_t size) -{ - printk("calloc called\n"); - return NULL; -} - -void -free(void *ptr) -{ - return kfree(ptr); -} - -int -puts(const char *format) -{ - printk("puts called\n"); - return 0; -} - -int -printf(const char *format, ...) -{ - printk("printf\n"); - return 0; -// return printk(format); -} - - -void -__linux_cap_init(uintptr_t cap_slot, uintptr_t cap_used, uintptr_t cap_size, uintptr_t cap_addr) -{ -// temp_cap_slot = cap_slot; -// temp_cap_used = cap_used; -// temp_cap_size = cap_size; -// temp_cap_addr = cap_addr; -// first_cap = (cap_t*) cap_addr; -} - - -void -__libc_setup(void *callback, void *stdin_p, void *stdout_p, void *stderr_p, - unsigned long heap_base, unsigned long heap_end) +void __init +__libc_setup(void *stdin_p, void *stdout_p, void *stderr_p, + unsigned long heap_base, unsigned long heap_end) { console_out = stdout_p; console_in = stdin_p; - __callback_buffer = callback; /* Setup the memory areas from iguana */ assert(heap_end > heap_base); @@ -165,106 +114,96 @@ __libc_setup(void *callback, void *stdin bootmem_area[0].pages = (heap_end >> PAGE_SHIFT) - bootmem_area[0].page_base; } -void -__lib_init(uintptr_t *buf) +void __init __lib_init(void) { - void* callback; - void* stdin_p; - void* stdout_p; - void* stderr_p; char* heap_base; size_t heap_size; uint32_t dma_size; - __lib_iguana_init(buf); - - callback = env_memsection_base(iguana_getenv("__OKL4_CALLBACK_BUFFER")); - stdin_p = NULL; //env_memsection_base(iguana_getenv("OKL4_SERIAL_SERVER")); - stdout_p = NULL; //env_memsection_base(iguana_getenv("OKL4_SERIAL_SERVER")); - stderr_p = NULL; //env_memsection_base(iguana_getenv("OKL4_SERIAL_SERVER")); - heap_base = (char*) env_const(iguana_getenv("HEAP_BASE")); - heap_size = env_const(iguana_getenv("HEAP_SIZE")); - - - __libc_setup(callback, stdin_p, stdout_p, stderr_p, - (unsigned long) heap_base, - (unsigned long) (heap_base + heap_size - 1)); - __cap_init(); - -// __linux_cap_init((uintptr_t) iguana_getenv(IGUANA_GETENV_CLIST_SLOT), -// (uintptr_t) iguana_getenv(IGUANA_GETENV_CLIST_USED), -// CLIST_MEMORY_SIZE / sizeof(cap_t), -// (uintptr_t) iguana_getenv(IGUANA_GETENV_CLIST_BASE)); -// + heap_size = genode_quota() - genode_used_mem() + - 8*1024*1024; // Leave some memory left for dynamic allocations + heap_base = genode_malloc(heap_size); + __libc_setup(0, 0, 0, (unsigned long) heap_base, + (unsigned long) (heap_base + heap_size - 1)); dma_heap_base = (uint32_t)heap_base; dma_heap_phys_base = memsection_virt_to_phys((uintptr_t)heap_base, - &dma_size); + &dma_size); } - -void __sys_entry(void *buf, int argc, char** argv); void _Exit(int status); int main(int argc, char** argv); +void __sys_entry(void *buf, int argc, char** argv){} -/* This is the entry point from the C libraries crt0 */ -void -__sys_entry(void *buf, int argc, char** argv) +void setup_tls(int thread_num) { - int result; - __lib_init(buf); - /* Start Linux */ - result = main(argc, argv); - /* Exit Linux Server */ - _Exit(result); } -void -setup_tls(int thread_num) +void __init start_main_thread(void) { - __tls_init(main_tls_area[thread_num]); + /* Set me as the pager for every user process started by Linux */ + genode_set_pager(); + genode_lock(timer_main_kernel_lock); + +#ifdef CONFIG_EARLY_PRINTK + /* early console initialisation */ + enable_early_printk(); +#endif + + start_kernel(); } -int -main(int argc, char **argv) +void __init start_timer_thread(void) { - int r; - /* Start a new thread */ - assert(argc > 0 && argv[0] != NULL); - - strlcpy(boot_command_line, argv[1], COMMAND_LINE_SIZE); - L4_KDB_SetThreadName(L4_myselfconst, "L_timer"); - + /* Create main kernel thread, doing paging, syscalls etc. */ thread_create(&main_thread); - r = L4_Set_Priority(main_thread, 99); - assert (r != 0); - - timer_thread = thread_l4tid(env_thread(iguana_getenv("MAIN"))); L4_KDB_SetThreadName(main_thread, "L_syscall"); /* Setup our TLS as well */ - setup_tls(TIMER_THREAD); - - thread_create(&intervm_thread); - r = L4_Set_Priority(intervm_thread, 98); - assert(r != 0); - L4_KDB_SetThreadName(intervm_thread, "L_intervm"); + __tls_init(main_tls_area[TIMER_THREAD]); /* Thread info setup. */ /* FIXME: remember for SMP startup */ - current_tinfo(smp_processor_id()) = (unsigned long)&init_thread_union.thread_info; + current_tinfo(smp_processor_id()) = + (unsigned long)&init_thread_union.thread_info; current_thread_info()->user_tid = L4_nilthread; current_thread_info()->user_handle = L4_nilthread; + /* Start linux main thread */ L4_Start_SpIp(main_thread, - (L4_Word_t) &main_stack[STACK_SIZE-1], - (L4_Word_t) start_kernel); - - L4_Start_SpIp(intervm_thread, - (L4_Word_t) &intervm_stack[STACK_SIZE-1], - (L4_Word_t) intervm_loop); + (L4_Word_t) &main_stack[STACK_SIZE-1], + (L4_Word_t) start_main_thread); - /* Now we go and do the timer stuff */ + /* Now we go and do the timer/IRQ stuff */ interrupt_loop(); +} + +int __init +main(int argc, char **argv) +{ + char* cmdline = genode_config_cmdline(); + + /* Do init stuff, especially get memory */ + __lib_init(); + + /* Copy kernel commandline from the XML config */ + if (cmdline) + memcpy(boot_command_line, cmdline, + min_t(size_t, COMMAND_LINE_SIZE, + sizeof(char)*strlen(cmdline))); + + /* Create timer thread, which provides so to say timer interrupts */ + thread_create(&timer_thread); + L4_KDB_SetThreadName(timer_thread, "L_timer"); + + timer_main_kernel_lock = genode_alloc_lock(); + + /* Start timer thread */ + L4_Start_SpIp(timer_thread, + (L4_Word_t) &timer_stack[STACK_SIZE-1], + (L4_Word_t) start_timer_thread); + + /* Now, work is done, lets go sleeping */ + genode_sleep_forever(); return 0; } diff -urNpB kernel-2.6.23-v2/arch/l4/kernel/process.c contrib/arch/l4/kernel/process.c --- kernel-2.6.23-v2/arch/l4/kernel/process.c +++ contrib/arch/l4/kernel/process.c @@ -23,6 +23,10 @@ #include #include +#include + +extern void* timer_main_kernel_lock; + extern void NORET_TYPE syscall_loop (void); static void new_thread_handler(struct thread_info *prev); static void new_process_handler(struct thread_info *prev); @@ -144,7 +148,7 @@ __execve(char *file, char **argv, char * void cpu_idle (void) { - int r; + //int r; /* Idle thread has special user_tid so we can identify it */ current_thread_info()->user_tid = L4_anythread; @@ -152,25 +156,17 @@ cpu_idle (void) //printk("Starting idle loop (%lx)\n", L4_Myself().raw); XXX: L4_Myself() is no longer valid - nt - r = L4_Set_Priority(L4_myselfconst, 99); - if (r == 0) { - printk("Failed: %lx\n", L4_ErrorCode()); - } - assert(r != 0); - atomic_inc(&init_mm.mm_count); current->mm = &init_mm; current->active_mm = &init_mm; while (1) { - while (!need_resched()) - { - /* Wait on timer_thread */ - if (!need_resched()){ - L4_Receive(timer_thread); - } + while (!need_resched()){ + genode_unlock(timer_main_kernel_lock); + L4_Receive(timer_thread); + genode_lock(timer_main_kernel_lock); + } - //printk("!"); schedule(); } } @@ -187,7 +183,7 @@ copy_thread(int nr, unsigned long clone_ unsigned long unused, struct task_struct * p, struct pt_regs * regs) { - int r = 0; + //int r = 0; //printk("%s %d %lx usp=%lx, task=%p, regs=%p\n", __func__, nr, clone_flags, usp, p, regs); if ((task_thread_info(p)->request.op != OP_KTHREAD) && @@ -222,9 +218,6 @@ copy_thread(int nr, unsigned long clone_ name); } - r = L4_Set_Priority(task_thread_info(p)->user_tid, 98); - assert(r != 0); - L4_Copy_regs (current_thread_info()->user_tid, task_thread_info(p)->user_tid); @@ -308,7 +301,7 @@ start_thread(struct pt_regs * regs, unsi //printk("%s current = %p pc = %lx, sp = %lx\n", __func__, current, pc, sp); if (current_thread_info()->user_tid.raw == L4_nilthread.raw) { - int r; + //int r; void * utcb; if (utcb_area.raw == L4_Nilpage.raw) @@ -328,8 +321,7 @@ start_thread(struct pt_regs * regs, unsi utcb, &handle); assert(thrd.raw != 0); - r = L4_Set_Priority(thrd, 98); - assert(r != 0); + /* * This will be disabled in libl4 with NDEBUG set, so it's OK. */ @@ -352,7 +344,8 @@ start_thread(struct pt_regs * regs, unsi // syscall_exit(1); set_need_restart(current_thread_info(), pc, sp, 0); - L4_AbortIpc_and_stop_Thread(thrd); + //L4_AbortIpc_and_stop_Thread(thrd); + L4_Stop(thrd); set_user_ipc_cancelled(current_thread_info()); /* Setup which messages we will recieve */ @@ -385,6 +378,29 @@ __switch_to(struct task_struct *prev, st /* XXX - is the race from here to the switch important? */ current_tinfo(smp_processor_id()) = (unsigned long)next_info; + /* Suspend running thread */ + if(prev_info->user_tid.raw != 0) + { + L4_Word_t dummy; + L4_ThreadId_t dummy_id; + L4_ExchangeRegisters(prev_info->user_tid, + L4_ExReg_Halt + L4_ExReg_AbortSendIPC, + 0, 0, 0, + 0, L4_nilthread, &dummy, &dummy, &dummy, + &dummy, &dummy, &dummy_id); + } + + /* Resume scheduled thread */ + if(next_info->user_tid.raw != 0) + { + L4_Word_t dummy; + L4_ThreadId_t dummy_id; + L4_ExchangeRegisters(next_info->user_tid, + L4_ExReg_Resume, 0, 0, 0, + 0, L4_nilthread, &dummy, &dummy, &dummy, + &dummy, &dummy, &dummy_id); + } + prev_info = arch_switch(prev_info, next_info); mb(); } else { diff -urNpB kernel-2.6.23-v2/arch/l4/kernel/setup.c contrib/arch/l4/kernel/setup.c --- kernel-2.6.23-v2/arch/l4/kernel/setup.c +++ contrib/arch/l4/kernel/setup.c @@ -14,8 +14,6 @@ #include #include -#include -#include #include #ifdef CONFIG_VT @@ -25,7 +23,9 @@ #include #include -#include +#include +#include + unsigned long VGA_offset; struct screen_info screen_info = { @@ -52,15 +52,16 @@ struct screen_info screen_info = { .orig_video_points = 16 }; #define IORESOURCE_RAM (IORESOURCE_BUSY | IORESOURCE_MEM) -static struct resource video_ram_resource = { - .name = "Video RAM area", - .start = 0xa0000, - .end 0xbffff, - .flags = IORESOURCE_RAM -}; +/* static struct resource video_ram_resource = { */ +/* .name = "Video RAM area", */ +/* .start = 0xa0000, */ +/* .end = 0xbffff, */ +/* .flags = IORESOURCE_RAM */ +/* }; */ void __init __setup_vga(void) { + /* char* vga_obj; envitem_t *ig_ref; @@ -72,7 +73,7 @@ void __init __setup_vga(void) VGA_offset = (unsigned long)vga_obj - video_ram_resource.start; request_resource(&iomem_resource, &video_ram_resource); - + */ } @@ -91,8 +92,6 @@ L4_Fpage_t utcb_area; extern unsigned long start_phys_mem, end_phys_mem; extern void * __rd_start, * __rd_end; -extern void enable_early_printk(void); - void __init setup_machine_name(void) { @@ -112,7 +111,7 @@ void __init setup_arch (char **command_line) { unsigned long base, area; - + char* initrd_name; setup_tls(1); /* Return the command line to the rest of the kernel */ @@ -156,19 +155,19 @@ setup_arch (char **command_line) task_thread_info(current)->user_tid = L4_nilthread; task_thread_info(current)->user_handle = L4_nilthread; -#ifdef CONFIG_EARLY_PRINTK - /* early console initialisation */ - enable_early_printk(); -#endif - /* Ramdisk setup */ #ifdef CONFIG_BLK_DEV_INITRD /* Board specific code should have set up initrd_start and initrd_end */ ROOT_DEV = Root_RAM0; /* FIXME! */ - initrd_start = 0; //naming_lookup("ramdisk"); - initrd_end = 0; //naming_lookup("ramdisk_end"); - printk("end: %lx\n", initrd_end); + initrd_name = genode_config_initrd(); + if(initrd_name) { + initrd_start = (unsigned long) genode_open(initrd_name, &initrd_end); + initrd_end = initrd_start + initrd_end; + } else { + initrd_start = 0; + initrd_end = 0; + } initrd_below_start_ok = 1; if (initrd_start) { diff -urNpB kernel-2.6.23-v2/arch/l4/kernel/sys_genode.c contrib/arch/l4/kernel/sys_genode.c --- kernel-2.6.23-v2/arch/l4/kernel/sys_genode.c +++ contrib/arch/l4/kernel/sys_genode.c @@ -0,0 +1,427 @@ +#define timer_t timer_t_linux + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#undef timer_t + +#include +#include +#include + +#include +#include +#include +#ifdef CONFIG_SCREEN_GENODE +#include +#endif +#ifdef CONFIG_NET_GENODE +#include +#endif +#ifdef CONFIG_BLOCK_GENODE +#include +#endif + +#include "assert.h" +#include "irq_impl.h" + +#include + + +extern L4_ThreadId_t main_thread; +extern L4_ThreadId_t timer_thread; +extern L4_ThreadId_t timer_handle; + +/* + * Mask is set (1) if enabled + */ +L4_Word_t irq_mask = 1; // Keep bit 1 reserverd for timer as it is somewhat magic + +#define NUM_CPUS 1 +fd_set pending_irqs[NUM_CPUS]; +#define PENDING_MASK_SIZE (NR_IRQS / 32) + +/* + * Need SMP-safe access to interrupt CSRs + */ +DEFINE_SPINLOCK(iguana_irq_lock); + +static inline void +iguana_enable_irq(unsigned int irq) +{ + printk("WARN: %s does not work by now!\n",__func__); + spin_lock(&iguana_irq_lock); + if (irq < 32) { + irq_mask |= (1UL << 31); /* always use bit 31 for hw irqs */ + //L4_LoadMR(0, irq); + //L4_AcknowledgeInterruptOnBehalf(timer_thread, 0, 0); + } else { + irq_mask |= (1UL << irq); + } + spin_unlock(&iguana_irq_lock); +} + +static inline void +iguana_disable_irq(unsigned int irq) +{ + printk("WARN: %s does not work by now!\n",__func__); + spin_lock(&iguana_irq_lock); + if (irq < 32) { + //L4_LoadMR(0, irq); + //L4_UnregisterInterrupt(timer_thread, 0, 0); + } else { + irq_mask &= ~(1UL << irq); + } + + spin_unlock(&iguana_irq_lock); +} + +static unsigned int +iguana_startup_irq(unsigned int irq) +{ + if (irq < 32) + hardware_register_interrupt(timer_thread, irq); + + iguana_enable_irq(irq); + + return 0; +} + +static void +iguana_ack_irq(unsigned int irq) +{ +} + +static void +iguana_end_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + iguana_enable_irq(irq); +} + +static void +iguana_cpu_set_irq_affinity(unsigned int irq, cpumask_t affinity) +{ + // XXX fixme + printk("%s called\n", __func__); +} + +static void +iguana_set_irq_affinity(unsigned int irq, cpumask_t affinity) +{ + spin_lock(&iguana_irq_lock); + iguana_cpu_set_irq_affinity(irq, affinity); + spin_unlock(&iguana_irq_lock); +} + +static void __init +init_iguana_irqs(struct hw_interrupt_type * ops, int imin, int imax) +{ + long i; + for (i = imin; i <= imax; ++i) { + irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL; + irq_desc[i].chip = ops; + } +} + +static struct hw_interrupt_type iguana_irq_type = { + .typename = "iguana", + .startup = iguana_startup_irq, + .shutdown = iguana_disable_irq, + .enable = iguana_enable_irq, + .disable = iguana_disable_irq, + .ack = iguana_ack_irq, + .end = iguana_end_irq, + .set_affinity = iguana_set_irq_affinity, +}; + +static void __init +iguana_init_irq(void) +{ + init_iguana_irqs(&iguana_irq_type, 0, NR_IRQS-1); +} + +void __init +init_IRQ(void) +{ + iguana_init_irq(); +} + +/* + * Iguana Family + */ +extern uintptr_t temp_cap_slot; +extern uintptr_t temp_cap_used; +extern uintptr_t temp_cap_size; +extern uintptr_t temp_cap_addr; + +extern void +__cap_init(uintptr_t cap_slot, uintptr_t cap_used, uintptr_t cap_size, uintptr_t cap_addr); + +memsection_ref_t vmalloc_memsect; +uintptr_t vmalloc_start, vmalloc_end; + +/* FIXME: Should be extended for SMP? */ +struct ig_irq_rec{ + unsigned short pending; + L4_ThreadId_t tid; +} irq_recs[NR_IRQS]; + +static int __init +iguana_arch_init(void) +{ +#if 0 + /* + * Enable the system error interrupts. These interrupts are + * all reported to the kernel as machine checks, so the handler + * is a nop so it can be called to count the individual events. + */ + + /* + FIXME: We need to setup capabilties library properly now! + Ideally we would do this really early, but this is about as early + as we get! + */ + __cap_init(temp_cap_slot, temp_cap_used, temp_cap_size, temp_cap_addr); +#endif + + /* Just take physical memory end + 1MB hole as starting point */ + unsigned long offset = 10*1024*1024; + vmalloc_start = (uintptr_t) genode_malloc(10); + vmalloc_start += (2*offset-1) & ~(offset-1); + + /* Let the vmalloc area size be 100MB and hope it doesn't collude */ + vmalloc_end = vmalloc_start + 100*1024*1024; + genode_printf("vmalloc area: %lx - %lx\n", vmalloc_start, vmalloc_end); + + return 0; +} + +arch_initcall(iguana_arch_init); + +extern void * __callback_buffer; + +#define BIT(x) (1<<(x)) +#define TIMER_IRQ 0 + +/* + * XXX: namespace clash. :-( + */ +#define device_create okl4_device_create + +//#include +//#include + +//server_t timer_server; +//device_t timer_dev; + +/* + * XXX this needs 32/64bit cleanup + merge into irq.c + */ +/* int mask_to_irq(L4_Word_t *mask) */ +/* { */ +/* int i; */ + +/* for (i = 0 ; i < NR_IGUANA_IRQS; i++) */ +/* { */ +/* if (*mask & (1 << i)) */ +/* { */ +/* *mask &= ~(1 << i); */ + +/* /\* Bit 31 is ia32 BSP's way of saying hardware interrupt *\/ */ +/* if (i == 31) */ +/* { */ +/* /\* read hw irq number from utcb->platform_reserved[0] *\/ */ +/* //printk("mask_to_irq: got hw irq %ld!\n", utcb_base_get()->platform_reserved[0]); */ +/* return utcb_base_get()->platform_reserved[0]; */ +/* } */ +/* else */ +/* { */ +/* return IGUANA_IRQ(i); */ +/* } */ +/* } */ +/* } */ +/* return -1; */ +/* } */ + +int iguana_alloc_irq(void) +{ + int i; + for (i = 0; i < NR_IGUANA_IRQS; i++){ + if (!(irq_mask & (1UL<> 8; */ +/* else */ +/* return 0; */ +/* } */ + +extern void* timer_main_kernel_lock; + +void +interrupt_loop(void) +{ + struct thread_info * curinfo; + + /* timer interrupt */ + int irq = IGUANA_IRQ(0); + + /* Wait for wake up message from timer init */ + L4_Call(main_thread); + + printk("START CLOCK LOOP\n"); + + while(1) { + genode_sleep(10); + genode_lock(timer_main_kernel_lock); +#ifdef CONFIG_SCREEN_GENODE + genode_input_handle_events(); +#endif +#ifdef CONFIG_NET_GENODE + genode_net_rx_receive(); +#endif +#ifdef CONFIG_BLOCK_GENODE + genode_block_collect_responses(); +#endif + curinfo = current_thread_info(); + curinfo->regs.mode ++; + + if (irqs_disabled()) + { + FD_SET(irq, &pending_irqs[smp_processor_id()]); + + /* Keep time going for missed ticks */ + if (pending_tick) + jiffies_64++; + IRQ_pending(smp_processor_id()) ++; + pending_tick = 1; + curinfo->regs.mode --; + genode_unlock(timer_main_kernel_lock); + } + else + { + isr_irq_disable(); + // Should loop over all bits potentially set + handle_irq(irq, NULL); + isr_irq_enable(); + pending_tick = 0; + isr_irq_disable(); + irq_enter(); + do_timer(1); + update_process_times(user_mode(&curinfo->regs)); + irq_exit(); + isr_irq_enable(); + curinfo->regs.mode --; + + genode_unlock(timer_main_kernel_lock); + if (need_resched()) { + L4_MsgTag_t msgtag = L4_Niltag; + L4_Msg_t msg; + L4_Set_MsgMsgTag( &msg, msgtag ); + L4_MsgLoad( &msg ); + L4_Send_Nonblocking(main_thread); + } + } + } +} + +static int irq_mask_to_num(void){ + int i; + int cpu = smp_processor_id(); + unsigned int least_sig; + + for (i = 0; i <= PENDING_MASK_SIZE; ++i){ + least_sig = fls(pending_irqs[cpu].fds_bits[i]); + if (least_sig == 0) + continue; + else{ + int bit = (i * sizeof(long)*8) + least_sig; + FD_CLR(bit-1, &pending_irqs[smp_processor_id()]); + return (bit - 1); + } + } + return -1; +} +/* + * This is called to handle pending interrupts from the main linux thread. + * We thus need to send a deceiving IPC to the L4 interrupt thread to + * ACK the interrupt. This is called with interrupts disabled + */ +void +l4_handle_pending(void) +{ + int irq_num; + struct thread_info * curinfo = current_thread_info(); + + curinfo->regs.mode ++; + + if (pending_tick) + { + irq_enter(); + do_timer(1); + update_process_times(user_mode(&curinfo->regs)); + + pending_tick = 0; + irq_exit(); + } + + /* + * XXX + * + * Concurrency problem: the FD_SET() and FD_CLR() are not + * atomic but can be accessed either in the timer thread + * context or the syscall loop thread context + * + * -gl + */ + while((irq_num = irq_mask_to_num()) != -1) + { + handle_irq(irq_num, NULL); + } + + IRQ_pending(smp_processor_id())--; + + curinfo->regs.mode --; +} + +void local_irq_enable(void) +{ + if (unlikely(!in_interrupt() && IRQ_pending(smp_processor_id()))) + { + IRQ_state(smp_processor_id()) = 1; + l4_handle_pending(); + } + IRQ_state(smp_processor_id()) = 0; +} + +EXPORT_SYMBOL(local_irq_enable); + diff -urNpB kernel-2.6.23-v2/arch/l4/kernel/syscall_loop.c contrib/arch/l4/kernel/syscall_loop.c --- kernel-2.6.23-v2/arch/l4/kernel/syscall_loop.c +++ contrib/arch/l4/kernel/syscall_loop.c @@ -23,10 +23,8 @@ #include #include -#include #include -#include -#include +#include #include @@ -36,6 +34,7 @@ extern L4_ThreadId_t timer_thread; extern L4_ThreadId_t timer_handle; extern L4_ThreadId_t main_thread; +extern void* timer_main_kernel_lock; extern unsigned long get_instr(unsigned long addr); extern unsigned long set_instr(unsigned long addr, unsigned long value); @@ -556,9 +555,12 @@ return_to_user: if (likely(reply_user_ipc(curinfo))) { curinfo->regs.mode = 0; L4_MsgLoad(&curinfo->regs.msg); + genode_unlock(timer_main_kernel_lock); /* Reply to caller and wait for next IPC */ tag = L4_ReplyWait(curinfo->user_tid, &from); + genode_lock(timer_main_kernel_lock); + } else { retry: if (user_need_restart(curinfo)) { @@ -570,10 +572,12 @@ retry: } curinfo->regs.mode = 0; /* Open Wait */ + genode_unlock(timer_main_kernel_lock); tag = L4_Wait (&from); + genode_lock(timer_main_kernel_lock); } - if (likely(from.raw == curinfo->user_handle.raw)) + if (likely(from.raw == curinfo->user_tid.raw)) { curinfo->regs.mode = 1; curinfo->tag = tag; @@ -587,6 +591,7 @@ retry: } else { +#if 0 /* XXX * Here we have to lookup the linux thread from * the L4 thread_id, which may be expensive. @@ -595,9 +600,12 @@ retry: * thread could use this to kill root processes. */ printk("illegal ipc from %lx, expected %lx\n", from.raw, - curinfo->user_handle.raw); + curinfo->user_tid.raw); L4_KDB_Enter("ill"); goto retry; +#endif + curinfo->regs.mode = 1; + curinfo->tag = tag; } } diff -urNpB kernel-2.6.23-v2/arch/l4/kernel/vmlinux.lds.S contrib/arch/l4/kernel/vmlinux.lds.S --- kernel-2.6.23-v2/arch/l4/kernel/vmlinux.lds.S +++ contrib/arch/l4/kernel/vmlinux.lds.S @@ -22,6 +22,10 @@ SECTIONS #endif /* read-only */ .text : { + /* begin of program image (link address) */ + _prog_img_beg = .; + + _stext = .; _text = .; /* Text and read-only data */ *(.text) SCHED_TEXT @@ -29,6 +33,18 @@ SECTIONS *(.fixup) *(.gnu.warning) *(.note*) + + . = ALIGN(0x04); + + _ctors_start = .; + KEEP (*(.ctors)) + KEEP (*(SORT(.ctors.*))) + _ctors_end = .; + _dtors_start = .; + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + _dtors_end = .; + . = ALIGN(PAGE_SIZE); __user_exregs_page = .; *(.exregspage) @@ -42,11 +58,25 @@ SECTIONS __ex_table : { *(__ex_table) } __stop___ex_table = .; + .eh_frame_hdr : { *(.eh_frame_hdr) } + RODATA - . = ALIGN(PAGE_SIZE); - + . = ALIGN(PAGE_SIZE); + + _prog_img_data = .; + .data : { /* Data */ + /* Leave space for parent capability parameters at start of data + * section. The protection domain creator is reponsible for storing + * sane values here. + */ + _parent_cap = .; + LONG(0xffffffff); + LONG(0xffffffff); + LONG(0xffffffff); + LONG(0xffffffff); + /* Align the initial ramdisk image (INITRD) on page boundaries. */ /* __rd_start = .; @@ -59,7 +89,16 @@ SECTIONS CONSTRUCTORS . = ALIGN(PAGE_SIZE); - } + } : rw + + /* exception frames for C++ */ + .eh_frame : { + __eh_frame_start__ = .; + KEEP (*(.eh_frame)) + LONG(0) + } : rw + .gcc_except_table : { KEEP(*(.gcc_except_table)) } + .dynamic : { *(.dynamic) } . = ALIGN(32); .data.cacheline_aligned : { *(.data.cacheline_aligned) } @@ -122,9 +161,15 @@ SECTIONS *(COMMON) _end = .; } + + /* end of program image -- must be after last section */ + _prog_img_end = .; + } PHDRS { main_seg PT_LOAD; + ro PT_LOAD; + rw PT_LOAD; } diff -urNpB kernel-2.6.23-v2/arch/l4/lib/checksum.c contrib/arch/l4/lib/checksum.c --- kernel-2.6.23-v2/arch/l4/lib/checksum.c +++ contrib/arch/l4/lib/checksum.c @@ -85,7 +85,7 @@ out: /* * computes a partial checksum, e.g. for TCP/UDP fragments */ -__wsum csum_partial(const void *buff, int len, __wsum sum) +asmlinkage __wsum csum_partial(const void *buff, int len, __wsum sum) { unsigned int result = do_csum(buff, len); diff -urNpB kernel-2.6.23-v2/arch/l4/mm/mmu.c contrib/arch/l4/mm/mmu.c --- kernel-2.6.23-v2/arch/l4/mm/mmu.c +++ contrib/arch/l4/mm/mmu.c @@ -39,7 +39,6 @@ void activate_mm(struct mm_struct *old, if (old_thrd.raw != L4_nilthread.raw) { - int r; thread_delete(old_thrd); current_thread_info()->user_tid = eas_create_thread(new->context.eas, @@ -48,8 +47,6 @@ void activate_mm(struct mm_struct *old, ¤t_thread_info()->user_handle); assert(current_thread_info()->user_tid.raw != 0); - r = L4_Set_Priority(current_thread_info()->user_tid, 98); - assert(r != 0); { char name[16]; diff -urNpB kernel-2.6.23-v2/arch/l4/sys-i386/Makefile contrib/arch/l4/sys-i386/Makefile --- kernel-2.6.23-v2/arch/l4/sys-i386/Makefile +++ contrib/arch/l4/sys-i386/Makefile @@ -4,7 +4,7 @@ CFLAGS += -O2 ELF_ARCH = i386 ELF_FORMAT = elf32-i386 -obj-y = crt0.o delay.o signal.o syscalls.o semaphore.o io.o sys_i386.o bitops.o user.o ptrace.o process.o ldt.o traps.o processor.o string.o dma.o memcpy.o strstr.o ioport.o +obj-y = delay.o signal.o syscalls.o semaphore.o io.o sys_i386.o bitops.o user.o ptrace.o process.o ldt.o traps.o processor.o string.o dma.o memcpy.o strstr.o ioport.o ifdef CONFIG_IA32_VDSO_ENABLE obj-y += sysenter.o vsyscall.o @@ -42,7 +42,7 @@ targets += vsyscall-note.o vsyscall.lds # The DSO images are built using a special linker script. quiet_cmd_syscall = SYSCALL $@ - cmd_syscall = $(CC) -m elf_i386 -nostdlib $(SYSCFLAGS_$(@F)) \ + cmd_syscall = $(CC) -m32 -nostdlib $(SYSCFLAGS_$(@F)) \ -Wl,-T,$(filter-out FORCE,$^) -o $@ export CPPFLAGS_vsyscall.lds += -P -C -U$(ARCH) diff -urNpB kernel-2.6.23-v2/arch/l4/sys-i386/crt0.S contrib/arch/l4/sys-i386/crt0.S --- kernel-2.6.23-v2/arch/l4/sys-i386/crt0.S +++ contrib/arch/l4/sys-i386/crt0.S @@ -31,13 +31,13 @@ ********************************************************************/ .text - .global _start + .global _wombat_start _stext: .global _stext -_start: +_wombat_start: push $0xfee1dead /* dummy frame thingy */ jmp __sys_entry /* off we go! */ /*NOTREACHED*/ - .end _start + .end _wombat_start diff -urNpB kernel-2.6.23-v2/arch/l4/sys-i386/dma.c contrib/arch/l4/sys-i386/dma.c --- kernel-2.6.23-v2/arch/l4/sys-i386/dma.c +++ contrib/arch/l4/sys-i386/dma.c @@ -11,7 +11,7 @@ #include #include #include -#include +//#include /* Allocate consistent (uncached, or the appearance of it) memory */ /* We ignore the flags at the moment */ diff -urNpB kernel-2.6.23-v2/arch/l4/sys-i386/ioport.c contrib/arch/l4/sys-i386/ioport.c --- kernel-2.6.23-v2/arch/l4/sys-i386/ioport.c +++ contrib/arch/l4/sys-i386/ioport.c @@ -13,8 +13,8 @@ */ asmlinkage long sys_iopl(unsigned long unused) { - unsigned long old = 0; /* XXX */ - unsigned long level; /* in %ebx */ + //unsigned long old = 0; /* XXX */ + //unsigned long level; /* in %ebx */ printk("%s: not implemented.\n", __func__); #if 0 diff -urNpB kernel-2.6.23-v2/arch/l4/sys-i386/signal.c contrib/arch/l4/sys-i386/signal.c --- kernel-2.6.23-v2/arch/l4/sys-i386/signal.c +++ contrib/arch/l4/sys-i386/signal.c @@ -189,8 +189,8 @@ restore_sigcontext(struct pt_regs *ptreg return err; -badframe: - return 1; +//badframe: +// return 1; } asmlinkage int sys_sigreturn(struct pt_regs *regs) diff -urNpB kernel-2.6.23-v2/arch/l4/sys-i386/syscalls.c contrib/arch/l4/sys-i386/syscalls.c --- kernel-2.6.23-v2/arch/l4/sys-i386/syscalls.c +++ contrib/arch/l4/sys-i386/syscalls.c @@ -10,8 +10,8 @@ #define __NR_Linux 0 -extern long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, - unsigned long flags, unsigned long fd, unsigned long pgoff); +extern asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, + unsigned long flags, unsigned long fd, unsigned long pgoff); unsigned int l4_i386_abi_syscall_start = 0; diff -urNpB kernel-2.6.23-v2/block/cfq-iosched.c contrib/block/cfq-iosched.c --- kernel-2.6.23-v2/block/cfq-iosched.c +++ contrib/block/cfq-iosched.c @@ -1427,6 +1427,7 @@ cfq_async_queue_prio(struct cfq_data *cf default: BUG(); } + return 0; } static struct cfq_queue * diff -urNpB kernel-2.6.23-v2/include/asm-l4/bug.h contrib/include/asm-l4/bug.h --- kernel-2.6.23-v2/include/asm-l4/bug.h +++ contrib/include/asm-l4/bug.h @@ -4,12 +4,13 @@ #ifndef __ASSEMBLY__ #include +#include +#include #define HAVE_ARCH_BUG #define BUG() do { \ - /*panic("kernel BUG at %s:%d!\n", __FILE__, __LINE__);*/ \ - printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ - pd_delete(pd_myself()); \ + genode_printf("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ + genode_exit(1); \ } while (0) #define HAVE_ARCH_BUG_ON @@ -23,6 +24,18 @@ BUG(); \ } while (0) + +#define HAVE_ARCH_WARN_ON +#define WARN_ON(condition) ({ \ + int __ret_warn_on = !!(condition); \ + if (unlikely(__ret_warn_on)) { \ + genode_printf("WARNING: at %s:%d %s()\n", __FILE__, \ + __LINE__, __FUNCTION__); \ + } \ + unlikely(__ret_warn_on); \ +}) + + extern int foo; #include diff -urNpB kernel-2.6.23-v2/include/asm-l4/i386/dma-mapping.h contrib/include/asm-l4/i386/dma-mapping.h --- kernel-2.6.23-v2/include/asm-l4/i386/dma-mapping.h +++ contrib/include/asm-l4/i386/dma-mapping.h @@ -26,7 +26,7 @@ #include #include #include -#include +//#include static inline int diff -urNpB kernel-2.6.23-v2/include/asm-l4/i386/ptrace.h contrib/include/asm-l4/i386/ptrace.h --- kernel-2.6.23-v2/include/asm-l4/i386/ptrace.h +++ contrib/include/asm-l4/i386/ptrace.h @@ -61,7 +61,7 @@ #define PTRACE_GET_THREAD_AREA 25 #define PTRACE_SET_THREAD_AREA 26 -extern inline void +static inline void l4_arch_setup_restart(struct pt_regs *regs) { i386_put_eax(regs, i386_save(regs)); @@ -70,7 +70,7 @@ l4_arch_setup_restart(struct pt_regs *re #define __NR_restart_syscall 0 -extern inline void +static inline void l4_arch_setup_sys_restart(struct pt_regs *regs) { i386_put_eax(regs, __NR_restart_syscall); diff -urNpB kernel-2.6.23-v2/include/asm-l4/i386/syscalls.h contrib/include/asm-l4/i386/syscalls.h --- kernel-2.6.23-v2/include/asm-l4/i386/syscalls.h +++ contrib/include/asm-l4/i386/syscalls.h @@ -47,7 +47,7 @@ extern l4_i386_abi_syscalls_t l4_i386_ab #ifdef CONFIG_IA32_VDSO_ENABLE -extern inline void +static inline void l4_i386_get_fast_syscall_args(struct pt_regs *regs) { /* TODO: ensure sp is valid */ @@ -69,7 +69,7 @@ l4_i386_get_fast_syscall_args(struct pt_ #endif /* ifdef CONFIG_IA32_VDSO_ENABLE */ -extern inline long +static inline long l4_arch_lookup_syscall (struct pt_regs *regs, L4_Word_t *abi) { L4_Word_t call; @@ -98,7 +98,7 @@ typedef L4_Word_t func_four_arg_t(L4_Wor typedef L4_Word_t func_five_arg_t(L4_Word_t, L4_Word_t, L4_Word_t, L4_Word_t, L4_Word_t); typedef L4_Word_t func_six_arg_t(L4_Word_t, L4_Word_t, L4_Word_t, L4_Word_t, L4_Word_t, L4_Word_t); -extern inline L4_Word_t +static inline L4_Word_t l4_arch_abi_call(struct pt_regs *regs, L4_Word_t sys_num, L4_Word_t abi) { L4_Word_t result = -1ul; @@ -159,13 +159,13 @@ l4_arch_abi_call(struct pt_regs *regs, L return result; } -extern inline long +static inline long l4_arch_get_error(struct pt_regs *regs) { return -(long)i386_eax(regs); } -extern inline int +static inline int l4_arch_restart_syscall(struct pt_regs *regs) { L4_Word_t temp; diff -urNpB kernel-2.6.23-v2/include/asm-l4/signal_l4.h contrib/include/asm-l4/signal_l4.h --- kernel-2.6.23-v2/include/asm-l4/signal_l4.h +++ contrib/include/asm-l4/signal_l4.h @@ -22,7 +22,7 @@ static inline int need_to_resched(struct extern void do_syscall_trace(int, void *); -extern inline void +static inline void syscall_entry(struct thread_info * my_info) { if (unlikely(need_syscall_trace(my_info))) @@ -34,7 +34,7 @@ syscall_entry(struct thread_info * my_in } } -extern inline void +static inline void syscall_exit(struct thread_info * my_info, int syscall) { if (unlikely( syscall && need_syscall_trace(my_info) )) @@ -46,7 +46,7 @@ syscall_exit(struct thread_info * my_inf } } -extern inline int +static inline int l4_work_pending(struct thread_info * my_info, int syscall, struct pt_regs *regs) { if (unlikely( need_to_resched(my_info) )) { @@ -59,7 +59,7 @@ l4_work_pending(struct thread_info * my_ return 0; } -extern inline int +static inline int l4_work_pending_preempt(struct pt_regs *regs) { int restart = 0; diff -urNpB kernel-2.6.23-v2/include/asm-l4/system.h contrib/include/asm-l4/system.h --- kernel-2.6.23-v2/include/asm-l4/system.h +++ contrib/include/asm-l4/system.h @@ -8,7 +8,7 @@ #include struct task_struct; -extern asmlinkage void *__switch_to(struct task_struct *prev, struct task_struct *next); +extern void *__switch_to(struct task_struct *prev, struct task_struct *next); #include #include diff -urNpB kernel-2.6.23-v2/include/asm-l4/uaccess.h contrib/include/asm-l4/uaccess.h --- kernel-2.6.23-v2/include/asm-l4/uaccess.h +++ contrib/include/asm-l4/uaccess.h @@ -101,7 +101,7 @@ static inline int verify_area(int type, return 0; } -#define access_ok(type,addr,size) 1 +#define access_ok(type,addr,size) (((unsigned long)addr != size) || 1) #endif diff -urNpB kernel-2.6.23-v2/include/asm-l4/unistd.h contrib/include/asm-l4/unistd.h --- kernel-2.6.23-v2/include/asm-l4/unistd.h +++ contrib/include/asm-l4/unistd.h @@ -30,19 +30,19 @@ asmlinkage long sys_wait4(pid_t pid, int __user *stat_addr, int options, struct rusage __user *ru); -extern long sys_open(const char *filename, int flags, int mode); -extern long sys_dup(unsigned int fildes); -extern long sys_close(unsigned int fd); +extern asmlinkage long sys_open(const char *filename, int flags, int mode); +extern asmlinkage long sys_dup(unsigned int fildes); +extern asmlinkage long sys_close(unsigned int fd); extern int __execve(char *file, char **argv, char **env); extern int sys_execve(char *file, char **argv, char **env); -extern long sys_setsid(void); -extern long sys_mount(char *dev_name, char *dir_name, char *type, +extern asmlinkage long sys_setsid(void); +extern asmlinkage long sys_mount(char *dev_name, char *dir_name, char *type, unsigned long flags, void *data); -extern long sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, +extern asmlinkage long sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp); -extern off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin); -extern ssize_t sys_read(unsigned int fd, char __user *buf, size_t count); -extern ssize_t sys_write(unsigned int fd, const char __user *buf, size_t count); +extern asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin); +extern asmlinkage ssize_t sys_read(unsigned int fd, char __user *buf, size_t count); +extern asmlinkage ssize_t sys_write(unsigned int fd, const char __user *buf, size_t count); #define KERNEL_CALL(ret_t, sys, args...) \ mm_segment_t fs = get_fs(); \ diff -urNpB kernel-2.6.23-v2/kernel/mutex.c contrib/kernel/mutex.c --- kernel-2.6.23-v2/kernel/mutex.c +++ contrib/kernel/mutex.c @@ -57,7 +57,7 @@ EXPORT_SYMBOL(__mutex_init); * We also put the fastpath first in the kernel image, to make sure the * branch is predicted by the CPU as default-untaken. */ -static void fastcall noinline __sched +void fastcall noinline __sched __mutex_lock_slowpath(atomic_t *lock_count); /*** @@ -93,7 +93,7 @@ void inline fastcall __sched mutex_lock( EXPORT_SYMBOL(mutex_lock); -static void fastcall noinline __sched +void fastcall noinline __sched __mutex_unlock_slowpath(atomic_t *lock_count); /*** @@ -197,7 +197,7 @@ done: return 0; } -static void fastcall noinline __sched +void fastcall noinline __sched __mutex_lock_slowpath(atomic_t *lock_count) { struct mutex *lock = container_of(lock_count, struct mutex, count); @@ -265,7 +265,7 @@ __mutex_unlock_common_slowpath(atomic_t /* * Release the lock, slowpath: */ -static fastcall noinline void +fastcall noinline void __mutex_unlock_slowpath(atomic_t *lock_count) { __mutex_unlock_common_slowpath(lock_count, 1); diff -urNpB kernel-2.6.23-v2/mm/slab.c contrib/mm/slab.c --- kernel-2.6.23-v2/mm/slab.c +++ contrib/mm/slab.c @@ -3758,6 +3758,7 @@ void kfree(const void *objp) { struct kmem_cache *c; unsigned long flags; + void *ptr = (void*)objp; if (unlikely(ZERO_OR_NULL_PTR(objp))) return; @@ -3765,7 +3766,7 @@ void kfree(const void *objp) kfree_debugcheck(objp); c = virt_to_cache(objp); debug_check_no_locks_freed(objp, obj_size(c)); - __cache_free(c, (void *)objp); + __cache_free(c, /*(void *)objp*/ptr); local_irq_restore(flags); } EXPORT_SYMBOL(kfree); diff -urNpB kernel-2.6.23-v2/scripts/checksyscalls.sh contrib/scripts/checksyscalls.sh --- kernel-2.6.23-v2/scripts/checksyscalls.sh +++ contrib/scripts/checksyscalls.sh @@ -119,5 +119,9 @@ sed -n -e '/^\#define/ { s/[^_]*__NR_\([ \#endif/p }' $1 } +echo "SRCTREE" +echo "${srctree}" +echo "END" + (ignore_list && syscall_list ${srctree}/include/asm-i386/unistd.h) | \ $* -E -x c - > /dev/null