Updated slram for 2.1.92 (with documentation)

Brad Keryan (keryan@andrew.cmu.edu)
Sun, 5 Apr 1998 23:48:03 -0400 (EDT)


This is the latest version of the slram patch (to use slow, uncacheable
memory on Pentium systems as a block device for swap partition). It is
against 2.1.92, has a few minor fixes/changes and now has documentation.

The patch is also available at http://www.keryan.ml.org/~keryan/patches/

Comments, suggestions, bugfixes etc. are always welcome.

Brad

--- CUT HERE ---

diff -urN linux-2.1.92-clean/Documentation/Configure.help linux-2.1.92/Documentation/Configure.help
--- linux-2.1.92-clean/Documentation/Configure.help Wed Apr 1 19:20:56 1998
+++ linux-2.1.92/Documentation/Configure.help Sun Apr 5 16:38:49 1998
@@ -115,6 +115,14 @@
window for vmalloc() plus PCI space uses up some memory too, thus
addresses above FD000000 should rather be kept free.

+Use slow memory as a ramdisk
+CONFIG_BLK_DEV_SLRAM
+ If you have a Pentium or 486 motherboard that cannot cache all of the
+ memory on your system, saying Y here will let you use the uncacheable
+ portion of your RAM (the slow RAM) as a ramdisk or a high-speed swap
+ device. For details, look at Documentation/slram.txt. If your
+ motherboard can cache all of its RAM or you're unsure, say N here.
+
Normal floppy disk support
CONFIG_BLK_DEV_FD
If you want to use your floppy disk drive(s) under Linux, say
diff -urN linux-2.1.92-clean/Documentation/slram.txt linux-2.1.92/Documentation/slram.txt
--- linux-2.1.92-clean/Documentation/slram.txt Wed Dec 31 19:00:00 1969
+++ linux-2.1.92/Documentation/slram.txt Sun Apr 5 17:09:44 1998
@@ -0,0 +1,73 @@
+ slram (slow RAM) for Linux 2.1.92
+ Brad Keryan <keryan@andrew.cmu.edu>
+ -----------------------------------
+
+Intro
+-----
+
+Slram (slow RAM) is a way to use large amounts of RAM on 486 and
+Pentium systems without slowing the system down, by reserving all RAM
+above a specified area for a special ramdisk. It is based on an old
+version of the z2ram driver from Linux/m68k.
+
+Why is something like this necessary? Many 486 and Pentium motherboard
+chipsets limit the amount of cacheable memory to either 16 or 64
+megabytes, so that the chipsets are cheaper and easier to design and
+produce. As a result, all RAM above the limit is not cached. The
+problem is that Linux places many kernel data structures at the top of
+memory, so not having these cached reduces the system's performance by
+a noticeable amount.
+
+Slram reserves the uncached space and uses it for a RAM disk, so the
+kernel doesn't use it. This way, only the RAM accesses for that RAM
+disk slow down, compared to normal RAM. Despite the fact that the RAM
+slram uses is slower than the RAM the rest of the system uses, it is
+much faster than disk, so using it as a swap partition will cause an
+improvement in system performance, depending how much swap the system
+uses.
+
+How to Use
+----------
+
+To use slram, first you need to find out how much RAM your motherboard caches.
+Usually the manufacturer is not going to tell you, but if you know what chipset
+the board uses, you may be able to find it at
+http://www.tomshardware.com/chipset.html
+
+If the amount of installed memory is less than the maximum cacheable memory,
+then you don't need slram.
+
+Next, you have to recompile your kernel with the slram driver, by answering
+Y to "Use slow memory as a ramdisk" (CONFIG_BLK_DEV_SLRAM) in make config.
+
+After you install the new kernel, you have to tell it how much memory your
+motherboard can cache, via the kernel command line parameter "fastmem".
+As an example, my system has an Intel Triton VX chipset and 96M of RAM, and
+the BIOS RAM check tells me it has 98304K on bootup. The chipset only caches
+64M of RAM, so in my /etc/lilo.conf I have the line:
+
+ append="fastmem=65536k mem=98304k"
+
+If you use another method to boot Linux (like GRUB, syslinux, or loadlin) there
+is an equivalent way to add the command line parameters.
+
+Finally, to actually use the RAM, you must create a device node for it and use
+that.
+
+mknod /dev/slram b 123 0
+
+will create the device node, and to use it you can do something like
+
+mkswap /dev/slram
+swapon -p 10 /dev/slram
+
+Note the "priority" option to swapon--that tells it to use a higher
+priority than the disk swap partitions, which on my system have a
+priority of 0. This is not the default, so if you have any disk swap
+partitions, you need to add "pri=0" to their entries in /etc/fstab.
+
+Bugs
+----
+
+If you find a bug or make an improvement in slram, or just can't get
+it to work, e-mail me at keryan@andrew.cmu.edu
diff -urN linux-2.1.92-clean/arch/i386/config.in linux-2.1.92/arch/i386/config.in
--- linux-2.1.92-clean/arch/i386/config.in Sun Mar 29 15:16:12 1998
+++ linux-2.1.92/arch/i386/config.in Sun Apr 5 15:40:21 1998
@@ -18,6 +18,7 @@
PPro/K6/6x86MX CONFIG_M686" Pentium
bool 'Math emulation' CONFIG_MATH_EMULATION
int ' Max physical memory in MB' CONFIG_MAX_MEMSIZE 1024
+bool 'Use slow memory as a ramdisk' CONFIG_BLK_DEV_SLRAM
endmenu

mainmenu_option next_comment
diff -urN linux-2.1.92-clean/arch/i386/kernel/setup.c linux-2.1.92/arch/i386/kernel/setup.c
--- linux-2.1.92-clean/arch/i386/kernel/setup.c Wed Feb 25 18:30:22 1998
+++ linux-2.1.92/arch/i386/kernel/setup.c Sun Apr 5 18:15:11 1998
@@ -29,7 +29,7 @@
#ifdef CONFIG_APM
#include <linux/apm_bios.h>
#endif
-#ifdef CONFIG_BLK_DEV_RAM
+#if defined(CONFIG_BLK_DEV_RAM) || defined(CONFIG_BLK_DEV_SLRAM)
#include <linux/blk.h>
#endif
#include <asm/uaccess.h>
@@ -42,6 +42,10 @@

char ignore_irq13 = 0; /* set if exception 16 works */
struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
+#ifdef CONFIG_BLK_DEV_SLRAM
+unsigned long end_fast_mem = 0; /* end of fast memory - in case something
+ is not cached this is interesting */
+#endif

/*
* Bus types ..
@@ -184,6 +188,21 @@
}
}
}
+#ifdef CONFIG_BLK_DEV_SLRAM
+ if (c == ' ' && strlen(from) > 8 && strncmp(from, "fastmem=", 8) == 0) {
+ if (to != command_line) to--;
+ {
+ end_fast_mem = simple_strtoul(from+8, &from, 0);
+ if ( *from == 'K' || *from == 'k' ) {
+ end_fast_mem = end_fast_mem << 10;
+ from++;
+ } else if ( *from == 'M' || *from == 'm' ) {
+ end_fast_mem = end_fast_mem << 20;
+ from++;
+ }
+ }
+ }
+#endif
c = *(from++);
if (!c)
break;
@@ -193,6 +212,18 @@
}
*to = '\0';
*cmdline_p = command_line;
+#ifdef CONFIG_BLK_DEV_SLRAM
+ if (!end_fast_mem)
+ end_fast_mem = memory_end;
+ if (!slram_size && (memory_end > end_fast_mem)) {
+ slram_size = memory_end - end_fast_mem;
+ printk("RAM above %luk declared slow, reserving %luk for slram\n", end_fast_mem >>10, slram_size >>10 );
+ slram_phys = end_fast_mem;
+ } else {
+ slram_phys = 0;
+ }
+ slram_virt = 0;
+#endif
memory_end += PAGE_OFFSET;
*memory_start_p = memory_start;
*memory_end_p = memory_end;
diff -urN linux-2.1.92-clean/arch/i386/mm/init.c linux-2.1.92/arch/i386/mm/init.c
--- linux-2.1.92-clean/arch/i386/mm/init.c Wed Mar 11 18:10:39 1998
+++ linux-2.1.92/arch/i386/mm/init.c Sun Apr 5 15:40:21 1998
@@ -31,6 +31,9 @@

extern void die_if_kernel(char *,struct pt_regs *,long);
extern void show_net_buffers(void);
+#ifdef CONFIG_BLK_DEV_SLRAM
+extern int end_fast_mem;
+#endif

/*
* BAD_PAGE is the page that is used for page faults when linux
@@ -337,11 +340,17 @@
start_low_mem += PAGE_SIZE;
}

- while (start_mem < end_mem) {
+ while (start_mem <
+#ifdef CONFIG_BLK_DEV_SLRAM
+ ((end_fast_mem+PAGE_OFFSET) & PAGE_MASK)
+#else
+ end_mem
+#endif
+ ) {
clear_bit(PG_reserved, &mem_map[MAP_NR(start_mem)].flags);
start_mem += PAGE_SIZE;
}
- for (tmp = PAGE_OFFSET ; tmp < end_mem ; tmp += PAGE_SIZE) {
+ for (tmp = end_mem - PAGE_SIZE; tmp >= PAGE_OFFSET ; tmp -= PAGE_SIZE) {
if (tmp >= MAX_DMA_ADDRESS)
clear_bit(PG_DMA, &mem_map[MAP_NR(tmp)].flags);
if (PageReserved(mem_map+MAP_NR(tmp))) {
diff -urN linux-2.1.92-clean/drivers/block/Makefile linux-2.1.92/drivers/block/Makefile
--- linux-2.1.92-clean/drivers/block/Makefile Fri Mar 6 13:48:00 1998
+++ linux-2.1.92/drivers/block/Makefile Sun Apr 5 15:40:21 1998
@@ -70,6 +70,14 @@
endif
endif

+ifeq ($(CONFIG_BLK_DEV_SLRAM),y)
+L_OBJS += slram.o
+else
+ ifeq ($(CONFIG_BLK_DEV_SLRAM),m)
+ M_OBJS += slram.o
+ endif
+endif
+
ifeq ($(CONFIG_BLK_DEV_LOOP),y)
L_OBJS += loop.o
else
diff -urN linux-2.1.92-clean/drivers/block/ll_rw_blk.c linux-2.1.92/drivers/block/ll_rw_blk.c
--- linux-2.1.92-clean/drivers/block/ll_rw_blk.c Sun Mar 29 15:24:05 1998
+++ linux-2.1.92/drivers/block/ll_rw_blk.c Sun Apr 5 15:40:21 1998
@@ -788,6 +788,9 @@
#ifdef CONFIG_DDV
ddv_init();
#endif
+#ifdef CONFIG_BLK_DEV_SLRAM
+ slram_init();
+#endif
return 0;
};

diff -urN linux-2.1.92-clean/drivers/block/slram.c linux-2.1.92/drivers/block/slram.c
--- linux-2.1.92-clean/drivers/block/slram.c Wed Dec 31 19:00:00 1969
+++ linux-2.1.92/drivers/block/slram.c Sun Apr 5 18:31:04 1998
@@ -0,0 +1,218 @@
+/*
+ * slram (slow RAM): a way to use large amounts of RAM on 486 and Pentium
+ * systems without slowing the system down. Reserves all RAM above a specified
+ * amount for a special ramdisk. Reason for existence: a number of 486 and
+ * Pentium motherboards cache only 16M or 64M.
+ *
+ * written by Brad Keryan <keryan@andrew.cmu.edu>
+ *
+ * Heavily based on z2ram by Ingo Wilken
+ * (Ingo.Wilken@informatik.uni-oldenburg.de) and on
+ * drivers/block/rd.c. Also drivers/block/ide.c.
+ */
+
+/* the original z2ram copyright is as follows: */
+/* Copyright (C) 1994 by Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)
+**
+** Permission to use, copy, modify, and distribute this software and its
+** documentation for any purpose and without fee is hereby granted, provided
+** that the above copyright notice appear in all copies and that both that
+** copyright notice and this permission notice appear in supporting
+** documentation. This software is provided "as is" without express or
+** implied warranty.
+*/
+
+/*
+ * Ported to 2.1.89 by Pavel Machek <pavel@elf.ucw.cz>
+ *
+ * Minor changes for 2.1.92pre2 by Adam Heath <adam.heath@usa.net>
+ *
+ * 4/5/98 - Set blk_size, fixed kernel command line parsing, added a readme
+ * (Documentation/slram.txt), added __initfunc, general cleanup - keryan
+ */
+
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/malloc.h>
+#include <linux/ioctl.h>
+#include <linux/fd.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+/* note: this is an experimental major number and is not guaranteed to not
+conflict with something else. Perhaps slram should share the major number of
+z2ram, because the two drivers accomplish the same thing on different
+architectures */
+#ifndef SLRAM_MAJOR
+#define SLRAM_MAJOR 123
+#endif
+
+#define MAJOR_NR SLRAM_MAJOR
+#define MINOR_NR 0
+#define DEVICE_NAME "slram"
+#define DEVICE_REQUEST do_slram_request
+#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+#define DEVICE_NO_RANDOM
+
+#include <linux/blk.h>
+
+#undef DEBUG
+
+/* not a module (yet) */
+#undef MODULE
+
+unsigned long slram_size = 0, slram_phys, slram_virt;
+
+/* only one device is possible right now */
+#define MAX_SLRAM 1
+static int slram_sizes[MAX_SLRAM] = { 0 };
+static int slram_blksizes[MAX_SLRAM] = { 1024 };
+
+static void do_slram_request (void)
+{
+ unsigned int minor;
+ unsigned int offset, len;
+
+ repeat:
+ INIT_REQUEST;
+
+ minor = MINOR(CURRENT->rq_dev);
+ if (minor != MINOR_NR) {
+ end_request(0);
+ goto repeat;
+ }
+
+ offset = CURRENT->sector << 9;
+ len = CURRENT->current_nr_sectors << 9;
+
+ /* should be handled by the blk_size checking in ll_rw_blk.c */
+#if 0
+ if ((offset + len) > slram_size) {
+ end_request(0);
+ goto repeat;
+ }
+#endif
+
+ switch(CURRENT->cmd) {
+ case READ :
+ memcpy(CURRENT->buffer, (char *) slram_virt + offset, len);
+ break;
+ case WRITE :
+ memcpy((char *) slram_virt + offset, CURRENT->buffer, len);
+ break;
+ default :
+ printk("do_slram_request: unknown command\n");
+ }
+ end_request(1);
+ goto repeat;
+}
+
+static int slram_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ /* more or less copied from rd.c */
+ int err;
+
+#ifdef DEBUG
+ printk(KERN_NOTICE "slram ioctl(0x%x, 0x%x)\n", cmd, arg);
+#endif
+
+ if (!inode || !inode->i_rdev)
+ return -EINVAL;
+
+ switch (cmd) {
+ case BLKFLSBUF:
+ if (!suser()) return -EACCES;
+ invalidate_buffers(inode->i_rdev);
+ return 0;
+ case BLKGETSIZE: /* Return device size, in 512-byte chunks */
+ if (!arg) return -EINVAL;
+ err = verify_area(VERIFY_WRITE, (long *) arg,
+ sizeof(long));
+ if (err)
+ return err;
+ put_user(slram_sizes[MINOR(inode->i_rdev)] * 2, (long *) arg);
+ return 0;
+ default:
+ break;
+ };
+
+ return 0;
+}
+
+static int slram_open(struct inode *inode, struct file *file)
+{
+ if (MINOR(inode->i_rdev) != MINOR_NR)
+ return -ENXIO;
+
+#ifdef MODULE
+ MOD_INC_USE_COUNT;
+#endif
+ return 0;
+}
+
+static int slram_release(struct inode *inode, struct file *file)
+{
+#ifdef MODULE
+ MOD_DEC_USE_COUNT;
+#endif
+ return 0;
+}
+
+static struct file_operations slram_fops = {
+ NULL, /* lseek - default */
+ block_read, /* read - general block-dev read */
+ block_write, /* write - general block-dev write */
+ NULL, /* readdir - bad */
+ NULL, /* select */
+ slram_ioctl, /* ioctl */
+ NULL, /* mmap */
+ slram_open, /* open */
+ slram_release, /* release */
+ block_fsync, /* fsync */
+};
+
+__initfunc(int slram_init(void))
+{
+ if (register_blkdev(MAJOR_NR, DEVICE_NAME, &slram_fops)) {
+ printk("Unable to allocate major %d for slram\n",
+ MAJOR_NR);
+ return -EIO;
+ }
+ blk_dev[MAJOR_NR].request_fn = do_slram_request;
+
+ slram_sizes[MINOR_NR] = slram_size >> 10;
+
+ blk_size[MAJOR_NR] = slram_sizes;
+ blksize_size[MAJOR_NR] = slram_blksizes;
+
+ slram_virt = (unsigned long) __va(slram_phys);
+ printk("Slow RAM %luk-%luk mapped to %lx for slram disk\n",
+ (slram_phys)>>10,
+ (slram_phys + slram_size)>>10,
+ slram_virt );
+
+ return 0;
+}
+
+void slram_unregister(void)
+{
+ unregister_blkdev(MAJOR_NR, DEVICE_NAME);
+
+ blk_dev[MAJOR_NR].request_fn = NULL;
+
+ blk_size[MAJOR_NR] = NULL;
+ blksize_size[MAJOR_NR] = NULL;
+}
+
diff -urN linux-2.1.92-clean/include/linux/blk.h linux-2.1.92/include/linux/blk.h
--- linux-2.1.92-clean/include/linux/blk.h Wed Apr 1 20:30:46 1998
+++ linux-2.1.92/include/linux/blk.h Sun Apr 5 17:52:04 1998
@@ -72,6 +72,7 @@
extern int z2_init(void);
extern int swim3_init(void);
extern int ps2esdi_init(void);
+extern int slram_init(void);

extern void set_device_ro(kdev_t dev,int flag);
void add_blkdev_randomness(int major);
@@ -92,6 +93,11 @@
extern int initrd_below_start_ok; /* 1 if it is not an error if initrd_start < memory_start */
void initrd_init(void);

+#endif
+
+#ifdef CONFIG_BLK_DEV_SLRAM
+extern unsigned long slram_size, slram_phys, slram_virt;
+void slram_unregister(void);
#endif

#define RO_IOCTLS(dev,where) \

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu