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