From: Martin Wilck <Martin.Wilck@fujitsu-siemens.com>
To: linux-ia64@vger.kernel.org
Subject: [Linux-ia64] IO-TLB: findings and debugging patch & tool
Date: Wed, 13 Jun 2001 20:40:19 +0000 [thread overview]
Message-ID: <marc-linux-ia64-105590693005728@msgid-missing> (raw)
Hi,
Below please find a shell archive that contains a kernel patch
& user space tool that have helped me clarify some of the IO-TLB issues.
According to my current results (obtained with a single controller),
about 900 buffers obtaining ~3500 slots are needed for each disk on
the 29160 with the aic7xxx driver. On my system with 4 disks, the system
stays stable with 4096 8kB-pages of swiotlb space (that is, 16 times more
than the default), the peak usage being 3621 buffers and 14294 2kB-slots.
This peak usage was obtained with 4 separate tar jobs each writing to a
different disk on the 29160. The aic7xxx driver accounts for all but 64
buffers occupying 64 slots.
The driver uses a lot more buffers than the 253 suggested by the max
number of SCBs because of fragmentation of the SCSI buffers (scatter lists).
Actually, the driver uses a maximum SCB count of 64 for all disks in my
system. Thus, with different disks, the buffer usage could be almost 4
times higher, and limiting the max number of buffers will not solve
the problem, espcecially in multiple-controller scenarios.
I would be grateful if someone could read the patch, espcecially the
proc reading routine that uses several pages, since I never wrote
something like that before, and i have the feeling it doesn't work 100%
correctly.
I will be _very_ grateful for any bug reports and comments.
The patch is against 2.4.4/IA64 (sorry, I had no time to upgrade to
2.4.5 yet).
I put the patch and tool source together a bit in a hurry, but I have run
it successfully and it has helped me quite a bit, and I will be out of
office until June 25, therefore I think I should submit it today.
Regards,
Martin
--
Martin Wilck <Martin.Wilck@fujitsu-siemens.com>
FSC EP PS DS1, Paderborn Tel. +49 5251 8 15113
#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.2.1).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
# Made on 2001-06-13 23:39 CEST by <martin@tl02.pdb.fsc.net>.
# Source directory was `/home/martin'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 14136 -rw-rw-r-- iotlb-mon-0.1/swiotlb.patch
# 358 -rw-rw-r-- iotlb-mon-0.1/Makefile
# 10494 -rw-rw-r-- iotlb-mon-0.1/iotlb-mon.c
#
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dirúILED
locale_dirúILED
first_param="$1"
for dir in $PATH
do
if test "$gettext_dir" = FAILED && test -f $dir/gettext \
&& ($dir/gettext --version >/dev/null 2>&1)
then
set `$dir/gettext --version 2>&1`
if test "$3" = GNU
then
gettext_dir=$dir
fi
fi
if test "$locale_dir" = FAILED && test -f $dir/shar \
&& ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
then
locale_dir=`$dir/shar --print-text-domain-dir`
fi
done
IFS="$save_IFS"
if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
then
echoìho
else
TEXTDOMAINDIR=$locale_dir
export TEXTDOMAINDIR
TEXTDOMAIN=sharutils
export TEXTDOMAIN
echo="$gettext_dir/gettext -s"
fi
if touch -am -t 200112312359.59 $$.touch >/dev/null 2>&1 && test ! -f 200112312359.59 -a -f $$.touch; then
shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"'
elif touch -am 123123592001.59 $$.touch >/dev/null 2>&1 && test ! -f 123123592001.59 -a ! -f 123123592001.5 -a -f $$.touch; then
shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"'
elif touch -am 1231235901 $$.touch >/dev/null 2>&1 && test ! -f 1231235901 -a -f $$.touch; then
shar_touch='touch -am $3$4$5$6$2 "$8"'
else
shar_touch=:
echo
$echo 'WARNING: not restoring timestamps. Consider getting and'
$echo "installing GNU \`touch', distributed in GNU File Utilities..."
echo
fi
rm -f 200112312359.59 123123592001.59 123123592001.5 1231235901 $$.touch
#
if mkdir _sh05939; then
$echo 'x -' 'creating lock directory'
else
$echo 'failed to create lock directory'
exit 1
fi
# ======= iotlb-mon-0.1/swiotlb.patch =======
if test ! -d 'iotlb-mon-0.1'; then
$echo 'x -' 'creating directory' 'iotlb-mon-0.1'
mkdir 'iotlb-mon-0.1'
fi
if test -f 'iotlb-mon-0.1/swiotlb.patch' && test "$first_param" != -c; then
$echo 'x -' SKIPPING 'iotlb-mon-0.1/swiotlb.patch' '(file already exists)'
else
$echo 'x -' extracting 'iotlb-mon-0.1/swiotlb.patch' '(text)'
sed 's/^X//' << 'SHAR_EOF' > 'iotlb-mon-0.1/swiotlb.patch' &&
--- linux-2.4.4-orig/Documentation/Configure.help Wed May 30 20:31:31 2001
+++ linux-2.4.4mw/Documentation/Configure.help Wed Jun 13 23:23:53 2001
@@ -17670,6 +17670,21 @@
X To use this option, you have to check that the "/proc file system
X support" (CONFIG_PROC_FS) is enabled, too.
X
+/proc/swiotlb support
+CONFIG_PROCFS_SWIOTLB
+ If you say Y here, you will find information on the software
+ IO-TLB usage in your machine in /proc/swiotlb.
+
+ IO-TLBs (Translation Lookaside Buffers) are needed if PCI devices
+ unable to do 64-bit addressing are used in machines with large RAM.
+ This is mainly useful for debugging purposes on machines with
+ >= 4GB RAM.
+
+ To use this option, you have to check that the "/proc file system
+ support" (CONFIG_PROC_FS) is enabled, too.
+
+ If unsure, say N.
+
X #
X # A couple of things I keep forgetting:
X # capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet,
--- linux-2.4.4-orig/arch/ia64/config.in Wed May 30 17:37:23 2001
+++ linux-2.4.4mw/arch/ia64/config.in Tue Jun 12 19:41:51 2001
@@ -111,6 +111,7 @@
X bool 'Performance monitor support' CONFIG_PERFMON
X tristate '/proc/pal support' CONFIG_IA64_PALINFO
X tristate '/proc/efi/vars support' CONFIG_EFI_VARS
+tristate '/proc/swiotlb support' CONFIG_PROCFS_SWIOTLB
X
X bool 'Networking support' CONFIG_NET
X bool 'System V IPC' CONFIG_SYSVIPC
--- linux-2.4.4-orig/arch/ia64/lib/swiotlb.c Wed May 30 17:36:58 2001
+++ linux-2.4.4mw/arch/ia64/lib/swiotlb.c Wed Jun 13 10:48:23 2001
@@ -24,6 +24,13 @@
X #include <linux/init.h>
X #include <linux/bootmem.h>
X
+#if defined CONFIG_PROCFS_SWIOTLB || defined CONFIG_PROCFS_SWIOTLB_MODULE
+# define EXPORT_IOTLB_SYMS 1
+# define IOTLB_STATIC
+#else
+# define IOTLB_STATIC static
+#endif
+
X #define ALIGN(val, align) ((unsigned long) \
X (((unsigned long) (val) + ((align) - 1)) & ~((align) - 1)))
X
@@ -36,19 +43,19 @@
X * Used to do a quick range check in swiotlb_unmap_single and swiotlb_sync_single, to see
X * if the memory was in fact allocated by this API.
X */
-static char *io_tlb_start, *io_tlb_end;
+IOTLB_STATIC char *io_tlb_start, *io_tlb_end;
X
X /*
X * The number of IO TLB blocks (in groups of 64) betweeen io_tlb_start and io_tlb_end.
X * This is command line adjustable via setup_io_tlb_npages.
X */
-static unsigned long io_tlb_nslabs = 1024;
+IOTLB_STATIC unsigned long io_tlb_nslabs = 1024;
X
X /*
X * This is a free list describing the number of free entries available from each index
X */
-static unsigned int *io_tlb_list;
-static unsigned int io_tlb_index;
+IOTLB_STATIC unsigned int *io_tlb_list;
+IOTLB_STATIC unsigned int io_tlb_index;
X
X /*
X * We need to save away the original address corresponding to a mapped entry for the sync
@@ -56,6 +63,16 @@
X */
X static unsigned char **io_tlb_orig_addr;
X
+#ifdef EXPORT_IOTLB_SYMS
+/*
+ * Usage data for /proc entries
+ */
+unsigned int io_tlb_used_buffers = 0;
+unsigned int io_tlb_used_slots = 0;
+unsigned int io_tlb_max_used_buffers = 0;
+unsigned int io_tlb_max_used_slots = 0;
+#endif
+
X /*
X * Protect the above data structures in the map and unmap calls
X */
@@ -173,6 +190,15 @@
X found:
X spin_unlock_irqrestore(&io_tlb_lock, flags);
X
+#ifdef EXPORT_IOTLB_SYMS
+ io_tlb_used_slots += nslots;
+ io_tlb_used_buffers++;
+ if (io_tlb_used_slots > io_tlb_max_used_slots)
+ io_tlb_max_used_slots = io_tlb_used_slots;
+ if (io_tlb_used_buffers > io_tlb_max_used_buffers)
+ io_tlb_max_used_buffers = io_tlb_used_buffers;
+#endif
+
X /*
X * Save away the mapping from the original address to the DMA address. This is
X * needed when we sync the memory. Then we sync the buffer if needed.
@@ -181,6 +207,7 @@
X if (direction = PCI_DMA_TODEVICE || direction = PCI_DMA_BIDIRECTIONAL)
X memcpy(dma_addr, buffer, size);
X
+ printk ("+%1d", nslots);
X return dma_addr;
X }
X
@@ -228,6 +255,11 @@
X io_tlb_list[i] = ++count;
X }
X spin_unlock_irqrestore(&io_tlb_lock, flags);
+#ifdef EXPORT_IOTLB_SYMS
+ io_tlb_used_buffers--;
+ io_tlb_used_slots -= nslots;
+#endif
+ printk ("-%1d", nslots);
X }
X
X static void
@@ -462,3 +494,15 @@
X EXPORT_SYMBOL(swiotlb_dma_address);
X EXPORT_SYMBOL(swiotlb_alloc_consistent);
X EXPORT_SYMBOL(swiotlb_free_consistent);
+
+#ifdef EXPORT_IOTLB_SYMS
+EXPORT_SYMBOL(io_tlb_start);
+EXPORT_SYMBOL(io_tlb_end);
+EXPORT_SYMBOL(io_tlb_nslabs);
+EXPORT_SYMBOL(io_tlb_index);
+EXPORT_SYMBOL(io_tlb_list);
+EXPORT_SYMBOL(io_tlb_used_buffers);
+EXPORT_SYMBOL(io_tlb_used_slots);
+EXPORT_SYMBOL(io_tlb_max_used_buffers);
+EXPORT_SYMBOL(io_tlb_max_used_slots);
+#endif /* EXPORT_IOTLB_SYMS */
a0 175
#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/malloc.h>
#include <linux/proc_fs.h>
X
MODULE_AUTHOR("Martin Wilck <Martin.Wilck@Fujitsu-Siemens.com>");
MODULE_DESCRIPTION("/proc interface for software IO/TLB status");
X
struct iotlb_info_struct {
X unsigned long n_slots;
X unsigned int index;
X unsigned int used_buffers;
X unsigned int used_slots;
X unsigned int max_used_buffers;
X unsigned int max_used_slots;
X void *start;
X void *end;
};
X
/* Variables exported from arch/ia64/lib/swiotlb.c */
extern char *io_tlb_start, *io_tlb_end;
extern unsigned long io_tlb_nslabs;
extern unsigned int *io_tlb_list;
extern unsigned int io_tlb_index;
extern unsigned int io_tlb_used_buffers;
extern unsigned int io_tlb_used_slots;
extern unsigned int io_tlb_max_used_buffers;
extern unsigned int io_tlb_max_used_slots;
X
static struct proc_dir_entry *swiotlb_proc_dir;
static struct proc_dir_entry *proc_iotlb_list;
static struct proc_dir_entry *proc_iotlb_params;
static struct proc_dir_entry *proc_iotlb_parameters;
X
static char *swiotlb_outbuf = NULL;
X
static int
read_iotlb_list(char *page, char **start, off_t offset, int count, int *eof, void *data)
{
X int nbytes = io_tlb_nslabs * sizeof (int);
X int kbytes = count + offset;
X char *buf;
X int cnt;
X
X MOD_INC_USE_COUNT;
X if (nbytes > PAGE_SIZE) {
X if (!swiotlb_outbuf) {
X swiotlb_outbuf = kmalloc (io_tlb_nslabs * sizeof (int), GFP_KERNEL);
X if (!swiotlb_outbuf) {
X cnt = -ENOMEM;
X goto exit;
X };
X };
X *start = buf = swiotlb_outbuf;
X } else {
X buf = page;
X };
X
X if (kbytes < nbytes)
X cnt = kbytes;
X else {
X cnt = nbytes;
X *eof = 1;
X };
X
X memcpy (buf, io_tlb_list, cnt);
X
X cnt -= offset;
X cnt = (cnt < 0 ? 0 : cnt);
X
X exit:
X MOD_DEC_USE_COUNT;
X return cnt;
X
}
X
static int
read_iotlb_params(char *page, char **start, off_t offset, int count, int *eof, void *data)
{
X struct iotlb_info_struct *iotlb_params X (struct iotlb_info_struct*) page;
X const int nbytes = sizeof (struct iotlb_info_struct);
X int res;
X
X MOD_INC_USE_COUNT;
X
X iotlb_params->n_slots = io_tlb_nslabs;
X iotlb_params->index = io_tlb_index;
X iotlb_params->used_buffers = io_tlb_used_buffers;
X iotlb_params->used_slots = io_tlb_used_slots;
X iotlb_params->max_used_buffers = io_tlb_max_used_buffers;
X iotlb_params->max_used_slots = io_tlb_max_used_slots;
X iotlb_params->start = io_tlb_start;
X iotlb_params->end = io_tlb_end;
X
X if (offset + count >= nbytes) {
X *eof = 1;
X res = (nbytes - offset < 0 ? 0 : nbytes - offset);
X } else {
X res = count;
X };
X
X MOD_DEC_USE_COUNT;
X return res;
}
X
static int
read_iotlb_parameters(char *page, char **start, off_t offset, int count, int *eof, void *data)
{
X int len, res;
X MOD_INC_USE_COUNT;
X len = sprintf (page,
X "Slots allocated : %8ld\n"
X "Current Index : %8d\n"
X "Buffers used : %8d\n"
X "Slots used : %8d\n"
X "Max Buffers used : %8d\n"
X "Max Slots used : %8d\n"
X "Start address : 0x%p\n"
X "End address : 0x%p\n",
X io_tlb_nslabs,
X io_tlb_index,
X io_tlb_used_buffers,
X io_tlb_used_slots,
X io_tlb_max_used_buffers,
X io_tlb_max_used_slots,
X (void*) io_tlb_start,
X (void*) io_tlb_end);
X if (offset + count >= len) {
X *eof = 1;
X len -= offset;
X res = (len < 0 ? 0 : len);
X } else
X res = count;
X MOD_DEC_USE_COUNT;
X return res;
}
X
static int __init
swiotlb_init_proc (void)
{
X printk (KERN_INFO "Loading /proc/swiotlb support\n");
X
X swiotlb_proc_dir = proc_mkdir ("swiotlb", NULL);
X proc_iotlb_list X create_proc_entry ("list", 0444, swiotlb_proc_dir);
X proc_iotlb_params X create_proc_entry ("params", 0444, swiotlb_proc_dir);
X proc_iotlb_parameters X create_proc_entry ("parameters", 0444, swiotlb_proc_dir);
X
X proc_iotlb_list->read_proc = read_iotlb_list;
X proc_iotlb_params->read_proc = read_iotlb_params;
X proc_iotlb_parameters->read_proc = read_iotlb_parameters;
X
X return 0;
}
X
X
static void __exit
swiotlb_exit_proc (void)
{
X printk (KERN_INFO "Unloading /proc/swiotlb support\n");
X if (swiotlb_outbuf)
X kfree (swiotlb_outbuf);
X remove_proc_entry ("list", swiotlb_proc_dir);
X remove_proc_entry ("params", swiotlb_proc_dir);
X remove_proc_entry ("parameters", swiotlb_proc_dir);
X remove_proc_entry ("swiotlb", 0);
}
X
module_init(swiotlb_init_proc);
module_exit(swiotlb_exit_proc);
--- linux-2.4.4-orig/arch/ia64/kernel/swiotlb_proc.c Wed Jun 13 23:28:08 2001
+++ linux-2.4.4mw/arch/ia64/kernel/swiotlb_proc.c Wed Jun 13 11:00:31 2001
@@ -0,0 +1,175 @@
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/proc_fs.h>
+
+MODULE_AUTHOR("Martin Wilck <Martin.Wilck@Fujitsu-Siemens.com>");
+MODULE_DESCRIPTION("/proc interface for software IO/TLB status");
+
+struct iotlb_info_struct {
+ unsigned long n_slots;
+ unsigned int index;
+ unsigned int used_buffers;
+ unsigned int used_slots;
+ unsigned int max_used_buffers;
+ unsigned int max_used_slots;
+ void *start;
+ void *end;
+};
+
+/* Variables exported from arch/ia64/lib/swiotlb.c */
+extern char *io_tlb_start, *io_tlb_end;
+extern unsigned long io_tlb_nslabs;
+extern unsigned int *io_tlb_list;
+extern unsigned int io_tlb_index;
+extern unsigned int io_tlb_used_buffers;
+extern unsigned int io_tlb_used_slots;
+extern unsigned int io_tlb_max_used_buffers;
+extern unsigned int io_tlb_max_used_slots;
+
+static struct proc_dir_entry *swiotlb_proc_dir;
+static struct proc_dir_entry *proc_iotlb_list;
+static struct proc_dir_entry *proc_iotlb_params;
+static struct proc_dir_entry *proc_iotlb_parameters;
+
+static char *swiotlb_outbuf = NULL;
+
+static int
+read_iotlb_list(char *page, char **start, off_t offset, int count, int *eof, void *data)
+{
+ int nbytes = io_tlb_nslabs * sizeof (int);
+ int kbytes = count + offset;
+ char *buf;
+ int cnt;
+
+ MOD_INC_USE_COUNT;
+ if (nbytes > PAGE_SIZE) {
+ if (!swiotlb_outbuf) {
+ swiotlb_outbuf = kmalloc (io_tlb_nslabs * sizeof (int), GFP_KERNEL);
+ if (!swiotlb_outbuf) {
+ cnt = -ENOMEM;
+ goto exit;
+ };
+ };
+ *start = buf = swiotlb_outbuf;
+ } else {
+ buf = page;
+ };
+
+ if (kbytes < nbytes)
+ cnt = kbytes;
+ else {
+ cnt = nbytes;
+ *eof = 1;
+ };
+
+ memcpy (buf, io_tlb_list, cnt);
+
+ cnt -= offset;
+ cnt = (cnt < 0 ? 0 : cnt);
+
+ exit:
+ MOD_DEC_USE_COUNT;
+ return cnt;
+
+}
+
+static int
+read_iotlb_params(char *page, char **start, off_t offset, int count, int *eof, void *data)
+{
+ struct iotlb_info_struct *iotlb_params + (struct iotlb_info_struct*) page;
+ const int nbytes = sizeof (struct iotlb_info_struct);
+ int res;
+
+ MOD_INC_USE_COUNT;
+
+ iotlb_params->n_slots = io_tlb_nslabs;
+ iotlb_params->index = io_tlb_index;
+ iotlb_params->used_buffers = io_tlb_used_buffers;
+ iotlb_params->used_slots = io_tlb_used_slots;
+ iotlb_params->max_used_buffers = io_tlb_max_used_buffers;
+ iotlb_params->max_used_slots = io_tlb_max_used_slots;
+ iotlb_params->start = io_tlb_start;
+ iotlb_params->end = io_tlb_end;
+
+ if (offset + count >= nbytes) {
+ *eof = 1;
+ res = (nbytes - offset < 0 ? 0 : nbytes - offset);
+ } else {
+ res = count;
+ };
+
+ MOD_DEC_USE_COUNT;
+ return res;
+}
+
+static int
+read_iotlb_parameters(char *page, char **start, off_t offset, int count, int *eof, void *data)
+{
+ int len, res;
+ MOD_INC_USE_COUNT;
+ len = sprintf (page,
+ "Slots allocated : %8ld\n"
+ "Current Index : %8d\n"
+ "Buffers used : %8d\n"
+ "Slots used : %8d\n"
+ "Max Buffers used : %8d\n"
+ "Max Slots used : %8d\n"
+ "Start address : 0x%p\n"
+ "End address : 0x%p\n",
+ io_tlb_nslabs,
+ io_tlb_index,
+ io_tlb_used_buffers,
+ io_tlb_used_slots,
+ io_tlb_max_used_buffers,
+ io_tlb_max_used_slots,
+ (void*) io_tlb_start,
+ (void*) io_tlb_end);
+ if (offset + count >= len) {
+ *eof = 1;
+ len -= offset;
+ res = (len < 0 ? 0 : len);
+ } else
+ res = count;
+ MOD_DEC_USE_COUNT;
+ return res;
+}
+
+static int __init
+swiotlb_init_proc (void)
+{
+ printk (KERN_INFO "Loading /proc/swiotlb support\n");
+
+ swiotlb_proc_dir = proc_mkdir ("swiotlb", NULL);
+ proc_iotlb_list + create_proc_entry ("list", 0444, swiotlb_proc_dir);
+ proc_iotlb_params + create_proc_entry ("params", 0444, swiotlb_proc_dir);
+ proc_iotlb_parameters + create_proc_entry ("parameters", 0444, swiotlb_proc_dir);
+
+ proc_iotlb_list->read_proc = read_iotlb_list;
+ proc_iotlb_params->read_proc = read_iotlb_params;
+ proc_iotlb_parameters->read_proc = read_iotlb_parameters;
+
+ return 0;
+}
+
+
+static void __exit
+swiotlb_exit_proc (void)
+{
+ printk (KERN_INFO "Unloading /proc/swiotlb support\n");
+ if (swiotlb_outbuf)
+ kfree (swiotlb_outbuf);
+ remove_proc_entry ("list", swiotlb_proc_dir);
+ remove_proc_entry ("params", swiotlb_proc_dir);
+ remove_proc_entry ("parameters", swiotlb_proc_dir);
+ remove_proc_entry ("swiotlb", 0);
+}
+
+module_init(swiotlb_init_proc);
+module_exit(swiotlb_exit_proc);
--- linux-2.4.4-orig/arch/ia64/kernel/Makefile Wed May 30 17:37:23 2001
+++ linux-2.4.4mw/arch/ia64/kernel/Makefile Tue Jun 12 20:05:49 2001
@@ -20,6 +20,7 @@
X obj-$(CONFIG_IA64_DIG) += iosapic.o
X obj-$(CONFIG_IA64_PALINFO) += palinfo.o
X obj-$(CONFIG_EFI_VARS) += efivars.o
+obj-$(CONFIG_PROCFS_SWIOTLB) += swiotlb_proc.o
X obj-$(CONFIG_PCI) += pci.o
X obj-$(CONFIG_SMP) += smp.o smpboot.o
X obj-$(CONFIG_IA64_MCA) += mca.o mca_asm.o
SHAR_EOF
(set 20 01 06 13 23 31 13 'iotlb-mon-0.1/swiotlb.patch'; eval "$shar_touch") &&
chmod 0664 'iotlb-mon-0.1/swiotlb.patch' ||
$echo 'restore of' 'iotlb-mon-0.1/swiotlb.patch' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'iotlb-mon-0.1/swiotlb.patch:' 'MD5 check failed'
ffe958de5009d238c1eee4277bb17e93 iotlb-mon-0.1/swiotlb.patch
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'iotlb-mon-0.1/swiotlb.patch'`"
test 14136 -eq "$shar_count" ||
$echo 'iotlb-mon-0.1/swiotlb.patch:' 'original size' '14136,' 'current size' "$shar_count!"
fi
fi
# ======= iotlb-mon-0.1/Makefile =======
if test -f 'iotlb-mon-0.1/Makefile' && test "$first_param" != -c; then
$echo 'x -' SKIPPING 'iotlb-mon-0.1/Makefile' '(file already exists)'
else
$echo 'x -' extracting 'iotlb-mon-0.1/Makefile' '(text)'
sed 's/^X//' << 'SHAR_EOF' > 'iotlb-mon-0.1/Makefile' &&
CFLAGS = -O2 -Wall
LDFLAGS = -s
PREFIX = /usr/local
X
OBJ = iotlb-mon.o
LIBS = -lncurses
EXE = iotlb-mon
X
sbindir = $(PREFIX)/sbin
X
default: $(EXE)
X
$(EXE): $(OBJ)
X $(CC) $(CFLAGS) $(LDFLAGS) -o $(EXE) $(OBJ) $(LIBS)
X
install: $(EXE)
X install -d $(sbindir)
X install -m 755 $(EXE) $(sbindir)
X
clean:
X rm -f $(EXE) $(OBJ) core
X
distclean: clean
X rm -f *~ '#'*
SHAR_EOF
(set 20 01 06 13 23 08 50 'iotlb-mon-0.1/Makefile'; eval "$shar_touch") &&
chmod 0664 'iotlb-mon-0.1/Makefile' ||
$echo 'restore of' 'iotlb-mon-0.1/Makefile' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'iotlb-mon-0.1/Makefile:' 'MD5 check failed'
54357a32a53e5ade6918ff7b409a31a0 iotlb-mon-0.1/Makefile
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'iotlb-mon-0.1/Makefile'`"
test 358 -eq "$shar_count" ||
$echo 'iotlb-mon-0.1/Makefile:' 'original size' '358,' 'current size' "$shar_count!"
fi
fi
# ======= iotlb-mon-0.1/iotlb-mon.c =======
if test -f 'iotlb-mon-0.1/iotlb-mon.c' && test "$first_param" != -c; then
$echo 'x -' SKIPPING 'iotlb-mon-0.1/iotlb-mon.c' '(file already exists)'
else
$echo 'x -' extracting 'iotlb-mon-0.1/iotlb-mon.c' '(text)'
sed 's/^X//' << 'SHAR_EOF' > 'iotlb-mon-0.1/iotlb-mon.c' &&
/*
X
X iotlb-mon.c - utility to monitor software IO-TLB usage on
X IA-64 Linux systems.
X
X (c) 2001 Martin Wilck <Martin.Wilck@Fujitsu-Siemens.com>
X
X Copying and modification granted under the terms of the
X GNU General Public License (GPL).
X
X *************************************************************
X This program comes with NO WARRANTY, for details see the GPL.
X *************************************************************
X
X Version 0.1, 13.06.2001
X
X Compiling iotlb-mon
X =========X
X Requires the ncurses library and header files.
X
X make; make PREFIX=[my_install_root] install
X
X Default for PREFIX is /usr/local.
X The program installs to $(PREFIX)/sbin.
X
X Using iotlb-mon
X =======X
X usage: ioltb-mon
X
X The kernel module "swiotlb_proc" must be loaded for this
X program to work.
X
X The program has two modes:
X --------------------------
X
X * Info mode: A IO-TLB usage summary is displayed.
X * List mode: A map of the IO-TLB list is displayed. Each entry
X in this list represents the number of free IO-TLB slots after
X the current entry, including the entry itself.
X
X The entries are displayed as follows:
X '0' - this entry occupied
X '1' - this entry free, next entry occupied,
X '2' - this entry & next entry free, ...,
X '9' - this entry & next 8 entries free,
X 'a' - this entry & next 9 entries free, ...,
X 'A' - this entry & next 35 entries free, ...,
X 'Z' - this entry & next 60 entries free, ...,
X '-' - this entry and more than 60 following entries free.
X
X Keyboard controls:
X ------------------
X
X q, x: quit
X l : switch to list mode
X i : switch to info mode
X + : increase timer interval (0.1 - 1 s)
X - : decrease timer interval
X
X The following keys apply only to list mode:
X
X n : move displayed window downward in the list ("next")
X p : move displayed window upward in the list ("previous")
X < : move displayed window to the beginning of the list
X > : move displayed window to the end of the list
X f : Toggle "follow index" mode - in that mode, the window will
X always follow the current slot index, so that the above
X keyboard controls may not have the desired effect.
X
X BUGS:
X -----
X
X Probably many.
X
X I don't believe the list-mode display yet, although it's
X not complete junk.
X It shows weird periodicities that may be due to
X a bug in the read code of the swiotlb_proc kernel module.
X
X Please report bugs and suggest improvements to
X <Martin.Wilck@Fujitsu-Siemens.com>.
X
X */
X
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <curses.h>
#include <sys/time.h>
X
#define N_INFO_FIELDS 8
#define PWIN_BORDER 1
#define INFO_X PWIN_BORDER
#define INFO_Y (PWIN_BORDER)
#define PWIN_HEIGHT (N_INFO_FIELDS+INFO_Y+PWIN_BORDER)
#define INFO_SPC 2
#define INFO_FLEN 18
#define INFO_UFMT "%18u"
#define INFO_PFMT "%18p"
#define PWIN_X 2
#define PWIN_Y 2
#define MIN_INTERVAL 1
#define MAX_INTERVAL 10
#define IWIN_HEIGHT (LINES - 1)
#define INDEX_STEP 1024
X
typedef enum {
X QUIT = 0,
X PARAMS,
X LIST
} run_t;
X
struct iotlb_info_struct {
X unsigned long n_slots;
X unsigned int index;
X unsigned int used_buffers;
X unsigned int used_slots;
X unsigned int max_used_buffers;
X unsigned int max_used_slots;
X void *start;
X void *end;
};
X
static const char *params_name = "/proc/swiotlb/params";
static const char *list_name = "/proc/swiotlb/list";
static const char *info_desc [N_INFO_FIELDS] = {
X "Allocated",
X "Index",
X "Used buffers",
X "Max used buffers",
X "Used slots",
X "Max used slots",
X "Start address",
X "End address"
};
X
static unsigned int first_index = 0;
static bool follow_index = FALSE;
static int iotlb_fd, list_fd;
static int interval = 5;
static WINDOW *mainwin, *pwin, *cwin, *iwin;
volatile sig_atomic_t alarm_received = 0;
X
void
cleanup ()
{
X endwin ();
X close (iotlb_fd);
X close (list_fd);
}
X
static int
info_len (int force)
{
X static int maxl = 0;
X int i;
X
X if (maxl && !force)
X return maxl;
X
X maxl = 0;
X for (i = 0; i < N_INFO_FIELDS; i++) {
X int l = strlen (info_desc[i]);
X if (l > maxl)
X maxl = l;
X };
X maxl++;
X return maxl;
}
X
static void
create_windows (void)
{
X int width = info_len(0) + INFO_SPC + INFO_FLEN + 2*PWIN_BORDER;
X
X pwin = newwin (PWIN_HEIGHT,
X width,
X PWIN_Y,
X (COLS - width) >> 1);
X cwin = newwin (1, 0, LINES - 1, 0);
X iwin = newwin (IWIN_HEIGHT, 0, 0, 0);
X
X if (!pwin || !cwin || !iwin) {
X cleanup ();
X fprintf (stderr, "Error creating windows");
X exit (1);
X };
X box (pwin, 0, 0);
}
X
static int
print_info_desc (int force)
{
X
X int maxl = info_len (force), i;
X mvwprintw (pwin, 0, INFO_X,
X "Software IO-TLB status");
X for (i = 0; i < N_INFO_FIELDS; i++) {
X mvwprintw (pwin, INFO_Y + i, INFO_X,
X "%s", info_desc[i]);
X mvwaddch (pwin, INFO_Y + i, INFO_X + maxl, ':');
X };
X
X return maxl;
}
X
static int
read_info (struct iotlb_info_struct *inf)
{ int nread;
X int st;
X
X st = lseek (iotlb_fd, 0, SEEK_SET);
X
X nread = read (iotlb_fd, inf, sizeof (struct iotlb_info_struct));
X if (nread != sizeof (struct iotlb_info_struct)) {
X cleanup ();
X fprintf (stderr, "error in read () on %s\n",
X params_name);
X exit (1);
X };
X
X return nread;
}
X
static void
print_info (void)
{
X struct iotlb_info_struct info;
X int nread, col;
X
X nread = read_info (&info);
X col = print_info_desc (0) + INFO_X + INFO_SPC;
X
X mvwprintw (pwin, INFO_Y + 0, col, INFO_UFMT, info.n_slots);
X mvwprintw (pwin, INFO_Y + 1, col, INFO_UFMT, info.index);
X mvwprintw (pwin, INFO_Y + 2, col, INFO_UFMT, info.used_buffers);
X mvwprintw (pwin, INFO_Y + 3, col, INFO_UFMT, info.max_used_buffers);
X mvwprintw (pwin, INFO_Y + 4, col, INFO_UFMT, info.used_slots);
X mvwprintw (pwin, INFO_Y + 5, col, INFO_UFMT, info.max_used_slots);
X mvwprintw (pwin, INFO_Y + 6, col, INFO_PFMT, info.start);
X mvwprintw (pwin, INFO_Y + 7, col, INFO_PFMT, info.end);
X wrefresh (pwin);
}
X
static int
read_list (unsigned int **lst, struct iotlb_info_struct *info)
{
X static int size = 0;
X static unsigned int *list = NULL;
X int nread, st, n, i;
X char *pos;
X
X nread = read_info (info);
X if (!list) {
X size = info->n_slots;
X if (size > 0) {
X list = malloc (size * sizeof (unsigned int));
X };
X if (!list) {
X cleanup ();
X fprintf (stderr,
X "Error in malloc ()\n");
X exit (1);
X };
X for (i = 0; i < size; i++)
X list[i] = 1;
X };
X
X st = lseek (list_fd, 0, SEEK_SET);
X
X pos = (char*) list;
X n = size * sizeof (unsigned int);
X do {
X nread = read (list_fd, pos, n);
/* pos += nread; */
X n -= nread;
X } while (0); /* (nread > 0); */
X
X if (nread < 0) {
X cleanup ();
X fprintf (stderr, "error in read () on %s: %d\n",
X list_name, nread);
X exit (1);
X };
X
X *lst = list;
X return size - n;
}
X
static chtype
make_ch (unsigned int v)
{
X chtype c;
X if (v < 10u)
X c = '0' + v;
X else if (v < 36u)
X c = 'a' + v - 10;
X else if (v < 62u)
X c = 'A' + v - 36;
X else
X c = '-';
X return c;
}
X
static void
print_list (void)
{
X unsigned int *list, index;
X int sz, mx, i, last;
X struct iotlb_info_struct info;
X
X sz = read_list (&list, &info);
X index = info.index;
X mx = COLS * IWIN_HEIGHT;
X
X if (first_index >= sz) {
X first_index = (sz - 1) & ~(INDEX_STEP - 1);
X };
X if (follow_index &&
X (first_index > index || index - first_index > mx)) {
X first_index = index & ~(INDEX_STEP - 1);
X };
X
X last = first_index + mx;
X if (last > sz)
X last = sz;
X
X mvwprintw (iwin, 0, 0, "IO-TLB list slot %8u - %8u. "
X "read %d, index %8u, used %8u",
X first_index, last, sz, index, info.used_slots);
X
X wmove (iwin, 1, 0);
X for (i = first_index; i < last; ++i) {
X if (i = index) {
X wattron (iwin, A_REVERSE);
X waddch (iwin, make_ch (list[i]));
X wattroff (iwin, A_REVERSE);
X } else if (i % 1024 = 0) {
X wattron (iwin, A_UNDERLINE);
X waddch (iwin, make_ch (list[i]));
X wattroff (iwin, A_UNDERLINE);
X } else
X waddch (iwin, make_ch (list[i]));
X };
X for (i = last; i < first_index + mx; i++)
X waddch (iwin, ' ');
X wrefresh (iwin);
}
X
void
alrm_handler (int sig)
{
X alarm_received = 1;
}
X
int
start_timer (long int decisec)
{
X static const struct itimerval itv0 = {
X { 0, 0}, { 0, 0}
X };
X struct itimerval itv;
X int st;
X long int sec = decisec / 10;
X long int usec = 100000 * (decisec % 10);
X struct sigaction act;
X
X act.sa_handler = alrm_handler;
X sigemptyset (&act.sa_mask);
X sigaction (SIGALRM, &act, NULL);
X
X itv.it_interval.tv_sec = sec;
X itv.it_interval.tv_usec = usec;
X itv.it_value.tv_sec = sec;
X itv.it_value.tv_usec = usec;
X
X setitimer (ITIMER_REAL, &itv0, NULL);
X st = setitimer (ITIMER_REAL, &itv, NULL);
X
X mvwprintw (cwin, 0, 0, "Timer interval (1/10 s): %3d", decisec);
X return st;
}
X
run_t
handle_input (run_t run)
{
X chtype ch;
X ch = wgetch(cwin);
X if (ch != ERR) {
X switch (ch) {
X case '+':
X if (interval < MAX_INTERVAL) {
X interval++;
X start_timer (interval);
X };
X break;
X case '-':
X if (interval > MIN_INTERVAL) {
X interval--;
X start_timer (interval);
X };
X break;
X case 'i':
X run = PARAMS;
X werase (iwin);
X wrefresh (iwin);
X box (pwin, 0, 0);
X break;
X case 'l':
X run = LIST;
X werase (pwin);
X wrefresh (pwin);
X break;
X case 'q':
X case 'x':
X run = QUIT;
X break;
X case 'f':
X follow_index = ~follow_index & 1;
X if (follow_index)
X mvwprintw (cwin, 0, COLS - 20,
X "Follow Index ON");
X else
X mvwprintw (cwin, 0, COLS - 20,
X "Follow Index OFF");
X break;
X case '<':
X first_index = 0;
X break;
X case '>':
X first_index = 1 << 24;
X break;
X case 'n':
X first_index += INDEX_STEP;
X break;
X case 'p':
X first_index -= INDEX_STEP;
X break;
X default:
X break;
X };
X wrefresh(cwin);
X };
X
X return run;
}
X
int
main (int argc, char **argv)
{
X sigset_t alrm_mask;
X run_t run = PARAMS;
X
X iotlb_fd = open (params_name, O_RDONLY, 0);
X list_fd = open (list_name, O_RDONLY, 0);
X if (iotlb_fd < 0 || list_fd < 0)
X perror ("open");
X
X mainwin = initscr ();
X cbreak ();
X noecho ();
X
X create_windows ();
X
X sigemptyset (&alrm_mask);
X sigaddset (&alrm_mask, SIGALRM);
X
X start_timer (interval);
X
X while (run != QUIT) {
X run = handle_input (run);
X sigprocmask (SIG_BLOCK, &alrm_mask, NULL);
X if (alarm_received) {
X alarm_received = 0;
X switch (run) {
X case PARAMS:
X print_info ();
X break;
X case LIST:
X print_list ();
X break;
X default:
X break;
X };
X };
X sigprocmask (SIG_UNBLOCK, &alrm_mask, NULL);
X };
X
X cleanup ();
X return 0;
}
SHAR_EOF
(set 20 01 06 13 23 06 48 'iotlb-mon-0.1/iotlb-mon.c'; eval "$shar_touch") &&
chmod 0664 'iotlb-mon-0.1/iotlb-mon.c' ||
$echo 'restore of' 'iotlb-mon-0.1/iotlb-mon.c' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'iotlb-mon-0.1/iotlb-mon.c:' 'MD5 check failed'
61f5d6a6e6d9a5e2d0fcf56d5caea078 iotlb-mon-0.1/iotlb-mon.c
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'iotlb-mon-0.1/iotlb-mon.c'`"
test 10494 -eq "$shar_count" ||
$echo 'iotlb-mon-0.1/iotlb-mon.c:' 'original size' '10494,' 'current size' "$shar_count!"
fi
fi
rm -fr _sh05939
exit 0
reply other threads:[~2001-06-13 20:40 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=marc-linux-ia64-105590693005728@msgid-missing \
--to=martin.wilck@fujitsu-siemens.com \
--cc=linux-ia64@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox