processor.h 6.75 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 *  include/asm-s390/processor.h
 *
 *  S390 version
 *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
 *    Author(s): Hartmut Penner (hp@de.ibm.com),
 *               Martin Schwidefsky (schwidefsky@de.ibm.com)
 *
 *  Derived from "include/asm-i386/processor.h"
 *    Copyright (C) 1994, Linus Torvalds
 */

#ifndef __ASM_S390_PROCESSOR_H
#define __ASM_S390_PROCESSOR_H

#include <asm/page.h>
#include <asm/ptrace.h>

19
#ifdef __KERNEL__
Linus Torvalds's avatar
Linus Torvalds committed
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
/*
 * Default implementation of macro that returns current
 * instruction pointer ("program counter").
 */
#define current_text_addr() ({ void *pc; __asm__("basr %0,0":"=a"(pc)); pc; })

/*
 *  CPU type and hardware bug flags. Kept separately for each CPU.
 *  Members of this structure are referenced in head.S, so think twice
 *  before touching them. [mj]
 */

typedef struct
{
        unsigned int version :  8;
        unsigned int ident   : 24;
        unsigned int machine : 16;
        unsigned int unused  : 16;
} __attribute__ ((packed)) cpuid_t;

struct cpuinfo_S390
{
        cpuid_t  cpu_id;
        __u16    cpu_addr;
        __u16    cpu_nr;
Linus Torvalds's avatar
Linus Torvalds committed
45
        unsigned long loops_per_jiffy;
Linus Torvalds's avatar
Linus Torvalds committed
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
        unsigned long *pgd_quick;
        unsigned long *pte_quick;
        unsigned long pgtable_cache_sz;
};

extern void print_cpu_info(struct cpuinfo_S390 *);

/* Lazy FPU handling on uni-processor */
extern struct task_struct *last_task_used_math;

/*
 * User space process size: 2GB (default).
 */
#define TASK_SIZE       (0x80000000)
/* This decides where the kernel will search for a free chunk of vm
 * space during mmap's.
 */
#define TASK_UNMAPPED_BASE      (TASK_SIZE / 2)

typedef struct {
66
        __u32 ar4;
Linus Torvalds's avatar
Linus Torvalds committed
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
} mm_segment_t;

/* if you change the thread_struct structure, you must
 * update the _TSS_* defines in entry.S
 */

struct thread_struct
 {
	s390_fp_regs fp_regs;
        __u32   ar2;                   /* kernel access register 2         */
        __u32   ar4;                   /* kernel access register 4         */
        __u32   ksp;                   /* kernel stack pointer             */
        __u32   user_seg;              /* HSTD                             */
        __u32   error_code;            /* error-code of last prog-excep.   */
        __u32   prot_addr;             /* address of protection-excep.     */
        __u32   trap_no;
        per_struct per_info;/* Must be aligned on an 4 byte boundary*/
Linus Torvalds's avatar
Linus Torvalds committed
84
	/* Used to give failing instruction back to user for ieee exceptions */
Linus Torvalds's avatar
Linus Torvalds committed
85 86 87
	addr_t  ieee_instruction_pointer; 
        /* pfault_wait is used to block the process on a pfault event */
	addr_t  pfault_wait;
Linus Torvalds's avatar
Linus Torvalds committed
88 89 90 91
};

typedef struct thread_struct thread_struct;

92
#define INIT_THREAD {{0,{{0},{0},{0},{0},{0},{0},{0},{0},{0},{0}, \
Linus Torvalds's avatar
Linus Torvalds committed
93 94 95 96 97
			    {0},{0},{0},{0},{0},{0}}},            \
                     0, 0,                                        \
                    sizeof(init_stack) + (__u32) &init_stack,     \
              (__pa((__u32) &swapper_pg_dir[0]) + _SEGMENT_TABLE),\
                     0,0,0,                                       \
Linus Torvalds's avatar
Linus Torvalds committed
98 99
                     (per_struct) {{{{0,}}},0,0,0,0,{{0,}}},      \
                     0, 0                                         \
Linus Torvalds's avatar
Linus Torvalds committed
100 101 102 103
}

/* need to define ... */
#define start_thread(regs, new_psw, new_stackp) do {            \
104 105
        regs->psw.mask  = PSW_USER_BITS;                        \
        regs->psw.addr  = new_psw | PSW_ADDR_AMODE31;           \
Linus Torvalds's avatar
Linus Torvalds committed
106 107 108 109
        regs->gprs[15]  = new_stackp ;                          \
} while (0)

/* Forward declaration, a strange C thing */
110
struct task_struct;
Linus Torvalds's avatar
Linus Torvalds committed
111 112 113 114 115 116
struct mm_struct;

/* Free all resources held by a thread. */
extern void release_thread(struct task_struct *);
extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);

117 118 119
/* Prepare to copy thread state - unlazy all lazy status */
#define prepare_to_copy(tsk)	do { } while (0)

Linus Torvalds's avatar
Linus Torvalds committed
120
/*
121
 * Return saved PC of a blocked thread.
Linus Torvalds's avatar
Linus Torvalds committed
122
 */
123
extern unsigned long thread_saved_pc(struct task_struct *t);
Linus Torvalds's avatar
Linus Torvalds committed
124 125

/*
126
 * Print register of task into buffer. Used in fs/proc/array.c.
Linus Torvalds's avatar
Linus Torvalds committed
127
 */
128
extern char *task_show_regs(struct task_struct *task, char *buffer);
Linus Torvalds's avatar
Linus Torvalds committed
129

130 131 132 133 134
unsigned long get_wchan(struct task_struct *p);
#define __KSTK_PTREGS(tsk) ((struct pt_regs *) \
        (((addr_t) tsk->thread_info + THREAD_SIZE - sizeof(struct pt_regs)) & -8L))
#define KSTK_EIP(tsk)	(__KSTK_PTREGS(tsk)->psw.addr)
#define KSTK_ESP(tsk)	(__KSTK_PTREGS(tsk)->gprs[15])
Linus Torvalds's avatar
Linus Torvalds committed
135

136
#define cpu_relax()	barrier()
Linus Torvalds's avatar
Linus Torvalds committed
137

138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
/*
 * Set PSW mask to specified value, while leaving the
 * PSW addr pointing to the next instruction.
 */

static inline void __load_psw_mask (unsigned long mask)
{
	unsigned long addr;

	psw_t psw;
	psw.mask = mask;

	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) : "memory", "cc" );
}
 
/*
160
 * Function to stop a processor until an interruption occurred
161 162 163 164 165 166
 */
static inline void enabled_wait(void)
{
	unsigned long reg;
	psw_t wait_psw;

167 168
	wait_psw.mask = PSW_BASE_BITS | PSW_MASK_IO | PSW_MASK_EXT |
		PSW_MASK_MCHECK | PSW_MASK_WAIT;
169 170 171 172 173 174 175 176 177 178
	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) : "memory", "cc" );
}

Linus Torvalds's avatar
Linus Torvalds committed
179 180 181 182 183 184 185
/*
 * Function to drop a processor into disabled wait state
 */

static inline void disabled_wait(unsigned long code)
{
        char psw_buffer[2*sizeof(psw_t)];
Linus Torvalds's avatar
Linus Torvalds committed
186
        char ctl_buf[4];
Linus Torvalds's avatar
Linus Torvalds committed
187 188 189
        psw_t *dw_psw = (psw_t *)(((unsigned long) &psw_buffer+sizeof(psw_t)-1)
                                  & -sizeof(psw_t));

190
        dw_psw->mask = PSW_BASE_BITS | PSW_MASK_WAIT;
Linus Torvalds's avatar
Linus Torvalds committed
191
        dw_psw->addr = code;
Linus Torvalds's avatar
Linus Torvalds committed
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
        /* 
         * Store status and then load disabled wait psw,
         * the processor is dead afterwards
         */

        asm volatile ("    stctl 0,0,0(%1)\n"
                      "    ni    0(%1),0xef\n" /* switch off protection */
                      "    lctl  0,0,0(%1)\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    0(%1),0x10\n" /* fake protection bit */
                      "    lpsw 0(%0)"
Linus Torvalds's avatar
Linus Torvalds committed
212
                      : : "a" (dw_psw), "a" (&ctl_buf) : "cc" );
Linus Torvalds's avatar
Linus Torvalds committed
213 214
}

215 216
#endif

Linus Torvalds's avatar
Linus Torvalds committed
217
#endif                                 /* __ASM_S390_PROCESSOR_H           */