xref: /illumos-gate/usr/src/uts/sun4u/opl/sys/drmach.h (revision 68ac2337)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #ifndef _SYS_DRMACH_H_
27 #define	_SYS_DRMACH_H_
28 
29 #pragma ident	"%Z%%M%	%I%	%E% SMI"
30 
31 #ifdef	__cplusplus
32 extern "C" {
33 #endif
34 
35 #ifndef _ASM
36 #include <sys/types.h>
37 #include <sys/memlist.h>
38 #include <sys/processor.h>
39 #include <sys/cpuvar.h>
40 #include <sys/sbd_ioctl.h>
41 #include <sys/sysevent.h>
42 #include <sys/ddi.h>
43 #include <sys/sunddi.h>
44 #include <sys/sunndi.h>
45 #include <sys/ddi_impldefs.h>
46 #include <sys/pte.h>
47 #include <sys/opl.h>
48 #endif
49 
50 
51 #define	MAX_BOARDS		plat_max_boards()
52 #define	MAX_CPU_UNITS_PER_BOARD	plat_max_cpu_units_per_board()
53 #define	MAX_MEM_UNITS_PER_BOARD	plat_max_mem_units_per_board()
54 #define	MAX_IO_UNITS_PER_BOARD	plat_max_io_units_per_board()
55 #define	MAX_CMP_UNITS_PER_BOARD	plat_max_cmp_units_per_board()
56 /*
57  * DR uses MAX_CORES_PER_CMP as number of virtual CPU within a CMP
58  */
59 #define	MAX_CORES_PER_CMP	OPL_MAX_CPU_PER_CMP
60 
61 
62 /* returned with drmach_board_find_devices callback */
63 #define	DRMACH_DEVTYPE_CPU	"cpu"
64 #define	DRMACH_DEVTYPE_MEM	"memory"
65 #define	DRMACH_DEVTYPE_PCI	"pci"
66 
67 #define	FMEM_LOOP_START		1
68 #define	FMEM_LOOP_COPY_READY	2
69 #define	FMEM_LOOP_COPY_DONE	3
70 #define	FMEM_LOOP_FMEM_READY	4
71 #define	FMEM_LOOP_RENAME_DONE	5
72 #define	FMEM_LOOP_DONE		6
73 #define	FMEM_LOOP_EXIT		7
74 
75 #define	FMEM_NO_ERROR		0
76 #define	FMEM_XC_TIMEOUT		1
77 #define	FMEM_COPY_TIMEOUT	2
78 #define	FMEM_SCF_BUSY		3
79 #define	FMEM_RETRY_OUT		4
80 #define	FMEM_TIMEOUT		5
81 #define	FMEM_HW_ERROR		6
82 #define	FMEM_TERMINATE		7
83 #define	FMEM_COPY_ERROR		8
84 #define	FMEM_SCF_ERR		9
85 
86 #define	SCF_CMD_BUSY		0x8000
87 #define	SCF_STATUS_READY	0x8000
88 #define	SCF_STATUS_SHUTDOWN	0x4000
89 #define	SCF_STATUS_POFF		0x2000
90 #define	SCF_STATUS_EVENT	0x1000
91 #define	SCF_STATUS_TIMER_ADJUST	0x0800
92 #define	SCF_STATUS_ALIVE	0x0400
93 #define	SCF_STATUS_MODE_CHANGED	0x0200
94 #define	SCF_STATUS_CMD_U_PARITY	0x0100
95 #define	SCF_STATUS_CMD_RTN_CODE	0x00f0
96 #define	SCF_STATUS_MODE_SWITCH	0x000c
97 #define	SCF_STATUS_CMD_COMPLETE	0x0002
98 #define	SCF_STATUS_CMD_L_PARITY	0x0001
99 
100 #define	SCF_RETRY_CNT		15
101 
102 /*
103  * dynamic memory blocks cannot be added back to phys_install
104  * safely if the alignment is smaller than the largest
105  * physical page size the OS supports.  The VM subsystem
106  * will try to coalesce smaller pages together and
107  * it assumes that the page structures are contiguous.
108  * That assumption does not hold so we have to work around it.
109  * On OPL, the largest page size is 256MB so we can just
110  * add such memory block back.  For everything else,
111  * we round them up to 4MB boundaries and make sure
112  * they are disjoint from phys_install.
113  */
114 
115 #define	MH_MPSS_ALIGNMENT	(256 * 1024 * 1024)
116 #define	MH_MIN_ALIGNMENT	(4 * 1024 * 1024)
117 #define	rounddown(x, y)		((x) & ~(y - 1))
118 
119 #ifndef _ASM
120 
121 /*
122  * OPL platform specific routines currently only defined
123  * in opl.c and referenced by DR.
124  */
125 
126 typedef void *drmachid_t;
127 
128 /*
129  *	There are several requirements to do copy rename:
130  *	1 There should be no subroutine calls/TLBmiss
131  *	  once the copying has begun.
132  *	2 There should be no external memory access by the CPU
133  *	  during the memory rename programming.
134  *
135  *	All data and instruction pages used in the copy rename
136  *	procedure are kept in locked pages to satisfy 1 and 2.
137  *	However that is not enough.  To satisfy 2, we must keep
138  *	all the data and instructions in the 2 assembly routines
139  *	drmach_fmem_loop_script and drmach_fmem_exec_script
140  *	in the same contiguous page.  They are packed into
141  *	the 2nd 8K page of the buffer as shown in the diagram
142  *	below.
143  *
144  *	Note that it is important to keep the "critical"
145  *	data in one 8K page to avoid any cache line
146  *	contention.   The assembly routines read all the
147  *	critical data into the cache so that there is no
148  *	external memory access during FMEM operation.
149  *
150  *	layout of the FMEM buffers:
151  *	They are all locked in TLB and the critical data
152  *	used in drmach_fmem_xxx assembly code are all
153  *	packed in the second page.
154  *
155  *	1st 8k page
156  *	+--------------------------------+
157  *	|drmach_copy_rename_program_t    |
158  *	+--------------------------------+
159  *	|drmach_copy_rename_data_t       |
160  *	|                                |
161  *	+--------------------------------+
162  *
163  *	2nd 8k page
164  *	+--------------------------------+
165  *	|drmach_copy_rename_critical_t   |
166  *	|                                |
167  *	+--------------------------------+
168  *	|run (drmach_copy_rename_prog__relocatable)
169  *	|(roundup boundary to 1K)        |
170  *	+--------------------------------+
171  *	| fmem_script                    |
172  *	|(roundup boundary to 1K)        |
173  *	+--------------------------------+
174  *	|loop_script                     |
175  *	|                                |
176  *	+--------------------------------+
177  *	|at least 1K NOP/0's             |
178  *	|                                |
179  *	+--------------------------------+
180  *
181  *	3rd 8k page
182  *	+--------------------------------+
183  *	|memlist_buffer (free_mlist)     |
184  *	|                                |
185  *	+--------------------------------+
186  *
187  *	4th 8k page - drmach_cr_stat_t.
188  *
189  */
190 
191 typedef struct {
192 	int16_t	scf_command;
193 	int8_t	scf_rsv1[2];
194 	int16_t	scf_status;
195 	int8_t	scf_rsv2[2];
196 	int8_t	scf_version;
197 	int8_t	scf_rsv3[3];
198 	int8_t	scf_rsv4[4];
199 	uint8_t	scf_tdata[16];
200 	uint8_t	scf_rdata[16];
201 } drmach_scf_regs_t;
202 
203 
204 
205 typedef struct {
206 	volatile uint_t	stat;
207 	volatile uint_t	error;
208 	int	op;
209 #define	OPL_FMEM_SCF_START 	0x1
210 #define	OPL_FMEM_MC_SUSPEND	0x2
211 } drmach_fmem_mbox_t;
212 
213 typedef struct {
214 	uint64_t		scf_reg_base;
215 	uint8_t			scf_td[16];
216 	uint64_t		save_log[8];
217 	uint64_t		save_local[8];
218 	uint64_t		pstate;
219 	uint64_t		delay;
220 	int			(*run)(void *arg, int cpuid);
221 	int			(*fmem)(void *arg, size_t sz);
222 	int			(*loop)(void *arg1, size_t sz, void *arg2);
223 	void			(*loop_rtn)(void *arg);
224 	uint64_t		inst_loop_ret;
225 	int			fmem_issued;
226 	volatile uchar_t 	stat[NCPU];
227 } drmach_copy_rename_critical_t;
228 
229 typedef struct {
230 	uint64_t		s_copybasepa;
231 	uint64_t		t_copybasepa;
232 	drmachid_t		s_mem;
233 	drmachid_t		t_mem;
234 	cpuset_t		cpu_ready_set;
235 	cpuset_t		cpu_slave_set;
236 	cpuset_t		cpu_copy_set;
237 	processorid_t		cpuid;
238 	drmach_fmem_mbox_t	fmem_status;
239 	volatile uchar_t 	error[NCPU];
240 	struct memlist		*c_ml;
241 	struct memlist		*cpu_ml[NCPU];
242 	void			(*mc_resume)(void);
243 	int			(*scf_fmem_end)(void);
244 	int			(*scf_fmem_cancel)(void);
245 	uint64_t		(*scf_get_base_addr)(void);
246 	uint64_t		copy_delay;
247 	uint64_t		stick_freq;
248 	uint64_t		copy_wait_time;
249 	processorid_t		slowest_cpuid;
250 } drmach_copy_rename_data_t;
251 
252 typedef struct {
253 	uint64_t	nbytes[NCPU];
254 } drmach_cr_stat_t;
255 
256 typedef struct drmach_copy_rename_program {
257 	drmach_copy_rename_critical_t		*critical;
258 	struct drmach_copy_rename_program	*locked_prog;
259 	struct drmach_copy_rename_program	*prog;
260 	drmach_copy_rename_data_t		*data;
261 	caddr_t					memlist_buffer;
262 	struct memlist				*free_mlist;
263 	drmach_cr_stat_t			*stat;
264 } drmach_copy_rename_program_t;
265 
266 #define	DRMACH_FMEM_LOCKED_PAGES	4
267 #define	DRMACH_FMEM_DATA_PAGE		0
268 #define	DRMACH_FMEM_CRITICAL_PAGE	1
269 #define	DRMACH_FMEM_MLIST_PAGE		2
270 #define	DRMACH_FMEM_STAT_PAGE		3
271 
272 /*
273  * layout of the FMEM buffers:
274  * 1st 8k page
275  * +--------------------------------+
276  * |drmach_copy_rename_program_t    |
277  * +--------------------------------+
278  * |drmach_copy_rename_data_t       |
279  * |                                |
280  * +--------------------------------+
281  *
282  * 2nd 8k page
283  * +--------------------------------+
284  * |drmach_copy_rename_critical_t   |
285  * |                                |
286  * +--------------------------------+
287  * |run (drmach_copy_rename_prog__relocatable)
288  * |(roundup boundary to 1K)        |
289  * +--------------------------------+
290  * | fmem_script                    |
291  * |(roundup boundary to 1K)        |
292  * +--------------------------------+
293  * |loop_script                     |
294  * |                                |
295  * +--------------------------------+
296  * |at least 1K NOP/0's             |
297  * |                                |
298  * +--------------------------------+
299  *
300  * 3rd 8k page
301  * +--------------------------------+
302  * |memlist_buffer (free_mlist)     |
303  * |                                |
304  * +--------------------------------+
305  *
306  * 4th 8k page - drmach_cr_stat_t.
307  *
308  */
309 
310 typedef struct {
311 	boolean_t	assigned;
312 	boolean_t	powered;
313 	boolean_t	configured;
314 	boolean_t	busy;
315 	boolean_t	empty;
316 	sbd_cond_t	cond;
317 	char		type[MAXNAMELEN];
318 	char		info[MAXPATHLEN];	/* TODO: what size? */
319 } drmach_status_t;
320 
321 typedef struct {
322 	int	size;
323 	char	*copts;
324 } drmach_opts_t;
325 
326 typedef struct {
327 	uint64_t mi_basepa;
328 	uint64_t mi_size;
329 	uint64_t mi_slice_size;
330 	uint64_t mi_alignment_mask;
331 } drmach_mem_info_t;
332 
333 extern sbd_error_t	*drmach_mem_get_info(drmachid_t, drmach_mem_info_t *);
334 extern int		drmach_board_is_floating(drmachid_t);
335 
336 extern sbd_error_t	*drmach_copy_rename_init(
337 				drmachid_t dst_id,
338 				drmachid_t src_id, struct memlist *src_copy_ml,
339 				drmachid_t *pgm_id);
340 extern sbd_error_t	*drmach_copy_rename_fini(drmachid_t id);
341 extern void		 drmach_copy_rename(drmachid_t id);
342 
343 extern sbd_error_t	*drmach_pre_op(int cmd, drmachid_t id,
344 						drmach_opts_t *opts);
345 extern sbd_error_t	*drmach_post_op(int cmd, drmachid_t id,
346 						drmach_opts_t *opts);
347 
348 extern sbd_error_t	*drmach_board_assign(int bnum, drmachid_t *id);
349 extern sbd_error_t	*drmach_board_connect(drmachid_t id,
350 						drmach_opts_t *opts);
351 extern sbd_error_t	*drmach_board_deprobe(drmachid_t id);
352 extern sbd_error_t	*drmach_board_disconnect(drmachid_t id,
353 						drmach_opts_t *opts);
354 extern sbd_error_t	*drmach_board_find_devices(drmachid_t id, void *a,
355 		sbd_error_t *(*found)(void *a, const char *, int, drmachid_t));
356 extern int		drmach_board_lookup(int bnum, drmachid_t *id);
357 extern sbd_error_t	*drmach_passthru(drmachid_t id,
358 						drmach_opts_t *opts);
359 
360 extern sbd_error_t	*drmach_board_name(int bnum, char *buf, int buflen);
361 
362 extern sbd_error_t	*drmach_board_poweroff(drmachid_t id);
363 extern sbd_error_t	*drmach_board_poweron(drmachid_t id);
364 extern sbd_error_t	*drmach_board_test(drmachid_t id, drmach_opts_t *opts,
365 				int force);
366 
367 extern sbd_error_t	*drmach_board_unassign(drmachid_t id);
368 
369 extern sbd_error_t	*drmach_configure(drmachid_t id, int flags);
370 
371 extern sbd_error_t	*drmach_cpu_disconnect(drmachid_t id);
372 extern sbd_error_t	*drmach_cpu_get_id(drmachid_t id, processorid_t *cpuid);
373 extern sbd_error_t	*drmach_cpu_get_impl(drmachid_t id, int *ip);
374 extern void		 drmach_cpu_flush_ecache_sync(void);
375 
376 extern sbd_error_t	*drmach_get_dip(drmachid_t id, dev_info_t **dip);
377 
378 extern sbd_error_t	*drmach_io_is_attached(drmachid_t id, int *yes);
379 extern sbd_error_t	*drmach_io_post_attach(drmachid_t id);
380 extern sbd_error_t	*drmach_io_post_release(drmachid_t id);
381 extern sbd_error_t	*drmach_io_pre_release(drmachid_t id);
382 extern sbd_error_t	*drmach_io_unrelease(drmachid_t id);
383 
384 extern sbd_error_t	*drmach_mem_add_span(drmachid_t id,
385 				uint64_t basepa, uint64_t size);
386 extern sbd_error_t	*drmach_mem_del_span(drmachid_t id,
387 				uint64_t basepa, uint64_t size);
388 extern sbd_error_t	*drmach_mem_disable(drmachid_t id);
389 extern sbd_error_t	*drmach_mem_enable(drmachid_t id);
390 extern sbd_error_t	*drmach_mem_get_base_physaddr(drmachid_t id,
391 				uint64_t *pa);
392 extern sbd_error_t	*drmach_mem_get_memlist(drmachid_t id,
393 				struct memlist **ml);
394 extern sbd_error_t	*drmach_mem_get_slice_size(drmachid_t, uint64_t *);
395 
396 extern sbd_error_t	*drmach_release(drmachid_t id);
397 extern sbd_error_t	*drmach_status(drmachid_t id, drmach_status_t *stat);
398 extern sbd_error_t	*drmach_unconfigure(drmachid_t id, int flags);
399 extern int		drmach_log_sysevent(int board, char *hint, int flag,
400 					    int verbose);
401 
402 extern int		drmach_verify_sr(dev_info_t *dip, int sflag);
403 extern void		drmach_suspend_last();
404 extern void		drmach_resume_first();
405 
406 #endif
407 
408 #ifdef __cplusplus
409 }
410 #endif
411 
412 #endif /* _SYS_DRMACH_H_ */
413