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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [arch/] [s390/] [appldata/] [appldata_os.c] - Blame information for rev 63

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 63 marcus.erl
/*
2
 * arch/s390/appldata/appldata_os.c
3
 *
4
 * Data gathering module for Linux-VM Monitor Stream, Stage 1.
5
 * Collects misc. OS related data (CPU utilization, running processes).
6
 *
7
 * Copyright (C) 2003,2006 IBM Corporation, IBM Deutschland Entwicklung GmbH.
8
 *
9
 * Author: Gerald Schaefer <gerald.schaefer@de.ibm.com>
10
 */
11
 
12
#include <linux/module.h>
13
#include <linux/init.h>
14
#include <linux/slab.h>
15
#include <linux/errno.h>
16
#include <linux/kernel_stat.h>
17
#include <linux/netdevice.h>
18
#include <linux/sched.h>
19
#include <asm/appldata.h>
20
#include <asm/smp.h>
21
 
22
#include "appldata.h"
23
 
24
 
25
#define MY_PRINT_NAME   "appldata_os"           /* for debug messages, etc. */
26
#define LOAD_INT(x) ((x) >> FSHIFT)
27
#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
28
 
29
/*
30
 * OS data
31
 *
32
 * This is accessed as binary data by z/VM. If changes to it can't be avoided,
33
 * the structure version (product ID, see appldata_base.c) needs to be changed
34
 * as well and all documentation and z/VM applications using it must be
35
 * updated.
36
 *
37
 * The record layout is documented in the Linux for zSeries Device Drivers
38
 * book:
39
 * http://oss.software.ibm.com/developerworks/opensource/linux390/index.shtml
40
 */
41
struct appldata_os_per_cpu {
42
        u32 per_cpu_user;       /* timer ticks spent in user mode   */
43
        u32 per_cpu_nice;       /* ... spent with modified priority */
44
        u32 per_cpu_system;     /* ... spent in kernel mode         */
45
        u32 per_cpu_idle;       /* ... spent in idle mode           */
46
 
47
        /* New in 2.6 */
48
        u32 per_cpu_irq;        /* ... spent in interrupts          */
49
        u32 per_cpu_softirq;    /* ... spent in softirqs            */
50
        u32 per_cpu_iowait;     /* ... spent while waiting for I/O  */
51
 
52
        /* New in modification level 01 */
53
        u32 per_cpu_steal;      /* ... stolen by hypervisor         */
54
        u32 cpu_id;             /* number of this CPU               */
55
} __attribute__((packed));
56
 
57
struct appldata_os_data {
58
        u64 timestamp;
59
        u32 sync_count_1;       /* after VM collected the record data, */
60
        u32 sync_count_2;       /* sync_count_1 and sync_count_2 should be the
61
                                   same. If not, the record has been updated on
62
                                   the Linux side while VM was collecting the
63
                                   (possibly corrupt) data */
64
 
65
        u32 nr_cpus;            /* number of (virtual) CPUs        */
66
        u32 per_cpu_size;       /* size of the per-cpu data struct */
67
        u32 cpu_offset;         /* offset of the first per-cpu data struct */
68
 
69
        u32 nr_running;         /* number of runnable threads      */
70
        u32 nr_threads;         /* number of threads               */
71
        u32 avenrun[3];         /* average nr. of running processes during */
72
                                /* the last 1, 5 and 15 minutes */
73
 
74
        /* New in 2.6 */
75
        u32 nr_iowait;          /* number of blocked threads
76
                                   (waiting for I/O)               */
77
 
78
        /* per cpu data */
79
        struct appldata_os_per_cpu os_cpu[0];
80
} __attribute__((packed));
81
 
82
static struct appldata_os_data *appldata_os_data;
83
 
84
static struct appldata_ops ops = {
85
        .name      = "os",
86
        .record_nr = APPLDATA_RECORD_OS_ID,
87
        .owner     = THIS_MODULE,
88
        .mod_lvl   = {0xF0, 0xF1},              /* EBCDIC "01" */
89
};
90
 
91
 
92
static inline void appldata_print_debug(struct appldata_os_data *os_data)
93
{
94
        int a0, a1, a2, i;
95
 
96
        P_DEBUG("--- OS - RECORD ---\n");
97
        P_DEBUG("nr_threads   = %u\n", os_data->nr_threads);
98
        P_DEBUG("nr_running   = %u\n", os_data->nr_running);
99
        P_DEBUG("nr_iowait    = %u\n", os_data->nr_iowait);
100
        P_DEBUG("avenrun(int) = %8x / %8x / %8x\n", os_data->avenrun[0],
101
                os_data->avenrun[1], os_data->avenrun[2]);
102
        a0 = os_data->avenrun[0];
103
        a1 = os_data->avenrun[1];
104
        a2 = os_data->avenrun[2];
105
        P_DEBUG("avenrun(float) = %d.%02d / %d.%02d / %d.%02d\n",
106
                LOAD_INT(a0), LOAD_FRAC(a0), LOAD_INT(a1), LOAD_FRAC(a1),
107
                LOAD_INT(a2), LOAD_FRAC(a2));
108
 
109
        P_DEBUG("nr_cpus = %u\n", os_data->nr_cpus);
110
        for (i = 0; i < os_data->nr_cpus; i++) {
111
                P_DEBUG("cpu%u : user = %u, nice = %u, system = %u, "
112
                        "idle = %u, irq = %u, softirq = %u, iowait = %u, "
113
                        "steal = %u\n",
114
                                os_data->os_cpu[i].cpu_id,
115
                                os_data->os_cpu[i].per_cpu_user,
116
                                os_data->os_cpu[i].per_cpu_nice,
117
                                os_data->os_cpu[i].per_cpu_system,
118
                                os_data->os_cpu[i].per_cpu_idle,
119
                                os_data->os_cpu[i].per_cpu_irq,
120
                                os_data->os_cpu[i].per_cpu_softirq,
121
                                os_data->os_cpu[i].per_cpu_iowait,
122
                                os_data->os_cpu[i].per_cpu_steal);
123
        }
124
 
125
        P_DEBUG("sync_count_1 = %u\n", os_data->sync_count_1);
126
        P_DEBUG("sync_count_2 = %u\n", os_data->sync_count_2);
127
        P_DEBUG("timestamp    = %lX\n", os_data->timestamp);
128
}
129
 
130
/*
131
 * appldata_get_os_data()
132
 *
133
 * gather OS data
134
 */
135
static void appldata_get_os_data(void *data)
136
{
137
        int i, j, rc;
138
        struct appldata_os_data *os_data;
139
        unsigned int new_size;
140
 
141
        os_data = data;
142
        os_data->sync_count_1++;
143
 
144
        os_data->nr_threads = nr_threads;
145
        os_data->nr_running = nr_running();
146
        os_data->nr_iowait  = nr_iowait();
147
        os_data->avenrun[0] = avenrun[0] + (FIXED_1/200);
148
        os_data->avenrun[1] = avenrun[1] + (FIXED_1/200);
149
        os_data->avenrun[2] = avenrun[2] + (FIXED_1/200);
150
 
151
        j = 0;
152
        for_each_online_cpu(i) {
153
                os_data->os_cpu[j].per_cpu_user =
154
                        cputime_to_jiffies(kstat_cpu(i).cpustat.user);
155
                os_data->os_cpu[j].per_cpu_nice =
156
                        cputime_to_jiffies(kstat_cpu(i).cpustat.nice);
157
                os_data->os_cpu[j].per_cpu_system =
158
                        cputime_to_jiffies(kstat_cpu(i).cpustat.system);
159
                os_data->os_cpu[j].per_cpu_idle =
160
                        cputime_to_jiffies(kstat_cpu(i).cpustat.idle);
161
                os_data->os_cpu[j].per_cpu_irq =
162
                        cputime_to_jiffies(kstat_cpu(i).cpustat.irq);
163
                os_data->os_cpu[j].per_cpu_softirq =
164
                        cputime_to_jiffies(kstat_cpu(i).cpustat.softirq);
165
                os_data->os_cpu[j].per_cpu_iowait =
166
                        cputime_to_jiffies(kstat_cpu(i).cpustat.iowait);
167
                os_data->os_cpu[j].per_cpu_steal =
168
                        cputime_to_jiffies(kstat_cpu(i).cpustat.steal);
169
                os_data->os_cpu[j].cpu_id = i;
170
                j++;
171
        }
172
 
173
        os_data->nr_cpus = j;
174
 
175
        new_size = sizeof(struct appldata_os_data) +
176
                   (os_data->nr_cpus * sizeof(struct appldata_os_per_cpu));
177
        if (ops.size != new_size) {
178
                if (ops.active) {
179
                        rc = appldata_diag(APPLDATA_RECORD_OS_ID,
180
                                           APPLDATA_START_INTERVAL_REC,
181
                                           (unsigned long) ops.data, new_size,
182
                                           ops.mod_lvl);
183
                        if (rc != 0) {
184
                                P_ERROR("os: START NEW DIAG 0xDC failed, "
185
                                        "return code: %d, new size = %i\n", rc,
186
                                        new_size);
187
                                P_INFO("os: stopping old record now\n");
188
                        } else
189
                                P_INFO("os: new record size = %i\n", new_size);
190
 
191
                        rc = appldata_diag(APPLDATA_RECORD_OS_ID,
192
                                           APPLDATA_STOP_REC,
193
                                           (unsigned long) ops.data, ops.size,
194
                                           ops.mod_lvl);
195
                        if (rc != 0)
196
                                P_ERROR("os: STOP OLD DIAG 0xDC failed, "
197
                                        "return code: %d, old size = %i\n", rc,
198
                                        ops.size);
199
                        else
200
                                P_INFO("os: old record size = %i stopped\n",
201
                                        ops.size);
202
                }
203
                ops.size = new_size;
204
        }
205
        os_data->timestamp = get_clock();
206
        os_data->sync_count_2++;
207
#ifdef APPLDATA_DEBUG
208
        appldata_print_debug(os_data);
209
#endif
210
}
211
 
212
 
213
/*
214
 * appldata_os_init()
215
 *
216
 * init data, register ops
217
 */
218
static int __init appldata_os_init(void)
219
{
220
        int rc, max_size;
221
 
222
        max_size = sizeof(struct appldata_os_data) +
223
                   (NR_CPUS * sizeof(struct appldata_os_per_cpu));
224
        if (max_size > APPLDATA_MAX_REC_SIZE) {
225
                P_ERROR("Max. size of OS record = %i, bigger than maximum "
226
                        "record size (%i)\n", max_size, APPLDATA_MAX_REC_SIZE);
227
                rc = -ENOMEM;
228
                goto out;
229
        }
230
        P_DEBUG("max. sizeof(os) = %i, sizeof(os_cpu) = %lu\n", max_size,
231
                sizeof(struct appldata_os_per_cpu));
232
 
233
        appldata_os_data = kzalloc(max_size, GFP_DMA);
234
        if (appldata_os_data == NULL) {
235
                P_ERROR("No memory for %s!\n", ops.name);
236
                rc = -ENOMEM;
237
                goto out;
238
        }
239
 
240
        appldata_os_data->per_cpu_size = sizeof(struct appldata_os_per_cpu);
241
        appldata_os_data->cpu_offset   = offsetof(struct appldata_os_data,
242
                                                        os_cpu);
243
        P_DEBUG("cpu offset = %u\n", appldata_os_data->cpu_offset);
244
 
245
        ops.data = appldata_os_data;
246
        ops.callback  = &appldata_get_os_data;
247
        rc = appldata_register_ops(&ops);
248
        if (rc != 0) {
249
                P_ERROR("Error registering ops, rc = %i\n", rc);
250
                kfree(appldata_os_data);
251
        } else {
252
                P_DEBUG("%s-ops registered!\n", ops.name);
253
        }
254
out:
255
        return rc;
256
}
257
 
258
/*
259
 * appldata_os_exit()
260
 *
261
 * unregister ops
262
 */
263
static void __exit appldata_os_exit(void)
264
{
265
        appldata_unregister_ops(&ops);
266
        kfree(appldata_os_data);
267
        P_DEBUG("%s-ops unregistered!\n", ops.name);
268
}
269
 
270
 
271
module_init(appldata_os_init);
272
module_exit(appldata_os_exit);
273
 
274
MODULE_LICENSE("GPL");
275
MODULE_AUTHOR("Gerald Schaefer");
276
MODULE_DESCRIPTION("Linux-VM Monitor Stream, OS statistics");

powered by: WebSVN 2.1.0

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