[prev in list] [next in list] [prev in thread] [next in thread]
List: linux-ia64
Subject: [Linux-ia64] IO-TLB monitoring patch & tool v0.2
From: Martin Wilck <Martin.Wilck () fujitsu-siemens ! com>
Date: 2001-06-25 19:30:55
[Download RAW message or body]
Hello,
Here is a corrected version of the kernel patch & tool for
monitoring IO-TLB usage. It works correctly now, and is even fun to watch!
It can display summary information or show a IO-TLB "map" in two different
modes.
Even if the aic7xxx problems may be history soon, this tool may
still be useful with other controllers/drivers.
Cheers
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-25 21:18 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
# ------ ---------- ------------------------------------------
# 358 -rw-rw-r-- iotlb-mon-0.2/Makefile
# 1347 -rw-rw-r-- iotlb-mon-0.2/README
# 12720 -rw-rw-r-- iotlb-mon-0.2/iotlb-mon.c
# 10022 -rw-rw-r-- iotlb-mon-0.2/swiotlb_proc.patch
#
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=FAILED
locale_dir=FAILED
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=echo
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 _sh04019; then
$echo 'x -' 'creating lock directory'
else
$echo 'failed to create lock directory'
exit 1
fi
# ============= iotlb-mon-0.2/Makefile ==============
if test ! -d 'iotlb-mon-0.2'; then
$echo 'x -' 'creating directory' 'iotlb-mon-0.2'
mkdir 'iotlb-mon-0.2'
fi
if test -f 'iotlb-mon-0.2/Makefile' && test "$first_param" != -c; then
$echo 'x -' SKIPPING 'iotlb-mon-0.2/Makefile' '(file already exists)'
else
$echo 'x -' extracting 'iotlb-mon-0.2/Makefile' '(text)'
sed 's/^X//' << 'SHAR_EOF' > 'iotlb-mon-0.2/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.2/Makefile'; eval "$shar_touch") &&
chmod 0664 'iotlb-mon-0.2/Makefile' ||
$echo 'restore of' 'iotlb-mon-0.2/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.2/Makefile:' 'MD5 check failed'
54357a32a53e5ade6918ff7b409a31a0 iotlb-mon-0.2/Makefile
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'iotlb-mon-0.2/Makefile'`"
test 358 -eq "$shar_count" ||
$echo 'iotlb-mon-0.2/Makefile:' 'original size' '358,' 'current size' \
"$shar_count!" fi
fi
# ============= iotlb-mon-0.2/README ==============
if test -f 'iotlb-mon-0.2/README' && test "$first_param" != -c; then
$echo 'x -' SKIPPING 'iotlb-mon-0.2/README' '(file already exists)'
else
$echo 'x -' extracting 'iotlb-mon-0.2/README' '(text)'
sed 's/^X//' << 'SHAR_EOF' > 'iotlb-mon-0.2/README' &&
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.2, 25.06.2001
X
X Installing the kernel patch
X ===========================
X
X Patch the 2.4.5 kernel + IA64 patch (30.05.2001)
X with the patch file (swiotlb_proc.patch) from this directory.
X Activate building the module in the "General setup" section
X (/proc/swiotlb support). Build & install kernel and modules as usual.
X The module built is called "swiotlb_proc.o".
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 Hit '?' in running program to display keyboard controls.
X
X BUGS:
X -----
X
X Probably many.
X Sometimes read () yields unreasonable sizes.
X
X Please report bugs and suggest improvements to
X <Martin.Wilck@Fujitsu-Siemens.com>.
X
SHAR_EOF
(set 20 01 06 25 21 17 59 'iotlb-mon-0.2/README'; eval "$shar_touch") &&
chmod 0664 'iotlb-mon-0.2/README' ||
$echo 'restore of' 'iotlb-mon-0.2/README' '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.2/README:' 'MD5 check failed'
c37d1441828e166ac808b1ae2410ccea iotlb-mon-0.2/README
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'iotlb-mon-0.2/README'`"
test 1347 -eq "$shar_count" ||
$echo 'iotlb-mon-0.2/README:' 'original size' '1347,' 'current size' \
"$shar_count!" fi
fi
# ============= iotlb-mon-0.2/iotlb-mon.c ==============
if test -f 'iotlb-mon-0.2/iotlb-mon.c' && test "$first_param" != -c; then
$echo 'x -' SKIPPING 'iotlb-mon-0.2/iotlb-mon.c' '(file already exists)'
else
$echo 'x -' extracting 'iotlb-mon-0.2/iotlb-mon.c' '(text)'
sed 's/^X//' << 'SHAR_EOF' > 'iotlb-mon-0.2/iotlb-mon.c' &&
/*
X
X iotlb-mon.c - utility to monitor software IO-TLB usage on
X IA-64 Linux systems.
X (c) 2001 Martin Wilck <Martin.Wilck@Fujitsu-Siemens.com>
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,
X GROUP,
X HELP
} 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 char *help_msg = "Hit 'h' or '?' for help";
static char *help_exit_msg = "Hit 'i', 'd', or 'c' to leave help";
static char *follow_off_msg = "Follow mode OFF";
static char *follow_on_msg = "Follow mode ON";
static char *current_msg = NULL;
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
void
refresh_cwin (void)
{
X werase (cwin);
X mvwprintw (cwin, 0, 0, current_msg);
X mvwprintw (cwin, 0, COLS - 30, "Timer interval (1/10 s): %3d", interval);
X wrefresh (cwin);
}
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 refresh_cwin ();
}
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);
X 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 chtype
make_group_ch (unsigned int *slot, const unsigned int *highest)
{
X chtype free = 0;
X
X for (; slot < highest; slot++)
X if (*slot)
X free++;
X if (free == 16)
X free = '*';
X else if (free <= 9)
X free += '0';
X else
X free += 'A' - 10;
X return free;
}
X
static void
print_list_group (void)
{
X unsigned int *list, *index, *curr, *next, *last;
X int sz, mx;
X struct iotlb_info_struct info;
X
X sz = read_list (&list, &info);
X index = list + info.index;
X
X mx = (COLS * IWIN_HEIGHT) << 4;
X
X if (mx >= sz)
X first_index = 0;
X
X if (first_index >= sz) {
X first_index = (sz - 1) & ~(INDEX_STEP - 1);
X };
X
X if (follow_index &&
X (list + first_index > index || index - (list + first_index) > mx)) {
X first_index = (index - list) & ~(INDEX_STEP - 1);
X };
X
X last = list + first_index + mx;
X if (last > list + sz)
X last = list + sz;
X
X werase (iwin);
X mvwprintw (iwin, 0, 0, "Condensed map of slot %8u - %8u. "
X "Current slot index: %u, total used slots: %u",
X first_index, last - list, info.index, info.used_slots);
X
X wmove (iwin, 1, 0);
X for (curr = list + first_index; curr < last; curr = next) {
X next = curr + 16;
X if (next > last)
X next = last;
X if (curr <= index && index < next) {
X wattron (iwin, A_REVERSE);
X waddch (iwin, make_group_ch (curr, next));
X wattroff (iwin, A_REVERSE);
X } else
X waddch (iwin, make_group_ch (curr, next));
X };
X wrefresh (iwin);
}
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 (mx >= sz)
X first_index = 0;
X
X if (first_index >= sz) {
X first_index = (sz - 1) & ~(INDEX_STEP - 1);
X };
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 werase (iwin);
X mvwprintw (iwin, 0, 0, "Map of slot %8u - %8u. "
X "Current slot index: %u, total used slots: %u",
X first_index, last, 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 % 2048 == 0) {
X wattron (iwin, A_REVERSE);
X waddch (iwin, make_ch (list[i]));
X wattroff (iwin, A_REVERSE);
X } else
X waddch (iwin, make_ch (list[i]));
X };
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 return st;
}
X
#define HELP_TAB 8
X
static void
help (void)
{
X int line = 0;
X werase (iwin);
X
X wattron (iwin, A_UNDERLINE);
X mvwprintw (iwin, line, 0, "iotlb-mon - Monitor the state of the IO-TLB buffers");
X wattroff (iwin, A_UNDERLINE);
X
X line ++;
X mvwprintw (iwin, line, 0, "(c) 2001 Martin Wilck \
<Martin.Wilck@Fujitsu-Siemens.com>"); X
X line += 2;
X wattron (iwin, A_UNDERLINE);
X mvwprintw (iwin, line, 0, "Keyboard controls:");
X wattroff (iwin, A_UNDERLINE);
X
X mvwprintw (iwin, ++line, 0, "h or ?");
X mvwprintw (iwin, line, HELP_TAB, "Show this help");
X mvwprintw (iwin, ++line, 0, "q or x");
X mvwprintw (iwin, line, HELP_TAB, "Exit utility");
X
X mvwprintw (iwin, ++line, 0, "+,-");
X mvwprintw (iwin, line, HELP_TAB, "Increase / decrease update interval by 1/10 \
sec"); X
X mvwprintw (iwin, ++line, 0, "i");
X wattron (iwin, A_UNDERLINE);
X mvwprintw (iwin, line, HELP_TAB, "Info mode: show IO-TLB usage summary");
X wattroff (iwin, A_UNDERLINE);
X
X mvwprintw (iwin, ++line, 0, "c");
X wattron (iwin, A_UNDERLINE);
X mvwprintw (iwin, line, HELP_TAB, "Condensed mode: show condensed slot usage map");
X wattroff (iwin, A_UNDERLINE);
X mvwprintw (iwin, ++line, HELP_TAB, "Each character represents 16 IO-TLB slots");
X mvwprintw (iwin, ++line, HELP_TAB, "Hex digit 0-F: Number of free slots in group");
X mvwprintw (iwin, ++line, HELP_TAB, "* : all slots in group are free");
X
X mvwprintw (iwin, ++line, 0, "d");
X wattron (iwin, A_UNDERLINE);
X mvwprintw (iwin, line, HELP_TAB, "Detailed mode: show detailed slot usage map");
X wattroff (iwin, A_UNDERLINE);
X mvwprintw (iwin, ++line, HELP_TAB, "Each character represents a single IO-TLB \
slot"); X mvwprintw (iwin, ++line, HELP_TAB, "0 : slot occupied");
X mvwprintw (iwin, ++line, HELP_TAB, "1-9, a-z, A-Z: number of free slots (including \
current)"); X mvwprintw (iwin, ++line, HELP_TAB, " after current \
position"); X mvwprintw (iwin, ++line, HELP_TAB, "- : >= 61 slots starting \
from current are free"); X
X mvwprintw (iwin, ++line, 0, "f");
X mvwprintw (iwin, line, HELP_TAB, "Toggle Follow mode: Page follows slot index "
X "(detailed / condensed mode)");
X mvwprintw (iwin, ++line, 0, "p,n");
X mvwprintw (iwin, line, HELP_TAB, "Previous / next page (detailed and condensed \
mode)"); X mvwprintw (iwin, ++line, 0, "<,>");
X mvwprintw (iwin, line, HELP_TAB, "First / last page (detailed and condensed \
mode)"); X
X wrefresh (iwin);
X
X current_msg = help_exit_msg;
X refresh_cwin ();
}
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 'h':
X case '?':
X run = HELP;
X werase (pwin);
X wrefresh (pwin);
X help ();
X break;
X case 'i':
X run = PARAMS;
X werase (iwin);
X wrefresh (iwin);
X box (pwin, 0, 0);
X current_msg = help_msg;
X break;
X case 'd':
X case 'l':
X run = LIST;
X werase (pwin);
X wrefresh (pwin);
X current_msg = help_msg;
X break;
X case 'c':
X case 'g':
X run = GROUP;
X werase (pwin);
X wrefresh (pwin);
X current_msg = help_msg;
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 current_msg = follow_on_msg;
X else
X current_msg = follow_off_msg;
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 refresh_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 fprintf (stderr, "ERROR: Could not open /proc/swiotlb.\n"
X " Is the swiotlb_proc module loaded ?\n");
X exit (1);
X };
X
X current_msg = help_msg;
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 case GROUP:
X print_list_group ();
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 25 21 13 10 'iotlb-mon-0.2/iotlb-mon.c'; eval "$shar_touch") &&
chmod 0664 'iotlb-mon-0.2/iotlb-mon.c' ||
$echo 'restore of' 'iotlb-mon-0.2/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.2/iotlb-mon.c:' 'MD5 check failed'
8efeb5b0783014a807e2095824095158 iotlb-mon-0.2/iotlb-mon.c
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'iotlb-mon-0.2/iotlb-mon.c'`"
test 12720 -eq "$shar_count" ||
$echo 'iotlb-mon-0.2/iotlb-mon.c:' 'original size' '12720,' 'current size' \
"$shar_count!" fi
fi
# ============= iotlb-mon-0.2/swiotlb_proc.patch ==============
if test -f 'iotlb-mon-0.2/swiotlb_proc.patch' && test "$first_param" != -c; then
$echo 'x -' SKIPPING 'iotlb-mon-0.2/swiotlb_proc.patch' '(file already exists)'
else
$echo 'x -' extracting 'iotlb-mon-0.2/swiotlb_proc.patch' '(text)'
sed 's/^X//' << 'SHAR_EOF' > 'iotlb-mon-0.2/swiotlb_proc.patch' &&
diff -ruN linux-2.4.5/Documentation/Configure.help \
linux-2.4.5mw/Documentation/Configure.help
--- linux-2.4.5/Documentation/Configure.help Mon Jun 25 14:45:01 2001
+++ linux-2.4.5mw/Documentation/Configure.help Mon Jun 25 21:02:47 2001
@@ -17776,6 +17776,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,
diff -ruN linux-2.4.5/arch/ia64/config.in linux-2.4.5mw/arch/ia64/config.in
--- linux-2.4.5/arch/ia64/config.in Mon Jun 25 14:45:01 2001
+++ linux-2.4.5mw/arch/ia64/config.in Mon Jun 25 21:02:47 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
diff -ruN linux-2.4.5/arch/ia64/kernel/Makefile \
linux-2.4.5mw/arch/ia64/kernel/Makefile
--- linux-2.4.5/arch/ia64/kernel/Makefile Mon Jun 25 14:45:01 2001
+++ linux-2.4.5mw/arch/ia64/kernel/Makefile Mon Jun 25 21:02:47 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
diff -ruN linux-2.4.5/arch/ia64/kernel/swiotlb_proc.c \
linux-2.4.5mw/arch/ia64/kernel/swiotlb_proc.c
--- linux-2.4.5/arch/ia64/kernel/swiotlb_proc.c Thu Jan 1 01:00:00 1970
+++ linux-2.4.5mw/arch/ia64/kernel/swiotlb_proc.c Mon Jun 25 18:44:47 2001
@@ -0,0 +1,176 @@
+#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 + offset;
+ } else {
+ buf = page + offset;
+ };
+
+ /* copy only if offset = 0 for max consistency */
+ if (!offset)
+ memcpy (buf, (char*) io_tlb_list, nbytes);
+
+ if (kbytes < nbytes)
+ cnt = count;
+ else {
+ cnt = nbytes - offset;
+ if (cnt < 0)
+ cnt = 0;
+ *eof = 1;
+ };
+
+ 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);
diff -ruN linux-2.4.5/arch/ia64/lib/swiotlb.c linux-2.4.5mw/arch/ia64/lib/swiotlb.c
--- linux-2.4.5/arch/ia64/lib/swiotlb.c Mon Jun 25 14:45:01 2001
+++ linux-2.4.5mw/arch/ia64/lib/swiotlb.c Mon Jun 25 21:02:47 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.
@@ -228,6 +254,10 @@
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
X }
X
X static void
@@ -462,3 +492,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 */
SHAR_EOF
(set 20 01 06 25 21 05 57 'iotlb-mon-0.2/swiotlb_proc.patch'; eval "$shar_touch") \
&& chmod 0664 'iotlb-mon-0.2/swiotlb_proc.patch' ||
$echo 'restore of' 'iotlb-mon-0.2/swiotlb_proc.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.2/swiotlb_proc.patch:' 'MD5 check failed'
509bf43c7d000ddf3845d2c791277122 iotlb-mon-0.2/swiotlb_proc.patch
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'iotlb-mon-0.2/swiotlb_proc.patch'`"
test 10022 -eq "$shar_count" ||
$echo 'iotlb-mon-0.2/swiotlb_proc.patch:' 'original size' '10022,' 'current size' \
"$shar_count!" fi
fi
rm -fr _sh04019
exit 0
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic