mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-22 23:12:24 +00:00
3351 lines
87 KiB
Diff
3351 lines
87 KiB
Diff
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,35 @@ 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 SND_GENODE
|
|
+ bool
|
|
+ select SND_PCM
|
|
+ default y
|
|
+
|
|
+config BLOCK_GENODE
|
|
+ bool
|
|
+ select BLOCK
|
|
+ default y
|
|
+
|
|
+config NET_GENODE
|
|
+ bool
|
|
+ select NET
|
|
+ default y
|
|
+
|
|
endmenu
|
|
|
|
config GENERIC_HWEIGHT
|
|
@@ -212,12 +236,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 +297,7 @@ config CPU_HAS_LLDSCD
|
|
|
|
config GENERIC_CALIBRATE_DELAY
|
|
bool
|
|
- default y
|
|
+ default n
|
|
|
|
config ISA
|
|
bool
|
|
@@ -311,7 +335,7 @@ source "net/Kconfig"
|
|
source "fs/Kconfig"
|
|
config OKL4FS
|
|
bool
|
|
- default m
|
|
+ default n
|
|
|
|
source "drivers/mmc/Kconfig"
|
|
|
|
@@ -360,17 +384,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 +408,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 +433,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 = slab allocator_avl cxx ipc heap console log_console lock env \
|
|
+ thread oklx startup avl_tree signal
|
|
+
|
|
+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,7 @@
|
|
-obj-y := ig_ramdisk.o
|
|
+obj-$(CONFIG_SCREEN_GENODE) += genode_fb.o
|
|
+obj-$(CONFIG_BLOCK_GENODE) += genode_block.o
|
|
+obj-$(CONFIG_SND_GENODE) += genode_audio.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_audio.c contrib/arch/l4/drivers/genode_audio.c
|
|
--- kernel-2.6.23-v2/arch/l4/drivers/genode_audio.c
|
|
+++ contrib/arch/l4/drivers/genode_audio.c
|
|
@@ -0,0 +1,325 @@
|
|
+/*
|
|
+ * Alsa soundcard driver for OKLinux/Genode
|
|
+ *
|
|
+ * Stefan Kalkowski <kalkowski@genode-labs.com>
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2006-2009
|
|
+ * Genode Labs, Feske & Helmuth Systementwicklung GbR
|
|
+ *
|
|
+ * This file is part of the Genode OS framework, which is distributed
|
|
+ * under the terms of the GNU General Public License version 2.
|
|
+ */
|
|
+
|
|
+#include <sound/driver.h>
|
|
+#include <linux/init.h>
|
|
+#include <linux/err.h>
|
|
+#include <linux/platform_device.h>
|
|
+#include <linux/slab.h>
|
|
+#include <linux/time.h>
|
|
+#include <linux/wait.h>
|
|
+#include <linux/moduleparam.h>
|
|
+#include <linux/module.h>
|
|
+#include <sound/core.h>
|
|
+#include <sound/control.h>
|
|
+#include <sound/tlv.h>
|
|
+#include <sound/pcm.h>
|
|
+#include <sound/rawmidi.h>
|
|
+#include <sound/initval.h>
|
|
+
|
|
+#include <genode/audio.h>
|
|
+#include <genode/printf.h>
|
|
+
|
|
+#define DEBUG 0
|
|
+
|
|
+#define PDBG(args...) do { \
|
|
+ if(DEBUG) { \
|
|
+ genode_printf("%s(): ", __FUNCTION__); \
|
|
+ genode_printf("\033[33m"); \
|
|
+ genode_printf(args); \
|
|
+ genode_printf("\033[0m\n"); \
|
|
+ } \
|
|
+ } while(0)
|
|
+
|
|
+
|
|
+static struct platform_device *platform_dev_ptr = 0;
|
|
+static void *packet_cache = 0;
|
|
+static short stopped = 1;
|
|
+
|
|
+static struct snd_pcm_hardware snd_genode_playback_props =
|
|
+{
|
|
+ .info = SNDRV_PCM_INFO_INTERLEAVED,
|
|
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
|
|
+ .rates = SNDRV_PCM_RATE_44100,
|
|
+ .rate_min = 44100,
|
|
+ .rate_max = 44100,
|
|
+ .channels_min = 2,
|
|
+ .channels_max = 2,
|
|
+};
|
|
+
|
|
+
|
|
+static void snd_genode_period_elapsed_callback(unsigned long data)
|
|
+{
|
|
+ PDBG("Enter");
|
|
+ snd_pcm_period_elapsed((struct snd_pcm_substream *)data);
|
|
+}
|
|
+
|
|
+
|
|
+/**********************
|
|
+ * Callback functions *
|
|
+ **********************/
|
|
+
|
|
+static int snd_genode_trigger(struct snd_pcm_substream *substream, int cmd)
|
|
+{
|
|
+ struct snd_pcm_runtime *runtime = substream->runtime;
|
|
+ spinlock_t *lock = runtime->private_data;
|
|
+ int err = 0;
|
|
+
|
|
+ spin_lock(lock);
|
|
+ switch (cmd) {
|
|
+ case SNDRV_PCM_TRIGGER_START:
|
|
+ case SNDRV_PCM_TRIGGER_RESUME:
|
|
+ PDBG("Start");
|
|
+ genode_audio_trigger_start(snd_genode_period_elapsed_callback,
|
|
+ (unsigned long)substream);
|
|
+ break;
|
|
+ case SNDRV_PCM_TRIGGER_STOP:
|
|
+ case SNDRV_PCM_TRIGGER_SUSPEND:
|
|
+ PDBG("Stop");
|
|
+ genode_audio_trigger_stop();
|
|
+ stopped = 1;
|
|
+ break;
|
|
+ default:
|
|
+ PDBG("Unknown %d", cmd);
|
|
+ err = -EINVAL;
|
|
+ break;
|
|
+ }
|
|
+ spin_unlock(lock);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
+static int snd_genode_prepare(struct snd_pcm_substream *substream)
|
|
+{
|
|
+ PDBG("buffer_size=%lx count=%d", snd_pcm_lib_buffer_bytes(substream),
|
|
+ snd_pcm_lib_period_bytes(substream));
|
|
+ genode_audio_prepare();
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
+static snd_pcm_uframes_t snd_genode_pointer(struct snd_pcm_substream *substream)
|
|
+{
|
|
+ struct snd_pcm_runtime *runtime = substream->runtime;
|
|
+ unsigned long v = genode_audio_position();
|
|
+ unsigned long pos = bytes_to_frames(runtime, v) % runtime->buffer_size;
|
|
+ PDBG("position=%lx", pos);
|
|
+ return pos;
|
|
+}
|
|
+
|
|
+
|
|
+static void snd_genode_runtime_free(struct snd_pcm_runtime *runtime)
|
|
+{
|
|
+ spinlock_t *lock = (spinlock_t*) runtime->private_data;
|
|
+ PDBG("Enter");
|
|
+ kfree(lock);
|
|
+ kfree(packet_cache);
|
|
+}
|
|
+
|
|
+
|
|
+static int snd_genode_hw_params(struct snd_pcm_substream *substream,
|
|
+ struct snd_pcm_hw_params *hw_params)
|
|
+{
|
|
+ PDBG("params_buffer_bytes=%lx", params_buffer_bytes(hw_params));
|
|
+ return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
|
|
+}
|
|
+
|
|
+
|
|
+static int snd_genode_hw_free(struct snd_pcm_substream *substream)
|
|
+{
|
|
+ PDBG("Enter");
|
|
+ return snd_pcm_lib_free_pages(substream);
|
|
+}
|
|
+
|
|
+
|
|
+static int snd_genode_playback_open(struct snd_pcm_substream *substream)
|
|
+{
|
|
+ struct snd_pcm_runtime *runtime = substream->runtime;
|
|
+ spinlock_t *lock;
|
|
+
|
|
+ PDBG("Enter");
|
|
+
|
|
+ if (!(lock = kmalloc(sizeof(spinlock_t), GFP_KERNEL)))
|
|
+ return -ENOMEM;
|
|
+ spin_lock_init(lock);
|
|
+ runtime->private_data = lock;
|
|
+ runtime->private_free = snd_genode_runtime_free;
|
|
+
|
|
+ runtime->hw = snd_genode_playback_props;
|
|
+ runtime->hw.buffer_bytes_max = genode_audio_packet_count()
|
|
+ * genode_audio_packet_size();
|
|
+ runtime->hw.period_bytes_min = genode_audio_packet_size();
|
|
+ runtime->hw.period_bytes_max = genode_audio_packet_size();
|
|
+ runtime->hw.periods_min = 1;
|
|
+ runtime->hw.periods_max = genode_audio_packet_count();
|
|
+
|
|
+ if (!(packet_cache = kmalloc(runtime->hw.buffer_bytes_max, GFP_KERNEL))) {
|
|
+ kfree(lock);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
+static int snd_genode_playback_close(struct snd_pcm_substream *substream)
|
|
+{
|
|
+ PDBG("Enter");
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
+static int snd_genode_copy(struct snd_pcm_substream *substream,
|
|
+ int channel, snd_pcm_uframes_t pos,
|
|
+ void __user *buf, snd_pcm_uframes_t count)
|
|
+{
|
|
+ struct snd_pcm_runtime *runtime = substream->runtime;
|
|
+ unsigned long size = frames_to_bytes(runtime, count);
|
|
+ static snd_pcm_uframes_t position = 0;
|
|
+
|
|
+ if (stopped)
|
|
+ stopped = 0;
|
|
+ else
|
|
+ if (position == pos)
|
|
+ return 0;
|
|
+ position = pos;
|
|
+
|
|
+ PDBG("copy=%lx %lx\n", pos, count);
|
|
+ copy_from_user(packet_cache, buf, size);
|
|
+ genode_audio_write(packet_cache, size);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
+static int snd_genode_silence(struct snd_pcm_substream *substream,
|
|
+ int channel, snd_pcm_uframes_t pos,
|
|
+ snd_pcm_uframes_t count)
|
|
+{
|
|
+ struct snd_pcm_runtime *runtime = substream->runtime;
|
|
+ unsigned long size = frames_to_bytes(runtime, count);
|
|
+
|
|
+ PDBG("silence=%lx", size);
|
|
+ genode_audio_fill_silence(size);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
+/****************************
|
|
+ * Initialization functions *
|
|
+ ****************************/
|
|
+
|
|
+#define SND_GENODE_DRIVER "snd_genode"
|
|
+
|
|
+
|
|
+static struct snd_pcm_ops snd_genode_playback_ops = {
|
|
+ .ioctl = snd_pcm_lib_ioctl,
|
|
+ .open = snd_genode_playback_open,
|
|
+ .close = snd_genode_playback_close,
|
|
+ .hw_params = snd_genode_hw_params,
|
|
+ .hw_free = snd_genode_hw_free,
|
|
+ .prepare = snd_genode_prepare,
|
|
+ .trigger = snd_genode_trigger,
|
|
+ .pointer = snd_genode_pointer,
|
|
+ .copy = snd_genode_copy,
|
|
+ .silence = snd_genode_silence,
|
|
+};
|
|
+
|
|
+
|
|
+static int __devinit snd_genode_probe(struct platform_device *devptr)
|
|
+{
|
|
+ int err = 0;
|
|
+ struct snd_card *card;
|
|
+ struct snd_pcm *pcm;
|
|
+
|
|
+ if(!(card = snd_card_new(0, SND_GENODE_DRIVER, THIS_MODULE, 0)))
|
|
+ return -ENOMEM;
|
|
+
|
|
+ if ((err = snd_pcm_new(card, "Genode PCM", 0, 1, 0, &pcm)) < 0) {
|
|
+ snd_card_free(card);
|
|
+ return err;
|
|
+ }
|
|
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_genode_playback_ops);
|
|
+ pcm->info_flags = 0;
|
|
+ strcpy(pcm->name, "Genode PCM");
|
|
+ if((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
|
|
+ snd_dma_continuous_data(GFP_KERNEL),
|
|
+ 0, genode_audio_packet_count()
|
|
+ * genode_audio_packet_size())) < 0) {
|
|
+ snd_card_free(card);
|
|
+ return err;
|
|
+ }
|
|
+
|
|
+ strcpy(card->driver, "Genode");
|
|
+ strcpy(card->shortname, "Genode");
|
|
+ sprintf(card->longname, "Genode %i", devptr->id + 1);
|
|
+ snd_card_set_dev(card, &devptr->dev);
|
|
+
|
|
+ if (!(err = snd_card_register(card)))
|
|
+ platform_set_drvdata(devptr, card);
|
|
+ else {
|
|
+ snd_card_free(card);
|
|
+ return err;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
+static int __devexit snd_genode_remove(struct platform_device *devptr)
|
|
+{
|
|
+ snd_card_free(platform_get_drvdata(devptr));
|
|
+ platform_set_drvdata(devptr, 0);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
+static struct platform_driver snd_genode_driver = {
|
|
+ .probe = snd_genode_probe,
|
|
+ .remove = __devexit_p(snd_genode_remove),
|
|
+ .driver = {
|
|
+ .name = SND_GENODE_DRIVER
|
|
+ },
|
|
+};
|
|
+
|
|
+
|
|
+static int __init alsa_card_genode_init(void)
|
|
+{
|
|
+ int err = 0;
|
|
+
|
|
+ if (!genode_audio_ready())
|
|
+ return err;
|
|
+
|
|
+ if (!(err = platform_driver_register(&snd_genode_driver))) {
|
|
+ platform_dev_ptr = platform_device_register_simple(SND_GENODE_DRIVER, 0, 0, 0);
|
|
+ if (!platform_get_drvdata(platform_dev_ptr)) {
|
|
+ platform_device_unregister(platform_dev_ptr);
|
|
+ err = -ENODEV;
|
|
+ }
|
|
+ }
|
|
+ return err;
|
|
+}
|
|
+
|
|
+
|
|
+static void __exit alsa_card_genode_exit(void)
|
|
+{
|
|
+ platform_device_unregister(platform_dev_ptr);
|
|
+ platform_driver_unregister(&snd_genode_driver);
|
|
+}
|
|
+
|
|
+module_init(alsa_card_genode_init);
|
|
+module_exit(alsa_card_genode_exit);
|
|
+
|
|
+MODULE_AUTHOR("Stefan Kalkowski <stefan.kalkowski@genode-labs.com>");
|
|
+MODULE_DESCRIPTION("Genode sound stub");
|
|
+MODULE_LICENSE("GPL");
|
|
+MODULE_SUPPORTED_DEVICE("{{ALSA,Genode sound stub}}");
|
|
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 <stefan.kalkowski@genode-labs.com>
|
|
+ * \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-2012 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 <linux/module.h>
|
|
+#include <linux/moduleparam.h>
|
|
+#include <linux/init.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/fs.h>
|
|
+#include <linux/errno.h>
|
|
+#include <linux/types.h>
|
|
+#include <linux/genhd.h>
|
|
+#include <linux/blkdev.h>
|
|
+#include <linux/hdreg.h>
|
|
+#include <asm/semaphore.h>
|
|
+
|
|
+/* Genode support library includes */
|
|
+#include <genode/config.h>
|
|
+#include <genode/block.h>
|
|
+
|
|
+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 <kalkowski@genode-labs.com>
|
|
+ * \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-2012 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 <linux/module.h>
|
|
+#include <linux/init.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/errno.h>
|
|
+#include <linux/string.h>
|
|
+#include <linux/mm.h>
|
|
+#include <linux/tty.h>
|
|
+#include <linux/slab.h>
|
|
+#include <linux/delay.h>
|
|
+#include <linux/fb.h>
|
|
+#include <linux/proc_fs.h>
|
|
+#include <linux/input.h>
|
|
+#include <linux/platform_device.h>
|
|
+#include <linux/screen_info.h>
|
|
+
|
|
+/* Platform includes */
|
|
+#include <asm/uaccess.h>
|
|
+
|
|
+/* Genode support lib includes */
|
|
+#include <genode/framebuffer.h>
|
|
+#include <genode/input.h>
|
|
+#include <oklx/ioctl.h>
|
|
+
|
|
+
|
|
+/**********************************
|
|
+ ** 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 <stefan.kalkowski@genode-labs.com>");
|
|
+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 <stefan.kalkowski@genode-labs.com>
|
|
+ * \date 2010-09-09
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2006-2012 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 <linux/etherdevice.h>
|
|
+#include <linux/errno.h>
|
|
+#include <linux/inet.h>
|
|
+#include <linux/init.h>
|
|
+#include <linux/jiffies.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/module.h>
|
|
+#include <linux/netdevice.h>
|
|
+#include <linux/string.h>
|
|
+#include <linux/types.h>
|
|
+
|
|
+#include <genode/net.h>
|
|
+
|
|
+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 <l4/kdebug.h>
|
|
|
|
+#include <genode/printf.h>
|
|
+
|
|
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<count; ++i)
|
|
+ buf[i]=p[i];
|
|
+ buf[i]=0;
|
|
+ genode_printf(buf);
|
|
}
|
|
|
|
static struct console l4kdb_cons = {
|
|
- .name = "l4con",
|
|
+ .name = "ttyKDB",
|
|
.write = l4kdb_cons_write,
|
|
.flags = CON_PRINTBUFFER,
|
|
.index = -1,
|
|
};
|
|
|
|
-static int __init l4kdb_console_init(void)
|
|
-{
|
|
- register_console(&l4kdb_cons);
|
|
- return 0;
|
|
-}
|
|
-
|
|
-console_initcall(l4kdb_console_init);
|
|
-
|
|
#ifdef CONFIG_EARLY_PRINTK
|
|
void
|
|
enable_early_printk(void)
|
|
@@ -38,5 +35,16 @@ disable_early_printk(void)
|
|
{
|
|
unregister_console(&l4kdb_cons);
|
|
}
|
|
+
|
|
+#else
|
|
+
|
|
+static int __init l4kdb_console_init(void)
|
|
+{
|
|
+ register_console(&l4kdb_cons);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+console_initcall(l4kdb_console_init);
|
|
+
|
|
#endif
|
|
|
|
diff -urNpB kernel-2.6.23-v2/arch/l4/include/wombat.h contrib/arch/l4/include/wombat.h
|
|
--- kernel-2.6.23-v2/arch/l4/include/wombat.h
|
|
+++ contrib/arch/l4/include/wombat.h
|
|
@@ -2,7 +2,7 @@
|
|
#include <linux/mm.h>
|
|
#include <asm/mmzone.h>
|
|
|
|
-#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 <linux/jiffies.h>
|
|
+#include <linux/delay.h>
|
|
+#include <linux/init.h>
|
|
+
|
|
+#include <asm/timex.h>
|
|
+
|
|
+#include <genode/lock.h>
|
|
+
|
|
+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 <linux/kernel.h>
|
|
|
|
#include <assert.h>
|
|
-#include <iguana/pd.h>
|
|
+#include <genode/exit.h>
|
|
|
|
/*
|
|
* 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 <unistd.h>
|
|
#include "internal.h"
|
|
|
|
-#include <iguana/env.h>
|
|
-#include <iguana/memsection.h>
|
|
+//#include <iguana/env.h>
|
|
+//#include <iguana/memsection.h>
|
|
|
|
#include <l4/kdebug.h>
|
|
|
|
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 <linux/syscalls.h>
|
|
#include <linux/string.h>
|
|
|
|
+#include <linux/pagemap.h> /* needed by 'asm/tlb.h' */
|
|
+
|
|
#define __KERNEL_SYSCALLS__
|
|
|
|
-#include <asm/unistd.h> /* execve */
|
|
+#include <asm/unistd.h> /* execve */
|
|
+#include <asm/tlb.h> /* '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 <asm/setup.h>
|
|
|
|
#include <iguana/thread.h>
|
|
-#include <iguana/cap.h>
|
|
#include <iguana/memsection.h>
|
|
#include <iguana/tls.h>
|
|
-#include <iguana/env.h>
|
|
|
|
-void *__callback_buffer;
|
|
+#include <genode/memory.h>
|
|
+#include <genode/sleep.h>
|
|
+#include <genode/config.h>
|
|
+#include <genode/lock.h>
|
|
|
|
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 <iguana/eas.h>
|
|
#include <iguana/thread.h>
|
|
|
|
+#include <genode/lock.h>
|
|
+
|
|
+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 <asm/tlbflush.h>
|
|
#include <asm/setup.h>
|
|
|
|
-#include <iguana/memsection.h>
|
|
-#include <iguana/cap.h>
|
|
#include <iguana/thread.h>
|
|
|
|
#ifdef CONFIG_VT
|
|
@@ -25,7 +23,9 @@
|
|
#include <linux/screen_info.h>
|
|
#include <asm/io.h>
|
|
|
|
-#include <iguana/env.h>
|
|
+#include <genode/config.h>
|
|
+#include <genode/open.h>
|
|
+
|
|
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,433 @@
|
|
+#define timer_t timer_t_linux
|
|
+
|
|
+#include <l4.h>
|
|
+#include <l4/interrupt.h>
|
|
+#include <l4/utcb.h>
|
|
+#include <wombat.h>
|
|
+
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/types.h>
|
|
+#include <linux/mm.h>
|
|
+#include <linux/sched.h>
|
|
+#include <linux/init.h>
|
|
+#include <linux/module.h>
|
|
+#undef timer_t
|
|
+
|
|
+#include <iguana/memsection.h>
|
|
+#include <iguana/thread.h>
|
|
+#include <iguana/hardware.h>
|
|
+
|
|
+#include <genode/memory.h>
|
|
+#include <genode/sleep.h>
|
|
+#include <genode/lock.h>
|
|
+#ifdef CONFIG_SCREEN_GENODE
|
|
+#include <genode/input.h>
|
|
+#endif
|
|
+#ifdef CONFIG_SND_GENODE
|
|
+#include <genode/audio.h>
|
|
+#endif
|
|
+#ifdef CONFIG_NET_GENODE
|
|
+#include <genode/net.h>
|
|
+#endif
|
|
+#ifdef CONFIG_BLOCK_GENODE
|
|
+#include <genode/block.h>
|
|
+#endif
|
|
+
|
|
+#include "assert.h"
|
|
+#include "irq_impl.h"
|
|
+
|
|
+#include <linux/posix_types.h>
|
|
+
|
|
+
|
|
+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 <driver/types.h>
|
|
+//#include <interfaces/vtimer_client.h>
|
|
+
|
|
+//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<<i))){
|
|
+ irq_mask |= (1UL<<i);
|
|
+ return IGUANA_IRQ(i);
|
|
+ }
|
|
+ }
|
|
+ return -1;
|
|
+}
|
|
+//extern void ig_serial_interrupt(void);
|
|
+//extern void ig_input_interrupt(void);
|
|
+
|
|
+static int pending_tick;
|
|
+
|
|
+/* static int */
|
|
+/* tid_to_int(L4_ThreadId_t tid) */
|
|
+/* { */
|
|
+/* return (int)L4_ThreadNo(tid); */
|
|
+/* } */
|
|
+
|
|
+/* L4_Word_t */
|
|
+/* corba_l4_error(CORBA_Environment *env) */
|
|
+/* { */
|
|
+/* L4_Word_t val = *(L4_Word_t *)(env); */
|
|
+
|
|
+/* if ((val & 0xff) == CORBA_SYSTEM_EXCEPTION) */
|
|
+/* return val >> 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_SND_GENODE
|
|
+ genode_audio_collect_acks();
|
|
+#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 <asm/setup.h>
|
|
|
|
#include <iguana/thread.h>
|
|
-#include <iguana/cap.h>
|
|
#include <iguana/memsection.h>
|
|
-#include <iguana/tls.h>
|
|
-#include <iguana/object.h>
|
|
+#include <genode/lock.h>
|
|
|
|
#include <linux/mman.h>
|
|
|
|
@@ -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/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 <iguana/thread.h>
|
|
#include <iguana/memsection.h>
|
|
#include <iguana/hardware.h>
|
|
-#include <iguana/physmem.h>
|
|
+//#include <iguana/physmem.h>
|
|
|
|
/* 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/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 <iguana/pd.h>
|
|
+#include <genode/printf.h>
|
|
+#include <genode/exit.h>
|
|
|
|
#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 <asm-generic/bug.h>
|
|
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 <iguana/thread.h>
|
|
#include <iguana/memsection.h>
|
|
#include <iguana/hardware.h>
|
|
-#include <iguana/physmem.h>
|
|
+//#include <iguana/physmem.h>
|
|
|
|
|
|
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/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/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
|