summaryrefslogtreecommitdiff
path: root/msr.h
blob: bf929737d1b3d452ab871ff2becaf006aadb9435 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
 * Author: Andreas Herrmann <andreas.herrmann3@amd.com>
 *
 * Copyright (C) 2008 Advanced Micro Devices, Inc.
 *
 * Licensed under the terms of the GNU GENERAL PUBLIC LICENSE version 2.
 * See file COPYING for details.
 */

#ifndef _msr_h
#define _msr_h


#define _RANGE(name, args...) \
unsigned char name##_range[] = { args }

#define _NAMES(name, args...) \
const char *name##_spec[] = { args }

#define _SPEC(addr, name, desc, prefix) \
{addr, #name, desc, prefix##name##_range, prefix##name##_spec}

#define MSR_MAX_LEN 32
struct reg_spec {
	unsigned int address;
	const char *name;
	const char *desc;
	unsigned char *bits;
	const char **spec;
};

static struct reg_spec *get_reg_spec(uint32_t msr, struct reg_spec *table)
{
	int i;
	for (i = 0; table[i].name; i++)
		if (msr == table[i].address)
			return &(table[i]);
	return NULL;
}

static uint32_t get_reg_addr(const char *name, struct reg_spec *table)
{
	int i;

	for (i = 0; table[i].name; i++)
		if (strcmp(name, table[i].name) == 0)
			return table[i].address;

	return -1;
}

static const char *get_reg_name(uint32_t reg, struct reg_spec *table)
{
	struct reg_spec *d;
	const char *s = NULL;

	d = get_reg_spec(reg, table);
	if (d)
		s = d->name;

	return s;
}

static void print_reg_bits(struct reg_spec *reg, uint64_t val, uint8_t list,
			   uint8_t verb)
{
	unsigned char *r;
	const char **d;
	int i, j, k;
	int first, any;
	uint64_t t;
	const char *s;

	if (!reg || !reg->bits || !reg->spec)
		return;

	any = 0;
	first = 1;
	r = reg->bits;
	d = reg->spec;
	for (i = 0, j = 0; r[i]; i++, j = k + 1){
		k = j + r[i] - 1;
		if (d[i] == 0) {
			if (verb == 2 || verb == 4)
				s = "res";
			else /* hide reserved fields */
				continue; 
		} else
			s = d[i];

		if (verb > 2)
			fprintf(stdout, "\n  ");
		else
			fprintf(stdout, "%s", first ? " (" : ",  ");

		if (list)
			printf("%d-%d:%s", j, k, s);
		else {
			if (r[i] == 64)
				t = val;
			else
				t = (val >> j) & ((1ULL<<r[i]) - 1);

			fprintf(stdout, "%s=%#llx", s, (unsigned long long) t);
		}
		first = 0;
		any = 1;
	}
	if (any && verb <= 2)
		fprintf(stdout, ")");
}

static void print_reg(struct reg_spec *reg, uint64_t val, uint8_t list,
		      uint8_t all, uint8_t verb)
{
	if (list) {
		if ((verb == 0 || verb == 3 || verb ==4) && reg->desc)
			fprintf(stdout, "%-*s: 0x%8.8x; %s",  all ? 20 : 0,
				reg->name, reg->address, reg->desc);
		else
			fprintf(stdout, "%-*s: 0x%8.8x",  all ? 20 : 0,
				reg->name, reg->address);

	} else
		fprintf(stdout, "%-*s = 0x%16.16llx", all ? 20 : 0,
			reg->name, (unsigned long long) val);

	if (verb)
		print_reg_bits(reg, val, list, verb);

	fprintf(stdout, "\n");
}

#endif /* _msr_h */