Subject: low-level hacking [was Re: Calling All Noobs... ]
From: rpw3@rpw3.org (Rob Warnock)
Date: Wed, 11 Jan 2006 05:01:57 -0600
Newsgroups: comp.lang.lisp
Message-ID: <G_qdnfy3B944eFnenZ2dnUVZ_v2dnZ2d@speakeasy.net>
Edi Weitz  <spamtrap@agharta.de> wrote:
+---------------
|  rpw3@rpw3.org (Rob Warnock) wrote:
| > You want scary? I'll give you scary! Try peeking & poking hardware
| > registers from within CMUCL, heh-heh!  MMAP some hardware into your
| > VM and then do (setf (system:sap-ref-32 (system:int-sap addr) 0)
| > new-value) [which in C is "*((u32*)(addr)+0) = new-value"]. I have a
| > whole toolkit of such low-level hacks that I use to do user-mode
| > debugging of hardware at my current POE.
| 
| Sounds interesting. Do you have plans to make that publicly available?
+---------------

I guess I could put up the very lowest-level stuff (~150 lines), but:

1. It's more a set of patterns than a true "module". It all loads
   into the "CL-USER" package, since that's where I usually work.

2. I don't have a fully fleshed-out example of how to use it for
   something serious that's not proprietary to some current or
   previous employer [most real applications involve page after page
   of symbolic hardware register locations and bit definitions!].

3. The low-level stuff isn't very useful if you don't have any
   interesting mmap'able hardware lying around you want to poke at...  ;-}

4. If applied to introspection of CMUCL itself [I've been using it
   for some of that lately], much of it is *NOT* GC-safe. You have
   to be very sure you know what you're doing, and sometimes need
   to do a (GC :FULL T) before starting a sequence of operations
   [or maybe wrap a SYSTEM:WITHOUT-GCING around it].

5. Calling MAKE-LISP-OBJ with a bad argument can easily crash CMUCL,
   and maybe your system.

6. You have to un CMUCL as root to mmap I/O memory space. Running
   CMUCL as root can crash your system. YOU HAVE BEEN WARNED!

But if you really think anyone else would find it useful...  ;-}  ;-}

Most of it is just abbreviations and shortcuts to facilities
that are already in CMUCL for anyone who looks at the source,
e.g., MAKE-LISP-OBJ is just (IMPORT 'KERNEL:MAKE-LISP-OBJ);
R32 and W32 are just SYSTEM:SAP-REF-32 wrappers:

    (defun r32 (addr)
      (declare (optimize (speed 3) (debug 0) (safety 0)))
      (system:sap-ref-32 (system:int-sap addr) 0))

    (defun w32 (addr &rest values)
      (declare (optimize (speed 3) (debug 0) (safety 0)))
      (loop for i fixnum from 0 by 4
	    and v of-type (unsigned-byte 32) in values
	do (setf (system:sap-ref-32 (system:int-sap addr) i) v))
      (values))

R8/W8/R16/W16 are similar, and D32 (formerly named DUMP32) is just
a loop around R32 & FORMAT. My MMAP is just a thin wrapper around
UNIX:UNIX-MMAP with a slightly simplified calling sequence for the
cases I mostly use, a typical use being (MMAP "/dev/mem" PCI-BUS-ADDRESS T)
[where the PCI bus address is where some device register got mapped
by the BIOS, which on Linux you find out *manually* with "lspci"]:

    (defun mmap (file offset length &optional write-p)
      (let* ((ofs32 (if (zerop (logand offset #x80000000))
		      offset
		      (- offset #x100000000))) ; Fake up a "(signed-byte 32)"
	     (mode (logior #+linux unix::O_SYNC     ; Not on BSD (*sigh*)
			   (if write-p unix:O_RDWR unix:O_RDONLY)))
	     (fd (unix:unix-open file mode 0)))
	(if (not fd)
	  (error "Can't open ~s: ~s" file (unix:get-unix-error-msg))
	  (unwind-protect
	      (let ((mode (logior unix:PROT_READ
				  (if write-p unix:PROT_WRITE 0))))
		(system:sap-int
		  (unix:unix-mmap nil length mode unix:MAP_SHARED fd ofs32)))
	    (unix:unix-close fd)))))

Is this level stuff really interesting to others?


-Rob

-----
Rob Warnock			<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607