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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.