/* * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* * @OSF_COPYRIGHT@ */ #ifndef _PPC_PROC_REG_H_ #define _PPC_PROC_REG_H_ #include /* Define some useful masks that convert from bit numbers */ #if __PPC__ #if _BIG_ENDIAN #ifndef ENDIAN_MASK #define ENDIAN_MASK(val,size) (1 << ((size-1) - val)) #endif #else #error code not ported to little endian targets yet #endif /* _BIG_ENDIAN */ #endif /* __PPC__ */ #define MASK32(PART) ENDIAN_MASK(PART ## _BIT, 32) #define MASK16(PART) ENDIAN_MASK(PART ## _BIT, 16) #define MASK8(PART) ENDIAN_MASK(PART ## _BIT, 8) #undef MASK #define MASK(PART) MASK32(PART) #define BITS_PER_WORD 32 #define BITS_PER_WORD_POW2 5 /* Defines for decoding the MSR bits */ #define MSR_SF_BIT 0 #define MSR_RES1_BIT 1 #define MSR_RES2_BIT 2 #define MSR_RES3_BIT 3 #define MSR_RES4_BIT 4 #define MSR_RES5_BIT 5 #define MSR_VEC_BIT 6 #define MSR_RES7_BIT 7 #define MSR_RES8_BIT 8 #define MSR_RES9_BIT 9 #define MSR_RES10_BIT 10 #define MSR_RES11_BIT 11 #define MSR_KEY_BIT 12 /* Key bit on 603e (not on 603) */ #define MSR_POW_BIT 13 #define MSR_TGPR_BIT 14 /* Temporary GPR mappings on 603/603e */ #define MSR_ILE_BIT 15 #define MSR_EE_BIT 16 #define MSR_PR_BIT 17 #define MSR_FP_BIT 18 #define MSR_ME_BIT 19 #define MSR_FE0_BIT 20 #define MSR_SE_BIT 21 #define MSR_BE_BIT 22 #define MSR_FE1_BIT 23 #define MSR_RES24_BIT 24 /* AL bit in power architectures */ #define MSR_IP_BIT 25 #define MSR_IR_BIT 26 #define MSR_DR_BIT 27 #define MSR_RES28_BIT 28 #define MSR_PM_BIT 29 #define MSR_RI_BIT 30 #define MSR_LE_BIT 31 /* MSR for kernel mode, interrupts disabled, running in virtual mode */ #define MSR_SUPERVISOR_INT_OFF (MASK(MSR_ME) | MASK(MSR_IR) | MASK(MSR_DR)) /* MSR for above but with interrupts enabled */ #define MSR_SUPERVISOR_INT_ON (MSR_SUPERVISOR_INT_OFF | MASK(MSR_EE)) /* MSR for physical mode code */ #define MSR_VM_OFF (MASK(MSR_ME)) /* MSR for physical instruction, virtual data */ #define MSR_PHYS_INST_VIRT_DATA (MASK(MSR_ME) | MASK(MSR_IR)) /* MSR mask for user-exported bits - identify bits that must be set/reset */ /* SET - external exceptions, machine check, vm on, user-level privs */ #define MSR_EXPORT_MASK_SET (MASK(MSR_EE)| MASK(MSR_ME)| \ MASK(MSR_IR)|MASK(MSR_DR)|MASK(MSR_PR)) /* only the following bits may be changed by a task */ #define MSR_IMPORT_BITS (MASK(MSR_FE0)|MASK(MSR_SE)|MASK(MSR_BE)| \ MASK(MSR_FE1)| MASK(MSR_PM) | MASK(MSR_LE)) #define MSR_PREPARE_FOR_IMPORT(origmsr, newmsr) \ ((origmsr & ~MSR_IMPORT_BITS) | (newmsr & MSR_IMPORT_BITS)) #define MSR_VEC_ON (MASK(MSR_VEC)) #define USER_MODE(msr) (msr & MASK(MSR_PR) ? TRUE : FALSE) /* seg reg values must be simple expressions so that assembler can cope */ #define SEG_REG_INVALID 0x0000 #define KERNEL_SEG_REG0_VALUE 0x20000000 /* T=0,Ks=0,Ku=1 PPC_SID_KERNEL=0*/ /* For SEG_REG_PROT we have T=0, Ks=0, Ku=1 */ #define SEG_REG_PROT 0x20000000 /* seg regs should have these bits set */ /* SR_COPYIN is used for copyin/copyout+remapping and must be * saved and restored in the thread context. */ /* SR_UNUSED_BY_KERN is unused by the kernel, and thus contains * the space ID of the currently interrupted user task immediately * after an exception and before interrupts are reenabled. It's used * purely for an assert. */ /* SR_KERNEL used for asserts... */ #define SR_COPYIN sr14 #define SR_UNUSED_BY_KERN sr13 #define SR_KERNEL sr0 #define SR_UNUSED_BY_KERN_NUM 13 #define SR_COPYIN_NAME sr14 #define SR_COPYIN_NUM 14 /* DSISR bits on data access exceptions */ #define DSISR_IO_BIT 0 /* NOT USED on 601 */ #define DSISR_HASH_BIT 1 #define DSISR_PROT_BIT 4 #define DSISR_IO_SPC_BIT 5 #define DSISR_WRITE_BIT 6 #define DSISR_WATCH_BIT 9 #define DSISR_EIO_BIT 11 /* SRR1 bits on data/instruction translation exceptions */ #define SRR1_TRANS_HASH_BIT 1 #define SRR1_TRANS_IO_BIT 3 #define SRR1_TRANS_PROT_BIT 4 #define SRR1_TRANS_NO_PTE_BIT 10 /* SRR1 bits on program exceptions */ #define SRR1_PRG_FE_BIT 11 #define SRR1_PRG_ILL_INS_BIT 12 #define SRR1_PRG_PRV_INS_BIT 13 #define SRR1_PRG_TRAP_BIT 14 /* BAT information */ /* Constants used when setting mask values */ #define BAT_INVALID 0 /* * Virtual to physical mapping macros/structures. * IMPORTANT NOTE: there is one mapping per HW page, not per MACH page. */ #define CACHE_LINE_SIZE 32 #define CACHE_LINE_POW2 5 #define cache_align(x) (((x) + CACHE_LINE_SIZE-1) & ~(CACHE_LINE_SIZE - 1)) #define PTE1_WIMG_GUARD_BIT 28 /* Needed for assembler */ #define PTE1_REFERENCED_BIT 23 /* ditto */ #define PTE1_CHANGED_BIT 24 #define PTE0_HASH_ID_BIT 25 #define PTE_NULL ((pte_t*) NULL) /* No pte found/associated with this */ #define PTE_EMPTY 0x7fffffbf /* Value in the pte0.word of a free pte */ #define PTE_WIMG_CB_CACHED 0 /* cached, writeback */ #define PTE_WIMG_CB_CACHED_GUARDED 1 /* cached, writeback, guarded */ #define PTE_WIMG_CB_CACHED_COHERENT 2 /* cached, writeback, coherent (default) */ #define PTE_WIMG_CB_CACHED_COHERENT_GUARDED 3 /* cached, writeback, coherent, guarded */ #define PTE_WIMG_UNCACHED 4 /* uncached */ #define PTE_WIMG_UNCACHED_GUARDED 5 /* uncached, guarded */ #define PTE_WIMG_UNCACHED_COHERENT 6 /* uncached, coherentt */ #define PTE_WIMG_UNCACHED_COHERENT_GUARDED 7 /* uncached, coherent, guarded */ #define PTE_WIMG_WT_CACHED 8 /* cached, writethru */ #define PTE_WIMG_WT_CACHED_GUARDED 9 /* cached, writethru, guarded */ #define PTE_WIMG_WT_CACHED_COHERENT 10 /* cached, writethru, coherent */ #define PTE_WIMG_WT_CACHED_COHERENT_GUARDED 11 /* cached, writethru, coherent, guarded */ #define PTE_WIMG_DEFAULT PTE_WIMG_CB_CACHED_COHERENT #define PTE_WIMG_IO PTE_WIMG_UNCACHED_COHERENT_GUARDED #ifndef ASSEMBLER #ifdef __GNUC__ #if _BIG_ENDIAN == 0 #error - bitfield structures are not checked for bit ordering in words #endif /* _BIG_ENDIAN */ /* Structures and types for machine registers */ typedef union { unsigned int word; struct { unsigned int htaborg : 16; unsigned int reserved : 7; unsigned int htabmask : 9; } bits; } sdr1_t; /* Block mapping registers. These values are model dependent. * Eventually, we will need to up these to 64 bit values. */ #define blokValid 0x1FFE0000 #define batMin 0x00020000 #define batMax 0x10000000 #define batICnt 4 #define batDCnt 4 /* BAT register structures. * Not used for standard mappings, but may be used * for mapping devices. Note that the 601 has a * different BAT layout than the other PowerPC processors */ typedef union { unsigned int word; struct { unsigned int blpi : 15; unsigned int reserved : 10; unsigned int wim : 3; unsigned int ks : 1; unsigned int ku : 1; unsigned int pp : 2; } bits; } bat601u_t; typedef union { unsigned int word; struct { unsigned int pbn : 15; unsigned int reserved : 10; unsigned int valid : 1; unsigned int bsm : 6; } bits; } bat601l_t; typedef struct bat601_t { bat601u_t upper; bat601l_t lower; } bat601_t; typedef union { unsigned int word; struct { unsigned int bepi : 15; unsigned int reserved : 4; unsigned int bl : 11; unsigned int vs : 1; unsigned int vp : 1; } bits; } batu_t; typedef union { unsigned int word; struct { unsigned int brpn : 15; unsigned int reserved : 10; unsigned int wimg : 4; unsigned int reserved2 : 1; unsigned int pp : 2; } bits; } batl_t; typedef struct bat_t { batu_t upper; batl_t lower; } bat_t; /* PTE entries * Used extensively for standard mappings */ typedef union { unsigned int word; struct { unsigned int valid : 1; unsigned int segment_id : 24; unsigned int hash_id : 1; unsigned int page_index : 6; /* Abbreviated */ } bits; struct { unsigned int valid : 1; unsigned int not_used : 5; unsigned int segment_id : 19; /* Least Sig 19 bits */ unsigned int hash_id : 1; unsigned int page_index : 6; } hash_bits; } pte0_t; typedef union { unsigned int word; struct { unsigned int phys_page : 20; unsigned int reserved3 : 3; unsigned int referenced : 1; unsigned int changed : 1; unsigned int wimg : 4; unsigned int reserved1 : 1; unsigned int protection : 2; } bits; } pte1_t; typedef struct pte_t { pte0_t pte0; pte1_t pte1; } pte_t; /* * A virtual address is decoded into various parts when looking for its PTE */ typedef struct va_full_t { unsigned int seg_num : 4; unsigned int page_index : 16; unsigned int byte_ofs : 12; } va_full_t; typedef struct va_abbrev_t { /* use bits.abbrev for abbreviated page index */ unsigned int seg_num : 4; unsigned int page_index : 6; unsigned int junk : 10; unsigned int byte_ofs : 12; } va_abbrev_t; typedef union { unsigned int word; va_full_t full; va_abbrev_t abbrev; } virtual_addr_t; /* A physical address can be split up into page and offset */ typedef struct pa_t { unsigned int page_no : 20; unsigned int offset : 12; } pa_t; typedef union { unsigned int word; pa_t bits; } physical_addr_t; /* * C-helper inline functions for accessing machine registers follow. */ #ifdef __ELF__ #define __CASMNL__ ";" #else #define __CASMNL__ "@" #endif /* Return the current GOT pointer */ extern unsigned int get_got(void); extern __inline__ unsigned int get_got(void) { unsigned int result; #ifndef __ELF__ __asm__ volatile("mr %0, r2" : "=r" (result)); #else __asm__ volatile("mr %0, 2" : "=r" (result)); #endif return result; } /* * Various memory/IO synchronisation instructions */ /* Use eieio as a memory barrier to order stores. * Useful for device control and PTE maintenance. */ #define eieio() \ __asm__ volatile("eieio") /* Use sync to ensure previous stores have completed. This is required when manipulating locks and/or maintaining PTEs or other shared structures on SMP machines. */ #define sync() \ __asm__ volatile("sync") /* Use isync to sychronize context; that is, the ensure no prefetching of instructions happen before the instruction. */ #define isync() \ __asm__ volatile("isync") /* * This guy will make sure all tlbs on all processors finish their tlbies */ #define tlbsync() \ __asm__ volatile("tlbsync") /* Invalidate TLB entry. Caution, requires context synchronization. */ extern void tlbie(unsigned int val); extern __inline__ void tlbie(unsigned int val) { __asm__ volatile("tlbie %0" : : "r" (val)); return; } /* * Access to various system registers */ extern unsigned int mflr(void); extern __inline__ unsigned int mflr(void) { unsigned int result; __asm__ volatile("mflr %0" : "=r" (result)); return result; } extern unsigned int mfpvr(void); extern __inline__ unsigned int mfpvr(void) { unsigned int result; __asm__ ("mfpvr %0" : "=r" (result)); return result; } /* mtmsr might need syncs etc around it, don't provide simple * inline macro */ extern unsigned int mfmsr(void); extern __inline__ unsigned int mfmsr(void) { unsigned int result; __asm__ volatile("mfmsr %0" : "=r" (result)); return result; } /* mtsr and mfsr must be macros since SR must be hardcoded */ #if __ELF__ #define mtsr(SR, REG) \ __asm__ volatile("sync" __CASMNL__ "mtsr %0, %1 " __CASMNL__ "isync" : : "i" (SR), "r" (REG)); #define mfsr(REG, SR) \ __asm__ volatile("mfsr %0, %1" : "=r" (REG) : "i" (SR)); #else #define mtsr(SR, REG) \ __asm__ volatile("sync" __CASMNL__ "mtsr sr%0, %1 " __CASMNL__ "isync" : : "i" (SR), "r" (REG)); #define mfsr(REG, SR) \ __asm__ volatile("mfsr %0, sr%1" : "=r" (REG) : "i" (SR)); #endif extern void mtsrin(unsigned int val, unsigned int reg); extern __inline__ void mtsrin(unsigned int val, unsigned int reg) { __asm__ volatile("sync" __CASMNL__ "mtsrin %0, %1" __CASMNL__ " isync" : : "r" (val), "r" (reg)); return; } extern unsigned int mfsrin(unsigned int reg); extern __inline__ unsigned int mfsrin(unsigned int reg) { unsigned int result; __asm__ volatile("mfsrin %0, %1" : "=r" (result) : "r" (reg)); return result; } extern void mtsdr1(unsigned int val); extern __inline__ void mtsdr1(unsigned int val) { __asm__ volatile("mtsdr1 %0" : : "r" (val)); return; } extern void mtdar(unsigned int val); extern __inline__ void mtdar(unsigned int val) { __asm__ volatile("mtdar %0" : : "r" (val)); return; } extern unsigned int mfdar(void); extern __inline__ unsigned int mfdar(void) { unsigned int result; __asm__ volatile("mfdar %0" : "=r" (result)); return result; } extern void mtdec(unsigned int val); extern __inline__ void mtdec(unsigned int val) { __asm__ volatile("mtdec %0" : : "r" (val)); return; } extern int isync_mfdec(void); extern __inline__ int isync_mfdec(void) { int result; __asm__ volatile("isync" __CASMNL__ "mfdec %0" : "=r" (result)); return result; } /* Read and write the value from the real-time clock * or time base registers. Note that you have to * use the right ones depending upon being on * 601 or 603/604. Care about carries between * the words and using the right registers must be * done by the calling function. */ extern void mttb(unsigned int val); extern __inline__ void mttb(unsigned int val) { __asm__ volatile("mtspr tbl, %0" : : "r" (val)); return; } extern unsigned int mftb(void); extern __inline__ unsigned int mftb(void) { unsigned int result; __asm__ volatile("mftb %0" : "=r" (result)); return result; } extern void mttbu(unsigned int val); extern __inline__ void mttbu(unsigned int val) { __asm__ volatile("mtspr tbu, %0" : : "r" (val)); return; } extern unsigned int mftbu(void); extern __inline__ unsigned int mftbu(void) { unsigned int result; __asm__ volatile("mftbu %0" : "=r" (result)); return result; } extern void mtrtcl(unsigned int val); extern __inline__ void mtrtcl(unsigned int val) { __asm__ volatile("mtspr 21,%0" : : "r" (val)); return; } extern unsigned int mfrtcl(void); extern __inline__ unsigned int mfrtcl(void) { unsigned int result; __asm__ volatile("mfspr %0,5" : "=r" (result)); return result; } extern void mtrtcu(unsigned int val); extern __inline__ void mtrtcu(unsigned int val) { __asm__ volatile("mtspr 20,%0" : : "r" (val)); return; } extern unsigned int mfrtcu(void); extern __inline__ unsigned int mfrtcu(void) { unsigned int result; __asm__ volatile("mfspr %0,4" : "=r" (result)); return result; } extern void mtl2cr(unsigned int val); extern __inline__ void mtl2cr(unsigned int val) { __asm__ volatile("mtspr l2cr, %0" : : "r" (val)); return; } extern unsigned int mfl2cr(void); extern __inline__ unsigned int mfl2cr(void) { unsigned int result; __asm__ volatile("mfspr %0, l2cr" : "=r" (result)); return result; } extern unsigned int cntlzw(unsigned int num); extern __inline__ unsigned int cntlzw(unsigned int num) { unsigned int result; __asm__ volatile("cntlzw %0, %1" : "=r" (result) : "r" (num)); return result; } /* functions for doing byte reversed loads and stores */ extern unsigned int lwbrx(unsigned int addr); extern __inline__ unsigned int lwbrx(unsigned int addr) { unsigned int result; __asm__ volatile("lwbrx %0, 0, %1" : "=r" (result) : "r" (addr)); return result; } extern void stwbrx(unsigned int data, unsigned int addr); extern __inline__ void stwbrx(unsigned int data, unsigned int addr) { __asm__ volatile("stwbrx %0, 0, %1" : : "r" (data), "r" (addr)); } /* Performance Monitor Register access routines */ extern unsigned long mfmmcr0(void); extern void mtmmcr0(unsigned long); extern unsigned long mfmmcr1(void); extern void mtmmcr1(unsigned long); extern unsigned long mfmmcr2(void); extern void mtmmcr2(unsigned long); extern unsigned long mfpmc1(void); extern void mtpmc1(unsigned long); extern unsigned long mfpmc2(void); extern void mtpmc2(unsigned long); extern unsigned long mfpmc3(void); extern void mtpmc3(unsigned long); extern unsigned long mfpmc4(void); extern void mtpmc4(unsigned long); extern unsigned long mfsia(void); extern unsigned long mfsda(void); /* macros since the argument n is a hard-coded constant */ #define mtibatu(n, reg) __asm__ volatile("mtibatu " # n ", %0" : : "r" (reg)) #define mtibatl(n, reg) __asm__ volatile("mtibatl " # n ", %0" : : "r" (reg)) #define mtdbatu(n, reg) __asm__ volatile("mtdbatu " # n ", %0" : : "r" (reg)) #define mtdbatl(n, reg) __asm__ volatile("mtdbatl " # n ", %0" : : "r" (reg)) #define mfibatu(reg, n) __asm__ volatile("mfibatu %0, " # n : "=r" (reg)) #define mfibatl(reg, n) __asm__ volatile("mfibatl %0, " # n : "=r" (reg)) #define mfdbatu(reg, n) __asm__ volatile("mfdbatu %0, " # n : "=r" (reg)) #define mfdbatl(reg, n) __asm__ volatile("mfdbatl %0, " # n : "=r" (reg)) #define mtsprg(n, reg) __asm__ volatile("mtsprg " # n ", %0" : : "r" (reg)) #define mfsprg(reg, n) __asm__ volatile("mfsprg %0, " # n : "=r" (reg)) #define mtspr(spr, val) __asm__ volatile("mtspr " # spr ", %0" : : "r" (val)) #define mfspr(reg, spr) __asm__ volatile("mfspr %0, " # spr : "=r" (reg)) #endif /* __GNUC__ */ #endif /* !ASSEMBLER */ #endif /* _PPC_PROC_REG_H_ */