/*********************************************************************** * * Copyright (C) 2000 Monta Vista Software Inc. * * Author : Jun Sun, jsun@mvista.com * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. **********************************************************************/ #include #include #include #include #include /****************** CONFIG ****************/ #define NUM_LOG_ENTRY 8 #define CLOCK_FREQUENCY 300 /* cycles per microsecond */ #define SYSCALL_NUMBER 191 /****************** END OF CONFIG ***************/ #define CMD_EXIT 0 #define CMD_DISPLAY 1 #define CMD_START 2 #define CMD_STOP 3 #define CMD_CONTINUE 4 #define CMD_SET_RANGE 5 #define CMD_LAST 6 struct IntrData { /* count interrupt and iret */ int breakCount; /* the test name */ const char * testName; /* flag to control logging */ unsigned logFlag; /* 0 - no logging; 1 - logging */ /* panic flag - set to 1 if something is realy wrong */ unsigned panicFlag; /* for synchro between start and end */ unsigned syncFlag; /* we only log interrupts within certain range */ unsigned rangeLow; unsigned rangeHigh; /* count the total number interrupts and intrs in range*/ unsigned numIntrs; unsigned numInRangeIntrs; /* error accounting */ unsigned skipSti; unsigned skipCli; unsigned syncStiError; unsigned syncCliError; unsigned stiBreakError; unsigned restoreSti; unsigned restoreCli; struct { /* worst blocking time */ unsigned blockingTime; const char * startFileName; unsigned startFileLine; unsigned startCount; const char *endFileName; unsigned endFileLine; unsigned endCount; } count[NUM_LOG_ENTRY]; }; unsigned pData; struct IntrData data; int kmem; char buf[81]; unsigned int GetInt(const char *prompt) { unsigned int i; printf("%s", prompt); scanf("%d", &i); return i; } unsigned int GetHex(const char *prompt) { unsigned int i; printf("%s", prompt); scanf("%x", &i); return i; } unsigned GetCommand() { for(;;) { unsigned cmd; printf("\n"); printf("Command Menu \n"); printf("=============\n"); printf("0-Exit 1-Display 2-Start logging 3-Stop logging 4-Continue "); printf("5-Set range\n"); printf("\n"); printf("Your choice : "); scanf("%u", &cmd); if ((cmd >= 0) && (cmd < CMD_LAST)) { return cmd; } else { printf("Invalid choice!!!!\n\n"); } } } unsigned GetKmemInt(unsigned offset) { off_t seekError; ssize_t size; unsigned num=0; assert((offset & 3) == 0); seekError = lseek(kmem, offset, SEEK_SET); assert(seekError != (off_t)-1); size = read(kmem, &num, sizeof(num)); assert(sizeof(num) == 4); assert(size == 4); return num; } char * GetKmemString(unsigned offset) { off_t seekError; ssize_t size; buf[80]=0; buf[0]=0; if (offset == 0) return buf; seekError = lseek(kmem, offset, SEEK_SET); assert(seekError != (off_t)-1); size = read(kmem, buf, 80); assert(size == 80); return buf; } void GetKmemBlock(unsigned offset, void * buf, unsigned bufSize) { off_t seekError; ssize_t size; seekError = lseek(kmem, offset, SEEK_SET); assert(seekError != (off_t)-1); size = read(kmem, buf, bufSize); assert(size == bufSize); } void SetKmemBlock(unsigned offset, void *buf, unsigned bufSize) { off_t seekError; ssize_t size; seekError = lseek(kmem, offset, SEEK_SET); assert(seekError != (off_t)-1); size = write(kmem, buf, bufSize); assert(size == bufSize); } void SetKmemInt(unsigned offset, unsigned x) { off_t seekError; ssize_t size; seekError = lseek(kmem, offset, SEEK_SET); assert(seekError != (off_t)-1); size = write(kmem, &x, sizeof(x)); assert(size == sizeof(x)); } void Display() { unsigned i; GetKmemBlock(pData, &data, sizeof(data)); printf("%s : \n", GetKmemString((unsigned)data.testName)); printf("breakCount : %7d\n", data.breakCount); printf("logFlag : %d ", data.logFlag); printf("panicFlag : %d ", data.panicFlag); printf("syncFlag : %d\n", data.syncFlag); printf("range : [%u(0x%x) : %u(0x%x)]\n", data.rangeLow, data.rangeLow, data.rangeHigh, data.rangeHigh); printf("numIntrs : %u\n", data.numIntrs); printf("numInRangeInts: %u\n", data.numInRangeIntrs); printf("skipSti skipCli syncSti syncCli stiBreak restSti restCli\n"); printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\t\n", data.skipSti, data.skipCli, data.syncStiError, data.syncCliError, data.stiBreakError, data.restoreSti, data.restoreCli); for (i=0; i< NUM_LOG_ENTRY; i++) { printf("log entry : %d\n", i); printf("\tblockingTime : %u (%u us)\n", data.count[i].blockingTime, data.count[i].blockingTime / CLOCK_FREQUENCY); printf("\tstartFileName : %-30s Line :", GetKmemString((unsigned)data.count[i].startFileName)); printf(" %-5u\n", data.count[i].startFileLine); /* printf("\tstartCount : %u\n", data.count[i].startCount);*/ printf("\tendFileName : %-30s Line :", GetKmemString((unsigned)data.count[i].endFileName)); printf(" %-5u\n", data.count[i].endFileLine); /* printf("\tendCount : %u\n", data.count[i].endCount);*/ } printf("\n"); } void StartLogging() { unsigned i; /* init first */ data.breakCount = 0; data.logFlag = 0; data.panicFlag = 0; data.syncFlag = 0; data.numIntrs = 0; data.numInRangeIntrs = 0; data.skipSti = data.skipCli = data.syncStiError = data.syncCliError = data.stiBreakError = data.restoreSti = data.restoreCli = 0; for (i=0; i< NUM_LOG_ENTRY; i++) { data.count[i].blockingTime = 0; data.count[i].startFileName = 0; data.count[i].startFileLine = 0; data.count[i].startCount = 0; data.count[i].endFileName = 0; data.count[i].endFileLine = 0; data.count[i].endCount = 0; } SetKmemBlock(pData, &data, sizeof(data)); /* turn the logging flag */ SetKmemInt(pData + ((unsigned)&data.logFlag - (unsigned)&data), 1); } void EndLogging() { /* turn the logging flag */ SetKmemInt(pData + ((unsigned)&data.logFlag - (unsigned)&data), 0); } void ContinueLoggin() { /* turn the logging flag */ SetKmemInt(pData + ((unsigned)&data.logFlag - (unsigned)&data), 1); } void SetRange() { data.rangeLow = GetInt("Input lower bound (decimal) : "); printf("\tlower bound is %u(0x%x)\n", data.rangeLow, data.rangeLow); data.rangeHigh = GetInt("Input upper bound (decimal) : "); printf("\tupper bound is %u(0x%x)\n", data.rangeHigh, data.rangeHigh); SetKmemInt(pData + ((unsigned)&data.rangeLow - (unsigned)&data), data.rangeLow); SetKmemInt(pData + ((unsigned)&data.rangeHigh - (unsigned)&data), data.rangeHigh); } main() { unsigned int cmd; unsigned long offset; kmem = open("/dev/kmem", O_RDWR); assert(kmem > 0); if (syscall(SYSCALL_NUMBER, &pData) != 0) { printf("failed to get jsunData address through syscall 191!\n"); pData = GetHex("Input manually the address of jsunData : "); } GetKmemBlock(pData, &data, sizeof(data)); for(;;) { cmd = GetCommand(); switch (cmd) { case CMD_DISPLAY: Display(); break; case CMD_START: StartLogging(); break; case CMD_STOP: EndLogging(); break; case CMD_CONTINUE: ContinueLoggin(); break; case CMD_SET_RANGE: SetRange(); break; case CMD_EXIT: close(kmem); return; default: assert(0 == 1); } } }