vserver 1.9.3
[linux-2.6.git] / include / asm-ppc64 / mmu.h
index 3b66f32..616389d 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <linux/config.h>
 #include <asm/page.h>
+#include <linux/stringify.h>
 
 #ifndef __ASSEMBLY__
 
@@ -27,43 +28,17 @@ typedef struct {
 #endif
 } mm_context_t;
 
-#ifdef CONFIG_HUGETLB_PAGE
-#define KERNEL_LOW_HPAGES      .htlb_segs = 0,
-#else
-#define KERNEL_LOW_HPAGES
-#endif
+#define STE_ESID_V     0x80
+#define STE_ESID_KS    0x20
+#define STE_ESID_KP    0x10
+#define STE_ESID_N     0x08
 
-#define KERNEL_CONTEXT(ea) ({ \
-               mm_context_t ctx = { .id = REGION_ID(ea), KERNEL_LOW_HPAGES}; \
-               ctx; })
-
-typedef struct {
-       unsigned long esid: 36; /* Effective segment ID */
-       unsigned long resv0:20; /* Reserved */
-       unsigned long v:     1; /* Entry valid (v=1) or invalid */
-       unsigned long resv1: 1; /* Reserved */
-       unsigned long ks:    1; /* Supervisor (privileged) state storage key */
-       unsigned long kp:    1; /* Problem state storage key */
-       unsigned long n:     1; /* No-execute if n=1 */
-       unsigned long resv2: 3; /* padding to a 64b boundary */
-} ste_dword0;
-
-typedef struct {
-       unsigned long vsid: 52; /* Virtual segment ID */
-       unsigned long resv0:12; /* Padding to a 64b boundary */
-} ste_dword1;
-
-typedef struct _STE {
-       union {
-               unsigned long dword0;
-               ste_dword0    dw0;
-       } dw0;
+#define STE_VSID_SHIFT 12
 
-       union {
-               unsigned long dword1;
-               ste_dword1    dw1;
-       } dw1;
-} STE;
+struct stab_entry {
+       unsigned long esid_data;
+       unsigned long vsid_data;
+};
 
 /* Hardware Page Table Entry */
 
@@ -132,20 +107,6 @@ typedef struct {
 
 extern HTAB htab_data;
 
-void invalidate_hpte( unsigned long slot );
-long select_hpte_slot( unsigned long vpn );
-void create_valid_hpte( unsigned long slot, unsigned long vpn,
-                       unsigned long prpn, unsigned hash,
-                       void * ptep, unsigned hpteflags,
-                       unsigned bolted );
-
-#define PD_SHIFT (10+12)               /* Page directory */
-#define PD_MASK  0x02FF
-#define PT_SHIFT (12)                  /* Page Table */
-#define PT_MASK  0x02FF
-
-#define LARGE_PAGE_SHIFT 24
-
 static inline unsigned long hpt_hash(unsigned long vpn, int large)
 {
        unsigned long vsid;
@@ -224,7 +185,7 @@ extern void htab_finish_init(void);
 #define STAB0_PHYS_ADDR        (STAB0_PAGE<<PAGE_SHIFT)
 #define STAB0_VIRT_ADDR        (KERNELBASE+STAB0_PHYS_ADDR)
 
-#define SLB_NUM_BOLTED         2
+#define SLB_NUM_BOLTED         3
 #define SLB_CACHE_ENTRIES      8
 
 /* Bits in the SLB ESID word */
@@ -241,156 +202,43 @@ extern void htab_finish_init(void);
 #define SLB_VSID_KERNEL                (SLB_VSID_KP|SLB_VSID_C)
 #define SLB_VSID_USER          (SLB_VSID_KP|SLB_VSID_KS)
 
-#define VSID_RANDOMIZER ASM_CONST(42470972311)
-#define VSID_MASK      0xfffffffffUL
-/* Because we never access addresses below KERNELBASE as kernel
- * addresses, this VSID is never used for anything real, and will
- * never have pages hashed into it */
-#define BAD_VSID       ASM_CONST(0)
-
-/* Block size masks */
-#define BL_128K        0x000
-#define BL_256K 0x001
-#define BL_512K 0x003
-#define BL_1M   0x007
-#define BL_2M   0x00F
-#define BL_4M   0x01F
-#define BL_8M   0x03F
-#define BL_16M  0x07F
-#define BL_32M  0x0FF
-#define BL_64M  0x1FF
-#define BL_128M 0x3FF
-#define BL_256M 0x7FF
-
-/* Used to set up SDR1 register */
-#define HASH_TABLE_SIZE_64K    0x00010000
-#define HASH_TABLE_SIZE_128K   0x00020000
-#define HASH_TABLE_SIZE_256K   0x00040000
-#define HASH_TABLE_SIZE_512K   0x00080000
-#define HASH_TABLE_SIZE_1M     0x00100000
-#define HASH_TABLE_SIZE_2M     0x00200000
-#define HASH_TABLE_SIZE_4M     0x00400000
-#define HASH_TABLE_MASK_64K    0x000   
-#define HASH_TABLE_MASK_128K   0x001   
-#define HASH_TABLE_MASK_256K   0x003   
-#define HASH_TABLE_MASK_512K   0x007
-#define HASH_TABLE_MASK_1M     0x00F   
-#define HASH_TABLE_MASK_2M     0x01F   
-#define HASH_TABLE_MASK_4M     0x03F   
-
-/* These are the Ks and Kp from the PowerPC books.  For proper operation,
- * Ks = 0, Kp = 1.
- */
-#define MI_AP          786
-#define MI_Ks          0x80000000      /* Should not be set */
-#define MI_Kp          0x40000000      /* Should always be set */
-
-/* The effective page number register.  When read, contains the information
- * about the last instruction TLB miss.  When MI_RPN is written, bits in
- * this register are used to create the TLB entry.
- */
-#define MI_EPN         787
-#define MI_EPNMASK     0xfffff000      /* Effective page number for entry */
-#define MI_EVALID      0x00000200      /* Entry is valid */
-#define MI_ASIDMASK    0x0000000f      /* ASID match value */
-                                       /* Reset value is undefined */
-
-/* A "level 1" or "segment" or whatever you want to call it register.
- * For the instruction TLB, it contains bits that get loaded into the
- * TLB entry when the MI_RPN is written.
- */
-#define MI_TWC         789
-#define MI_APG         0x000001e0      /* Access protection group (0) */
-#define MI_GUARDED     0x00000010      /* Guarded storage */
-#define MI_PSMASK      0x0000000c      /* Mask of page size bits */
-#define MI_PS8MEG      0x0000000c      /* 8M page size */
-#define MI_PS512K      0x00000004      /* 512K page size */
-#define MI_PS4K_16K    0x00000000      /* 4K or 16K page size */
-#define MI_SVALID      0x00000001      /* Segment entry is valid */
-                                       /* Reset value is undefined */
-
-/* Real page number.  Defined by the pte.  Writing this register
- * causes a TLB entry to be created for the instruction TLB, using
- * additional information from the MI_EPN, and MI_TWC registers.
- */
-#define MI_RPN         790
-
-/* Define an RPN value for mapping kernel memory to large virtual
- * pages for boot initialization.  This has real page number of 0,
- * large page size, shared page, cache enabled, and valid.
- * Also mark all subpages valid and write access.
- */
-#define MI_BOOTINIT    0x000001fd
-
-#define MD_CTR         792     /* Data TLB control register */
-#define MD_GPM         0x80000000      /* Set domain manager mode */
-#define MD_PPM         0x40000000      /* Set subpage protection */
-#define MD_CIDEF       0x20000000      /* Set cache inhibit when MMU dis */
-#define MD_WTDEF       0x10000000      /* Set writethrough when MMU dis */
-#define MD_RSV4I       0x08000000      /* Reserve 4 TLB entries */
-#define MD_TWAM                0x04000000      /* Use 4K page hardware assist */
-#define MD_PPCS                0x02000000      /* Use MI_RPN prob/priv state */
-#define MD_IDXMASK     0x00001f00      /* TLB index to be loaded */
-#define MD_RESETVAL    0x04000000      /* Value of register at reset */
-
-#define M_CASID                793     /* Address space ID (context) to match */
-#define MC_ASIDMASK    0x0000000f      /* Bits used for ASID value */
-
+#define VSID_MULTIPLIER        ASM_CONST(200730139)    /* 28-bit prime */
+#define VSID_BITS      36
+#define VSID_MODULUS   ((1UL<<VSID_BITS)-1)
 
-/* These are the Ks and Kp from the PowerPC books.  For proper operation,
- * Ks = 0, Kp = 1.
- */
-#define MD_AP          794
-#define MD_Ks          0x80000000      /* Should not be set */
-#define MD_Kp          0x40000000      /* Should always be set */
+#define CONTEXT_BITS   20
+#define USER_ESID_BITS 15
 
-/* The effective page number register.  When read, contains the information
- * about the last instruction TLB miss.  When MD_RPN is written, bits in
- * this register are used to create the TLB entry.
- */
-#define MD_EPN         795
-#define MD_EPNMASK     0xfffff000      /* Effective page number for entry */
-#define MD_EVALID      0x00000200      /* Entry is valid */
-#define MD_ASIDMASK    0x0000000f      /* ASID match value */
-                                       /* Reset value is undefined */
-
-/* The pointer to the base address of the first level page table.
- * During a software tablewalk, reading this register provides the address
- * of the entry associated with MD_EPN.
- */
-#define M_TWB          796
-#define        M_L1TB          0xfffff000      /* Level 1 table base address */
-#define M_L1INDX       0x00000ffc      /* Level 1 index, when read */
-                                       /* Reset value is undefined */
-
-/* A "level 1" or "segment" or whatever you want to call it register.
- * For the data TLB, it contains bits that get loaded into the TLB entry
- * when the MD_RPN is written.  It is also provides the hardware assist
- * for finding the PTE address during software tablewalk.
- */
-#define MD_TWC         797
-#define MD_L2TB                0xfffff000      /* Level 2 table base address */
-#define MD_L2INDX      0xfffffe00      /* Level 2 index (*pte), when read */
-#define MD_APG         0x000001e0      /* Access protection group (0) */
-#define MD_GUARDED     0x00000010      /* Guarded storage */
-#define MD_PSMASK      0x0000000c      /* Mask of page size bits */
-#define MD_PS8MEG      0x0000000c      /* 8M page size */
-#define MD_PS512K      0x00000004      /* 512K page size */
-#define MD_PS4K_16K    0x00000000      /* 4K or 16K page size */
-#define MD_WT          0x00000002      /* Use writethrough page attribute */
-#define MD_SVALID      0x00000001      /* Segment entry is valid */
-                                       /* Reset value is undefined */
-
-
-/* Real page number.  Defined by the pte.  Writing this register
- * causes a TLB entry to be created for the data TLB, using
- * additional information from the MD_EPN, and MD_TWC registers.
- */
-#define MD_RPN         798
-
-/* This is a temporary storage register that could be used to save
- * a processor working register during a tablewalk.
+/*
+ * This macro generates asm code to compute the VSID scramble
+ * function.  Used in slb_allocate() and do_stab_bolted.  The function
+ * computed is: (protovsid*VSID_MULTIPLIER) % VSID_MODULUS
+ *
+ *     rt = register continaing the proto-VSID and into which the
+ *             VSID will be stored
+ *     rx = scratch register (clobbered)
+ *
+ *     - rt and rx must be different registers
+ *     - The answer will end up in the low 36 bits of rt.  The higher
+ *       bits may contain other garbage, so you may need to mask the
+ *       result.
  */
-#define M_TW           799
+#define ASM_VSID_SCRAMBLE(rt, rx)      \
+       lis     rx,VSID_MULTIPLIER@h;                                   \
+       ori     rx,rx,VSID_MULTIPLIER@l;                                \
+       mulld   rt,rt,rx;               /* rt = rt * MULTIPLIER */      \
+                                                                       \
+       srdi    rx,rt,VSID_BITS;                                        \
+       clrldi  rt,rt,(64-VSID_BITS);                                   \
+       add     rt,rt,rx;               /* add high and low bits */     \
+       /* Now, r3 == VSID (mod 2^36-1), and lies between 0 and         \
+        * 2^36-1+2^28-1.  That in particular means that if r3 >=       \
+        * 2^36-1, then r3+1 has the 2^36 bit set.  So, if r3+1 has     \
+        * the bit clear, r3 already has the answer we want, if it      \
+        * doesn't, the answer is the low 36 bits of r3+1.  So in all   \
+        * cases the answer is the low 36 bits of (r3 + ((r3+1) >> 36))*/\
+       addi    rx,rt,1;                                                \
+       srdi    rx,rx,VSID_BITS;        /* extract 2^36 bit */          \
+       add     rt,rt,rx
 
 #endif /* _PPC64_MMU_H_ */