OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [cris/] [kernel/] [debug.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * arch/cris/kernel/debug.c
3
 * Various debug routines:
4
 * o Logging of interrupt enabling/disabling. /proc/debug_interrupt
5
 *   gives result and enables logging when read.
6
 *
7
 * Copyright (C) 2003 Axis Communications AB
8
 */
9
 
10
#include <linux/config.h>
11
#include <asm/system.h>
12
#include <linux/init.h>
13
#include <linux/proc_fs.h>
14
#include <asm/svinto.h>
15
 
16
#ifdef CONFIG_ETRAX_DEBUG_INTERRUPT
17
#define LOG_INT_SIZE 8192
18
#define DEBUG_INT_PROC_FILE "debug_interrupt"
19
#define LOG_INT_SHOW_MIN_USEC 45000
20
 
21
/* These are global and can be used to trig certain events. */
22
int log_int_pos = 0;
23
int log_int_size = LOG_INT_SIZE;
24
int log_int_trig0_pos = 0;
25
int log_int_trig1_pos = 0;
26
 
27
int log_int_enable = 0; /* Enabled every read of /proc/debug_interrupt */
28
 
29
struct log_int_struct
30
{
31
  unsigned long pc;
32
  unsigned long ev_timer_data;
33
};
34
 
35
static struct log_int_struct log_ints[LOG_INT_SIZE];
36
 
37
//static unsigned long prev_log_int_t = 0;
38
static unsigned long prev_logged_ccr = 0;
39
static unsigned long prev_ei_timer_data = 0;
40
static unsigned long prev_di_timer_data = 0;
41
 
42
#define CCR_EI_BIT 5
43
enum {
44
        INT_OLD_MASK = 0x01, INT_OLD_BIT = 0,
45
        INT_NEW_MASK = 0x02, INT_NEW_BIT = 1,
46
        INT_EI_CHANGE_MASK = 0x04, INT_EI_CHANGE_BIT = 2,
47
        INT_ACTION_RESTORE = 0x08, INT_ACTION_RESTORE_BIT = 3,
48
        INT_ACTION_MISSED = 0x10, INT_ACTION_MISSED_BIT = 4,
49
        INT_ACTION_LONG = 0x20,  INT_ACTION_LONG_BIT = 5,
50
 
51
        INT_OLD_EI = INT_OLD_MASK, INT_OLD_EI_BIT = INT_OLD_BIT,
52
        INT_NEW_EI = INT_NEW_MASK, INT_NEW_EI_BIT = INT_NEW_BIT,
53
        INT_EV_DI = INT_OLD_EI | INT_EI_CHANGE_MASK,
54
        INT_EV_NOP_DI = 0,
55
        INT_EV_EI = INT_NEW_EI | INT_EI_CHANGE_MASK,
56
        INT_EV_NOP_EI = INT_OLD_EI | INT_NEW_EI,
57
        INT_EV_RESTORE_DI= INT_EV_DI | INT_EI_CHANGE_MASK | INT_ACTION_RESTORE,
58
        INT_EV_RESTORE_EI= INT_EV_EI | INT_EI_CHANGE_MASK | INT_ACTION_RESTORE,
59
        INT_EV_RESTORE_NOP_DI = INT_EV_NOP_DI | INT_ACTION_RESTORE,
60
        INT_EV_RESTORE_NOP_EI = INT_EV_NOP_EI | INT_ACTION_RESTORE,
61
};
62
 
63
void log_int(unsigned long pc, unsigned long curr_ccr, unsigned long next_ccr)
64
{
65
        unsigned long t;
66
        int ev;
67
        static int no_change_cnt = 0;
68
 
69
        /* Just disable interrupts without logging here,
70
         * the caller will either do ei, di or restore
71
         */
72
        __asm__ __volatile__ ("di" : : :"memory");
73
        t = *R_TIMER_DATA;
74
 
75
        if (curr_ccr & CCR_EI_MASK) {
76
                prev_ei_timer_data = t;
77
                ev = INT_OLD_EI;
78
        } else {
79
                prev_di_timer_data = t;
80
                if ( (((prev_ei_timer_data >> 8) & 0x000000FF) -
81
                      ((prev_di_timer_data >> 8) & 0x000000FF)) & ~0x03)
82
                                            ev = INT_ACTION_LONG;
83
                else
84
                        ev = 0;
85
        }
86
        if ((curr_ccr ^ prev_logged_ccr) & CCR_EI_MASK)
87
                ev |= INT_ACTION_MISSED;
88
        if (next_ccr & CCR_EI_MASK)
89
                ev |= INT_NEW_EI;
90
        if ((curr_ccr ^ next_ccr) & CCR_EI_MASK) {
91
                ev |= INT_EI_CHANGE_MASK;
92
                no_change_cnt = 0;
93
        } else
94
                no_change_cnt++;
95
 
96
        prev_logged_ccr = next_ccr;
97
 
98
        if (log_int_enable &&
99
            ((ev & (INT_EI_CHANGE_MASK | INT_ACTION_MISSED | INT_ACTION_LONG))
100
             || (no_change_cnt < 40)) &&
101
            log_int_pos < LOG_INT_SIZE) {
102
                int i;
103
                i = log_int_pos;
104
                log_int_pos++;
105
                log_ints[i].pc = pc;
106
                log_ints[i].ev_timer_data = (t & 0x00FFFFFF) |
107
                        ((ev & 0xFF) << 24);
108
 
109
        }
110
//      __asm__ __volatile__ ("move %0,$ccr" : : "rm" (curr_ccr) : "memory");
111
}
112
void log_int_di(void)
113
{
114
  unsigned long pc;
115
  unsigned long flags;
116
  __asm__ __volatile__ ("move $srp,%0" : "=rm" (pc) : : "memory");
117
  __asm__ __volatile__ ("move $ccr,%0" : "=rm" (flags) : : "memory");
118
  log_int(pc, flags, 0);
119
}
120
 
121
void log_int_ei(void)
122
{
123
  unsigned long pc;
124
  unsigned long flags;
125
  __asm__ __volatile__ ("move $srp,%0" : "=rm" (pc) : : "memory");
126
  __asm__ __volatile__ ("move $ccr,%0" : "=rm" (flags) : : "memory");
127
  log_int(pc, flags, CCR_EI_MASK);
128
}
129
 
130
 
131
static int log_int_read_proc(char *page, char **start, off_t off, int count,
132
                             int *eof, void *data)
133
{
134
        int i, len = 0;
135
        off_t   begin = 0;
136
        int j, t0, t1, t, thigh, tlow, tdi0;
137
        int di0, ei1;
138
        len += sprintf(page + len, "trig0: %i trig1: %i\n", log_int_trig0_pos, log_int_trig1_pos);
139
        for (i = 0; i < log_int_pos-1; i++) {
140
 
141
                if (((log_ints[i].ev_timer_data >> 24) & INT_NEW_EI)) {
142
                        di0 = i;
143
                        while (di0 < log_int_pos-1 && (((log_ints[di0].ev_timer_data >> 24) & INT_NEW_EI)))
144
                                di0++;
145
                        ei1 = di0+1;
146
                        while (ei1 < log_int_pos-1 && (((log_ints[ei1].ev_timer_data >> 24) & INT_NEW_EI) == 0))
147
                                ei1++;
148
                        thigh = timer_data_to_ns(log_ints[ei1].ev_timer_data);
149
                        tlow = timer_data_to_ns(log_ints[di0].ev_timer_data);
150
                        tdi0 = timer_data_to_ns(log_ints[di0].ev_timer_data);
151
 
152
                        t = thigh-tlow;
153
                        j = di0-1;
154
                        if ((t > LOG_INT_SHOW_MIN_USEC) || (log_int_trig0_pos-30 < j && j < log_int_trig1_pos+30)) {
155
 
156
                        for (; j <= ei1; j++) {
157
                                t0 = ((log_ints[j+1].ev_timer_data & 0xFF) -
158
                                      (log_ints[j].ev_timer_data & 0xFF));
159
                                t1 = (((log_ints[j+1].ev_timer_data >> 8) & 0xFF) -
160
                                      ((log_ints[j].ev_timer_data >> 8) & 0xFF));
161
                                if (t1 == 0 || t1 == 1) {
162
                                        if (t0 < 0)
163
                                                t0 += 256;
164
                                } else {
165
                                        if (t1 < 0)
166
                                                t1 += 256;
167
                                }
168
                                thigh = timer_data_to_ns(log_ints[j+1].ev_timer_data);
169
                                tlow = timer_data_to_ns(log_ints[j].ev_timer_data);
170
                                t = thigh-tlow;
171
                                len += sprintf(page + len, "%4i PC %08lX-%08lX %08lX-%08lX %s high %i in %-6i ns %-7i to %-7i = %-5i ns, from first di %i ns %s\n",
172
                                               j, log_ints[j].pc, log_ints[j+1].pc,
173
                                               log_ints[j].ev_timer_data, log_ints[j+1].ev_timer_data,
174
                                               ((log_ints[j].ev_timer_data >> 24) & INT_NEW_EI)!= 0?"ei":"di", t1, t,
175
                                               tlow, thigh, thigh-tlow, thigh-tdi0,
176
                                               j==log_int_trig0_pos?"TRIG0":(j==log_int_trig1_pos?"TRIG1":""));
177
                                if (len+begin > off+count)
178
                                        goto done;
179
                                if (len+begin < off) {
180
                                        begin += len;
181
                                        len = 0;
182
                                }
183
                        }
184
 
185
                        len += sprintf(page + len,"\n");
186
                        i = ei1-2;
187
                        }
188
 
189
                }
190
 
191
        }
192
        log_int_enable = 1;
193
        log_int_pos = 0;
194
        log_int_trig0_pos = 0;
195
        log_int_trig1_pos = 0;
196
        *eof = 1;
197
done:
198
        if (off >= len+begin)
199
                return 0;
200
        *start = page + (off-begin);
201
        return ((count < begin+len-off) ? count : begin+len-off);
202
}
203
 
204
static int __init
205
log_int_init(void)
206
{
207
        create_proc_read_entry (DEBUG_INT_PROC_FILE, 0, 0, log_int_read_proc, NULL);
208
        printk(KERN_INFO "/proc/" DEBUG_INT_PROC_FILE " size %i.\r\n",
209
               LOG_INT_SIZE);
210
        return 0;
211
}
212
module_init(log_int_init);
213
#endif /* CONFIG_ETRAX_DEBUG_INTERRUPT */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.