things to do (or not) in (or near) kernel space
using scheme
actually, a way of accessing hardware from a userspace repl.
taken from newsgroup comp.lang.scheme .. .
From: Rob Warnock (rpw3 (at) rpw3 (dot) org)
+--------------- | Harri Haataja wrote: | > I find the desire some (esp Linux) people have to push things to | > kernel space very strange. I would think everything that is | > possible to do in the much more safe and managed user space, | > should be kept there. | | I agree for most things, but I can't see a kernel exploration | system / rapid driver development platform working particularly | well in user space ;-) +--------------- Uh... It works *extremely* well, actually! And it's *much* easier to do debugging when the code-under-test is in user mode! Building a bringup environment for new (and often initially broken!) hardware was precisely what I used Scheme for when I first started using it back at SGI circa 1992!! All I had to do was add a few primitives in C (dynamically-loadable into SCM, later MzScheme) for poking at the system & hardware: malloc & free ; Note: *Not* from GC'd space mpin ; Pin a virtual address range of the process ; in physical memory, similar to unix v.7 "sys()". vir->phys ; Once you've pinned it, where is it? [Needed for DMA] mmap ; Map the hardware registers into process space. peek & poke ; In 8/16/32/64-bit flavors That was enough to let me do almost complete debugging in user mode of several generations of networking cards -- multi-port FDDI, Ethernet, ATM, and HIPPI, to name a few -- including testing of both PIO & DMA transfers. (That's why you need to "pin" pages, so other processes' data won't get paged into that spot while you're DMA'ing into it!) The code looked a bit like this (pardon dusty memories for any mistakes): (define bridge-path "/hw/module/1/slot/io3/pci/controller") (define big0-path "/hw/module/1/slot/io3/pci/0/usrpci/mem32") (define brj (mmap bridge-path 0 #x1000000 1)) (define dev0cf (+ brj #x20000)) (define dev0 'notyet) (define dev0m 'notyet) (let ((tmp (r32 dev0cf))) (if (= tmp #x210a9) (begin (print "FOO present on device 0 - Enabling mem space") (w32 (+ dev0cf 4) (logior PCCSR_MASTER_EN PCCSR_MEM_SPACE)) (print "Mapping a big window") (set! dev0 (mmap big0-path (r32 (+ dev0cf #x10)) #x8000000 1)) (set! dev0m (+ dev0 #x7800000))))) At that point, "dev0" contained the process-virtual address of the device's on-board registers, and "dev0m" pointed to its shared memory buffers. Peeking (r32) and poking (w32) at those addresses, one could put the device through all of its paces (except interrupts! -- but every bit that could cause an interrupt had a corresponding pollable flag bit, so in practice that wasn't a serious limitation). +--------------- | You may well be right but I can imagine things like rapidly | prototyping a new file-system might be fun in Scheme? +--------------- You can do *that* in user mode, too! It wasn't in Scheme (would have been easier had it been!), but when consulting for AMD in the late 80's, I reimplemented the IBM CMS filesystem (at least well enough to read/allocate/write CMD "mini-disk" user files with that "interesting" B-tree filesystem they had) completely in user space under Amdahl's UTS-5. You can do the same in modern Unixes/Linux, too. Just write a user-mode NFS daemon (one easy way to hook a user process into the filesystem dispatch) that munges raw partitions into whatever filesystem you like (the way database vendors do for performance). IMHO and IME, anything that *can* be done in user mode *should* be done in user-mode, at least during development. -Rob
Just go for it! It's really easy to get started:
- Run some O/S on your machine that allows you to “mmap()” PCI bus space into user mode (possibly requiring superuser privilege, but hey, it's *your* machine, right?). Note: Some OSs don't provide “mmap()” access though device special files per se, but *do* let you use some other access path, such as /dev/mem, /dev/kmem, or /dev/mmem, etc., to map at least the memory space of I/O busses into use process space.
- Run some Scheme on your machine that allows you to dynamically link in libraries at runtime (almost any of the popular ones, at least if the answer to #1 was some flavor of Unix or Linux), or use one of the ones that compile to C and let you link in stuff statically.
- Find *some* card or chip whose memory register layout you know. (Older ones are sometimes easier to find documentation for.)
- Hack up a peek/poke/mmap/etc. library for your Scheme, map in that card (or chip), and start poking around to see what you can see.
WARNING! It is *very* likely that you will crash the host several times while getting this all to work. DO NOT USE A CRITICAL OR SHARED COMPUTER!