1/*
2 * Copyright (c) 2000-2007 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28#ifdef	XNU_KERNEL_PRIVATE
29
30#ifndef _PPC_SAVEAREA_H_
31#define _PPC_SAVEAREA_H_
32
33#ifndef ASSEMBLER
34
35#include <sys/appleapiopts.h>
36
37#ifdef __APPLE_API_PRIVATE
38
39#if	defined(MACH_KERNEL_PRIVATE) || defined(BSD_KERNEL_PRIVATE)
40#include <stdint.h>
41#include <mach/vm_types.h>
42
43#pragma pack(4)							/* Make sure the structure stays as we defined it */
44typedef struct savearea_comm {
45
46/*
47 *	The following fields are common to all saveareas and are used to manage individual
48 *	contexts.
49 *
50 *	Fields that start with "save" are part of the individual saveareas.  Those that
51 *	start with "sac" pertain to the free pool stuff and are valid only on the first slot
52 *	in the page.
53 */
54
55
56/*	Keep the save_prev, sac_next, and sac_prev in these positions, some assembler code depends upon it to
57 *	match up with fields in saveanchor.
58 */
59                                                /* offset 0x000 */
60	addr64_t		save_prev;					/* The address of the previous (or next) savearea */
61	addr64_t		sac_next;					/* Points to next savearea page that has a free slot  - real */
62	addr64_t		sac_prev;					/* Points to previous savearea page that has a free slot  - real */
63	unsigned int	save_level;					/* Context ID */
64	unsigned int	save_01C;
65
66												/*	 0x20 */
67	unsigned int	save_time[2];				/* Context save time - for debugging or performance */
68	struct thread	*save_act;					/* Associated thread */
69    unsigned int	save_02c;
70	uint64_t		sac_vrswap;					/* XOR mask to swap V to R or vice versa */
71	unsigned int	save_flags;					/* Various flags */
72	unsigned int	sac_flags;					/* Various flags */
73
74                                                /* offset 0x040 */
75	uint64_t		save_misc0;					/* Various stuff */
76	uint64_t		save_misc1;					/* Various stuff - snapshot chain during hibernation */
77	unsigned int	sac_alloc;					/* Bitmap of allocated slots */
78    unsigned int	save_054;
79    unsigned int	save_misc2;
80    unsigned int	save_misc3;
81
82												/* offset 0x0060 */
83} savearea_comm;
84#pragma pack()
85
86/*
87 *	This type of savearea contains all of the general context.
88 */
89
90#pragma pack(4)							/* Make sure the structure stays as we defined it */
91typedef struct savearea {
92
93	savearea_comm	save_hdr;					/* Stuff common to all saveareas */
94
95	uint64_t		save_xdat0;					/* Exception data 0 */
96	uint64_t		save_xdat1;					/* Exception data 1 */
97	uint64_t		save_xdat2;					/* Exception data 2 */
98	uint64_t		save_xdat3;					/* Exception data 3 */
99                                                /* offset 0x0080 */
100	uint64_t	 	save_r0;
101	uint64_t	 	save_r1;
102	uint64_t	 	save_r2;
103	uint64_t	 	save_r3;
104                                                /* offset 0x0A0 */
105	uint64_t	 	save_r4;
106	uint64_t	 	save_r5;
107	uint64_t	 	save_r6;
108	uint64_t	 	save_r7;
109                                                /* offset 0x0C0 */
110	uint64_t	 	save_r8;
111	uint64_t	 	save_r9;
112	uint64_t	 	save_r10;
113	uint64_t	 	save_r11;
114                                                /* offset 0x0E0 */
115	uint64_t	 	save_r12;
116	uint64_t	 	save_r13;
117	uint64_t	 	save_r14;
118	uint64_t	 	save_r15;
119                                                /* offset 0x100 */
120	uint64_t	 	save_r16;
121	uint64_t	 	save_r17;
122	uint64_t	 	save_r18;
123	uint64_t	 	save_r19;
124                                                /* offset 0x120 */
125	uint64_t	 	save_r20;
126	uint64_t	 	save_r21;
127	uint64_t	 	save_r22;
128	uint64_t	 	save_r23;
129                                                /* offset 0x140 */
130	uint64_t	 	save_r24;
131	uint64_t	 	save_r25;
132	uint64_t	 	save_r26;
133	uint64_t	 	save_r27;
134                                                /* offset 0x160 */
135	uint64_t	 	save_r28;
136	uint64_t		save_r29;
137	uint64_t	 	save_r30;
138	uint64_t	 	save_r31;
139                                                /* offset 0x180 */
140	uint64_t	 	save_srr0;
141 	uint64_t	 	save_srr1;
142	uint64_t	 	save_xer;
143	uint64_t	 	save_lr;
144                                                /* offset 0x1A0 */
145	uint64_t	 	save_ctr;
146	uint64_t	 	save_dar;
147	unsigned int	save_cr;
148	unsigned int 	save_dsisr;
149	unsigned int	save_exception;
150	unsigned int	save_vrsave;
151                                                /* offset 0x1C0 */
152	unsigned int	save_vscr[4];
153	unsigned int	save_fpscrpad;
154	unsigned int	save_fpscr;
155    unsigned int	save_1d8[2];
156                                                /* offset 0x1E0 */
157	unsigned int	save_1E0[8];
158                                                /* offset 0x200 - keep on 128 byte bndry */
159    uint32_t        save_pmc[8];
160    uint64_t        save_mmcr0;					/* offset 0x220 */
161    uint64_t        save_mmcr1;
162    uint64_t        save_mmcr2;
163
164	unsigned int	save_238[2];
165												/* offset 0x240 */
166	unsigned int	save_instr[16];				/* Instrumentation or emulation. Note: save_instr[0] is number of instructions */
167												/* offset 0x280 */
168} savearea_t;
169#pragma pack()
170
171
172/*
173 *	This type of savearea contains all of the floating point context.
174 */
175
176#pragma pack(4)							/* Make sure the structure stays as we defined it */
177typedef struct savearea_fpu {
178
179	savearea_comm	save_hdr;					/* Stuff common to all saveareas */
180
181	unsigned int	save_060[8];				/* Fill 32 bytes */
182												/* offset 0x0080 */
183	double			save_fp0;
184	double			save_fp1;
185	double			save_fp2;
186	double			save_fp3;
187
188	double			save_fp4;
189	double			save_fp5;
190	double			save_fp6;
191	double			save_fp7;
192
193	double			save_fp8;
194	double			save_fp9;
195	double			save_fp10;
196	double			save_fp11;
197
198	double			save_fp12;
199	double			save_fp13;
200	double			save_fp14;
201	double			save_fp15;
202
203	double			save_fp16;
204	double			save_fp17;
205	double			save_fp18;
206	double			save_fp19;
207
208	double			save_fp20;
209	double			save_fp21;
210	double			save_fp22;
211	double			save_fp23;
212
213	double			save_fp24;
214	double			save_fp25;
215	double			save_fp26;
216	double			save_fp27;
217
218	double			save_fp28;
219	double			save_fp29;
220	double			save_fp30;
221	double			save_fp31;
222												/* offset 0x180 */
223	unsigned int	save_180[8];
224	unsigned int	save_1A0[8];
225	unsigned int	save_1C0[8];
226	unsigned int	save_1E0[8];
227	unsigned int	save_200[8];
228	unsigned int	save_220[8];
229	unsigned int	save_240[8];
230	unsigned int	save_260[8];
231
232												/* offset 0x280 */
233} savearea_fpu;
234#pragma pack()
235
236
237
238/*
239 *	This type of savearea contains all of the vector context.
240 */
241
242#pragma pack(4)							/* Make sure the structure stays as we defined it */
243typedef struct savearea_vec {
244
245	savearea_comm	save_hdr;					/* Stuff common to all saveareas */
246
247	unsigned int	save_060[7];				/* Fill 32 bytes */
248	unsigned int	save_vrvalid;				/* Valid registers in saved context */
249
250												/* offset 0x0080 */
251	unsigned int	save_vr0[4];
252	unsigned int	save_vr1[4];
253	unsigned int	save_vr2[4];
254	unsigned int	save_vr3[4];
255	unsigned int	save_vr4[4];
256	unsigned int	save_vr5[4];
257	unsigned int	save_vr6[4];
258	unsigned int	save_vr7[4];
259	unsigned int	save_vr8[4];
260	unsigned int	save_vr9[4];
261	unsigned int	save_vr10[4];
262	unsigned int	save_vr11[4];
263	unsigned int	save_vr12[4];
264	unsigned int	save_vr13[4];
265	unsigned int	save_vr14[4];
266	unsigned int	save_vr15[4];
267	unsigned int	save_vr16[4];
268	unsigned int	save_vr17[4];
269	unsigned int	save_vr18[4];
270	unsigned int	save_vr19[4];
271	unsigned int	save_vr20[4];
272	unsigned int	save_vr21[4];
273	unsigned int	save_vr22[4];
274	unsigned int	save_vr23[4];
275	unsigned int	save_vr24[4];
276	unsigned int	save_vr25[4];
277	unsigned int	save_vr26[4];
278	unsigned int	save_vr27[4];
279	unsigned int	save_vr28[4];
280	unsigned int	save_vr29[4];
281	unsigned int	save_vr30[4];
282	unsigned int	save_vr31[4];
283
284												/* offset 0x280 */
285} savearea_vec;
286#pragma pack()
287#endif /* MACH_KERNEL_PRIVATE || BSD_KERNEL_PRIVATE */
288
289#ifdef	MACH_KERNEL_PRIVATE
290
291#pragma pack(4)							/* Make sure the structure stays as we defined it */
292struct Saveanchor {
293
294/*
295 *	Note that this force aligned in aligned_data.s and must be in V=R storage.
296 *	Also, all addresses in chains are physical.  This structure can only be
297 *	updated with translation and interrupts disabled. This is because it is
298 *	locked during exception processing and if we were to take a PTE miss while the
299 *	lock were held, well, that would be very bad now wouldn't it?
300 *  Note that the first 24 bytes must be the same format as a savearea header.
301 */
302
303	unsigned int			savelock;		/* 000 Lock word for savearea free list manipulation */
304    int						saveRSVD4;		/* 004 reserved */
305	addr64_t				savepoolfwd;	/* 008 Forward anchor for the free pool */
306	addr64_t				savepoolbwd;	/* 010 Backward anchor for the free pool */
307	volatile addr64_t		savefree;		/* 018 Anchor for the global free list */
308	volatile unsigned int	savefreecnt;	/* 020 Number of saveareas on global free list */
309	volatile int			saveadjust;		/* 024 If 0 number of saveareas is ok, otherwise # to change (pos means grow, neg means shrink */
310	volatile int			saveinuse;		/* 028 Number of areas in use counting those on the local free list */
311	unsigned int			savetarget;		/* 02C Number of saveareas needed */
312	int						savemaxcount;	/* 030 Maximum saveareas ever allocated */
313	unsigned int			saveinusesnapshot;		/* 034 snapshot inuse count */
314	volatile addr64_t		savefreesnapshot;		/* 038 snapshot global free list header */
315/*											   040 */
316};
317#pragma pack()
318
319extern struct Saveanchor	saveanchor;			/* Aliged savearea anchor */
320
321#define sac_cnt		(4096 / sizeof(struct savearea))	/* Number of saveareas per page */
322#define sac_empty	(0xFFFFFFFF << (32 - sac_cnt))	/* Mask with all entries empty */
323#define sac_perm	0x40000000				/* Page permanently assigned */
324#define sac_permb	1						/* Page permanently assigned - bit position */
325
326#define LocalSaveTarget	(((8 + sac_cnt - 1) / sac_cnt) * sac_cnt)	/* Target for size of local savearea free list */
327#define LocalSaveMin	(LocalSaveTarget / 2)	/* Min size of local savearea free list before we grow */
328#define LocalSaveMax	(LocalSaveTarget * 2)	/* Max size of local savearea free list before we trim */
329
330#define FreeListMin		(2 * LocalSaveTarget)	/* Always make sure there are enough to fill local list twice per processor */
331#define SaveLowHysteresis	LocalSaveTarget		/* The number off from target before we adjust upwards */
332#define SaveHighHysteresis	(2 * FreeListMin)	/* The number off from target before we adjust downwards */
333#define InitialSaveAreas 	(2 * FreeListMin)	/* The number of saveareas to make at boot time */
334#define InitialSaveTarget	FreeListMin			/* The number of saveareas for an initial target. This should be the minimum ever needed. */
335#define	InitialSaveBloks	(InitialSaveAreas + sac_cnt - 1) / sac_cnt	/* The number of savearea blocks to allocate at boot */
336#define BackPocketSaveBloks	8				/* Number of pages of back pocket saveareas */
337
338void			save_queue(ppnum_t);		/* Add a new savearea block to the free list */
339addr64_t		save_get_init(void);		/* special savearea-get for cpu initialization (returns physical address) */
340struct savearea	*save_get(void);			/* Obtains a savearea from the free list (returns virtual address) */
341reg64_t			save_get_phys_32(void);		/* Obtains a savearea from the free list (returns phys addr in r3) */
342reg64_t			save_get_phys_64(void);		/* Obtains a savearea from the free list (returns phys addr in r3) */
343struct savearea	*save_alloc(void);			/* Obtains a savearea and allocates blocks if needed */
344struct savearea	*save_cpv(addr64_t);		/* Converts a physical savearea address to virtual */
345void			save_ret(struct savearea *);	/* Returns a savearea to the free list by virtual address */
346void			save_ret_wMSR(struct savearea *, reg64_t);	/* returns a savearea and restores an MSR */
347void			save_ret_phys(reg64_t);		/* Returns a savearea to the free list by physical address */
348void			save_adjust(void);			/* Adjust size of the global free list */
349struct savearea_comm	*save_trim_free(void);	/* Remove free pages from savearea pool */
350int				save_recover(void);			/* returns nonzero if we can recover enough from the free pool */
351void 			savearea_init(vm_offset_t addr);	/* Boot-time savearea initialization */
352
353void 			save_fake_zone_info(		/* report savearea usage statistics as fake zone info */
354					int *count,
355					vm_size_t *cur_size,
356					vm_size_t *max_size,
357					vm_size_t *elem_size,
358					vm_size_t *alloc_size,
359					int *collectable,
360					int *exhaustable);
361
362void			save_snapshot(void);
363void			save_snapshot_restore(void);
364void save_release(struct savearea *);
365
366#endif /* MACH_KERNEL_PRIVATE */
367#endif /* __APPLE_API_PRIVATE */
368
369#endif /* ndef ASSEMBLER */
370
371#define SAVattach	0x80000000				/* Savearea has valid context */
372#define SAVrststk	0x00010000				/* Indicates that the current stack should be reset to empty */
373#define SAVsyscall	0x00020000				/* Indicates that the savearea is associated with a syscall */
374#define SAVredrive	0x00040000				/* Indicates that the low-level fault handler associated */
375#define SAVredriveb	13						/* Indicates that the low-level fault handler associated */
376#define	SAVinstrument 0x00080000			/* Indicates that we should return instrumentation data */
377#define	SAVinstrumentb 12					/* Indicates that we should return instrumentation data */
378#define	SAVeat 		0x00100000				/* Indicates that interruption should be ignored */
379#define	SAVeatb 	11						/* Indicates that interruption should be ignored */
380#define	SAVinject 	0x00200000				/* Indicates that save_instr contains code to inject */
381#define	SAVinjectb 	10						/* Indicates that save_instr contains code to inject */
382#define SAVtype		0x0000FF00				/* Shows type of savearea */
383#define SAVtypeshft	8						/* Shift to position type */
384#define SAVempty	0x86					/* Savearea is on free list */
385#define SAVgeneral	0x01					/* Savearea contains general context */
386#define SAVfloat	0x02					/* Savearea contains floating point context */
387#define SAVvector	0x03					/* Savearea contains vector context */
388
389
390
391#endif /* _PPC_SAVEAREA_H_ */
392
393#endif	/* XNU_KERNEL_PRIVATE */
394