Background
Creating a DTS file is a crucial step in integrating a custom peripheral with the Linux kernel. Unfortunately, this subject is rather hazy at the present time, and it’s in particular difficult to obtain that initial DTS to boot the system up with for the first time.
It’s important to take the DTS (and the DTB compiled from it) for what it is: A simple data tree (think XML) containing information that is read by the kernel as it boots up. By convention, some standard entries tell it what resources (memory and interrupts) to allocate, and the rest of them can be read by the specific driver to obtain application-specific information (e.g. the clock frequency driving the hardware). Like XML, you’re free to add whatever nodes you want to the tree, as long as you have reason enough to assume their names aren’t used for something else.
As of writing this post, there is no automatic process for generating a DTS that includes custom peripherals for Zynq. On the other hand, it’s not all that difficult to add the entry manually, when all the other hardware peripheral’s nodes are available. The two methods described below take different approaches: The first reverse-engineers the DTS from an existing, running Linux kernel. If custom peripherals are declared in the loaded DTB, they will appear here. The significant drawback of this method is that pointers to other nodes in the tree (e.g. “interrupt-parent”) appear as numeric values, and not by a name reference, which makes the whole thing harder to understand and more fragile to changes. Also note that if there are differences in the processor configuration between the running system and yours, this device tree will not be useful. But it’s an excellent way to verify the small details are in place.
The second method focuses on getting the device tree from a system configuration in Xilinx’ EDK. This ensures a perfect match between the processor configuration and the device tree, but if the driver expects some extra attributes, they may get missed. In theory, these attributes should be generated automatically from the IP core’s attributes, but there is nothing stopping the driver’s author from manually editing the DTS tree to add hints to the driver.
I’ve already written a general post on device trees for Microblaze (and several general info). But the principles are the same for any processor. I should mention, that it was written before kernel 3.3, which seems to have another notation for interrupts.
I’ve also described how to run the process for a Microblaze processor in a previous post, which is the basis for this one.
I assume ISE 14.2, but it’s probably not very relevant.
Method #1: Ask a running kernel
The /proc filesystem has a full outline of the device tree the kernel uses. So after booting the board with Linux, go something like
zynq> mount /dev/mmcblk0p1 /mnt/
zynq> cd /proc/
zynq> tar -czf /mnt/devtree.tar.gz device-tree
zynq> poweroff
In this example, I’ve assumed that the system was booted from the SD card, and the data is stored to it.
After the board has powered off, attach the SD card to your computer, and copy the devtree.tar.gz to some Linux kernel source’s root directory. From there, go:
$ tar -xzf devtree.tar.gz
$ scripts/dtc/dtc -I fs -O dts -o reverse.dts device-tree/
And the reverse-engineered device tree is now given as reverse.dts. It’s recommended to remove all these files from the Linux source, just to avoid future confusion.
The truth is, that the DTS can be disassembled from the DTB with the same utility with something like
$ scripts/dtc/dtc -I dtb -O dts -o fromdtb.dts boot_with_this.dtb
But I prefer getting it from the running kernel for one simple reason: There’s often a chance for confusion regarding exactly which DTB file is loaded at bootup, with all those contradicting parameters fed into the boot loaders. The kernel just tells us what it got.
Method #2: Using Xilinx’ tools
For the sake of those who skipped the introduction:
The DTS file generated by the procedure described below is not good for direct use. See remarks above.
In fact, peripherals in the PL (that is, implemented in logic fabric) don’t appear in the DTS. I suppose that’s why the Zynq-Linux wiki currenly says that there’s no support for automatic device tree generation.
But the actual configuration parameters appear to be consistent. So if not for direct use, the generated DTS files can at least help with verifying the used DTS file is consistent.
Anyhow, I’m pretty confident that this method will be OK some day, if not already, when the device-tree package gets up-to-date enough.
Preparations
First create a special directory, and make it the working directory of your shell.
The device tree file is generated automatically with the libgen utility with the help of a Tcl script. As of ISE 14.2, this script needs to be loaded separately with git:
bash> git clone git://git.xilinx.com/device-tree.git
This downloads the entire Git repository, and creates a single directory, ‘bsp’. Change the name of the directory inside it from ‘device-tree_v0_00_x’ to ‘device-tree’.
Another web page explains how to make SDK recognize the script, but I prefer command line for things like this.
Obtaining XML and MSS files
From the XPS, pick Project > Export Hardware Design to SDK. This may launch a full implementation process, but this can be avoided by unchecking “Include bitstream and BMM file” in the dialog box that appears on this request. Once the SDK is open (and just any workspace directory chosen), go File > New > Xilinx Board Support package, and accept the defaults offered in the dialog boxes. That will, among others, produce an MSS file under e.g. standalone_bsp_0/ in the workspace directory. Copy that file (typically system.mss) so it’s alongside with ‘bsp’.
Then copy the XML file (typically system.xml) from the SDK\SDK_Export\hw directory, also alongside with ‘bsp’
Edit the copy you made of system.mss, so that the BEGIN OS to END part reads
BEGIN OS
PARAMETER OS_NAME = device-tree
PARAMETER PROC_INSTANCE = ps7_cortexa9_0
END
and not “standalone” for OS.
Creating the DTS file
Open a DOS Window or Linux prompt terminal with libgen in its PATH. The easiest way is to launch a “Xilinx shell” from the EDK’s project menu, Xilinx Tools > Launch Shell.
Navigate to the working directory, where the ‘bsp’ directory is. Just to avoid confusions, this is what a plain ‘dir’ command should say (more or less):
C:\experiments>dir
Volume in drive C has no label.
Volume Serial Number is 83E2-6332
Directory of C:\experiments
07/31/2012 05:04 PM <DIR> .
07/31/2012 05:04 PM <DIR> ..
07/31/2012 04:52 PM <DIR> bsp
07/31/2012 03:55 PM 3,360 system.mss
07/31/2012 12:15 PM 639,484 system.xml
2 File(s) 642,844 bytes
3 Dir(s) 3,239,301,120 bytes free
And then run libgen as follows:
libgen -hw system.xml -lp device-tree -pe ps7_cortexa9_0 -log libgen.log system.mss
Which generates a xilinx.dts in ps7_cortexa9_0\libsrc\device-tree. Copy this file to arch/microblaze/boot/dts/ in the to-be compiled kernel source tree. If you can’t find the file there, and libgen didn’t complain about some error, you may have forgotten to edit system.mss as mentioned just above.
Introduction
In the past, a LiveDVD was offered along with the evaluation kit for Xillybus, to make the setup quicker. As it turned out, there was no demand for this prepackaged kit, so it’s no longer available. But the steps for creating the image are documented here anyhow.
This procedure was made on Fedora 14, it should work on other (Red Hat based) distros as well.
Creating the ISO image
This page shows the specifics of creating the Xillybus LiveDVD image. It’s based upon a more general guide on the same subject, which is better read first.
As a matter of precaution, the ISO image is generated under the same distribution for which the it’s made. This may not be necessary, but helps working under the install directory as chroot. I suppose working under the same processor arch should be good enough (and even that isn’t really necessary).
The ISO image generated from scratch, since something got stuck when trying to make a based-upon image with
# livecd-creator --config=fedora-livecd-desktop.ks --fslabel=cleancd --cache=/var/cache/live
# livecd-creator -f xillydvd -c fedora-livecd-desktop-xillybus.ks -b cleancd.iso
So instead, I did the whole thing on one go:
# livecd-creator --config=fedora-livecd-desktop-xillybus.ks --fslabel=xillydvd-1.1 --cache=/var/cache/live
Note: Do not label the ISO “xillybus”. This will create false entries in the diagnostic tool (since it looks for the string “xillybus”)
After all packages were installed, I got the waited-for shell prompt for some final hacks. Procedure goes:
In commands, carried out from a non-chroot shell (but as root):
# cd /var/tmp/imgcreate-vrhjSz/iso-h1Amel
# vi isolinux/isolinux.cfg # Remove all "quiet" and "rhgb"
# cd /var/tmp/imgcreate-vrhjSz/install_root/
# tar --preserve-permissions -xvzf /path/to/xillypack.tar.gz
# mkdir usr/share/xillybus/misc/kickstart
# cp /path/to/livecd/*.ks usr/share/xillybus/misc/kickstart
# cp /path/to/xillypack.tar.gz usr/share/xillybus/misc/
# vi usr/share/hwdata/pci.ids # Add an entry
# chroot .
# cd /usr/share/xillybus/module/
# make install TARGET=`ls /lib/modules`
# make clean
# exit
# cd
The last exit quits the chroot shell, and it’s important to leave the directory or the installation will fail to unmount. Then I went to the orignal shell prompt and quitted it as well, so that the installation finished.
Note that there is no leading slash in the destination paths before the chroot, or the files fall outside the install root!
The shell received by the installation itself isn’t used, because of the possibility of exiting it accidentally.
Notes:
The xilly-diagnostic executable solves a setuid issue. It must be recompiled when moving architectures (32/64 bit in particular). The source can be found in /usr/share/xillybus/misc/. The binary is at /usr/local/bin/
gcc -O3 -Wall -o xilly-diagnostic xilly-diagnostic.c
Git has this thing about trailing white spaces in source files, for good reasons. Somehow it looks like there isn’t a widely spread utility for cleaning up a lot of files in one go. On the other hand, there are plenty of them out there, but none met my needs. So I wrote yet another one. Here it is.
#!/bin/bash
numargs=$#
for ((i=0; i<numargs; i=i+1)) ; do
if [ -e "$1" ] ; then
/usr/bin/perl -p0777e 'exit ((/[ \t]+$/m) ? 1 : 0)' "$1" || echo Trimmed \"$1\"
/usr/bin/perl -pi.orig-$$ -e 's/[ \t]+$//' "$1" && rm -f "$1.orig-$$"
else
echo "***" No such file \"$1\" "***"
fi
shift;
done
Among the things it does good, is that it accepts the files to trim as arguments, so it’s comfy to use from command line. Another thing is that it tells you which files it trimmed, and which ones it didn’t find. And what it also does, is to create a backup file (by adding a .orig+process number prefix) which is deleted immediately after a successful trimming. Just in case the system crashes right in the middle of trimming a file.
There is a slight problem with the “Trimmed” message appearing before actually trimming each file. This can be somewhat confusing if the script is interrupted in the middle of action.
Neither am I so happy with having two (slightly) different regular expressions for producing the message and doing the work. Maybe there’s some corner case I wasn’t aware of, which can produce false reporting.
In retrospective, I should have done this as a Perl script, and not as a bash script doing two one-liners. But I don’t have any motivation to fix this. If it ain’t broke… (yet?)
Intro
This is a general description of how to create a custom LiveCD/LiveDVD. It should have been simple: Take an existing LiveCD, make some slight modifications, and then create a new LiveCD with these modifications built in. A specific case is detailed here.
As it turns out, this is all but simple. The automatic tools for creating a LiveCD image are extremely difficult to work with manually, and they are based upon Kickstart. As a result, the natural level of customization is choosing which packages are in and which are out. There is no room for small personal hacks.
Fedora’s (that is, Red Hat’s) suggestion of how to create LiveCDs is explained in their page about the subject. The flow is basically to grab one of the suggested Kickstart configuration files for LiveCDs, possibly add or remove some packages, and then run livecd-creator (which is an extremely complicated Python script) on that Kickstart file. Livecd-creator fetches the packages from some repository (that is, all packages needed for setting up the system), and installs the new Linux system on a clean ext3 filesystem, which is mounted on a loop device. Then the loop device’s image file is put in a squashfs filesystem, so it takes much less disk space. That squashfs image is then put into the LiveCD’s ISO image and then a lot of other things happen, which I didn’t bother to reverse engineer: At that point I realized I should be looking for another solution.
Bottom line: It’s too complicated to unpack, change and repack the ISO image.
The not-so-attractive solution
The straightforward thing to do, is to pack the modification we want to do in an RPM package, put it in a local repository and add both the package and the repository to the Kickstart configuration file we’re using. That requires the knowledge of RPM packing, and besides, each test cycle would involve creating a new LiveCD image from scratch. If one has a local repository for all packages needed, it may be reasonable, but if they are downloaded from a remove server, this is a recipe for losing one’s sanity.
The preferred solution
Well, the trick based upon two small cracks in the machinery:
- livecd-creator allows making a LiveCD based upon an existing image. In that mode, livecd-creator opens the existing filesystem image, reads the RPM database for the already installed packages, and compares with the Kickstart file given. It then installs and/or removes packages as necessary, and packs the result into a new ISO image.
- Kickstart configuration files have a %post clause, where any script can be inserted for execution after packages have been added or removed.
Note that if the Kickstart file’s package list is identical to what is already installed, the script in the %post clause is not executed. So before breaking this down to shell commands, here is the outline of the procedure:
- Create a LiveCD with the automatic tools as originally intended, with one of those pre-made Kickstart files. This will take quite some time, but it’s done once. This is the basis on which we can hack many times.
- Modify the Kickstart file, so there is at least one change in the packages.
- Add a %post clause, so that we have our custom script executed from within the LiveCD’s root filesystem. Or even better, just run bash and get a shell prompt.
- Run livecd-creator based upon the existing ISO image with our modified Kickstart file. After a small change in packages, our script will run. Or we get a shell prompt to do some manual hacking.
Step by step
First we generate a by-the-book LiveCD image. Following Fedora’s document on the subject, first install the tools:
# yum install livecd-tools spin-kickstarts
The latter is merely a collection of configurations for Kickstart
And then copy a cute image:
# cp /usr/share/spin-kickstarts/fedora-livecd-design-suite.ks .
# cp /usr/share/spin-kickstarts/fedora-live-mini.ks .
(the latter is included in the former)
Trash Selinux (if necessary):
# setenforce 0
And, well, kick off (as root, since loop devices and mounts are part of the action):
# livecd-creator --config=fedora-livecd-desktop.ks --fslabel=mycd --cache=/var/cache/live
This will take some time, depending on the connection quality between you and the RPM repositories. Eventually, assuming you had the patience and disk space (> 5 GB?) you’ll find an mycd.iso file in the running directory.
Now let’s make a copy of the Kickstart file and hack it slightly:
$ cp fedora-livecd-desktop.ks fedora-livecd-desktop-modified.ks
As described in Fedoras page about Kickstart files, there are several sections there. One section starts with %packages and ends with %end. This sections contains packages to be installed. Edit our Kickstart copy and make a change in its package list. I added gcc and kernel-devel (each on in a line of its own).
And then, at the end of the Kickstart file, add:
%post
echo You are now in the chroot filesystem
/bin/bash
%end
Now go:
# livecd-creator -f modified -c fedora-livecd-desktop-modified.ks -b mycd.iso
This takes a few minutes. livecd-creator will go to the repositories and see that all packages are updated, so it will only install or remove the packages we edited the Kickstart file for.
And then we will get a shell prompt. I’ve added the echo command to remind ourselves that this shell prompt doesn’t indicate that the operation was finished. On the contrary, we get the shell prompt when the guts are out in the open.
The bash shell will execute from within the liveCD’s chroot, so commands such as “make install” and “/sbin/depmod -a” are expected to run cleanly. On the other hand, the filesystem is mounted and visible to our computer, so it’s easy to copy files into the chroot filesystem.
The real importance of this shell prompt is that it halts the installation, and gives us time to modify the to-be installed root filesystem. If we want to copy files into that filesystem, it’s easily done from any other root shell. If we want another chroot shell, well, use chroot.
The liveCD’s root is visible to the “outside world” at something like /var/tmp/imgcreate-q2Hvwg/install_root. Use mount or df from any shell except our special chroot shell to find out where it is.
Exit the shell when finished to making changes: Type “exit” or CTRL-D. livecd-creator then packs our modified filesystem into an neat ISO image, in this case modified.iso. If further hacks are needed, use this new ISO image as the basis (instead of mycd.iso above).
Quirks
When working on the modifications, it’s worth to note that it doesn’t reflect the actual situation when the liveCD is booted from. For example, /etc/passwd may not contain any meaningful user (even not root) and the /home directory may be completely empty. I haven’t bothered to work out how this is settled when the system boots up for real, since I didn’t need this information.
Another thing is that if the packages have been updated on the repository, the based-upon-ISO process may take time, because several packages are updated. This can also pollute the ext3 image to grow larger than necessary when squashed. Unused data regions are still compressed into the image. Working on a phased-out distribution can be advantageous. Or make a local repository which isn’t updated.
Yet another thing that should have been so simple, but required hacking. Using (Beta) Xemacs 21.5.29, it didn’t have a menu item for pretty printing. Nor was there a clear way to connect with CUPS.
First thing first, make sure to have a nice popup for printing. If not for any other reason, it gives me a chance to abort printing resulting from accidentally pressing the “Print” toolbar button.
# yum install gtklp
Then type “gtklp” at command prompt to set up things. In particular, go to Output > Sheet Usage and change “Sheets per page” to 1 if it happened to be 9 (making very tiny printouts). After making sure gtklp remembers that setting, uncheck GtkLP > Save all preferences on exit (it’s a bad thing, I think).
For the record, gtklp expects postscript in its standard input, so it’s perfect for working with XEmacs.
In XEmacs, choose Options > Edit init file, and add the following (in the end of the file, I guess)
(custom-set-variables
'(ps-paper-type (quote a4))
'(lpr-command "gtklp"))
(easy-menu-add-item nil '("file") ["Pretty-print this buffer" ps-print-buffer-with-faces ] "Page Setup...")
(setq-default toolbar-print-function 'ps-print-buffer-with-faces)
This adds a not-so-elegant (but working) pretty-print menu item in the file menu. But the last command does something much better: It turns the “print” icon into pretty-print.
Short summary
Kernel 2.6.35.4 kernel on x86_64 doesn’t seem to handle large memory allocations well. In particular,
- Running malloc() with Gigabyte chunks can cause a kernel oops
- Quickly allocating all memory will make the system hang (but not oops)
If anyone has an idea why this is, some helpful clues or whatever, please comment below.
I should also mention that I applied the patch, which fixes the general system freeze on rapid disk I/O, mentioned in another post of mine. I didn’t feel like going on crashing my system over and over again, so I skipped the test without this patch.
Allocating a huge chunk
Running a vanilla 2.6.35.4 kernel on a x86_64 machine (as 64-bit Linux), I wanted to see how well my 16 GB of RAM worked. So I decided to allocate a lot of memory and see what happens. More precisely, I wrote the following somewhat dirty program, and ran it (calling it memeater):
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int main() {
long int size = 1024*1024*1024;
long int i;
size *= 4;
char *p = malloc(size);
printf("Size is %ld, Pointer is %08lx\n", size, (unsigned long int) p);
if (p)
for (i=0; i<size/1024; i++) {
*p = 0;
p += 1024;
}
getc(stdin);
return 0;
}
A short explanation: This program merely requires 4 Gigabyte of memory in a single malloc(). The loop writes something on each memory page (a 4096 jump rather that 1024 would be OK as well, I believe). This is necessary, since memory allocation doesn’t really consume memory until used.
It then expects the user to press RETURN on console, so that the memory is held until deliberately released.
In theory, this shouldn’t be a problem. Allocating 4 Gigs of memory should either return a pointer or a NULL. Definitely not oops as follows:
May 17 18:11:14 kernel: general protection fault: 0000 [#3] SMP
May 17 18:11:14 kernel: last sysfs file: /sys/devices/virtual/sound/timer/uevent
May 17 18:11:14 kernel: CPU 4
May 17 18:11:14 kernel: Modules linked in: nfsd exportfs it87 hwmon_vid vmnet vmblock vmci vmmon cpufreq_ondemand
acpi_cpufreq freq_table mperf ipv6 dm_multipath kvm_intel kvm uinput snd_hda_codec_hdmi snd_hda_codec_realtek snd_hda_
intel snd_hda_codec snd_hwdep snd_seq snd_seq_device snd_pcm snd_timer snd iTCO_wdt ppdev 8139too soundcore
8139cp tulip parport_pc r8169 iTCO_vendor_support pcspkr snd_page_alloc parport i2c_i801 mii sha256_generic
cryptd aes_x86_64 aes
_generic dm_crypt raid456 async_raid6_recov async_pq raid6_pq async_xor xor async_memcpy async_tx ata_generic
pata_acpi pata_jmicron radeon ttm drm_kms_helper drm i2c_algo_bit i2c_core [last unloaded: microcode]
May 17 18:11:14 kernel:
May 17 18:11:14 kernel: Pid: 3056, comm: memeater Tainted: G D 2.6.35.4-OCHO3 #1 P55-UD3R/P55-UD3R
May 17 18:11:14 kernel: RIP: 0010:[<ffffffff811024ae>] [<ffffffff811024ae>] mem_cgroup_charge_statistics+0x9/0x50
May 17 18:11:14 kernel: RSP: 0018:ffff88040a85fa48 EFLAGS: 00010246
May 17 18:11:14 kernel: RAX: 00000000ffffff01 RBX: ffffea000a918e00 RCX: 0000000000000060
May 17 18:11:14 kernel: RDX: 0000000000000000 RSI: ffff8804142c8a00 RDI: ffbfc90001817000
May 17 18:11:14 kernel: RBP: ffff88040a85fa48 R08: ffff880409eba958 R09: 00000000ffffffc0
May 17 18:11:14 kernel: R10: 0000000000400000 R11: ffffea000a9d0df0 R12: 0000000000000001
May 17 18:11:14 kernel: R13: ffff8804142c8a00 R14: ffbfc90001817000 R15: ffff880409fadcc0
May 17 18:11:14 kernel: FS: 00007f36017db700(0000) GS:ffff880002100000(0000) knlGS:0000000000000000
May 17 18:11:14 kernel: CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
May 17 18:11:14 kernel: CR2: 0000000001861000 CR3: 0000000001a42000 CR4: 00000000000006e0
May 17 18:11:14 kernel: DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
May 17 18:11:14 kernel: DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
May 17 18:11:14 kernel: Process memeater (pid: 3056, threadinfo ffff88040a85e000, task ffff880409fadcc0)
May 17 18:11:14 kernel: Stack:
May 17 18:11:14 kernel: ffff88040a85fa98 ffffffff8110579c ffff88040a85faa8 ffffffff810ec2d1
May 17 18:11:14 kernel: <0> ffff88040a85fa88 ffffea000a918e00 00007f35e72e1000 8000000305040067
May 17 18:11:14 kernel: <0> 0000000000099000 ffff880409eba958 ffff88040a85faa8 ffffffff81105826
May 17 18:11:14 kernel: Call Trace:
May 17 18:11:14 kernel: [<ffffffff8110579c>] __mem_cgroup_uncharge_common+0x194/0x1e5
May 17 18:11:14 kernel: [<ffffffff810ec2d1>] ? free_pages_and_swap_cache+0x63/0x80
May 17 18:11:14 kernel: [<ffffffff81105826>] mem_cgroup_uncharge_page+0x27/0x29
May 17 18:11:14 kernel: [<ffffffff810e7267>] page_remove_rmap+0x28/0x50
May 17 18:11:14 kernel: [<ffffffff810dd7b3>] unmap_vmas+0x5c5/0x928
May 17 18:11:14 kernel: [<ffffffff810e2ec1>] exit_mmap+0xce/0x132
May 17 18:11:14 kernel: [<ffffffff8104ad9b>] mmput+0x5e/0xca
May 17 18:11:14 kernel: [<ffffffff8104f1cf>] exit_mm+0x114/0x121
May 17 18:11:14 kernel: [<ffffffff81050b7b>] do_exit+0x226/0x726
May 17 18:11:14 kernel: [<ffffffff8105a08e>] ? try_to_del_timer_sync+0x7b/0x89
May 17 18:11:14 kernel: [<ffffffff810510f8>] do_group_exit+0x7d/0xa5
May 17 18:11:14 kernel: [<ffffffff8105ee27>] get_signal_to_deliver+0x373/0x395
May 17 18:11:14 kernel: [<ffffffff812c4dce>] ? n_tty_read+0x6b3/0x786
May 17 18:11:14 kernel: [<ffffffff81009010>] do_signal+0x72/0x68d
May 17 18:11:14 kernel: [<ffffffff812c758d>] ? tty_ldisc_deref+0xe/0x10
May 17 18:11:14 kernel: [<ffffffff812c025f>] ? tty_read+0x8c/0xc5
May 17 18:11:14 kernel: [<ffffffff81009657>] do_notify_resume+0x2c/0x6e
May 17 18:11:14 kernel: [<ffffffff81009f00>] int_signal+0x12/0x17
May 17 18:11:14 kernel: Code: ff 4c 89 e3 4d 8b 24 24 4c 39 eb 75 de 48 c7 c7 60 29 a6 81 e8 b5 eb 39 00 5b 41 5c 41 5d 41 5e c9
c3 55 48 89 e5 0f 1f 44 00 00 <48> 8b 87 10 11 00 00 80 fa 01 19 c9 83 c9 01 f6 06 02 48 63 c9
May 17 18:11:14 kernel: RIP [<ffffffff811024ae>] mem_cgroup_charge_statistics+0x9/0x50
May 17 18:11:14 kernel: RSP <ffff88040a85fa48>
May 17 18:11:14 kernel: ---[ end trace 4d26f08f6051ed51 ]---
May 17 18:11:14 kernel: Fixing recursive fault but reboot is needed
And I should mention that when I tried this for 16 GB, the system just hung. But that’s explained next.
Allocating all RAM
So I said, OK, that must be because nobody is really expected to allocate those huge chunks in one go. So what happens when the memory just ends? I have some swap space, so this should work…
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int main() {
long int size = 1024*1024;
long int i,k;
size *= 16;
for (k=0; k<1024; k++) {
char *p = malloc(size);
printf("Size is %ld, Pointer is %08lx\n", size, (unsigned long int) p);
if (p)
for (i=0; i<size/1024; i++) {
*p = 0;
p += 1024;
}
}
getc(stdin);
return 0;
}
The idea here is simple: Loop 1024 times, allocating 16MB at a time. This is sane and eventually takes 16 GB.
But no, the system just hung. No oops, no drama. Just nothing happened. Processes were stalled, typing and switching consoles with Shift-Alt-Fx worked. Ctrl-Alt-Delete is ignored. No reboot. Only a reset got me out of this.
For the record, running the program with chunks of 14 MB each, so almost all memory was allocated (14 GB out of 16 GB), worked cleanly, and the system remained stable.
Of course I have swap
And this is the proof: This is my /proc/meminfo with a system barely doing anything:
MemTotal: 16463436 kB
MemFree: 14909616 kB
Buffers: 75428 kB
Cached: 664284 kB
SwapCached: 0 kB
Active: 459044 kB
Inactive: 604272 kB
Active(anon): 324088 kB
Inactive(anon): 115208 kB
Active(file): 134956 kB
Inactive(file): 489064 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 4194300 kB
SwapFree: 4194300 kB
Dirty: 1348 kB
Writeback: 0 kB
AnonPages: 323592 kB
Mapped: 116232 kB
Shmem: 115704 kB
Slab: 95920 kB
SReclaimable: 46340 kB
SUnreclaim: 49580 kB
KernelStack: 4008 kB
PageTables: 36940 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 12426016 kB
Committed_AS: 1576024 kB
VmallocTotal: 34359738367 kB
VmallocUsed: 123416 kB
VmallocChunk: 34359587772 kB
HardwareCorrupted: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
DirectMap4k: 8064 kB
DirectMap2M: 16764928 kB
Sometimes I’ve sees some of the swap actually used. It’s not like it doesn’t work.
On Thunderbird 3.0.7, this little extra file turned the folder names with new mail red and bold:
(the “chrome” directory needs to be created)
$ cat ~/.thunderbird/sdf2k45i.default/chrome/userChrome.css
@namespace
url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); /* set default namespace to XUL */
/* Setting the color of folders containing new messages to red */
treechildren::-moz-tree-cell-text(folderNameCol, newMessages-true) {
font-weight: bold;
color: red !important;
}
This should have been obvious: Have a “new mail” icon in the system tray when new mail is fetched by Thunderbird on a FC12 Linux machine. I ended up writing my own script.
My starting point was the “Gnome Integration” add-on. Not that I liked that it forced me to have another notification popup on new mails (aside from Thunderbird’s native one) if I wanted the icon. But when an icon was added to the system tray for each new mail arriving (that is, a lot of icons in the tray), I knew I had to do a thing of my own.
So I wrote a small, and not so sophisticated script, which checks if an icon is there (more precisely: If a process owning the icon is running) and gives up if it already exists.
The lucky things about the “Gnome Integration” add-on is that it allows choosing the command for the mail notification. So instead of running whatever puts that unnecessary popup, it runs my script, which puts the icon in place if necessary. Popup away, single icon instead. Could I ask for more?
Here’s the script. I saved it as /usr/local/bin/new-mail-icon (you can put it anywhere you want, but make sure the executable has the same name):
#!/bin/bash
THEDIR=$HOME/.thunderbird
ICON=$THEDIR/green-mail-unread.png
LOCKFILE=$THEDIR/new-mail-icon-process
NOW=`date "+%F %T"`
if [ -e $LOCKFILE ] && grep new-mail-icon /proc/`cat $LOCKFILE`/cmdline > /dev/null 2>/dev/null ;
then exit 0;
else
( echo $BASHPID > $LOCKFILE
zenity --notification --window-icon=$ICON --text="New mail on $NOW"
rm -f $LOCKFILE
) &
fi
Important notes about the script:
- It relies on that the script’s name is “new-mail-icon”. This is how it detects another icon exists. If the script has another name, several icons will appear. Or change the argument to the grep command.
- There is a slight race condition if two of these scripts are run in parallel (which is an unlikely situation, and still). It’s possible that more than one icon will appear, if two (or more) scripts race on the little time gap between checking for the locking file and writing to it.
The script above doesn’t just check if the lockfile exists, but also verifies that the process holding it exists and has the correct command line. This makes it behave correctly if the system shuts down or crashes, leaving the lock file in place.
Then set the Gnome Integration add-on preferences as follows. Note that the “Show icon” is not checked. The icon is created by running my script instead of the notification application. It’s a hack indeed.
Using Fedora Core 12, I wanted some control over my wobbling windows, and in particular which corner is the hot spot for displaying all open windows.
The first thing I needed to find out, is the name of the toolkit doing this: So it’s Compiz.
First, install the Compiz Configuration Setting Manager
# yum install ccsm
It now appears in System > Preferences (as Compiz Configuration Setting Manager).
The next issue is that the settings are ignored. This is because compiz is executed with the gconf plugin by /usr/bin/compiz-gtk, which is what the Gnome environment runs.
So following one of the comments in this bug report, edit /usr/bin/compiz-gtk so that the runCompiz function in the file’s beginning says:
exec compiz --ignore-desktop-hints glib ccp $@
And to get this launched, go to System > Preferences > Desktop effects, turn off the effects and turn them on again (choose “standard” and then “compiz” again). Note that the preferences in the Desktop effect are now ignored, and the ones chosen in Compiz Configuration Setting Manager are used instead. But hey, this is what I wanted in the first place.
In particular, I moved the “hot corner” to the bottom left, which I hit by accident much less. This is done in Compiz Configuration Setting Manager > Window Management > Application Switcher > Scale > Initiate Window Picker. Maybe I should exchange this with a keystroke instead.
When compiz crashes
That’s an ugly one. The windows lose their window manager frames, so they can’t be moved. Navigating between windows is impossible or difficult. The trick is to get compiz up and running without messing things up too much.
Quick solution. Use CTRL-ALT-F3 to get a plain textual console, log in, and type:
$ compiz --display :0 --ignore-desktop-hints glib ccp --replace &
Note that ampersand at the end. It’s a bad idea to have compiz running in the foreground (even worse to stop it).
This should be an alias, as a matter of fact. The –display flag is redundant if the command is issued from a shell window (as opposed to the text console).
The –replace flag is most likely not necessary (since compiz has crashed anyhow), but it doesn’t hurt.
Looking at my system log (kernel 2.6.35.4), this is a common thing:
Apr 24 12:04:49 kernel: radeon 0000:01:00.0: ffff8802d0aa1a00 reserve failed for wait
Apr 24 12:04:49 kernel: radeon 0000:01:00.0: ffff8802d0aa1a00 reserve failed for wait
Apr 24 12:04:51 kernel: radeon 0000:01:00.0: ffff8802d0aa1a00 reserve failed for wait
Apr 24 12:04:51 kernel: radeon 0000:01:00.0: ffff8802d0aa1a00 reserve failed for wait
Apr 24 12:04:57 kernel: radeon 0000:01:00.0: ffff8802d0aa1a00 reserve failed for wait
Apr 24 12:05:08 kernel: radeon 0000:01:00.0: ffff8802d0aa1a00 reserve failed for wait
Apr 24 12:05:14 kernel: radeon 0000:01:00.0: ffff8802d0aa1a00 reserve failed for wait
This doesn’t sound too good, but it looks like it’s harmless, according to this and this. It also looks like the decision was to remove the error message, rather than to fix something else. I suppose this issue is old news pretty soon.
It has been suggested that this error message appears only when compiz (that cool OpenGL toy making all kinds of effects on the desktop).
So just let it be.