[S390] Add four level page tables for CONFIG_64BIT=y.
[safe/jmp/linux-2.6] / include / asm-s390 / processor.h
index cbbd114..5a21f45 100644 (file)
@@ -13,7 +13,6 @@
 #ifndef __ASM_S390_PROCESSOR_H
 #define __ASM_S390_PROCESSOR_H
 
-#include <asm/page.h>
 #include <asm/ptrace.h>
 
 #ifdef __KERNEL__
@@ -21,7 +20,7 @@
  * Default implementation of macro that returns current
  * instruction pointer ("program counter").
  */
-#define current_text_addr() ({ void *pc; __asm__("basr %0,0":"=a"(pc)); pc; })
+#define current_text_addr() ({ void *pc; asm("basr %0,0" : "=a" (pc)); pc; })
 
 /*
  *  CPU type and hardware bug flags. Kept separately for each CPU.
@@ -37,6 +36,11 @@ typedef struct
         unsigned int unused  : 16;
 } __attribute__ ((packed)) cpuid_t;
 
+static inline void get_cpu_id(cpuid_t *ptr)
+{
+       asm volatile("stidp 0(%1)" : "=m" (*ptr) : "a" (ptr));
+}
+
 struct cpuinfo_S390
 {
         cpuid_t  cpu_id;
@@ -51,30 +55,39 @@ struct cpuinfo_S390
         unsigned long pgtable_cache_sz;
 };
 
+extern void s390_adjust_jiffies(void);
 extern void print_cpu_info(struct cpuinfo_S390 *);
-
-/* Lazy FPU handling on uni-processor */
-extern struct task_struct *last_task_used_math;
+extern int get_cpu_capability(unsigned int *);
 
 /*
  * User space process size: 2GB for 31 bit, 4TB for 64 bit.
  */
 #ifndef __s390x__
 
-# define TASK_SIZE             (0x80000000UL)
-# define TASK_UNMAPPED_BASE    (TASK_SIZE / 2)
-# define DEFAULT_TASK_SIZE     (0x80000000UL)
+#define TASK_SIZE              (1UL << 31)
+#define TASK_UNMAPPED_BASE     (1UL << 30)
 
 #else /* __s390x__ */
 
-# define TASK_SIZE             (test_thread_flag(TIF_31BIT) ? \
-                                       (0x80000000UL) : (0x40000000000UL))
-# define TASK_UNMAPPED_BASE    (TASK_SIZE / 2)
-# define DEFAULT_TASK_SIZE     (0x40000000000UL)
+#define TASK_SIZE_OF(tsk)      (test_tsk_thread_flag(tsk,TIF_31BIT) ? \
+                                       (1UL << 31) : (1UL << 53))
+#define TASK_UNMAPPED_BASE     (test_thread_flag(TIF_31BIT) ? \
+                                       (1UL << 30) : (1UL << 41))
+#define TASK_SIZE              TASK_SIZE_OF(current)
 
 #endif /* __s390x__ */
 
-#define MM_VM_SIZE(mm)         DEFAULT_TASK_SIZE
+#ifdef __KERNEL__
+
+#ifndef __s390x__
+#define STACK_TOP              (1UL << 31)
+#else /* __s390x__ */
+#define STACK_TOP              (1UL << (test_thread_flag(TIF_31BIT) ? 31:53))
+#endif /* __s390x__ */
+
+#define STACK_TOP_MAX          STACK_TOP
+
+#endif
 
 #define HAVE_ARCH_PICK_MMAP_LAYOUT
 
@@ -89,10 +102,8 @@ struct thread_struct {
        s390_fp_regs fp_regs;
        unsigned int  acrs[NUM_ACRS];
         unsigned long ksp;              /* kernel stack pointer             */
-        unsigned long user_seg;         /* HSTD                             */
        mm_segment_t mm_segment;
         unsigned long prot_addr;        /* address of protection-excep.     */
-        unsigned int error_code;        /* error-code of last prog-excep.   */
         unsigned int trap_no;
         per_struct per_info;
        /* Used to give failing instruction back to user for ieee exceptions */
@@ -124,22 +135,9 @@ struct stack_frame {
 
 #define ARCH_MIN_TASKALIGN     8
 
-#ifndef __s390x__
-# define __SWAPPER_PG_DIR __pa(&swapper_pg_dir[0]) + _SEGMENT_TABLE
-#else /* __s390x__ */
-# define __SWAPPER_PG_DIR __pa(&swapper_pg_dir[0]) + _REGION_TABLE
-#endif /* __s390x__ */
-
-#define INIT_THREAD {{0,{{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},             \
-                           {0},{0},{0},{0},{0},{0}}},                         \
-                    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},         \
-                    sizeof(init_stack) + (unsigned long) &init_stack,         \
-                    __SWAPPER_PG_DIR,                                         \
-                    {0},                                                      \
-                    0,0,0,                                                    \
-                    (per_struct) {{{{0,}}},0,0,0,0,{{0,}}},                   \
-                    0, 0                                                      \
-} 
+#define INIT_THREAD {                                                  \
+       .ksp = sizeof(init_stack) + (unsigned long) &init_stack,        \
+}
 
 /*
  * Do necessary setup to start up a new thread.
@@ -147,7 +145,8 @@ struct stack_frame {
 #ifndef __s390x__
 
 #define start_thread(regs, new_psw, new_stackp) do {            \
-        regs->psw.mask  = PSW_USER_BITS;                        \
+       set_fs(USER_DS);                                        \
+       regs->psw.mask  = psw_user_bits;                        \
         regs->psw.addr  = new_psw | PSW_ADDR_AMODE;             \
         regs->gprs[15]  = new_stackp ;                          \
 } while (0)
@@ -155,13 +154,15 @@ struct stack_frame {
 #else /* __s390x__ */
 
 #define start_thread(regs, new_psw, new_stackp) do {            \
-        regs->psw.mask  = PSW_USER_BITS;                        \
+       set_fs(USER_DS);                                        \
+       regs->psw.mask  = psw_user_bits;                        \
         regs->psw.addr  = new_psw;                              \
         regs->gprs[15]  = new_stackp;                           \
 } while (0)
 
 #define start_thread31(regs, new_psw, new_stackp) do {          \
-       regs->psw.mask  = PSW_USER32_BITS;                      \
+       set_fs(USER_DS);                                        \
+       regs->psw.mask  = psw_user32_bits;                      \
         regs->psw.addr  = new_psw;                              \
         regs->gprs[15]  = new_stackp;                           \
 } while (0)
@@ -171,6 +172,7 @@ struct stack_frame {
 /* Forward declaration, a strange C thing */
 struct task_struct;
 struct mm_struct;
+struct seq_file;
 
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
@@ -187,26 +189,44 @@ extern unsigned long thread_saved_pc(struct task_struct *t);
 /*
  * Print register of task into buffer. Used in fs/proc/array.c.
  */
-extern char *task_show_regs(struct task_struct *task, char *buffer);
+extern void task_show_regs(struct seq_file *m, struct task_struct *task);
 
 extern void show_registers(struct pt_regs *regs);
+extern void show_code(struct pt_regs *regs);
 extern void show_trace(struct task_struct *task, unsigned long *sp);
 
 unsigned long get_wchan(struct task_struct *p);
-#define __KSTK_PTREGS(tsk) ((struct pt_regs *) \
-        ((unsigned long) tsk->thread_info + THREAD_SIZE - sizeof(struct pt_regs)))
-#define KSTK_EIP(tsk)  (__KSTK_PTREGS(tsk)->psw.addr)
-#define KSTK_ESP(tsk)  (__KSTK_PTREGS(tsk)->gprs[15])
+#define task_pt_regs(tsk) ((struct pt_regs *) \
+        (task_stack_page(tsk) + THREAD_SIZE) - 1)
+#define KSTK_EIP(tsk)  (task_pt_regs(tsk)->psw.addr)
+#define KSTK_ESP(tsk)  (task_pt_regs(tsk)->gprs[15])
 
 /*
  * Give up the time slice of the virtual PU.
  */
+static inline void cpu_relax(void)
+{
+       if (MACHINE_HAS_DIAG44)
+               asm volatile("diag 0,0,68");
+       barrier();
+}
+
+static inline void psw_set_key(unsigned int key)
+{
+       asm volatile("spka 0(%0)" : : "d" (key));
+}
+
+/*
+ * Set PSW to specified value.
+ */
+static inline void __load_psw(psw_t psw)
+{
 #ifndef __s390x__
-# define cpu_relax()   asm volatile ("diag 0,0,68" : : : "memory")
-#else /* __s390x__ */
-# define cpu_relax() \
-       asm volatile ("ex 0,%0" : : "i" (__LC_DIAG44_OPCODE) : "memory")
-#endif /* __s390x__ */
+       asm volatile("lpsw  0(%0)" : : "a" (&psw), "m" (psw) : "cc");
+#else
+       asm volatile("lpswe 0(%0)" : : "a" (&psw), "m" (psw) : "cc");
+#endif
+}
 
 /*
  * Set PSW mask to specified value, while leaving the
@@ -216,25 +236,25 @@ unsigned long get_wchan(struct task_struct *p);
 static inline void __load_psw_mask (unsigned long mask)
 {
        unsigned long addr;
-
        psw_t psw;
+
        psw.mask = mask;
 
 #ifndef __s390x__
-       asm volatile (
-               "    basr %0,0\n"
-               "0:  ahi  %0,1f-0b\n"
-               "    st   %0,4(%1)\n"
-               "    lpsw 0(%1)\n"
+       asm volatile(
+               "       basr    %0,0\n"
+               "0:     ahi     %0,1f-0b\n"
+               "       st      %0,4(%1)\n"
+               "       lpsw    0(%1)\n"
                "1:"
-               : "=&d" (addr) : "a" (&psw), "m" (psw) : "memory", "cc" );
+               : "=&d" (addr) : "a" (&psw), "m" (psw) : "memory", "cc");
 #else /* __s390x__ */
-       asm volatile (
-               "    larl  %0,1f\n"
-               "    stg   %0,8(%1)\n"
-               "    lpswe 0(%1)\n"
+       asm volatile(
+               "       larl    %0,1f\n"
+               "       stg     %0,8(%1)\n"
+               "       lpswe   0(%1)\n"
                "1:"
-               : "=&d" (addr) : "a" (&psw), "m" (psw) : "memory", "cc" );
+               : "=&d" (addr) : "a" (&psw), "m" (psw) : "memory", "cc");
 #endif /* __s390x__ */
 }
  
@@ -243,30 +263,8 @@ static inline void __load_psw_mask (unsigned long mask)
  */
 static inline void enabled_wait(void)
 {
-       unsigned long reg;
-       psw_t wait_psw;
-
-       wait_psw.mask = PSW_BASE_BITS | PSW_MASK_IO | PSW_MASK_EXT |
-               PSW_MASK_MCHECK | PSW_MASK_WAIT;
-#ifndef __s390x__
-       asm volatile (
-               "    basr %0,0\n"
-               "0:  la   %0,1f-0b(%0)\n"
-               "    st   %0,4(%1)\n"
-               "    oi   4(%1),0x80\n"
-               "    lpsw 0(%1)\n"
-               "1:"
-               : "=&a" (reg) : "a" (&wait_psw), "m" (wait_psw)
-               : "memory", "cc" );
-#else /* __s390x__ */
-       asm volatile (
-               "    larl  %0,0f\n"
-               "    stg   %0,8(%1)\n"
-               "    lpswe 0(%1)\n"
-               "0:"
-               : "=&a" (reg) : "a" (&wait_psw), "m" (wait_psw)
-               : "memory", "cc" );
-#endif /* __s390x__ */
+       __load_psw_mask(PSW_BASE_BITS | PSW_MASK_IO | PSW_MASK_EXT |
+                       PSW_MASK_MCHECK | PSW_MASK_WAIT | PSW_DEFAULT_KEY);
 }
 
 /*
@@ -275,81 +273,111 @@ static inline void enabled_wait(void)
 
 static inline void disabled_wait(unsigned long code)
 {
-        char psw_buffer[2*sizeof(psw_t)];
         unsigned long ctl_buf;
-        psw_t *dw_psw = (psw_t *)(((unsigned long) &psw_buffer+sizeof(psw_t)-1)
-                                  & -sizeof(psw_t));
+        psw_t dw_psw;
 
-        dw_psw->mask = PSW_BASE_BITS | PSW_MASK_WAIT;
-        dw_psw->addr = code;
+        dw_psw.mask = PSW_BASE_BITS | PSW_MASK_WAIT;
+        dw_psw.addr = code;
         /* 
          * Store status and then load disabled wait psw,
          * the processor is dead afterwards
          */
 #ifndef __s390x__
-        asm volatile ("    stctl 0,0,0(%2)\n"
-                      "    ni    0(%2),0xef\n" /* switch off protection */
-                      "    lctl  0,0,0(%2)\n"
-                      "    stpt  0xd8\n"       /* store timer */
-                      "    stckc 0xe0\n"       /* store clock comparator */
-                      "    stpx  0x108\n"      /* store prefix register */
-                      "    stam  0,15,0x120\n" /* store access registers */
-                      "    std   0,0x160\n"    /* store f0 */
-                      "    std   2,0x168\n"    /* store f2 */
-                      "    std   4,0x170\n"    /* store f4 */
-                      "    std   6,0x178\n"    /* store f6 */
-                      "    stm   0,15,0x180\n" /* store general registers */
-                      "    stctl 0,15,0x1c0\n" /* store control registers */
-                      "    oi    0x1c0,0x10\n" /* fake protection bit */
-                      "    lpsw 0(%1)"
-                      : "=m" (ctl_buf)
-                     : "a" (dw_psw), "a" (&ctl_buf), "m" (dw_psw) : "cc" );
+       asm volatile(
+               "       stctl   0,0,0(%2)\n"
+               "       ni      0(%2),0xef\n"   /* switch off protection */
+               "       lctl    0,0,0(%2)\n"
+               "       stpt    0xd8\n"         /* store timer */
+               "       stckc   0xe0\n"         /* store clock comparator */
+               "       stpx    0x108\n"        /* store prefix register */
+               "       stam    0,15,0x120\n"   /* store access registers */
+               "       std     0,0x160\n"      /* store f0 */
+               "       std     2,0x168\n"      /* store f2 */
+               "       std     4,0x170\n"      /* store f4 */
+               "       std     6,0x178\n"      /* store f6 */
+               "       stm     0,15,0x180\n"   /* store general registers */
+               "       stctl   0,15,0x1c0\n"   /* store control registers */
+               "       oi      0x1c0,0x10\n"   /* fake protection bit */
+               "       lpsw    0(%1)"
+               : "=m" (ctl_buf)
+               : "a" (&dw_psw), "a" (&ctl_buf), "m" (dw_psw) : "cc");
 #else /* __s390x__ */
-        asm volatile ("    stctg 0,0,0(%2)\n"
-                      "    ni    4(%2),0xef\n" /* switch off protection */
-                      "    lctlg 0,0,0(%2)\n"
-                      "    lghi  1,0x1000\n"
-                      "    stpt  0x328(1)\n"      /* store timer */
-                      "    stckc 0x330(1)\n"      /* store clock comparator */
-                      "    stpx  0x318(1)\n"      /* store prefix register */
-                      "    stam  0,15,0x340(1)\n" /* store access registers */
-                      "    stfpc 0x31c(1)\n"      /* store fpu control */
-                      "    std   0,0x200(1)\n"    /* store f0 */
-                      "    std   1,0x208(1)\n"    /* store f1 */
-                      "    std   2,0x210(1)\n"    /* store f2 */
-                      "    std   3,0x218(1)\n"    /* store f3 */
-                      "    std   4,0x220(1)\n"    /* store f4 */
-                      "    std   5,0x228(1)\n"    /* store f5 */
-                      "    std   6,0x230(1)\n"    /* store f6 */
-                      "    std   7,0x238(1)\n"    /* store f7 */
-                      "    std   8,0x240(1)\n"    /* store f8 */
-                      "    std   9,0x248(1)\n"    /* store f9 */
-                      "    std   10,0x250(1)\n"   /* store f10 */
-                      "    std   11,0x258(1)\n"   /* store f11 */
-                      "    std   12,0x260(1)\n"   /* store f12 */
-                      "    std   13,0x268(1)\n"   /* store f13 */
-                      "    std   14,0x270(1)\n"   /* store f14 */
-                      "    std   15,0x278(1)\n"   /* store f15 */
-                      "    stmg  0,15,0x280(1)\n" /* store general registers */
-                      "    stctg 0,15,0x380(1)\n" /* store control registers */
-                      "    oi    0x384(1),0x10\n" /* fake protection bit */
-                      "    lpswe 0(%1)"
-                      : "=m" (ctl_buf)
-                     : "a" (dw_psw), "a" (&ctl_buf),
-                       "m" (dw_psw) : "cc", "0", "1");
+       asm volatile(
+               "       stctg   0,0,0(%2)\n"
+               "       ni      4(%2),0xef\n"   /* switch off protection */
+               "       lctlg   0,0,0(%2)\n"
+               "       lghi    1,0x1000\n"
+               "       stpt    0x328(1)\n"     /* store timer */
+               "       stckc   0x330(1)\n"     /* store clock comparator */
+               "       stpx    0x318(1)\n"     /* store prefix register */
+               "       stam    0,15,0x340(1)\n"/* store access registers */
+               "       stfpc   0x31c(1)\n"     /* store fpu control */
+               "       std     0,0x200(1)\n"   /* store f0 */
+               "       std     1,0x208(1)\n"   /* store f1 */
+               "       std     2,0x210(1)\n"   /* store f2 */
+               "       std     3,0x218(1)\n"   /* store f3 */
+               "       std     4,0x220(1)\n"   /* store f4 */
+               "       std     5,0x228(1)\n"   /* store f5 */
+               "       std     6,0x230(1)\n"   /* store f6 */
+               "       std     7,0x238(1)\n"   /* store f7 */
+               "       std     8,0x240(1)\n"   /* store f8 */
+               "       std     9,0x248(1)\n"   /* store f9 */
+               "       std     10,0x250(1)\n"  /* store f10 */
+               "       std     11,0x258(1)\n"  /* store f11 */
+               "       std     12,0x260(1)\n"  /* store f12 */
+               "       std     13,0x268(1)\n"  /* store f13 */
+               "       std     14,0x270(1)\n"  /* store f14 */
+               "       std     15,0x278(1)\n"  /* store f15 */
+               "       stmg    0,15,0x280(1)\n"/* store general registers */
+               "       stctg   0,15,0x380(1)\n"/* store control registers */
+               "       oi      0x384(1),0x10\n"/* fake protection bit */
+               "       lpswe   0(%1)"
+               : "=m" (ctl_buf)
+               : "a" (&dw_psw), "a" (&ctl_buf), "m" (dw_psw) : "cc", "0");
 #endif /* __s390x__ */
 }
 
 /*
+ * Basic Machine Check/Program Check Handler.
+ */
+
+extern void s390_base_mcck_handler(void);
+extern void s390_base_pgm_handler(void);
+extern void s390_base_ext_handler(void);
+
+extern void (*s390_base_mcck_handler_fn)(void);
+extern void (*s390_base_pgm_handler_fn)(void);
+extern void (*s390_base_ext_handler_fn)(void);
+
+/*
  * CPU idle notifier chain.
  */
-#define CPU_IDLE       0
-#define CPU_NOT_IDLE   1
+#define S390_CPU_IDLE          0
+#define S390_CPU_NOT_IDLE      1
 
 struct notifier_block;
 int register_idle_notifier(struct notifier_block *nb);
 int unregister_idle_notifier(struct notifier_block *nb);
 
+#define ARCH_LOW_ADDRESS_LIMIT 0x7fffffffUL
+
+#endif
+
+/*
+ * Helper macro for exception table entries
+ */
+#ifndef __s390x__
+#define EX_TABLE(_fault,_target)                       \
+       ".section __ex_table,\"a\"\n"                   \
+       "       .align 4\n"                             \
+       "       .long  " #_fault "," #_target "\n"      \
+       ".previous\n"
+#else
+#define EX_TABLE(_fault,_target)                       \
+       ".section __ex_table,\"a\"\n"                   \
+       "       .align 8\n"                             \
+       "       .quad  " #_fault "," #_target "\n"      \
+       ".previous\n"
 #endif
 
 #endif                                 /* __ASM_S390_PROCESSOR_H           */