📄 llsc4.c
字号:
/* * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 2000 Silicon Graphics, Inc. * Copyright (C) 2000 by Jack Steiner (steiner@sgi.com) */#include <linux/config.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/init.h>#include <linux/interrupt.h>#include <linux/smp.h>#include <linux/kernel_stat.h>#include <linux/mm.h>#include <linux/delay.h>#include <linux/string.h>#include <asm/efi.h>#include <asm/page.h>#include <linux/threads.h>extern void bringup_set_led_bits(u8 bits, u8 mask);#include "llsc4.h"#ifdef STANDALONE#include "lock.h"#endif#ifdef INTTESTstatic int inttest=0;#endif/* * Test parameter table for AUTOTEST */typedef struct { int passes; int linecount; int linepad;} autotest_table_t;autotest_table_t autotest_table[] = { {1000000, 2, 0x2b4 }, {1000000, 16, 0, }, {1000000, 16, 4, }, {1000000, 128, 0x44 }, {1000000, 128, 0x84 }, {1000000, 128, 0x200 }, {1000000, 128, 0x204 }, {1000000, 128, 0x2b4 }, {1000000, 2, 8*MB+0x2b4 }, {1000000, 16, 8*MB+0 }, {1000000, 16, 8*MB+4 }, {1000000, 128, 8*MB+0x44 }, {1000000, 128, 8*MB+0x84 }, {1000000, 128, 8*MB+0x200 }, {1000000, 128, 8*MB+0x204 }, {1000000, 128, 8*MB+0x2b4 }, {0}};/* * Array of virtual addresses available for test purposes. */typedef struct { long vstart; long vend; long nextaddr; int wrapcount;} memmap_t;memmap_t memmap[MAXCHUNKS];int memmapx=0;typedef struct { void *addr; long data[16]; long data_fc[16];} capture_line_t;typedef struct { int size; void *blockaddr; void *shadaddr; long blockdata[16]; long shaddata[16]; long blockdata_fc[16]; long shaddata_fc[16]; long synerr;} capture_t;/* * PORTING NOTE: revisit this statement. On hardware we put mbase at 0 and * the rest of the tables have to start at 1MB to skip PROM tables. */#define THREADPRIVATE(t) ((threadprivate_t*)(((long)mbase)+1024*1024+t*((sizeof(threadprivate_t)+511)/512*512)))#define k_capture mbase->sk_capture#define k_go mbase->sk_go#define k_linecount mbase->sk_linecount#define k_passes mbase->sk_passes#define k_napticks mbase->sk_napticks#define k_stop_on_error mbase->sk_stop_on_error#define k_verbose mbase->sk_verbose#define k_threadprivate mbase->sk_threadprivate#define k_blocks mbase->sk_blocks#define k_iter_msg mbase->sk_iter_msg#define k_vv mbase->sk_vv#define k_linepad mbase->sk_linepad#define k_options mbase->sk_options#define k_testnumber mbase->sk_testnumber#define k_currentpass mbase->sk_currentpassstatic long blocks[MAX_LINECOUNT]; /* addresses of data blocks */static control_t *mbase;static vint initialized=0;static unsigned int ran_conf_llsc(int);static int rerr(capture_t *, char *, void *, void *, int, int, int, int, int, int);static void dumpline(void *, char *, char *, void *, void *, int);static int checkstop(int, int, uint);static void spin(int);static void capturedata(capture_t *, uint, void *, void *, int);static int randn(uint max, uint *seed);static uint zrandom (uint *zranseed);static int set_lock(uint *, uint);static int clr_lock(uint *, uint);static void Speedo(void);int autotest_enabled=0;static int autotest_explicit_flush=0;static int llsctest_number=-1;static int errstop_enabled=0;static int fail_enabled=0;static int selective_trigger=0;static int __init autotest_enable(char *str){ autotest_enabled = 1; return 1;}static int __init set_llscxflush(char *str){ autotest_explicit_flush = 1; return 1;}static int __init set_llscselt(char *str){ selective_trigger = 1; return 1;}static int __init set_llsctest(char *str){ llsctest_number = simple_strtol(str, &str, 10); if (llsctest_number < 0 || llsctest_number > 15) llsctest_number = -1; return 1;}static int __init set_llscerrstop(char *str){ errstop_enabled = 1; return 1;}static int __init set_llscfail(char *str){ fail_enabled = 8; return 1;}static void print_params(void){ printk ("********* Enter AUTOTEST facility on master cpu *************\n"); printk (" Test options:\n"); printk (" llsctest=<n>\t%d\tTest number to run (all = -1)\n", llsctest_number); printk (" llscerrstop \t%s\tStop on error\n", errstop_enabled ? "on" : "off"); printk (" llscxflush \t%s\tEnable explicit FC in test\n", autotest_explicit_flush ? "on" : "off"); printk (" llscfail \t%s\tForce a failure to test the trigger & error messages\n", fail_enabled ? "on" : "off"); printk (" llscselt \t%s\tSelective triger on failures\n", selective_trigger ? "on" : "off"); printk ("\n");}__setup("autotest", autotest_enable);__setup("llsctest=", set_llsctest);__setup("llscerrstop", set_llscerrstop);__setup("llscxflush", set_llscxflush);__setup("llscfail", set_llscfail);__setup("llscselt", set_llscselt);extern inline voidflush_buddy(void *p){ long lp; if (autotest_explicit_flush) { lp = (long)p; lp ^= 0x40; asm volatile ("fc %0" :: "r"(lp) : "memory"); ia64_sync_i(); ia64_srlz_d(); }}static intset_lock(uint *lock, uint id){ uint old; flush_buddy(lock); old = cmpxchg_acq(lock, 0, id); return (old == 0);}static intclr_lock(uint *lock, uint id){ uint old; flush_buddy(lock); old = cmpxchg_rel(lock, id, 0); return (old == id);}static voidzero_lock(uint *lock){ flush_buddy(lock); *lock = 0;}/*------------------------------------------------------------------------+| Routine : ran_conf_llsc - ll/sc shared data test || Description: This test checks the coherency of shared data |+------------------------------------------------------------------------*/static unsigned intran_conf_llsc(int thread){ private_t pval; share_t sval, sval2; uint vv, linei, slinei, sharei, pass; long t; lock_t lockpat; share_t *sharecopy; long verbose, napticks, passes, linecount, lcount; dataline_t *linep, *slinep; int s, seed; threadprivate_t *tp; uint iter_msg, iter_msg_i=0; int vv_mask; int correct_errors; int errs=0; int stillbad; capture_t capdata; private_t *privp; share_t *sharep; linecount = k_linecount; napticks = k_napticks; verbose = k_verbose; passes = k_passes; iter_msg = k_iter_msg; seed = (thread + 1) * 647; tp = THREADPRIVATE(thread); vv_mask = (k_vv>>((thread%16)*4)) & 0xf; correct_errors = k_options&0xff; memset (&tp->private, 0, sizeof(tp->private)); memset (&capdata, 0, sizeof(capdata)); for (pass = 1; passes == 0 || pass < passes; pass++) { lockpat = (pass & 0x0fffffff) + (thread <<28); tp->threadpasses = pass; if (checkstop(thread, pass, lockpat)) return 0; iter_msg_i++; if (iter_msg && iter_msg_i > iter_msg) { printk("Thread %d, Pass %d\n", thread, pass); iter_msg_i = 0; } lcount = 0; /* * Select line to perform operations on. */ linei = randn(linecount, &seed); sharei = randn(2, &seed); slinei = (linei + (linecount/2))%linecount; /* I dont like this - fix later */ linep = (dataline_t *)blocks[linei]; slinep = (dataline_t *)blocks[slinei]; if (sharei == 0) sharecopy = &slinep->share0; else sharecopy = &slinep->share1; vv = randn(4, &seed); if ((vv_mask & (1<<vv)) == 0) continue; if (napticks) { t = randn(napticks, &seed); udelay(t); } privp = &linep->private[thread]; sharep = &linep->share[sharei]; switch(vv) { case 0: /* Read and verify private count on line. */ pval = *privp; if (verbose) printk("Line:%3d, Thread:%d:%d. Val: %x\n", linei, thread, vv, tp->private[linei]); if (pval != tp->private[linei]) { capturedata(&capdata, pass, privp, NULL, sizeof(*privp)); stillbad = (*privp != tp->private[linei]); if (rerr(&capdata, "Private count", linep, slinep, thread, pass, linei, tp->private[linei], pval, stillbad)) { return 1; } if (correct_errors) { flush_buddy(privp); tp->private[linei] = *privp; } errs++; } break; case 1: /* Read, verify, and increment private count on line. */ pval = *privp; if (verbose) printk("Line:%3d, Thread:%d:%d. Val: %x\n", linei, thread, vv, tp->private[linei]); if (pval != tp->private[linei]) { capturedata(&capdata, pass, privp, NULL, sizeof(*privp)); stillbad = (*privp != tp->private[linei]); if (rerr(&capdata, "Private count & inc", linep, slinep, thread, pass, linei, tp->private[linei], pval, stillbad)) { return 1; } errs++; } pval++; flush_buddy(privp); *privp = pval; tp->private[linei] = pval; break; case 2: /* Lock line, read and verify shared data. */ if (verbose) printk("Line:%3d, Thread:%d:%d. Val: %x\n", linei, thread, vv, *sharecopy); lcount = 0; while (LOCK(sharei) != 1) { if (checkstop(thread, pass, lockpat)) return 0; if (lcount++>1000000) { capturedata(&capdata, pass, LOCKADDR(sharei), NULL, sizeof(lock_t)); stillbad = (GETLOCK(sharei) != 0); rerr(&capdata, "Shared data lock", linep, slinep, thread, pass, linei, 0, GETLOCK(sharei), stillbad); return 1; } if ((lcount&0x3fff) == 0) udelay(1000); } sval = *sharep; sval2 = *sharecopy; if (pass > 12 && thread == 0 && fail_enabled == 1) sval++; if (sval != sval2) { capturedata(&capdata, pass, sharep, sharecopy, sizeof(*sharecopy)); stillbad = (*sharep != *sharecopy); if (!stillbad && *sharep != sval && *sharecopy == sval2) stillbad = 2; if (rerr(&capdata, "Shared data", linep, slinep, thread, pass, linei, sval2, sval, stillbad)) { return 1; } if (correct_errors) *sharep = *sharecopy; errs++; } if ( (s=UNLOCK(sharei)) != 1) { capturedata(&capdata, pass, LOCKADDR(sharei), NULL, 4); stillbad = (GETLOCK(sharei) != lockpat); if (rerr(&capdata, "Shared data unlock", linep, slinep, thread, pass, linei, lockpat, GETLOCK(sharei), stillbad)) return 1; if (correct_errors) ZEROLOCK(sharei); errs++; } break; case 3: /* Lock line, read and verify shared data, modify shared data. */ if (verbose) printk("Line:%3d, Thread:%d:%d. Val: %x\n", linei, thread, vv, *sharecopy); lcount = 0; while (LOCK(sharei) != 1) { if (checkstop(thread, pass, lockpat)) return 0; if (lcount++>1000000) { capturedata(&capdata, pass, LOCKADDR(sharei), NULL, sizeof(lock_t)); stillbad = (GETLOCK(sharei) != 0); rerr(&capdata, "Shared data lock & inc", linep, slinep, thread, pass, linei, 0, GETLOCK(sharei), stillbad); return 1; } if ((lcount&0x3fff) == 0) udelay(1000); } sval = *sharep; sval2 = *sharecopy; if (sval != sval2) { capturedata(&capdata, pass, sharep, sharecopy, sizeof(*sharecopy)); stillbad = (*sharep != *sharecopy); if (!stillbad && *sharep != sval && *sharecopy == sval2) stillbad = 2; if (rerr(&capdata, "Shared data & inc", linep, slinep, thread, pass, linei, sval2, sval, stillbad)) { return 1; } errs++; } flush_buddy(sharep); *sharep = lockpat; flush_buddy(sharecopy); *sharecopy = lockpat; if ( (s=UNLOCK(sharei)) != 1) { capturedata(&capdata, pass, LOCKADDR(sharei), NULL, 4); stillbad = (GETLOCK(sharei) != lockpat); if (rerr(&capdata, "Shared data & inc unlock", linep, slinep, thread, pass, linei, thread, GETLOCK(sharei), stillbad)) return 1; if (correct_errors) ZEROLOCK(sharei); errs++; } break; } } return (errs > 0);}static voidtrigger_la(long val){ long *p; p = (long*)0xc0000a0001000020L; /* PI_CPU_NUM */ *p = val;}static longgetsynerr(void){ long err, *errp; errp = (long*)0xc0000e0000000340L; /* SYN_ERR */ err = *errp; if (err) *errp = -1L; return (err & ~0x60);}static intrerr(capture_t *cap, char *msg, void *lp, void *slp, int thread, int pass, int linei, int exp, int found, int stillbad){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -