📄 bte_regr_test.c
字号:
/* * * * Copyright (c) 2002 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * Further, this software is distributed without any warranty that it is * free of the rightful claim of any third person regarding infringement * or the like. Any license provided herein, whether implied or * otherwise, applies only to this software file. Patent licenses, if * any, provided herein do not apply to combinations of this program with * other software, or any other product whatsoever. * * You should have received a copy of the GNU General Public * License along with this program; if not, write the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. * * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, * Mountain View, CA 94043, or: * * http://www.sgi.com * * For further information regarding this notice, see: * * http://oss.sgi.com/projects/GenInfo/NoticeExplan *//*********************************************************************** * Block Transfer Engine regression tests. * * The following set of tests can be used to test for regressions. * It is implemented as a loadable module. * * To enable the tests, the kernel must be booted with the * "btetest" command line flag. If the tests are compiled into the * kernel, additional values may be passed with * "bte_test=t,v,ht,tn,tx,ti,ta,tc" * where: * t = Bitmask of tests to run. * v = Level of verbosity. * ht = Number of seconds to try to force a notification hang. * hu = Number of uSecs to wait until warning of hang. * tn = Min number of lines to rate test with (2 raised to). * tx = Max number of lines to rate test with (2 raised to). * ti = Number of iterations per timing. * ta = Aternate through cpus on each pass. * tc = Use/Don't Use memcopy * * When loaded as a module, each of those values has a seperate * parameter. Just do a modinfo bte_test.o to get those names * and valid ranges. * * Tests are performed in the following order. * * Standard Transfer Test - Just transfers a block of initialized * data to a cleared block and ensures that memory before and after * is untouched, but that the body has all the correct values. * * Transfer Rate Test - Data is transfered from node to node * to ensure every node is able to BTE data. Timings are created * for each node. * * Notification Hang Test - Attempts to force the Notification * hang problem to arise. A hang occurs when the BTE fails * to invalidate a processors cache line for the notification * word, resulting in the processor not seeing the updated * value. * * Invalid Transfer Test - In this test, we attempt to transfer * data from a valid address to a nasid which does not exist. * **********************************************************************/#define BTE_TIME 1 /* Needed to ensure bte_copy records * timings */// #define BTE_DEBUG// #define BTE_DEBUG_VERBOSE#include <linux/kernel.h>#include <linux/init.h>#include <linux/module.h>#include <linux/slab.h>#include <linux/sched.h>#include <asm/sn/nodepda.h>#include <asm/processor.h>#include <asm/sn/bte_copy.h>/*********************************************************************** * Local defines, structs, and typedefs. * **********************************************************************//* * The following struct defines standard transfers to use while * testing. */typedef struct brt_xfer_entry_s { int source_offset; int dest_offset; int length;} brt_xfer_entry_t;/* * BRT_TEST_BLOCK_SIZE needs to accomodate the largest transfer that * is found in brt_xfer_tests. */#define BRT_TEST_BLOCK_SIZE 1024/* Flags for selecting tests to run. */#define TEST_REGRESSION 0x00000001 /* Standard Transfer */#define TEST_TIME 0x00000002 /* Timed Transfer */#define TEST_NOTIFY 0x00000004 /* Notification Hang */#define TEST_NONODE 0x00000008 /* Invalid Nasid Xfer *//*********************************************************************** * Global variables. * **********************************************************************//* * bte_setup_time - Time it takes for bte_copy to get locks * acquired and values into SHUB registers to start the * xfer. * * bte_transfer_time - Time where hardware is doing the xfer. * * bte_tear_down_time - Time to unlock and return. * * bte_execute_time - Time from first call until return. */volatile static u64 bte_setup_time;volatile static u64 bte_transfer_time;volatile static u64 bte_tear_down_time;volatile static u64 bte_execute_time;/* Tests to run during standard transfer tests. */static brt_xfer_entry_t brt_xfer_tests[] = { {0, 0, 2 * L1_CACHE_BYTES}, /* The ideal case. */ {0, 0, 35}, /* Symetrical aligned test. */ {L1_CACHE_BYTES, L1_CACHE_BYTES, 35}, {0, 0, L1_CACHE_BYTES + 35}, {L1_CACHE_BYTES, L1_CACHE_BYTES, L1_CACHE_BYTES + 35}, {0, 0, (2 * L1_CACHE_BYTES) + 35}, {L1_CACHE_BYTES, L1_CACHE_BYTES, (2 * L1_CACHE_BYTES) + 35}, {0, 0, (4 * L1_CACHE_BYTES) + 35}, {L1_CACHE_BYTES, L1_CACHE_BYTES, (4 * L1_CACHE_BYTES) + 35}, {(0 + 25), (0 + 25), 35}, /* Symetrical unaligned test. */ {(L1_CACHE_BYTES + 25), (L1_CACHE_BYTES + 25), 35}, {(0 + 25), (0 + 25), L1_CACHE_BYTES + 35}, {(L1_CACHE_BYTES + 25), (L1_CACHE_BYTES + 25), (L1_CACHE_BYTES + 25) + 35}, {(0 + 25), (0 + 25), (2 * L1_CACHE_BYTES) + 35}, {(L1_CACHE_BYTES + 25), (L1_CACHE_BYTES + 25), (2 * L1_CACHE_BYTES) + 35}, {(0 + 25), (0 + 25), (4 * L1_CACHE_BYTES) + 35}, {(L1_CACHE_BYTES + 25), (L1_CACHE_BYTES + 25), (4 * L1_CACHE_BYTES) + 35}, {(0 + 25), (0 + 26), 35}, /* Asymetrical unaligned test. */ {(L1_CACHE_BYTES + 25), (L1_CACHE_BYTES + 26), 35}, {(0 + 25), (0 + 26), L1_CACHE_BYTES + 35}, {(L1_CACHE_BYTES + 25), (L1_CACHE_BYTES + 26), (L1_CACHE_BYTES + 25) + 35}, {(0 + 25), (0 + 26), (2 * L1_CACHE_BYTES) + 35}, {(L1_CACHE_BYTES + 25), (L1_CACHE_BYTES + 26), (2 * L1_CACHE_BYTES) + 35}, {(0 + 25), (0 + 26), (4 * L1_CACHE_BYTES) + 35}, {(L1_CACHE_BYTES + 25), (L1_CACHE_BYTES + 26), (4 * L1_CACHE_BYTES) + 35}, {0, 0, 0} /* Terminator */};static atomic_t brt_thread_cnt; /* Threads in test. */volatile static int brt_exit_flag; /* Flag termination of hang test *//* command line/module parameters */static int selected_tests = 0;static int verbose = 0;static int hang_timeout = 10;static int hang_usec = 12;static int tm_min_lines = 1;static int tm_max_lines = 3;static int tm_iterations = 1;static int tm_alternate = 0;static int tm_memcpy = 1;static int ix_iterations = 1000;static int ix_srcnasid = -1;/*********************************************************************** * Local Function Prototypes. * **********************************************************************/static int __init brt_test_init(void);static void __exit brt_test_exit(void);/* Standard Transfer Test related functions. */static int brt_tst_std_xfer(void);static int brt_std_xfer(char *, char *, int, int, int, int);static void brt_hex_dump(char *, int);/* Timed Transfer Test related functions. */static int brt_tst_time_xfers(void);static void brt_time_xfer(int, int, int);/* Notification Hang Test related functions. */static int brt_tst_notify_hang(void);static int brt_notify_thrd(void *);/* Transfers to Invalid Nasid Test related functions. */static int brt_tst_invalid_xfers(void);#if !defined(MODULE)/* Kernel command line handler. */static int __init brt_setup(char *);#endif /* !defined(MODULE) *//*********************************************************************** * Module Load/Unload. * **********************************************************************/#define brt_marker() \ printk("**************************************************" \ "**********************.\n"); \ printk("\n"); \ printk("**************************************************" \ "**********************.\n"); \ printk("\n"); \ printk("**************************************************" \ "**********************.\n"); \ printk("\n");static int __initbrt_test_init(void){ int some_tests_removed; if (numnodes < 2) { printk("These tests are best run on multinode " "systems.\n"); } if (!pda.cpu_bte_if[0]->bte_test_buf) { some_tests_removed = 0; /* Timed Transfers go node-to-node. */ if (selected_tests & TEST_TIME) { some_tests_removed = 1; selected_tests &= ~(TEST_TIME); } /* Notification Hang runs on all cpus simultaneously */ if (selected_tests & TEST_NOTIFY) { some_tests_removed = 1; selected_tests &= ~(TEST_NOTIFY); } /* Invalid Tests */ if (selected_tests & TEST_NONODE) { some_tests_removed = 1; selected_tests &= ~(TEST_NONODE); } if (some_tests_removed) { printk("Test Buffers were not allocated.\n"); printk("Please reboot the system and supply " "the \"btetest\" kernel flag\n"); printk("Some tests were removed.\n"); } } brt_marker(); printk("brt_test(): Starting.\n"); if (selected_tests & TEST_REGRESSION) { if (brt_tst_std_xfer()) { printk("Standard Transfers had errors.\n"); } } if (selected_tests & TEST_TIME) { if (tm_min_lines < 0) { tm_min_lines = 0; } if (tm_max_lines < 0) { tm_max_lines = 0; } if (tm_max_lines > BTE_LEN_MASK) { tm_max_lines = BTE_LEN_MASK; } if (tm_min_lines > tm_max_lines) { tm_min_lines = tm_max_lines; } if (brt_tst_time_xfers()) { printk("Timed transfers had errors.\n"); } } if (selected_tests & TEST_NOTIFY) { if (hang_usec < 8) { hang_usec = 8; } if (hang_usec > 256) { hang_usec = 256; } if (brt_tst_notify_hang()) { printk("Notification Hang test had errors.\n"); } } if (selected_tests & TEST_NONODE) { if (brt_tst_invalid_xfers()) { printk("Invalid Nasid test had errors.\n"); } } return (1); /* Prevent module load. */}static void __exitbrt_test_exit(void){}/*********************************************************************** * Standard Transfer Test. * * This test has a table of transfers defined above. For each * transfer, it calls bte_unaligned_copy. It compares the actual * result with the expected result. If they differ, it prints out * information about the transfer and hex dumps the actual block * **********************************************************************//* * Allocate the needed buffers and then initiate each xfer specified * by brt_xfer_tests. */static intbrt_tst_std_xfer(void){ char *block_1; char *block_2; int iteration = 0; brt_xfer_entry_t *cur_test; int cpu; int err_cnt; block_1 = kmalloc(BRT_TEST_BLOCK_SIZE, GFP_KERNEL); ASSERT(!((u64) block_1 & L1_CACHE_MASK)); block_2 = kmalloc(BRT_TEST_BLOCK_SIZE, GFP_KERNEL); ASSERT(!((u64) block_2 & L1_CACHE_MASK)); cur_test = brt_xfer_tests; err_cnt = 0; while (cur_test->length) { for (cpu = 0; cpu < smp_num_cpus; cpu++) { set_cpus_allowed(current, (1UL << cpu)); if (verbose > 1) { printk("Cpu %d Transfering %d from " "%d to %d.\n", smp_processor_id(), cur_test->length, cur_test->source_offset, cur_test->dest_offset); } err_cnt += brt_std_xfer(block_1, block_2, cur_test->source_offset, cur_test->dest_offset, cur_test->length, ++iteration); } cur_test++; } kfree(block_2); kfree(block_1); return ((err_cnt ? 1 : 0));}/* * Perform a single transfer and ensure the result matches * the expected. Returns the number of differences found. * * Testing is performed by setting the source buffer to a * known value, and zeroing out the destination. * * After the copy, if the destination has only the known * source values at the correct place, we know we had a * good transfer. * */static intbrt_std_xfer(char *src, char *dst, int src_offset, int dst_offset, int len, int magic){ int i, ret; int err_cnt = 0; if (verbose > 3) { printk("brt_test(src=0x%lx, dst=0x%lx, src_offset=%d, " "dst_offset=%d, len=%d, magic=%d\n", (u64) src, (u64) dst, src_offset, dst_offset, len, magic); } memset(src, ((magic + 1) & 0xff), BRT_TEST_BLOCK_SIZE); memset((src + src_offset), magic, len); if (verbose > 8) { printk("Before transfer: Source is\n"); brt_hex_dump(src, BRT_TEST_BLOCK_SIZE); } memset(dst, 0, BRT_TEST_BLOCK_SIZE); if (verbose > 8) { printk("Before transfer: dest is\n"); brt_hex_dump(dst, BRT_TEST_BLOCK_SIZE); } ret = BTE_UNALIGNED_COPY(__pa(src + src_offset), __pa(dst + dst_offset), len, BTE_NOTIFY); if (ret != BTE_SUCCESS) { printk("brt_test: BTE_UNALIGNED_COPY() error: %d\n", ret); return (1); } /* Check head */ for (i = 0; i < dst_offset; i++) { if ((dst[i] & 0xff) != 0) { err_cnt++; } } /* Check body */ for (i = 0; i < len; i++) { if ((dst[dst_offset + i] & 0xff) != (magic & 0xff)) { err_cnt++; } } /* Check foot */ for (i = (dst_offset + len); i < BRT_TEST_BLOCK_SIZE; i++) { if ((dst[i] & 0xff) != 0) { err_cnt++; } } if ((verbose > 3) || err_cnt) { printk("brt_test: %d errors during basic " "transfer test.\n", err_cnt); brt_hex_dump(dst, BRT_TEST_BLOCK_SIZE); } return (err_cnt);}/* * Dump a block of data to console as hex. */static voidbrt_hex_dump(char *block_to_dump, int block_len){ int i; char fmt_line[128]; char *fmt_eol = fmt_line; for (i = 0; i < block_len; i++) { if (!(i % 16)) { if (i > 0) { printk("%s\n", fmt_line); } sprintf(fmt_line, "0x%lx %05d ", __pa(&block_to_dump[i]), i); fmt_eol = fmt_line; } while (*fmt_eol++) { /* empty */ }; fmt_eol--; sprintf(fmt_eol, "%s%02x", (!(i % 4) ? " " : ""), (block_to_dump[i] & 0xff)); } printk("%s\n", fmt_line);}/*********************************************************************** * Transfer Rate Test. * * This test migrates to each cpu one at a time. This is done to * get a complete view of how each of the bte engines is performing * and help ensure that each virtual interface is being used. * NOTE: All virtual interfaces will not necessarily be used. * * Now that we have migrated to the desired cpu, we transfer from
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -