summaryrefslogtreecommitdiffstats
path: root/libpdbg/target.h
blob: 04897ed2e05e6db7f1abdcdcd6ddf9b77618028b (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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
/* Copyright 2016 IBM Corp.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * 	http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef __TARGET_H
#define __TARGET_H

#include <stdint.h>
#include <ccan/list/list.h>
#include <ccan/str/str.h>
#include <ccan/container_of/container_of.h>
#include <ccan/short_types/short_types.h>
#include "compiler.h"
#include "libpdbg.h"

enum chip_type {CHIP_UNKNOWN, CHIP_P8, CHIP_P8NV, CHIP_P9};

struct pdbg_target_class {
	char *name;
	struct list_head targets;
	struct list_node class_head_link;
};

struct pdbg_target {
	char *name;
	char *compatible;
	char *class;
	int (*probe)(struct pdbg_target *target);
	void (*release)(struct pdbg_target *target);
	uint64_t (*translate)(struct pdbg_target *target, uint64_t addr);
	int index;
	enum pdbg_target_status status;
	const char *dn_name;
	struct list_node list;
	struct list_head properties;
	struct list_head children;
	struct pdbg_target *parent;
	u32 phandle;
	bool probed;
	struct list_node class_link;
	void *priv;
};

struct pdbg_target *require_target_parent(struct pdbg_target *target);
struct pdbg_target_class *find_target_class(const char *name);
struct pdbg_target_class *require_target_class(const char *name);
struct pdbg_target_class *get_target_class(const char *name);
bool pdbg_target_is_class(struct pdbg_target *target, const char *class);

/* This works and should be safe because struct pdbg_target is guaranteed to be
 * the first member of the specialised type (see the DECLARE_HW_UNIT definition
 * below). I'm not sure how sane it is though. Probably not very but it does
 * remove a bunch of tedious container_of() typing */
#define translate_cast(x) (uint64_t (*)(struct pdbg_target *, uint64_t)) (x)

extern struct list_head empty_list;
extern struct list_head target_classes;

#define for_each_class_target(class_name, target)			\
	list_for_each((find_target_class(class_name) ? &require_target_class(class_name)->targets : &empty_list), target, class_link)

#define for_each_target_class(target_class)			\
	list_for_each(&target_classes, target_class, class_head_link)

struct hw_unit_info {
	void *hw_unit;
	size_t size;
};
struct hw_unit_info *find_compatible_target(const char *compat);

/* We can't pack the structs themselves directly into a special
 * section because there doesn't seem to be any standard way of doing
 * that due to alignment rules. So instead we pack pointers into a
 * special section.
 *
 * If this macro fails to compile for you, you've probably not
 * declared the struct pdbg_target as the first member of the
 * container struct. Not doing so will break other assumptions.
 * */
#define DECLARE_HW_UNIT(name)						\
	static inline void name ##_hw_unit_check(void) {		\
		((void)sizeof(char[1 - 2 * (container_off(typeof(name), target) != 0)])); \
	}								\
	const struct hw_unit_info __used name ##_hw_unit =              \
	{ .hw_unit = &name, .size = sizeof(name) }; 	                \
	const struct hw_unit_info __used __section("hw_units") *name ##_hw_unit_p = &name ##_hw_unit

struct htm {
	struct pdbg_target target;
	int (*start)(struct htm *);
	int (*stop)(struct htm *);
	int (*status)(struct htm *);
	int (*dump)(struct htm *, char *);
	int (*record)(struct htm *, char *);
};
#define target_to_htm(x) container_of(x, struct htm, target)

struct adu {
	struct pdbg_target target;
	int (*getmem)(struct adu *, uint64_t, uint64_t *, int, uint8_t);
	int (*putmem)(struct adu *, uint64_t, uint64_t, int, int, uint8_t);
	int (*read)(struct adu *, uint64_t, uint8_t *, uint64_t, uint8_t, bool);
	int (*write)(struct adu *, uint64_t, uint8_t *, uint64_t, uint8_t, bool);
};
#define target_to_adu(x) container_of(x, struct adu, target)

struct pib {
	struct pdbg_target target;
	int (*read)(struct pib *, uint64_t, uint64_t *);
	int (*write)(struct pib *, uint64_t, uint64_t);
	void *priv;
};
#define target_to_pib(x) container_of(x, struct pib, target)

struct opb {
	struct pdbg_target target;
	int (*read)(struct opb *, uint32_t, uint32_t *);
	int (*write)(struct opb *, uint32_t, uint32_t);
};
#define target_to_opb(x) container_of(x, struct opb, target)

struct fsi {
	struct pdbg_target target;
	int (*read)(struct fsi *, uint32_t, uint32_t *);
	int (*write)(struct fsi *, uint32_t, uint32_t);
	enum chip_type chip_type;
};
#define target_to_fsi(x) container_of(x, struct fsi, target)

struct core {
	struct pdbg_target target;
	bool release_spwkup;
};
#define target_to_core(x) container_of(x, struct core, target)

struct thread {
	struct pdbg_target target;
	struct thread_state status;
	int id;
	int (*step)(struct thread *, int);
	int (*start)(struct thread *);
	int (*stop)(struct thread *);
	int (*sreset)(struct thread *);

	bool ram_did_quiesce; /* was the thread quiesced by ram mode */

	/* ram_setup() should be called prior to using ram_instruction() to
	 * actually ram the instruction and return the result. ram_destroy()
	 * should be called at completion to clean-up. */
	bool ram_is_setup;
	int (*ram_setup)(struct thread *);
	int (*ram_instruction)(struct thread *, uint64_t opcode, uint64_t *scratch);
	int (*ram_destroy)(struct thread *);
	int (*ram_getxer)(struct pdbg_target *, uint64_t *value);
	int (*ram_putxer)(struct pdbg_target *, uint64_t value);
	int (*enable_attn)(struct pdbg_target *);
};
#define target_to_thread(x) container_of(x, struct thread, target)

/* Place holder for chiplets which we just want translation for */
struct chiplet {
        struct pdbg_target target;
	int (*getring)(struct chiplet *, uint64_t, int64_t, uint32_t[]);
};
#define target_to_chiplet(x) container_of(x, struct chiplet, target)

struct xbus {
	struct pdbg_target target;
	uint32_t ring_id;
};
#define target_to_xbus(x) container_of(x, struct xbus, target)
#endif
OpenPOWER on IntegriCloud