Commit 06da5d99 authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Linus Torvalds

[PATCH] s390/s390x unification (7/7)

Merge s390x and s390 to one architecture.
parent e6268940
...@@ -15,18 +15,9 @@ ...@@ -15,18 +15,9 @@
* assume GCC is being used. * assume GCC is being used.
*/ */
typedef unsigned short __kernel_dev_t;
typedef unsigned long __kernel_ino_t;
typedef unsigned short __kernel_mode_t;
typedef unsigned short __kernel_nlink_t;
typedef long __kernel_off_t; typedef long __kernel_off_t;
typedef int __kernel_pid_t; typedef int __kernel_pid_t;
typedef unsigned short __kernel_ipc_pid_t;
typedef unsigned short __kernel_uid_t;
typedef unsigned short __kernel_gid_t;
typedef unsigned long __kernel_size_t; typedef unsigned long __kernel_size_t;
typedef int __kernel_ssize_t;
typedef int __kernel_ptrdiff_t;
typedef long __kernel_time_t; typedef long __kernel_time_t;
typedef long __kernel_suseconds_t; typedef long __kernel_suseconds_t;
typedef long __kernel_clock_t; typedef long __kernel_clock_t;
...@@ -36,15 +27,45 @@ typedef int __kernel_daddr_t; ...@@ -36,15 +27,45 @@ typedef int __kernel_daddr_t;
typedef char * __kernel_caddr_t; typedef char * __kernel_caddr_t;
typedef unsigned short __kernel_uid16_t; typedef unsigned short __kernel_uid16_t;
typedef unsigned short __kernel_gid16_t; typedef unsigned short __kernel_gid16_t;
#ifdef __GNUC__
typedef long long __kernel_loff_t;
#endif
#ifndef __s390x__
typedef unsigned short __kernel_dev_t;
typedef unsigned long __kernel_ino_t;
typedef unsigned short __kernel_mode_t;
typedef unsigned short __kernel_nlink_t;
typedef unsigned short __kernel_ipc_pid_t;
typedef unsigned short __kernel_uid_t;
typedef unsigned short __kernel_gid_t;
typedef int __kernel_ssize_t;
typedef int __kernel_ptrdiff_t;
typedef unsigned int __kernel_uid32_t; typedef unsigned int __kernel_uid32_t;
typedef unsigned int __kernel_gid32_t; typedef unsigned int __kernel_gid32_t;
typedef unsigned short __kernel_old_uid_t; typedef unsigned short __kernel_old_uid_t;
typedef unsigned short __kernel_old_gid_t; typedef unsigned short __kernel_old_gid_t;
#ifdef __GNUC__ #else /* __s390x__ */
typedef long long __kernel_loff_t;
#endif typedef unsigned int __kernel_dev_t;
typedef unsigned int __kernel_ino_t;
typedef unsigned int __kernel_mode_t;
typedef unsigned int __kernel_nlink_t;
typedef int __kernel_ipc_pid_t;
typedef unsigned int __kernel_uid_t;
typedef unsigned int __kernel_gid_t;
typedef long __kernel_ssize_t;
typedef long __kernel_ptrdiff_t;
typedef unsigned long __kernel_sigset_t; /* at least 32 bits */
typedef __kernel_uid_t __kernel_old_uid_t;
typedef __kernel_gid_t __kernel_old_gid_t;
typedef __kernel_uid_t __kernel_uid32_t;
typedef __kernel_gid_t __kernel_gid32_t;
#endif /* __s390x__ */
typedef struct { typedef struct {
#if defined(__KERNEL__) || defined(__USE_ALL) #if defined(__KERNEL__) || defined(__USE_ALL)
......
...@@ -44,6 +44,9 @@ struct cpuinfo_S390 ...@@ -44,6 +44,9 @@ struct cpuinfo_S390
__u16 cpu_nr; __u16 cpu_nr;
unsigned long loops_per_jiffy; unsigned long loops_per_jiffy;
unsigned long *pgd_quick; unsigned long *pgd_quick;
#ifdef __s390x__
unsigned long *pmd_quick;
#endif /* __s390x__ */
unsigned long *pte_quick; unsigned long *pte_quick;
unsigned long pgtable_cache_sz; unsigned long pgtable_cache_sz;
}; };
...@@ -54,58 +57,90 @@ extern void print_cpu_info(struct cpuinfo_S390 *); ...@@ -54,58 +57,90 @@ extern void print_cpu_info(struct cpuinfo_S390 *);
extern struct task_struct *last_task_used_math; extern struct task_struct *last_task_used_math;
/* /*
* User space process size: 2GB (default). * User space process size: 2GB for 31 bit, 4TB for 64 bit.
*/ */
#define TASK_SIZE (0x80000000) #ifndef __s390x__
/* This decides where the kernel will search for a free chunk of vm
* space during mmap's. # define TASK_SIZE (0x80000000UL)
*/ # define TASK_UNMAPPED_BASE (TASK_SIZE / 2)
#define TASK_UNMAPPED_BASE (TASK_SIZE / 2)
#else /* __s390x__ */
# define TASK_SIZE (0x20000000000UL)
# define TASK31_SIZE (0x80000000UL)
# define TASK_UNMAPPED_BASE (test_thread_flag(TIF_31BIT) ? \
(TASK31_SIZE / 2) : (TASK_SIZE / 2))
#endif /* __s390x__ */
typedef struct { typedef struct {
__u32 ar4; __u32 ar4;
} mm_segment_t; } mm_segment_t;
/* if you change the thread_struct structure, you must /*
* update the _TSS_* defines in entry.S * Thread structure
*/ */
struct thread_struct {
struct thread_struct
{
s390_fp_regs fp_regs; s390_fp_regs fp_regs;
__u32 ar2; /* kernel access register 2 */ unsigned int ar2; /* kernel access register 2 */
__u32 ar4; /* kernel access register 4 */ unsigned int ar4; /* kernel access register 4 */
__u32 ksp; /* kernel stack pointer */ unsigned long ksp; /* kernel stack pointer */
__u32 user_seg; /* HSTD */ unsigned long user_seg; /* HSTD */
__u32 error_code; /* error-code of last prog-excep. */ unsigned long prot_addr; /* address of protection-excep. */
__u32 prot_addr; /* address of protection-excep. */ unsigned int error_code; /* error-code of last prog-excep. */
__u32 trap_no; unsigned int trap_no;
per_struct per_info;/* Must be aligned on an 4 byte boundary*/ per_struct per_info;
/* Used to give failing instruction back to user for ieee exceptions */ /* Used to give failing instruction back to user for ieee exceptions */
addr_t ieee_instruction_pointer; unsigned long ieee_instruction_pointer;
/* pfault_wait is used to block the process on a pfault event */ /* pfault_wait is used to block the process on a pfault event */
addr_t pfault_wait; unsigned long pfault_wait;
}; };
typedef struct thread_struct thread_struct; typedef struct thread_struct thread_struct;
#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}, \ #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, \
sizeof(init_stack) + (__u32) &init_stack, \ sizeof(init_stack) + (unsigned long) &init_stack, \
(__pa((__u32) &swapper_pg_dir[0]) + _SEGMENT_TABLE),\ __SWAPPER_PG_DIR, \
0,0,0, \ 0,0,0, \
(per_struct) {{{{0,}}},0,0,0,0,{{0,}}}, \ (per_struct) {{{{0,}}},0,0,0,0,{{0,}}}, \
0, 0 \ 0, 0 \
} }
/* need to define ... */ /*
* Do necessary setup to start up a new thread.
*/
#ifndef __s390x__
#define start_thread(regs, new_psw, new_stackp) do { \ #define start_thread(regs, new_psw, new_stackp) do { \
regs->psw.mask = PSW_USER_BITS; \ regs->psw.mask = PSW_USER_BITS; \
regs->psw.addr = new_psw | PSW_ADDR_AMODE31; \ regs->psw.addr = new_psw | PSW_ADDR_AMODE; \
regs->gprs[15] = new_stackp ; \ regs->gprs[15] = new_stackp ; \
} while (0) } while (0)
#else /* __s390x__ */
#define start_thread(regs, new_psw, new_stackp) do { \
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; \
regs->psw.addr = new_psw; \
regs->gprs[15] = new_stackp; \
} while (0)
#endif /* __s390x__ */
/* Forward declaration, a strange C thing */ /* Forward declaration, a strange C thing */
struct task_struct; struct task_struct;
struct mm_struct; struct mm_struct;
...@@ -129,14 +164,19 @@ extern char *task_show_regs(struct task_struct *task, char *buffer); ...@@ -129,14 +164,19 @@ extern char *task_show_regs(struct task_struct *task, char *buffer);
unsigned long get_wchan(struct task_struct *p); unsigned long get_wchan(struct task_struct *p);
#define __KSTK_PTREGS(tsk) ((struct pt_regs *) \ #define __KSTK_PTREGS(tsk) ((struct pt_regs *) \
(((addr_t) tsk->thread_info + THREAD_SIZE - sizeof(struct pt_regs)) & -8L)) (((unsigned long) tsk->thread_info + THREAD_SIZE - sizeof(struct pt_regs)) & -8L))
#define KSTK_EIP(tsk) (__KSTK_PTREGS(tsk)->psw.addr) #define KSTK_EIP(tsk) (__KSTK_PTREGS(tsk)->psw.addr)
#define KSTK_ESP(tsk) (__KSTK_PTREGS(tsk)->gprs[15]) #define KSTK_ESP(tsk) (__KSTK_PTREGS(tsk)->gprs[15])
/* /*
* Give up the time slice of the virtual PU. * Give up the time slice of the virtual PU.
*/ */
#define cpu_relax() asm volatile ("diag 0,0,68" : : : "memory") #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__ */
/* /*
* Set PSW mask to specified value, while leaving the * Set PSW mask to specified value, while leaving the
...@@ -150,6 +190,7 @@ static inline void __load_psw_mask (unsigned long mask) ...@@ -150,6 +190,7 @@ static inline void __load_psw_mask (unsigned long mask)
psw_t psw; psw_t psw;
psw.mask = mask; psw.mask = mask;
#ifndef __s390x__
asm volatile ( asm volatile (
" basr %0,0\n" " basr %0,0\n"
"0: ahi %0,1f-0b\n" "0: ahi %0,1f-0b\n"
...@@ -157,6 +198,14 @@ static inline void __load_psw_mask (unsigned long mask) ...@@ -157,6 +198,14 @@ static inline void __load_psw_mask (unsigned long mask)
" lpsw 0(%1)\n" " lpsw 0(%1)\n"
"1:" "1:"
: "=&d" (addr) : "a" (&psw) : "memory", "cc" ); : "=&d" (addr) : "a" (&psw) : "memory", "cc" );
#else /* __s390x__ */
asm volatile (
" larl %0,1f\n"
" stg %0,8(%1)\n"
" lpswe 0(%1)\n"
"1:"
: "=&d" (addr) : "a" (&psw) : "memory", "cc" );
#endif /* __s390x__ */
} }
/* /*
...@@ -169,6 +218,7 @@ static inline void enabled_wait(void) ...@@ -169,6 +218,7 @@ static inline void enabled_wait(void)
wait_psw.mask = PSW_BASE_BITS | PSW_MASK_IO | PSW_MASK_EXT | wait_psw.mask = PSW_BASE_BITS | PSW_MASK_IO | PSW_MASK_EXT |
PSW_MASK_MCHECK | PSW_MASK_WAIT; PSW_MASK_MCHECK | PSW_MASK_WAIT;
#ifndef __s390x__
asm volatile ( asm volatile (
" basr %0,0\n" " basr %0,0\n"
"0: la %0,1f-0b(%0)\n" "0: la %0,1f-0b(%0)\n"
...@@ -177,6 +227,14 @@ static inline void enabled_wait(void) ...@@ -177,6 +227,14 @@ static inline void enabled_wait(void)
" lpsw 0(%1)\n" " lpsw 0(%1)\n"
"1:" "1:"
: "=&a" (reg) : "a" (&wait_psw) : "memory", "cc" ); : "=&a" (reg) : "a" (&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) : "memory", "cc" );
#endif /* __s390x__ */
} }
/* /*
...@@ -196,7 +254,7 @@ static inline void disabled_wait(unsigned long code) ...@@ -196,7 +254,7 @@ static inline void disabled_wait(unsigned long code)
* Store status and then load disabled wait psw, * Store status and then load disabled wait psw,
* the processor is dead afterwards * the processor is dead afterwards
*/ */
#ifndef __s390x__
asm volatile (" stctl 0,0,0(%1)\n" asm volatile (" stctl 0,0,0(%1)\n"
" ni 0(%1),0xef\n" /* switch off protection */ " ni 0(%1),0xef\n" /* switch off protection */
" lctl 0,0,0(%1)\n" " lctl 0,0,0(%1)\n"
...@@ -213,6 +271,38 @@ static inline void disabled_wait(unsigned long code) ...@@ -213,6 +271,38 @@ static inline void disabled_wait(unsigned long code)
" oi 0(%1),0x10\n" /* fake protection bit */ " oi 0(%1),0x10\n" /* fake protection bit */
" lpsw 0(%0)" " lpsw 0(%0)"
: : "a" (dw_psw), "a" (&ctl_buf) : "cc" ); : : "a" (dw_psw), "a" (&ctl_buf) : "cc" );
#else /* __s390x__ */
asm volatile (" stctg 0,0,0(%1)\n"
" ni 4(%1),0xef\n" /* switch off protection */
" lctlg 0,0,0(%1)\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(%0)"
: : "a" (dw_psw), "a" (&ctl_buf) : "cc", "0", "1");
#endif /* __s390x__ */
} }
#endif #endif
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
* Offsets in the user_regs_struct. They are used for the ptrace * Offsets in the user_regs_struct. They are used for the ptrace
* system call and in entry.S * system call and in entry.S
*/ */
#ifndef __s390x__
#define PT_PSWMASK 0x00 #define PT_PSWMASK 0x00
#define PT_PSWADDR 0x04 #define PT_PSWADDR 0x04
#define PT_GPR0 0x08 #define PT_GPR0 0x08
...@@ -92,18 +94,89 @@ ...@@ -92,18 +94,89 @@
#define PT_LASTOFF PT_IEEE_IP #define PT_LASTOFF PT_IEEE_IP
#define PT_ENDREGS 0x140-1 #define PT_ENDREGS 0x140-1
#define GPR_SIZE 4
#define CR_SIZE 4
#define STACK_FRAME_OVERHEAD 96 /* size of minimum stack frame */
#else /* __s390x__ */
#define PT_PSWMASK 0x00
#define PT_PSWADDR 0x08
#define PT_GPR0 0x10
#define PT_GPR1 0x18
#define PT_GPR2 0x20
#define PT_GPR3 0x28
#define PT_GPR4 0x30
#define PT_GPR5 0x38
#define PT_GPR6 0x40
#define PT_GPR7 0x48
#define PT_GPR8 0x50
#define PT_GPR9 0x58
#define PT_GPR10 0x60
#define PT_GPR11 0x68
#define PT_GPR12 0x70
#define PT_GPR13 0x78
#define PT_GPR14 0x80
#define PT_GPR15 0x88
#define PT_ACR0 0x90
#define PT_ACR1 0x94
#define PT_ACR2 0x98
#define PT_ACR3 0x9C
#define PT_ACR4 0xA0
#define PT_ACR5 0xA4
#define PT_ACR6 0xA8
#define PT_ACR7 0xAC
#define PT_ACR8 0xB0
#define PT_ACR9 0xB4
#define PT_ACR10 0xB8
#define PT_ACR11 0xBC
#define PT_ACR12 0xC0
#define PT_ACR13 0xC4
#define PT_ACR14 0xC8
#define PT_ACR15 0xCC
#define PT_ORIGGPR2 0xD0
#define PT_FPC 0xD8
#define PT_FPR0 0xE0
#define PT_FPR1 0xE8
#define PT_FPR2 0xF0
#define PT_FPR3 0xF8
#define PT_FPR4 0x100
#define PT_FPR5 0x108
#define PT_FPR6 0x110
#define PT_FPR7 0x118
#define PT_FPR8 0x120
#define PT_FPR9 0x128
#define PT_FPR10 0x130
#define PT_FPR11 0x138
#define PT_FPR12 0x140
#define PT_FPR13 0x148
#define PT_FPR14 0x150
#define PT_FPR15 0x158
#define PT_CR_9 0x160
#define PT_CR_10 0x168
#define PT_CR_11 0x170
#define PT_IEEE_IP 0x1A8
#define PT_LASTOFF PT_IEEE_IP
#define PT_ENDREGS 0x1B0-1
#define GPR_SIZE 8
#define CR_SIZE 8
#define STACK_FRAME_OVERHEAD 160 /* size of minimum stack frame */
#endif /* __s390x__ */
#define NUM_GPRS 16 #define NUM_GPRS 16
#define NUM_FPRS 16 #define NUM_FPRS 16
#define NUM_CRS 16 #define NUM_CRS 16
#define NUM_ACRS 16 #define NUM_ACRS 16
#define GPR_SIZE 4
#define FPR_SIZE 8 #define FPR_SIZE 8
#define FPC_SIZE 4 #define FPC_SIZE 4
#define FPC_PAD_SIZE 4 /* gcc insists on aligning the fpregs */ #define FPC_PAD_SIZE 4 /* gcc insists on aligning the fpregs */
#define CR_SIZE 4
#define ACR_SIZE 4 #define ACR_SIZE 4
#define STACK_FRAME_OVERHEAD 96 /* size of minimum stack frame */
#define PTRACE_OLDSETOPTIONS 21 #define PTRACE_OLDSETOPTIONS 21
...@@ -113,13 +186,39 @@ ...@@ -113,13 +186,39 @@
#include <linux/types.h> #include <linux/types.h>
#include <asm/setup.h> #include <asm/setup.h>
typedef union
{
float f;
double d;
__u64 ui;
struct
{
__u32 hi;
__u32 lo;
} fp;
} freg_t;
typedef struct
{
__u32 fpc;
freg_t fprs[NUM_FPRS];
} s390_fp_regs;
#define FPC_EXCEPTION_MASK 0xF8000000
#define FPC_FLAGS_MASK 0x00F80000
#define FPC_DXC_MASK 0x0000FF00
#define FPC_RM_MASK 0x00000003
#define FPC_VALID_MASK 0xF8F8FF03
/* this typedef defines how a Program Status Word looks like */ /* this typedef defines how a Program Status Word looks like */
typedef struct typedef struct
{ {
__u32 mask; unsigned long mask;
__u32 addr; unsigned long addr;
} __attribute__ ((aligned(8))) psw_t; } __attribute__ ((aligned(8))) psw_t;
#ifndef __s390x__
#define PSW_MASK_PER 0x40000000UL #define PSW_MASK_PER 0x40000000UL
#define PSW_MASK_DAT 0x04000000UL #define PSW_MASK_DAT 0x04000000UL
#define PSW_MASK_IO 0x02000000UL #define PSW_MASK_IO 0x02000000UL
...@@ -132,7 +231,7 @@ typedef struct ...@@ -132,7 +231,7 @@ typedef struct
#define PSW_MASK_CC 0x00003000UL #define PSW_MASK_CC 0x00003000UL
#define PSW_MASK_PM 0x00000F00UL #define PSW_MASK_PM 0x00000F00UL
#define PSW_ADDR_AMODE31 0x80000000UL #define PSW_ADDR_AMODE 0x80000000UL
#define PSW_ADDR_INSN 0x7FFFFFFFUL #define PSW_ADDR_INSN 0x7FFFFFFFUL
#define PSW_BASE_BITS 0x00080000UL #define PSW_BASE_BITS 0x00080000UL
...@@ -142,34 +241,41 @@ typedef struct ...@@ -142,34 +241,41 @@ typedef struct
#define PSW_ASC_SECONDARY 0x00008000UL #define PSW_ASC_SECONDARY 0x00008000UL
#define PSW_ASC_HOME 0x0000C000UL #define PSW_ASC_HOME 0x0000C000UL
#define PSW_KERNEL_BITS (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY) #else /* __s390x__ */
#define PSW_USER_BITS (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME | \
#define PSW_MASK_PER 0x4000000000000000UL
#define PSW_MASK_DAT 0x0400000000000000UL
#define PSW_MASK_IO 0x0200000000000000UL
#define PSW_MASK_EXT 0x0100000000000000UL
#define PSW_MASK_KEY 0x00F0000000000000UL
#define PSW_MASK_MCHECK 0x0004000000000000UL
#define PSW_MASK_WAIT 0x0002000000000000UL
#define PSW_MASK_PSTATE 0x0001000000000000UL
#define PSW_MASK_ASC 0x0000C00000000000UL
#define PSW_MASK_CC 0x0000300000000000UL
#define PSW_MASK_PM 0x00000F0000000000UL
#define PSW_ADDR_AMODE 0x0000000000000000UL
#define PSW_ADDR_INSN 0xFFFFFFFFFFFFFFFFUL
#define PSW_BASE_BITS 0x0000000180000000UL
#define PSW_BASE32_BITS 0x0000000080000000UL
#define PSW_ASC_PRIMARY 0x0000000000000000UL
#define PSW_ASC_ACCREG 0x0000400000000000UL
#define PSW_ASC_SECONDARY 0x0000800000000000UL
#define PSW_ASC_HOME 0x0000C00000000000UL
#define PSW_USER32_BITS (PSW_BASE32_BITS | PSW_MASK_DAT | PSW_ASC_HOME | \
PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | \ PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | \
PSW_MASK_PSTATE) PSW_MASK_PSTATE)
typedef union #endif /* __s390x__ */
{
float f;
double d;
__u64 ui;
struct
{
__u32 hi;
__u32 lo;
} fp;
} freg_t;
typedef struct #define PSW_KERNEL_BITS (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY)
{ #define PSW_USER_BITS (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME | \
__u32 fpc; PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | \
freg_t fprs[NUM_FPRS]; PSW_MASK_PSTATE)
} s390_fp_regs;
#define FPC_EXCEPTION_MASK 0xF8000000
#define FPC_FLAGS_MASK 0x00F80000
#define FPC_DXC_MASK 0x0000FF00
#define FPC_RM_MASK 0x00000003
#define FPC_VALID_MASK 0xF8F8FF03
/* /*
* The first entries in pt_regs and user_regs_struct * The first entries in pt_regs and user_regs_struct
...@@ -180,9 +286,9 @@ typedef struct ...@@ -180,9 +286,9 @@ typedef struct
typedef struct typedef struct
{ {
psw_t psw; psw_t psw;
__u32 gprs[NUM_GPRS]; unsigned long gprs[NUM_GPRS];
__u32 acrs[NUM_ACRS]; unsigned int acrs[NUM_ACRS];
__u32 orig_gpr2; unsigned long orig_gpr2;
} s390_regs; } s390_regs;
/* /*
...@@ -192,24 +298,27 @@ typedef struct ...@@ -192,24 +298,27 @@ typedef struct
struct pt_regs struct pt_regs
{ {
psw_t psw; psw_t psw;
__u32 gprs[NUM_GPRS]; unsigned long gprs[NUM_GPRS];
__u32 acrs[NUM_ACRS]; unsigned int acrs[NUM_ACRS];
__u32 orig_gpr2; unsigned long orig_gpr2;
__u32 trap; unsigned int trap;
}; } __attribute__ ((packed));
/* /*
* Now for the program event recording (trace) definitions. * Now for the program event recording (trace) definitions.
*/ */
typedef struct typedef struct
{ {
__u32 cr[3]; unsigned long cr[3];
} per_cr_words; } per_cr_words;
#define PER_EM_MASK 0xE8000000 #define PER_EM_MASK 0xE8000000UL
typedef struct typedef struct
{ {
#ifdef __s390x__
unsigned : 32;
#endif /* __s390x__ */
unsigned em_branching : 1; unsigned em_branching : 1;
unsigned em_instruction_fetch : 1; unsigned em_instruction_fetch : 1;
/* /*
...@@ -224,33 +333,34 @@ typedef struct ...@@ -224,33 +333,34 @@ typedef struct
unsigned : 1; unsigned : 1;
unsigned storage_alt_space_ctl : 1; unsigned storage_alt_space_ctl : 1;
unsigned : 21; unsigned : 21;
addr_t starting_addr; unsigned long starting_addr;
addr_t ending_addr; unsigned long ending_addr;
} per_cr_bits; } per_cr_bits;
typedef struct typedef struct
{ {
__u16 perc_atmid; /* 0x096 */ unsigned short perc_atmid;
__u32 address; /* 0x098 */ unsigned long address;
__u8 access_id; /* 0x0a1 */ unsigned char access_id;
} per_lowcore_words; } per_lowcore_words;
typedef struct typedef struct
{ {
unsigned perc_branching : 1; /* 0x096 */ unsigned perc_branching : 1;
unsigned perc_instruction_fetch : 1; unsigned perc_instruction_fetch : 1;
unsigned perc_storage_alteration : 1; unsigned perc_storage_alteration : 1;
unsigned perc_gpr_alt_unused : 1; unsigned perc_gpr_alt_unused : 1;
unsigned perc_store_real_address : 1; unsigned perc_store_real_address : 1;
unsigned : 4; unsigned : 3;
unsigned atmid_psw_bit_31 : 1;
unsigned atmid_validity_bit : 1; unsigned atmid_validity_bit : 1;
unsigned atmid_psw_bit_32 : 1; unsigned atmid_psw_bit_32 : 1;
unsigned atmid_psw_bit_5 : 1; unsigned atmid_psw_bit_5 : 1;
unsigned atmid_psw_bit_16 : 1; unsigned atmid_psw_bit_16 : 1;
unsigned atmid_psw_bit_17 : 1; unsigned atmid_psw_bit_17 : 1;
unsigned si : 2; unsigned si : 2;
addr_t address; /* 0x098 */ unsigned long address;
unsigned : 4; /* 0x0a1 */ unsigned : 4;
unsigned access_id : 4; unsigned access_id : 4;
} per_lowcore_bits; } per_lowcore_bits;
...@@ -272,8 +382,8 @@ typedef struct ...@@ -272,8 +382,8 @@ typedef struct
* These addresses are copied into cr10 & cr11 if single * These addresses are copied into cr10 & cr11 if single
* stepping is switched off * stepping is switched off
*/ */
__u32 starting_addr; unsigned long starting_addr;
__u32 ending_addr; unsigned long ending_addr;
union { union {
per_lowcore_words words; per_lowcore_words words;
per_lowcore_bits bits; per_lowcore_bits bits;
...@@ -282,9 +392,9 @@ typedef struct ...@@ -282,9 +392,9 @@ typedef struct
typedef struct typedef struct
{ {
__u32 len; unsigned int len;
addr_t kernel_addr; unsigned long kernel_addr;
addr_t process_addr; unsigned long process_addr;
} ptrace_area; } ptrace_area;
/* /*
...@@ -313,8 +423,8 @@ typedef enum ...@@ -313,8 +423,8 @@ typedef enum
typedef struct typedef struct
{ {
addr_t lowaddr; unsigned long lowaddr;
addr_t hiaddr; unsigned long hiaddr;
ptprot_flags prot; ptprot_flags prot;
} ptprot_area; } ptprot_area;
...@@ -331,9 +441,9 @@ typedef struct ...@@ -331,9 +441,9 @@ typedef struct
struct user_regs_struct struct user_regs_struct
{ {
psw_t psw; psw_t psw;
__u32 gprs[NUM_GPRS]; unsigned long gprs[NUM_GPRS];
__u32 acrs[NUM_ACRS]; unsigned int acrs[NUM_ACRS];
__u32 orig_gpr2; unsigned long orig_gpr2;
s390_fp_regs fp_regs; s390_fp_regs fp_regs;
/* /*
* These per registers are in here so that gdb can modify them * These per registers are in here so that gdb can modify them
...@@ -341,13 +451,13 @@ struct user_regs_struct ...@@ -341,13 +451,13 @@ struct user_regs_struct
* watchpoints. This is the way intel does it. * watchpoints. This is the way intel does it.
*/ */
per_struct per_info; per_struct per_info;
addr_t ieee_instruction_pointer; unsigned long ieee_instruction_pointer;
/* Used to give failing instruction back to user for ieee exceptions */ /* Used to give failing instruction back to user for ieee exceptions */
}; };
#ifdef __KERNEL__ #ifdef __KERNEL__
#define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0) #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
#define instruction_pointer(regs) ((regs)->psw.addr & PSW_MASK_INSN) #define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN)
extern void show_regs(struct pt_regs * regs); extern void show_regs(struct pt_regs * regs);
#endif #endif
......
...@@ -20,9 +20,9 @@ ...@@ -20,9 +20,9 @@
#define QDIO_NAME "qdio " #define QDIO_NAME "qdio "
#ifndef CONFIG_ARCH_S390X #ifndef __s390x__
#define QDIO_32_BIT #define QDIO_32_BIT
#endif /* CONFIG_ARCH_S390X */ #endif /* __s390x__ */
/**** CONSTANTS, that are relied on without using these symbols *****/ /**** CONSTANTS, that are relied on without using these symbols *****/
#define QDIO_MAX_QUEUES_PER_IRQ 32 /* used in width of unsigned int */ #define QDIO_MAX_QUEUES_PER_IRQ 32 /* used in width of unsigned int */
......
...@@ -63,10 +63,17 @@ struct rw_semaphore { ...@@ -63,10 +63,17 @@ struct rw_semaphore {
struct list_head wait_list; struct list_head wait_list;
}; };
#ifndef __s390x__
#define RWSEM_UNLOCKED_VALUE 0x00000000 #define RWSEM_UNLOCKED_VALUE 0x00000000
#define RWSEM_ACTIVE_BIAS 0x00000001 #define RWSEM_ACTIVE_BIAS 0x00000001
#define RWSEM_ACTIVE_MASK 0x0000ffff #define RWSEM_ACTIVE_MASK 0x0000ffff
#define RWSEM_WAITING_BIAS (-0x00010000) #define RWSEM_WAITING_BIAS (-0x00010000)
#else /* __s390x__ */
#define RWSEM_UNLOCKED_VALUE 0x0000000000000000L
#define RWSEM_ACTIVE_BIAS 0x0000000000000001L
#define RWSEM_ACTIVE_MASK 0x00000000ffffffffL
#define RWSEM_WAITING_BIAS (-0x0000000100000000L)
#endif /* __s390x__ */
#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS #define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS
#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) #define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
...@@ -94,11 +101,19 @@ static inline void __down_read(struct rw_semaphore *sem) ...@@ -94,11 +101,19 @@ static inline void __down_read(struct rw_semaphore *sem)
signed long old, new; signed long old, new;
__asm__ __volatile__( __asm__ __volatile__(
#ifndef __s390x__
" l %0,0(%2)\n" " l %0,0(%2)\n"
"0: lr %1,%0\n" "0: lr %1,%0\n"
" ahi %1,%3\n" " ahi %1,%3\n"
" cs %0,%1,0(%2)\n" " cs %0,%1,0(%2)\n"
" jl 0b" " jl 0b"
#else /* __s390x__ */
" lg %0,0(%2)\n"
"0: lgr %1,%0\n"
" aghi %1,%3\n"
" csg %0,%1,0(%2)\n"
" jl 0b"
#endif /* __s390x__ */
: "=&d" (old), "=&d" (new) : "=&d" (old), "=&d" (new)
: "a" (&sem->count), "i" (RWSEM_ACTIVE_READ_BIAS) : "a" (&sem->count), "i" (RWSEM_ACTIVE_READ_BIAS)
: "cc", "memory" ); : "cc", "memory" );
...@@ -114,6 +129,7 @@ static inline int __down_read_trylock(struct rw_semaphore *sem) ...@@ -114,6 +129,7 @@ static inline int __down_read_trylock(struct rw_semaphore *sem)
signed long old, new; signed long old, new;
__asm__ __volatile__( __asm__ __volatile__(
#ifndef __s390x__
" l %0,0(%2)\n" " l %0,0(%2)\n"
"0: ltr %1,%0\n" "0: ltr %1,%0\n"
" jm 1f\n" " jm 1f\n"
...@@ -121,6 +137,15 @@ static inline int __down_read_trylock(struct rw_semaphore *sem) ...@@ -121,6 +137,15 @@ static inline int __down_read_trylock(struct rw_semaphore *sem)
" cs %0,%1,0(%2)\n" " cs %0,%1,0(%2)\n"
" jl 0b\n" " jl 0b\n"
"1:" "1:"
#else /* __s390x__ */
" lg %0,0(%2)\n"
"0: ltgr %1,%0\n"
" jm 1f\n"
" aghi %1,%3\n"
" csg %0,%1,0(%2)\n"
" jl 0b\n"
"1:"
#endif /* __s390x__ */
: "=&d" (old), "=&d" (new) : "=&d" (old), "=&d" (new)
: "a" (&sem->count), "i" (RWSEM_ACTIVE_READ_BIAS) : "a" (&sem->count), "i" (RWSEM_ACTIVE_READ_BIAS)
: "cc", "memory" ); : "cc", "memory" );
...@@ -136,11 +161,19 @@ static inline void __down_write(struct rw_semaphore *sem) ...@@ -136,11 +161,19 @@ static inline void __down_write(struct rw_semaphore *sem)
tmp = RWSEM_ACTIVE_WRITE_BIAS; tmp = RWSEM_ACTIVE_WRITE_BIAS;
__asm__ __volatile__( __asm__ __volatile__(
#ifndef __s390x__
" l %0,0(%2)\n" " l %0,0(%2)\n"
"0: lr %1,%0\n" "0: lr %1,%0\n"
" a %1,%3\n" " a %1,%3\n"
" cs %0,%1,0(%2)\n" " cs %0,%1,0(%2)\n"
" jl 0b" " jl 0b"
#else /* __s390x__ */
" lg %0,0(%2)\n"
"0: lgr %1,%0\n"
" ag %1,%3\n"
" csg %0,%1,0(%2)\n"
" jl 0b"
#endif /* __s390x__ */
: "=&d" (old), "=&d" (new) : "=&d" (old), "=&d" (new)
: "a" (&sem->count), "m" (tmp) : "a" (&sem->count), "m" (tmp)
: "cc", "memory" ); : "cc", "memory" );
...@@ -156,11 +189,19 @@ static inline int __down_write_trylock(struct rw_semaphore *sem) ...@@ -156,11 +189,19 @@ static inline int __down_write_trylock(struct rw_semaphore *sem)
signed long old; signed long old;
__asm__ __volatile__( __asm__ __volatile__(
#ifndef __s390x__
" l %0,0(%1)\n" " l %0,0(%1)\n"
"0: ltr %0,%0\n" "0: ltr %0,%0\n"
" jnz 1f\n" " jnz 1f\n"
" cs %0,%2,0(%1)\n" " cs %0,%2,0(%1)\n"
" jl 0b\n" " jl 0b\n"
#else /* __s390x__ */
" lg %0,0(%1)\n"
"0: ltgr %0,%0\n"
" jnz 1f\n"
" csg %0,%2,0(%1)\n"
" jl 0b\n"
#endif /* __s390x__ */
"1:" "1:"
: "=&d" (old) : "=&d" (old)
: "a" (&sem->count), "d" (RWSEM_ACTIVE_WRITE_BIAS) : "a" (&sem->count), "d" (RWSEM_ACTIVE_WRITE_BIAS)
...@@ -176,11 +217,19 @@ static inline void __up_read(struct rw_semaphore *sem) ...@@ -176,11 +217,19 @@ static inline void __up_read(struct rw_semaphore *sem)
signed long old, new; signed long old, new;
__asm__ __volatile__( __asm__ __volatile__(
#ifndef __s390x__
" l %0,0(%2)\n" " l %0,0(%2)\n"
"0: lr %1,%0\n" "0: lr %1,%0\n"
" ahi %1,%3\n" " ahi %1,%3\n"
" cs %0,%1,0(%2)\n" " cs %0,%1,0(%2)\n"
" jl 0b" " jl 0b"
#else /* __s390x__ */
" lg %0,0(%2)\n"
"0: lgr %1,%0\n"
" aghi %1,%3\n"
" csg %0,%1,0(%2)\n"
" jl 0b"
#endif /* __s390x__ */
: "=&d" (old), "=&d" (new) : "=&d" (old), "=&d" (new)
: "a" (&sem->count), "i" (-RWSEM_ACTIVE_READ_BIAS) : "a" (&sem->count), "i" (-RWSEM_ACTIVE_READ_BIAS)
: "cc", "memory" ); : "cc", "memory" );
...@@ -198,11 +247,19 @@ static inline void __up_write(struct rw_semaphore *sem) ...@@ -198,11 +247,19 @@ static inline void __up_write(struct rw_semaphore *sem)
tmp = -RWSEM_ACTIVE_WRITE_BIAS; tmp = -RWSEM_ACTIVE_WRITE_BIAS;
__asm__ __volatile__( __asm__ __volatile__(
#ifndef __s390x__
" l %0,0(%2)\n" " l %0,0(%2)\n"
"0: lr %1,%0\n" "0: lr %1,%0\n"
" a %1,%3\n" " a %1,%3\n"
" cs %0,%1,0(%2)\n" " cs %0,%1,0(%2)\n"
" jl 0b" " jl 0b"
#else /* __s390x__ */
" lg %0,0(%2)\n"
"0: lgr %1,%0\n"
" ag %1,%3\n"
" csg %0,%1,0(%2)\n"
" jl 0b"
#endif /* __s390x__ */
: "=&d" (old), "=&d" (new) : "=&d" (old), "=&d" (new)
: "a" (&sem->count), "m" (tmp) : "a" (&sem->count), "m" (tmp)
: "cc", "memory" ); : "cc", "memory" );
...@@ -220,11 +277,19 @@ static inline void __downgrade_write(struct rw_semaphore *sem) ...@@ -220,11 +277,19 @@ static inline void __downgrade_write(struct rw_semaphore *sem)
tmp = -RWSEM_WAITING_BIAS; tmp = -RWSEM_WAITING_BIAS;
__asm__ __volatile__( __asm__ __volatile__(
#ifndef __s390x__
" l %0,0(%2)\n" " l %0,0(%2)\n"
"0: lr %1,%0\n" "0: lr %1,%0\n"
" a %1,%3\n" " a %1,%3\n"
" cs %0,%1,0(%2)\n" " cs %0,%1,0(%2)\n"
" jl 0b" " jl 0b"
#else /* __s390x__ */
" lg %0,0(%2)\n"
"0: lgr %1,%0\n"
" ag %1,%3\n"
" csg %0,%1,0(%2)\n"
" jl 0b"
#endif /* __s390x__ */
: "=&d" (old), "=&d" (new) : "=&d" (old), "=&d" (new)
: "a" (&sem->count), "m" (tmp) : "a" (&sem->count), "m" (tmp)
: "cc", "memory" ); : "cc", "memory" );
...@@ -240,11 +305,19 @@ static inline void rwsem_atomic_add(long delta, struct rw_semaphore *sem) ...@@ -240,11 +305,19 @@ static inline void rwsem_atomic_add(long delta, struct rw_semaphore *sem)
signed long old, new; signed long old, new;
__asm__ __volatile__( __asm__ __volatile__(
#ifndef __s390x__
" l %0,0(%2)\n" " l %0,0(%2)\n"
"0: lr %1,%0\n" "0: lr %1,%0\n"
" ar %1,%3\n" " ar %1,%3\n"
" cs %0,%1,0(%2)\n" " cs %0,%1,0(%2)\n"
" jl 0b" " jl 0b"
#else /* __s390x__ */
" lg %0,0(%2)\n"
"0: lgr %1,%0\n"
" agr %1,%3\n"
" csg %0,%1,0(%2)\n"
" jl 0b"
#endif /* __s390x__ */
: "=&d" (old), "=&d" (new) : "=&d" (old), "=&d" (new)
: "a" (&sem->count), "d" (delta) : "a" (&sem->count), "d" (delta)
: "cc", "memory" ); : "cc", "memory" );
...@@ -258,11 +331,19 @@ static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem) ...@@ -258,11 +331,19 @@ static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem)
signed long old, new; signed long old, new;
__asm__ __volatile__( __asm__ __volatile__(
#ifndef __s390x__
" l %0,0(%2)\n" " l %0,0(%2)\n"
"0: lr %1,%0\n" "0: lr %1,%0\n"
" ar %1,%3\n" " ar %1,%3\n"
" cs %0,%1,0(%2)\n" " cs %0,%1,0(%2)\n"
" jl 0b" " jl 0b"
#else /* __s390x__ */
" lg %0,0(%2)\n"
"0: lgr %1,%0\n"
" agr %1,%3\n"
" csg %0,%1,0(%2)\n"
" jl 0b"
#endif /* __s390x__ */
: "=&d" (old), "=&d" (new) : "=&d" (old), "=&d" (new)
: "a" (&sem->count), "d" (delta) : "a" (&sem->count), "d" (delta)
: "cc", "memory" ); : "cc", "memory" );
......
...@@ -7,16 +7,20 @@ ...@@ -7,16 +7,20 @@
* between kernel and user space. * between kernel and user space.
* *
* Pad space is left for: * Pad space is left for:
* - 64-bit time_t to solve y2038 problem * - 64-bit time_t to solve y2038 problem (for !__s390x__)
* - 2 miscellaneous 32-bit values * - 2 miscellaneous 32-bit values
*/ */
struct semid64_ds { struct semid64_ds {
struct ipc64_perm sem_perm; /* permissions .. see ipc.h */ struct ipc64_perm sem_perm; /* permissions .. see ipc.h */
__kernel_time_t sem_otime; /* last semop time */ __kernel_time_t sem_otime; /* last semop time */
#ifndef __s390x__
unsigned long __unused1; unsigned long __unused1;
#endif /* ! __s390x__ */
__kernel_time_t sem_ctime; /* last change time */ __kernel_time_t sem_ctime; /* last change time */
#ifndef __s390x__
unsigned long __unused2; unsigned long __unused2;
#endif /* ! __s390x__ */
unsigned long sem_nsems; /* no. of semaphores in array */ unsigned long sem_nsems; /* no. of semaphores in array */
unsigned long __unused3; unsigned long __unused3;
unsigned long __unused4; unsigned long __unused4;
......
...@@ -15,9 +15,15 @@ ...@@ -15,9 +15,15 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#ifndef __s390x__
#define IPL_DEVICE (*(unsigned long *) (0x10404)) #define IPL_DEVICE (*(unsigned long *) (0x10404))
#define INITRD_START (*(unsigned long *) (0x1040C)) #define INITRD_START (*(unsigned long *) (0x1040C))
#define INITRD_SIZE (*(unsigned long *) (0x10414)) #define INITRD_SIZE (*(unsigned long *) (0x10414))
#else /* __s390x__ */
#define IPL_DEVICE (*(unsigned long *) (0x10400))
#define INITRD_START (*(unsigned long *) (0x10408))
#define INITRD_SIZE (*(unsigned long *) (0x10410))
#endif /* __s390x__ */
#define COMMAND_LINE ((char *) (0x10480)) #define COMMAND_LINE ((char *) (0x10480))
/* /*
...@@ -26,10 +32,18 @@ ...@@ -26,10 +32,18 @@
extern unsigned long machine_flags; extern unsigned long machine_flags;
#define MACHINE_IS_VM (machine_flags & 1) #define MACHINE_IS_VM (machine_flags & 1)
#define MACHINE_HAS_IEEE (machine_flags & 2)
#define MACHINE_IS_P390 (machine_flags & 4) #define MACHINE_IS_P390 (machine_flags & 4)
#define MACHINE_HAS_CSP (machine_flags & 8)
#define MACHINE_HAS_MVPG (machine_flags & 16) #define MACHINE_HAS_MVPG (machine_flags & 16)
#define MACHINE_HAS_DIAG44 (machine_flags & 32)
#ifndef __s390x__
#define MACHINE_HAS_IEEE (machine_flags & 2)
#define MACHINE_HAS_CSP (machine_flags & 8)
#else /* __s390x__ */
#define MACHINE_HAS_IEEE (1)
#define MACHINE_HAS_CSP (1)
#endif /* __s390x__ */
#define MACHINE_HAS_SCLP (!MACHINE_IS_P390) #define MACHINE_HAS_SCLP (!MACHINE_IS_P390)
...@@ -50,9 +64,15 @@ extern unsigned int console_irq; ...@@ -50,9 +64,15 @@ extern unsigned int console_irq;
#else #else
#ifndef __s390x__
#define IPL_DEVICE 0x10404 #define IPL_DEVICE 0x10404
#define INITRD_START 0x1040C #define INITRD_START 0x1040C
#define INITRD_SIZE 0x10414 #define INITRD_SIZE 0x10414
#else /* __s390x__ */
#define IPL_DEVICE 0x10400
#define INITRD_START 0x10408
#define INITRD_SIZE 0x10410
#endif /* __s390x__ */
#define COMMAND_LINE 0x10480 #define COMMAND_LINE 0x10480
#endif #endif
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* between kernel and user space. * between kernel and user space.
* *
* Pad space is left for: * Pad space is left for:
* - 64-bit time_t to solve y2038 problem * - 64-bit time_t to solve y2038 problem (for !__s390x__)
* - 2 miscellaneous 32-bit values * - 2 miscellaneous 32-bit values
*/ */
...@@ -15,11 +15,17 @@ struct shmid64_ds { ...@@ -15,11 +15,17 @@ struct shmid64_ds {
struct ipc64_perm shm_perm; /* operation perms */ struct ipc64_perm shm_perm; /* operation perms */
size_t shm_segsz; /* size of segment (bytes) */ size_t shm_segsz; /* size of segment (bytes) */
__kernel_time_t shm_atime; /* last attach time */ __kernel_time_t shm_atime; /* last attach time */
#ifndef __s390x__
unsigned long __unused1; unsigned long __unused1;
#endif /* ! __s390x__ */
__kernel_time_t shm_dtime; /* last detach time */ __kernel_time_t shm_dtime; /* last detach time */
#ifndef __s390x__
unsigned long __unused2; unsigned long __unused2;
#endif /* ! __s390x__ */
__kernel_time_t shm_ctime; /* last change time */ __kernel_time_t shm_ctime; /* last change time */
#ifndef __s390x__
unsigned long __unused3; unsigned long __unused3;
#endif /* ! __s390x__ */
__kernel_pid_t shm_cpid; /* pid of creator */ __kernel_pid_t shm_cpid; /* pid of creator */
__kernel_pid_t shm_lpid; /* pid of last operator */ __kernel_pid_t shm_lpid; /* pid of last operator */
unsigned long shm_nattch; /* no. of current attaches */ unsigned long shm_nattch; /* no. of current attaches */
......
...@@ -12,13 +12,24 @@ ...@@ -12,13 +12,24 @@
#define __NUM_FPRS 16 #define __NUM_FPRS 16
#define __NUM_ACRS 16 #define __NUM_ACRS 16
/* #ifndef __s390x__
Has to be at least _NSIG_WORDS from asm/signal.h
*/ /* Has to be at least _NSIG_WORDS from asm/signal.h */
#define _SIGCONTEXT_NSIG 64 #define _SIGCONTEXT_NSIG 64
#define _SIGCONTEXT_NSIG_BPW 32 #define _SIGCONTEXT_NSIG_BPW 32
/* Size of stack frame allocated when calling signal handler. */ /* Size of stack frame allocated when calling signal handler. */
#define __SIGNAL_FRAMESIZE 96 #define __SIGNAL_FRAMESIZE 96
#else /* __s390x__ */
/* Has to be at least _NSIG_WORDS from asm/signal.h */
#define _SIGCONTEXT_NSIG 64
#define _SIGCONTEXT_NSIG_BPW 64
/* Size of stack frame allocated when calling signal handler. */
#define __SIGNAL_FRAMESIZE 160
#endif /* __s390x__ */
#define _SIGCONTEXT_NSIG_WORDS (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW) #define _SIGCONTEXT_NSIG_WORDS (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW)
#define _SIGMASK_COPY_SIZE (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS) #define _SIGMASK_COPY_SIZE (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS)
......
...@@ -171,9 +171,15 @@ struct sigaction { ...@@ -171,9 +171,15 @@ struct sigaction {
__sighandler_t _sa_handler; __sighandler_t _sa_handler;
void (*_sa_sigaction)(int, struct siginfo *, void *); void (*_sa_sigaction)(int, struct siginfo *, void *);
} _u; } _u;
#ifndef __s390x__ /* lovely */
sigset_t sa_mask; sigset_t sa_mask;
unsigned long sa_flags; unsigned long sa_flags;
void (*sa_restorer)(void); void (*sa_restorer)(void);
#else /* __s390x__ */
unsigned long sa_flags;
void (*sa_restorer)(void);
sigset_t sa_mask;
#endif /* __s390x__ */
}; };
#define sa_handler _u._sa_handler #define sa_handler _u._sa_handler
......
...@@ -72,10 +72,17 @@ signal_processor(__u16 cpu_addr, sigp_order_code order_code) ...@@ -72,10 +72,17 @@ signal_processor(__u16 cpu_addr, sigp_order_code order_code)
sigp_ccode ccode; sigp_ccode ccode;
__asm__ __volatile__( __asm__ __volatile__(
#ifndef __s390x__
" sr 1,1\n" /* parameter=0 in gpr 1 */ " sr 1,1\n" /* parameter=0 in gpr 1 */
" sigp 1,%1,0(%2)\n" " sigp 1,%1,0(%2)\n"
" ipm %0\n" " ipm %0\n"
" srl %0,28\n" " srl %0,28\n"
#else /* __s390x__ */
" sgr 1,1\n" /* parameter=0 in gpr 1 */
" sigp 1,%1,0(%2)\n"
" ipm %0\n"
" srl %0,28"
#endif /* __s390x__ */
: "=d" (ccode) : "=d" (ccode)
: "d" (__cpu_logical_map[cpu_addr]), "a" (order_code) : "d" (__cpu_logical_map[cpu_addr]), "a" (order_code)
: "cc" , "memory", "1" ); : "cc" , "memory", "1" );
...@@ -86,15 +93,23 @@ signal_processor(__u16 cpu_addr, sigp_order_code order_code) ...@@ -86,15 +93,23 @@ signal_processor(__u16 cpu_addr, sigp_order_code order_code)
* Signal processor with parameter * Signal processor with parameter
*/ */
extern __inline__ sigp_ccode extern __inline__ sigp_ccode
signal_processor_p(__u32 parameter,__u16 cpu_addr,sigp_order_code order_code) signal_processor_p(unsigned long parameter,__u16 cpu_addr,
sigp_order_code order_code)
{ {
sigp_ccode ccode; sigp_ccode ccode;
__asm__ __volatile__( __asm__ __volatile__(
#ifndef __s390x__
" lr 1,%1\n" /* parameter in gpr 1 */ " lr 1,%1\n" /* parameter in gpr 1 */
" sigp 1,%2,0(%3)\n" " sigp 1,%2,0(%3)\n"
" ipm %0\n" " ipm %0\n"
" srl %0,28\n" " srl %0,28\n"
#else /* __s390x__ */
" lgr 1,%1\n" /* parameter in gpr 1 */
" sigp 1,%2,0(%3)\n"
" ipm %0\n"
" srl %0,28\n"
#endif /* __s390x__ */
: "=d" (ccode) : "=d" (ccode)
: "d" (parameter), "d" (__cpu_logical_map[cpu_addr]), : "d" (parameter), "d" (__cpu_logical_map[cpu_addr]),
"a" (order_code) "a" (order_code)
...@@ -106,18 +121,27 @@ signal_processor_p(__u32 parameter,__u16 cpu_addr,sigp_order_code order_code) ...@@ -106,18 +121,27 @@ signal_processor_p(__u32 parameter,__u16 cpu_addr,sigp_order_code order_code)
* Signal processor with parameter and return status * Signal processor with parameter and return status
*/ */
extern __inline__ sigp_ccode extern __inline__ sigp_ccode
signal_processor_ps(__u32 *statusptr, __u32 parameter, signal_processor_ps(__u32 *statusptr, unsigned long parameter,
__u16 cpu_addr, sigp_order_code order_code) __u16 cpu_addr, sigp_order_code order_code)
{ {
sigp_ccode ccode; sigp_ccode ccode;
__asm__ __volatile__( __asm__ __volatile__(
#ifndef __s390x__
" sr 2,2\n" /* clear status so it doesn't contain rubbish if not saved. */ " sr 2,2\n" /* clear status so it doesn't contain rubbish if not saved. */
" lr 3,%2\n" /* parameter in gpr 3 */ " lr 3,%2\n" /* parameter in gpr 3 */
" sigp 2,%3,0(%4)\n" " sigp 2,%3,0(%4)\n"
" st 2,%1\n" " st 2,%1\n"
" ipm %0\n" " ipm %0\n"
" srl %0,28\n" " srl %0,28\n"
#else /* __s390x__ */
" sgr 2,2\n" /* clear status so it doesn't contain rubbish if not saved. */
" lgr 3,%2\n" /* parameter in gpr 3 */
" sigp 2,%3,0(%4)\n"
" stg 2,%1\n"
" ipm %0\n"
" srl %0,28\n"
#endif /* __s390x__ */
: "=d" (ccode), "=m" (*statusptr) : "=d" (ccode), "=m" (*statusptr)
: "d" (parameter), "d" (__cpu_logical_map[cpu_addr]), : "d" (parameter), "d" (__cpu_logical_map[cpu_addr]),
"a" (order_code) "a" (order_code)
......
...@@ -52,7 +52,11 @@ extern volatile unsigned long cpu_possible_map; ...@@ -52,7 +52,11 @@ extern volatile unsigned long cpu_possible_map;
extern inline unsigned int num_online_cpus(void) extern inline unsigned int num_online_cpus(void)
{ {
#ifndef __s390x__
return hweight32(cpu_online_map); return hweight32(cpu_online_map);
#else /* __s390x__ */
return hweight64(cpu_online_map);
#endif /* __s390x__ */
} }
extern inline int any_online_cpu(unsigned int mask) extern inline int any_online_cpu(unsigned int mask)
......
...@@ -11,6 +11,22 @@ ...@@ -11,6 +11,22 @@
#ifndef __ASM_SPINLOCK_H #ifndef __ASM_SPINLOCK_H
#define __ASM_SPINLOCK_H #define __ASM_SPINLOCK_H
#ifdef __s390x__
/*
* Grmph, take care of %&#! user space programs that include
* asm/spinlock.h. The diagnose is only available in kernel
* context.
*/
#ifdef __KERNEL__
#include <asm/lowcore.h>
#define __DIAG44_INSN "ex"
#define __DIAG44_OPERAND __LC_DIAG44_OPCODE
#else
#define __DIAG44_INSN "#"
#define __DIAG44_OPERAND 0
#endif
#endif /* __s390x__ */
/* /*
* Simple spin lock operations. There are two variants, one clears IRQ's * Simple spin lock operations. There are two variants, one clears IRQ's
* on the local processor, one does not. * on the local processor, one does not.
...@@ -19,8 +35,13 @@ ...@@ -19,8 +35,13 @@
*/ */
typedef struct { typedef struct {
#ifndef __s390x__
volatile unsigned long lock; volatile unsigned long lock;
} spinlock_t; } spinlock_t;
#else /* __s390x__ */
volatile unsigned int lock;
} __attribute__ ((aligned (4))) spinlock_t;
#endif /* __s390x__ */
#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
#define spin_lock_init(lp) do { (lp)->lock = 0; } while(0) #define spin_lock_init(lp) do { (lp)->lock = 0; } while(0)
...@@ -29,6 +50,7 @@ typedef struct { ...@@ -29,6 +50,7 @@ typedef struct {
extern inline void _raw_spin_lock(spinlock_t *lp) extern inline void _raw_spin_lock(spinlock_t *lp)
{ {
#ifndef __s390x__
unsigned int reg1, reg2; unsigned int reg1, reg2;
__asm__ __volatile(" bras %0,1f\n" __asm__ __volatile(" bras %0,1f\n"
"0: diag 0,0,68\n" "0: diag 0,0,68\n"
...@@ -37,11 +59,26 @@ extern inline void _raw_spin_lock(spinlock_t *lp) ...@@ -37,11 +59,26 @@ extern inline void _raw_spin_lock(spinlock_t *lp)
" jl 0b\n" " jl 0b\n"
: "=&d" (reg1), "=&d" (reg2), "+m" (lp->lock) : "=&d" (reg1), "=&d" (reg2), "+m" (lp->lock)
: "a" (&lp->lock) : "cc" ); : "a" (&lp->lock) : "cc" );
#else /* __s390x__ */
unsigned long reg1, reg2;
__asm__ __volatile(" bras %1,1f\n"
"0: " __DIAG44_INSN " 0,%4\n"
"1: slr %0,%0\n"
" cs %0,%1,0(%3)\n"
" jl 0b\n"
: "=&d" (reg1), "=&d" (reg2), "+m" (lp->lock)
: "a" (&lp->lock), "i" (__DIAG44_OPERAND)
: "cc" );
#endif /* __s390x__ */
} }
extern inline int _raw_spin_trylock(spinlock_t *lp) extern inline int _raw_spin_trylock(spinlock_t *lp)
{ {
#ifndef __s390x__
unsigned long result, reg; unsigned long result, reg;
#else /* __s390x__ */
unsigned int result, reg;
#endif /* __s390x__ */
__asm__ __volatile(" slr %0,%0\n" __asm__ __volatile(" slr %0,%0\n"
" basr %1,0\n" " basr %1,0\n"
"0: cs %0,%1,0(%3)" "0: cs %0,%1,0(%3)"
...@@ -80,6 +117,7 @@ typedef struct { ...@@ -80,6 +117,7 @@ typedef struct {
#define rwlock_is_locked(x) ((x)->lock != 0) #define rwlock_is_locked(x) ((x)->lock != 0)
#ifndef __s390x__
#define _raw_read_lock(rw) \ #define _raw_read_lock(rw) \
asm volatile(" l 2,0(%1)\n" \ asm volatile(" l 2,0(%1)\n" \
" j 1f\n" \ " j 1f\n" \
...@@ -90,7 +128,21 @@ typedef struct { ...@@ -90,7 +128,21 @@ typedef struct {
" jl 0b" \ " jl 0b" \
: "+m" ((rw)->lock) : "a" (&(rw)->lock) \ : "+m" ((rw)->lock) : "a" (&(rw)->lock) \
: "2", "3", "cc" ) : "2", "3", "cc" )
#else /* __s390x__ */
#define _raw_read_lock(rw) \
asm volatile(" lg 2,0(%1)\n" \
" j 1f\n" \
"0: " __DIAG44_INSN " 0,%2\n" \
"1: nihh 2,0x7fff\n" /* clear high (=write) bit */ \
" la 3,1(2)\n" /* one more reader */ \
" csg 2,3,0(%1)\n" /* try to write new value */ \
" jl 0b" \
: "+m" ((rw)->lock) \
: "a" (&(rw)->lock), "i" (__DIAG44_OPERAND) \
: "2", "3", "cc" )
#endif /* __s390x__ */
#ifndef __s390x__
#define _raw_read_unlock(rw) \ #define _raw_read_unlock(rw) \
asm volatile(" l 2,0(%1)\n" \ asm volatile(" l 2,0(%1)\n" \
" j 1f\n" \ " j 1f\n" \
...@@ -101,7 +153,21 @@ typedef struct { ...@@ -101,7 +153,21 @@ typedef struct {
" jl 0b" \ " jl 0b" \
: "+m" ((rw)->lock) : "a" (&(rw)->lock) \ : "+m" ((rw)->lock) : "a" (&(rw)->lock) \
: "2", "3", "cc" ) : "2", "3", "cc" )
#else /* __s390x__ */
#define _raw_read_unlock(rw) \
asm volatile(" lg 2,0(%1)\n" \
" j 1f\n" \
"0: " __DIAG44_INSN " 0,%2\n" \
"1: lgr 3,2\n" \
" bctgr 3,0\n" /* one less reader */ \
" csg 2,3,0(%1)\n" \
" jl 0b" \
: "+m" ((rw)->lock) \
: "a" (&(rw)->lock), "i" (__DIAG44_OPERAND) \
: "2", "3", "cc" )
#endif /* __s390x__ */
#ifndef __s390x__
#define _raw_write_lock(rw) \ #define _raw_write_lock(rw) \
asm volatile(" lhi 3,1\n" \ asm volatile(" lhi 3,1\n" \
" sll 3,31\n" /* new lock value = 0x80000000 */ \ " sll 3,31\n" /* new lock value = 0x80000000 */ \
...@@ -112,7 +178,20 @@ typedef struct { ...@@ -112,7 +178,20 @@ typedef struct {
" jl 0b" \ " jl 0b" \
: "+m" ((rw)->lock) : "a" (&(rw)->lock) \ : "+m" ((rw)->lock) : "a" (&(rw)->lock) \
: "2", "3", "cc" ) : "2", "3", "cc" )
#else /* __s390x__ */
#define _raw_write_lock(rw) \
asm volatile(" llihh 3,0x8000\n" /* new lock value = 0x80...0 */ \
" j 1f\n" \
"0: " __DIAG44_INSN " 0,%2\n" \
"1: slgr 2,2\n" /* old lock value must be 0 */ \
" csg 2,3,0(%1)\n" \
" jl 0b" \
: "+m" ((rw)->lock) \
: "a" (&(rw)->lock), "i" (__DIAG44_OPERAND) \
: "2", "3", "cc" )
#endif /* __s390x__ */
#ifndef __s390x__
#define _raw_write_unlock(rw) \ #define _raw_write_unlock(rw) \
asm volatile(" slr 3,3\n" /* new lock value = 0 */ \ asm volatile(" slr 3,3\n" /* new lock value = 0 */ \
" j 1f\n" \ " j 1f\n" \
...@@ -123,15 +202,34 @@ typedef struct { ...@@ -123,15 +202,34 @@ typedef struct {
" jl 0b" \ " jl 0b" \
: "+m" ((rw)->lock) : "a" (&(rw)->lock) \ : "+m" ((rw)->lock) : "a" (&(rw)->lock) \
: "2", "3", "cc" ) : "2", "3", "cc" )
#else /* __s390x__ */
#define _raw_write_unlock(rw) \
asm volatile(" slgr 3,3\n" /* new lock value = 0 */ \
" j 1f\n" \
"0: " __DIAG44_INSN " 0,%2\n" \
"1: llihh 2,0x8000\n" /* old lock value must be 0x8..0 */\
" csg 2,3,0(%1)\n" \
" jl 0b" \
: "+m" ((rw)->lock) \
: "a" (&(rw)->lock), "i" (__DIAG44_OPERAND) \
: "2", "3", "cc" )
#endif /* __s390x__ */
extern inline int _raw_write_trylock(rwlock_t *rw) extern inline int _raw_write_trylock(rwlock_t *rw)
{ {
unsigned int result, reg; unsigned int result, reg;
__asm__ __volatile__(" lhi %0,1\n" __asm__ __volatile__(
#ifndef __s390x__
" lhi %0,1\n"
" sll %0,31\n" " sll %0,31\n"
" basr %1,0\n" " basr %1,0\n"
"0: cs %0,%1,0(%3)\n" "0: cs %0,%1,0(%3)\n"
#else /* __s390x__ */
" llihh %0,0x8000\n"
" basr %1,0\n"
"0: csg %0,%1,0(%3)\n"
#endif /* __s390x__ */
: "=&d" (result), "=&d" (reg), "+m" (rw->lock) : "=&d" (result), "=&d" (reg), "+m" (rw->lock)
: "a" (&rw->lock) : "cc" ); : "a" (&rw->lock) : "cc" );
return !result; return !result;
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#ifndef _S390_STAT_H #ifndef _S390_STAT_H
#define _S390_STAT_H #define _S390_STAT_H
#ifndef __s390x__
struct __old_kernel_stat { struct __old_kernel_stat {
unsigned short st_dev; unsigned short st_dev;
unsigned short st_ino; unsigned short st_ino;
...@@ -46,8 +47,6 @@ struct stat { ...@@ -46,8 +47,6 @@ struct stat {
unsigned long __unused5; unsigned long __unused5;
}; };
#define STAT_HAVE_NSEC 1
/* This matches struct stat64 in glibc2.1, hence the absolutely /* This matches struct stat64 in glibc2.1, hence the absolutely
* insane amounts of padding around dev_t's. * insane amounts of padding around dev_t's.
*/ */
...@@ -76,4 +75,31 @@ struct stat64 { ...@@ -76,4 +75,31 @@ struct stat64 {
unsigned long long st_ino; unsigned long long st_ino;
}; };
#else /* __s390x__ */
struct stat {
unsigned long st_dev;
unsigned long st_ino;
unsigned long st_nlink;
unsigned int st_mode;
unsigned int st_uid;
unsigned int st_gid;
unsigned int __pad1;
unsigned long st_rdev;
unsigned long st_size;
unsigned long st_atime;
unsigned long st_atime_nsec;
unsigned long st_mtime;
unsigned long st_mtime_nsec;
unsigned long st_ctime;
unsigned long st_ctime_nsec;
unsigned long st_blksize;
long st_blocks;
unsigned long __unused[3];
};
#endif /* __s390x__ */
#define STAT_HAVE_NSEC 1
#endif #endif
...@@ -18,6 +18,7 @@ typedef __kernel_fsid_t fsid_t; ...@@ -18,6 +18,7 @@ typedef __kernel_fsid_t fsid_t;
#endif #endif
struct statfs { struct statfs {
#ifndef __s390x__
long f_type; long f_type;
long f_bsize; long f_bsize;
long f_blocks; long f_blocks;
...@@ -28,6 +29,18 @@ struct statfs { ...@@ -28,6 +29,18 @@ struct statfs {
__kernel_fsid_t f_fsid; __kernel_fsid_t f_fsid;
long f_namelen; long f_namelen;
long f_spare[6]; long f_spare[6];
#else /* __s390x__ */
int f_type;
int f_bsize;
long f_blocks;
long f_bfree;
long f_bavail;
long f_files;
long f_ffree;
__kernel_fsid_t f_fsid;
int f_namelen;
int f_spare[6];
#endif /* __s390x__ */
}; };
#endif #endif
...@@ -49,13 +49,24 @@ static inline void * memchr(const void * cs,int c,size_t count) ...@@ -49,13 +49,24 @@ static inline void * memchr(const void * cs,int c,size_t count)
{ {
void *ptr; void *ptr;
__asm__ __volatile__ (" lr 0,%2\n" __asm__ __volatile__ (
#ifndef __s390x__
" lr 0,%2\n"
" lr 1,%1\n" " lr 1,%1\n"
" la %0,0(%3,%1)\n" " la %0,0(%3,%1)\n"
"0: srst %0,1\n" "0: srst %0,1\n"
" jo 0b\n" " jo 0b\n"
" brc 13,1f\n" " brc 13,1f\n"
" slr %0,%0\n" " slr %0,%0\n"
#else /* __s390x__ */
" lgr 0,%2\n"
" lgr 1,%1\n"
" la %0,0(%3,%1)\n"
"0: srst %0,1\n"
" jo 0b\n"
" brc 13,1f\n"
" slgr %0,%0\n"
#endif /* __s390x__ */
"1:" "1:"
: "=&a" (ptr) : "a" (cs), "d" (c), "d" (count) : "=&a" (ptr) : "a" (cs), "d" (c), "d" (count)
: "cc", "0", "1" ); : "cc", "0", "1" );
...@@ -66,9 +77,16 @@ static __inline__ char *strcpy(char *dest, const char *src) ...@@ -66,9 +77,16 @@ static __inline__ char *strcpy(char *dest, const char *src)
{ {
char *tmp = dest; char *tmp = dest;
__asm__ __volatile__ (" sr 0,0\n" __asm__ __volatile__ (
#ifndef __s390x__
" sr 0,0\n"
"0: mvst %0,%1\n" "0: mvst %0,%1\n"
" jo 0b" " jo 0b"
#else /* __s390x__ */
" slgr 0,0\n"
"0: mvst %0,%1\n"
" jo 0b"
#endif /* __s390x__ */
: "+&a" (dest), "+&a" (src) : : "+&a" (dest), "+&a" (src) :
: "cc", "memory", "0" ); : "cc", "memory", "0" );
return tmp; return tmp;
...@@ -78,12 +96,22 @@ static __inline__ size_t strlen(const char *s) ...@@ -78,12 +96,22 @@ static __inline__ size_t strlen(const char *s)
{ {
size_t len; size_t len;
__asm__ __volatile__ (" sr 0,0\n" __asm__ __volatile__ (
#ifndef __s390x__
" sr 0,0\n"
" lr %0,%1\n" " lr %0,%1\n"
"0: srst 0,%0\n" "0: srst 0,%0\n"
" jo 0b\n" " jo 0b\n"
" lr %0,0\n" " lr %0,0\n"
" sr %0,%1" " sr %0,%1"
#else /* __s390x__ */
" slgr 0,0\n"
" lgr %0,%1\n"
"0: srst 0,%0\n"
" jo 0b\n"
" lgr %0,0\n"
" sgr %0,%1"
#endif /* __s390x__ */
: "=&a" (len) : "a" (s) : "=&a" (len) : "a" (s)
: "cc", "0" ); : "cc", "0" );
return len; return len;
...@@ -93,25 +121,30 @@ static __inline__ char *strcat(char *dest, const char *src) ...@@ -93,25 +121,30 @@ static __inline__ char *strcat(char *dest, const char *src)
{ {
char *tmp = dest; char *tmp = dest;
__asm__ __volatile__ (" sr 0,0\n" __asm__ __volatile__ (
#ifndef __s390x__
" sr 0,0\n"
"0: srst 0,%0\n" "0: srst 0,%0\n"
" jo 0b\n" " jo 0b\n"
" lr %0,0\n" " lr %0,0\n"
" sr 0,0\n" " sr 0,0\n"
"1: mvst %0,%1\n" "1: mvst %0,%1\n"
" jo 1b" " jo 1b"
#else /* __s390x__ */
" slgr 0,0\n"
"0: srst 0,%0\n"
" jo 0b\n"
" lgr %0,0\n"
" slgr 0,0\n"
"1: mvst %0,%1\n"
" jo 1b"
#endif /* __s390x__ */
: "+&a" (dest), "+&a" (src) : : "+&a" (dest), "+&a" (src) :
: "cc", "memory", "0" ); : "cc", "memory", "0" );
return tmp; return tmp;
} }
extern void *alloca(size_t); extern void *alloca(size_t);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* __S390_STRING_H_ */ #endif /* __S390_STRING_H_ */
...@@ -23,6 +23,15 @@ struct task_struct; ...@@ -23,6 +23,15 @@ struct task_struct;
extern struct task_struct *resume(void *, void *); extern struct task_struct *resume(void *, void *);
#ifdef __s390x__
#define __FLAG_SHIFT 56
extern void __misaligned_u16(void);
extern void __misaligned_u32(void);
extern void __misaligned_u64(void);
#else /* __s390x__ */
#define __FLAG_SHIFT 24
#endif /* __s390x__ */
static inline void save_fp_regs(s390_fp_regs *fpregs) static inline void save_fp_regs(s390_fp_regs *fpregs)
{ {
asm volatile ( asm volatile (
...@@ -88,7 +97,7 @@ static inline void restore_fp_regs(s390_fp_regs *fpregs) ...@@ -88,7 +97,7 @@ static inline void restore_fp_regs(s390_fp_regs *fpregs)
#define nop() __asm__ __volatile__ ("nop") #define nop() __asm__ __volatile__ ("nop")
#define xchg(ptr,x) \ #define xchg(ptr,x) \
((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(void *)(ptr),sizeof(*(ptr))))
static inline unsigned long __xchg(unsigned long x, void * ptr, int size) static inline unsigned long __xchg(unsigned long x, void * ptr, int size)
{ {
...@@ -137,6 +146,17 @@ static inline unsigned long __xchg(unsigned long x, void * ptr, int size) ...@@ -137,6 +146,17 @@ static inline unsigned long __xchg(unsigned long x, void * ptr, int size)
: "memory", "cc", "0" ); : "memory", "cc", "0" );
x = old; x = old;
break; break;
#ifdef __s390x__
case 8:
asm volatile (
" lg %0,0(%2)\n"
"0: csg %0,%1,0(%2)\n"
" jl 0b\n"
: "=&d" (old) : "d" (x), "a" (ptr)
: "memory", "cc", "0" );
x = old;
break;
#endif /* __s390x__ */
} }
return x; return x;
} }
...@@ -208,6 +228,14 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) ...@@ -208,6 +228,14 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
: "=&d" (prev) : "0" (old), "d" (new), "a" (ptr) : "=&d" (prev) : "0" (old), "d" (new), "a" (ptr)
: "memory", "cc" ); : "memory", "cc" );
return prev; return prev;
#ifdef __s390x__
case 8:
asm volatile (
" csg %0,%2,0(%3)\n"
: "=&d" (prev) : "0" (old), "d" (new), "a" (ptr)
: "memory", "cc" );
return prev;
#endif /* __s390x__ */
} }
return old; return old;
} }
...@@ -241,15 +269,15 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) ...@@ -241,15 +269,15 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
/* interrupt control.. */ /* interrupt control.. */
#define local_irq_enable() ({ \ #define local_irq_enable() ({ \
__u8 __dummy; \ unsigned long __dummy; \
__asm__ __volatile__ ( \ __asm__ __volatile__ ( \
"stosm 0(%1),0x03" : "=m" (__dummy) : "a" (&__dummy) ); \ "stosm 0(%1),0x03" : "=m" (__dummy) : "a" (&__dummy) ); \
}) })
#define local_irq_disable() ({ \ #define local_irq_disable() ({ \
__u32 __flags; \ unsigned long __flags; \
__asm__ __volatile__ ( \ __asm__ __volatile__ ( \
"stnsm 0(%1),0xFC" : "=m" (__flags) : "a" (&__flags) ); \ "stnsm 0(%1),0xfc" : "=m" (__flags) : "a" (&__flags) ); \
__flags; \ __flags; \
}) })
...@@ -263,9 +291,70 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) ...@@ -263,9 +291,70 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
({ \ ({ \
unsigned long flags; \ unsigned long flags; \
local_save_flags(flags); \ local_save_flags(flags); \
!((flags >> 24) & 3); \ !((flags >> __FLAG_SHIFT) & 3); \
}) })
#ifdef __s390x__
#define __load_psw(psw) \
__asm__ __volatile__("lpswe 0(%0)" : : "a" (&psw) : "cc" );
#define __ctl_load(array, low, high) ({ \
__asm__ __volatile__ ( \
" la 1,%0\n" \
" bras 2,0f\n" \
" lctlg 0,0,0(1)\n" \
"0: ex %1,0(2)" \
: : "m" (array), "a" (((low)<<4)+(high)) : "1", "2" ); \
})
#define __ctl_store(array, low, high) ({ \
__asm__ __volatile__ ( \
" la 1,%0\n" \
" bras 2,0f\n" \
" stctg 0,0,0(1)\n" \
"0: ex %1,0(2)" \
: "=m" (array) : "a" (((low)<<4)+(high)): "1", "2" ); \
})
#define __ctl_set_bit(cr, bit) ({ \
__u8 __dummy[24]; \
__asm__ __volatile__ ( \
" la 1,%0\n" /* align to 8 byte */ \
" aghi 1,7\n" \
" nill 1,0xfff8\n" \
" bras 2,0f\n" /* skip indirect insns */ \
" stctg 0,0,0(1)\n" \
" lctlg 0,0,0(1)\n" \
"0: ex %1,0(2)\n" /* execute stctl */ \
" lg 0,0(1)\n" \
" ogr 0,%2\n" /* set the bit */ \
" stg 0,0(1)\n" \
"1: ex %1,6(2)" /* execute lctl */ \
: "=m" (__dummy) : "a" (cr*17), "a" (1L<<(bit)) \
: "cc", "0", "1", "2"); \
})
#define __ctl_clear_bit(cr, bit) ({ \
__u8 __dummy[24]; \
__asm__ __volatile__ ( \
" la 1,%0\n" /* align to 8 byte */ \
" aghi 1,7\n" \
" nill 1,0xfff8\n" \
" bras 2,0f\n" /* skip indirect insns */ \
" stctg 0,0,0(1)\n" \
" lctlg 0,0,0(1)\n" \
"0: ex %1,0(2)\n" /* execute stctl */ \
" lg 0,0(1)\n" \
" ngr 0,%2\n" /* set the bit */ \
" stg 0,0(1)\n" \
"1: ex %1,6(2)" /* execute lctl */ \
: "=m" (__dummy) : "a" (cr*17), "a" (~(1L<<(bit))) \
: "cc", "0", "1", "2"); \
})
#else /* __s390x__ */
#define __load_psw(psw) \ #define __load_psw(psw) \
__asm__ __volatile__("lpsw 0(%0)" : : "a" (&psw) : "cc" ); __asm__ __volatile__("lpsw 0(%0)" : : "a" (&psw) : "cc" );
...@@ -324,6 +413,7 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) ...@@ -324,6 +413,7 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
: "=m" (__dummy) : "a" (cr*17), "a" (~(1<<(bit))) \ : "=m" (__dummy) : "a" (cr*17), "a" (~(1<<(bit))) \
: "cc", "0", "1", "2"); \ : "cc", "0", "1", "2"); \
}) })
#endif /* __s390x__ */
/* For spinlocks etc */ /* For spinlocks etc */
#define local_irq_save(x) ((x) = local_irq_disable()) #define local_irq_save(x) ((x) = local_irq_disable())
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/lowcore.h>
/* /*
* low level task data that entry.S needs immediate access to * low level task data that entry.S needs immediate access to
...@@ -46,26 +47,35 @@ struct thread_info { ...@@ -46,26 +47,35 @@ struct thread_info {
#define init_thread_info (init_thread_union.thread_info) #define init_thread_info (init_thread_union.thread_info)
#define init_stack (init_thread_union.stack) #define init_stack (init_thread_union.stack)
/*
* Size of kernel stack for each process
*/
#ifndef __s390x__
#define THREAD_ORDER 1
#define ASYNC_ORDER 1
#else /* __s390x__ */
#define THREAD_ORDER 2
#define ASYNC_ORDER 2
#endif /* __s390x__ */
#define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER)
#define ASYNC_SIZE (PAGE_SIZE << ASYNC_ORDER)
/* how to get the thread information struct from C */ /* how to get the thread information struct from C */
static inline struct thread_info *current_thread_info(void) static inline struct thread_info *current_thread_info(void)
{ {
return (struct thread_info *)((*(unsigned long *) 0xc40)-8192); return (struct thread_info *)((*(unsigned long *) __LC_KERNEL_STACK)-THREAD_SIZE);
} }
/* thread information allocation */ /* thread information allocation */
#define alloc_thread_info() ((struct thread_info *) \ #define alloc_thread_info() ((struct thread_info *) \
__get_free_pages(GFP_KERNEL,1)) __get_free_pages(GFP_KERNEL,THREAD_ORDER))
#define free_thread_info(ti) free_pages((unsigned long) (ti), 1) #define free_thread_info(ti) free_pages((unsigned long) (ti),THREAD_ORDER)
#define get_thread_info(ti) get_task_struct((ti)->task) #define get_thread_info(ti) get_task_struct((ti)->task)
#define put_thread_info(ti) put_task_struct((ti)->task) #define put_thread_info(ti) put_task_struct((ti)->task)
#endif #endif
/*
* Size of kernel stack for each process
*/
#define THREAD_SIZE (2*PAGE_SIZE)
/* /*
* thread information flags bit numbers * thread information flags bit numbers
*/ */
...@@ -77,6 +87,7 @@ static inline struct thread_info *current_thread_info(void) ...@@ -77,6 +87,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */ #define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */
#define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling #define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling
TIF_NEED_RESCHED */ TIF_NEED_RESCHED */
#define TIF_31BIT 18 /* 32bit process */
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) #define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
...@@ -85,6 +96,7 @@ static inline struct thread_info *current_thread_info(void) ...@@ -85,6 +96,7 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_RESTART_SVC (1<<TIF_RESTART_SVC) #define _TIF_RESTART_SVC (1<<TIF_RESTART_SVC)
#define _TIF_USEDFPU (1<<TIF_USEDFPU) #define _TIF_USEDFPU (1<<TIF_USEDFPU)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
#define _TIF_31BIT (1<<TIF_31BIT)
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
#define local_flush_tlb() \ #define local_flush_tlb() \
do { __asm__ __volatile__("ptlb": : :"memory"); } while (0) do { __asm__ __volatile__("ptlb": : :"memory"); } while (0)
#ifndef CONFIG_SMP #ifndef CONFIG_SMP
/* /*
...@@ -70,7 +69,13 @@ extern void smp_ptlb_all(void); ...@@ -70,7 +69,13 @@ extern void smp_ptlb_all(void);
static inline void global_flush_tlb(void) static inline void global_flush_tlb(void)
{ {
if (MACHINE_HAS_CSP) { #ifndef __s390x__
if (!MACHINE_HAS_CSP) {
smp_ptlb_all();
return;
}
#endif /* __s390x__ */
{
long dummy = 0; long dummy = 0;
__asm__ __volatile__ ( __asm__ __volatile__ (
" la 4,1(%0)\n" " la 4,1(%0)\n"
...@@ -78,8 +83,7 @@ static inline void global_flush_tlb(void) ...@@ -78,8 +83,7 @@ static inline void global_flush_tlb(void)
" slr 3,3\n" " slr 3,3\n"
" csp 2,4" " csp 2,4"
: : "a" (&dummy) : "cc", "2", "3", "4" ); : : "a" (&dummy) : "cc", "2", "3", "4" );
} else }
smp_ptlb_all();
} }
/* /*
......
...@@ -27,15 +27,21 @@ typedef unsigned short __u16; ...@@ -27,15 +27,21 @@ typedef unsigned short __u16;
typedef __signed__ int __s32; typedef __signed__ int __s32;
typedef unsigned int __u32; typedef unsigned int __u32;
#ifndef __s390x__
#if defined(__GNUC__) && !defined(__STRICT_ANSI__) #if defined(__GNUC__) && !defined(__STRICT_ANSI__)
typedef __signed__ long long __s64; typedef __signed__ long long __s64;
typedef unsigned long long __u64; typedef unsigned long long __u64;
#endif #endif
#else /* __s390x__ */
typedef __signed__ long __s64;
typedef unsigned long __u64;
#endif
/* A address type so that arithmetic can be done on it & it can be upgraded to /* A address type so that arithmetic can be done on it & it can be upgraded to
64 bit when necessary 64 bit when necessary
*/ */
typedef __u32 addr_t; typedef unsigned long addr_t;
typedef __s32 saddr_t; typedef __signed__ long saddr_t;
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
...@@ -44,7 +50,11 @@ typedef __s32 saddr_t; ...@@ -44,7 +50,11 @@ typedef __s32 saddr_t;
*/ */
#ifdef __KERNEL__ #ifdef __KERNEL__
#ifndef __s390x__
#define BITS_PER_LONG 32 #define BITS_PER_LONG 32
#else
#define BITS_PER_LONG 64
#endif
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
...@@ -57,11 +67,17 @@ typedef unsigned short u16; ...@@ -57,11 +67,17 @@ typedef unsigned short u16;
typedef signed int s32; typedef signed int s32;
typedef unsigned int u32; typedef unsigned int u32;
#ifndef __s390x__
typedef signed long long s64; typedef signed long long s64;
typedef unsigned long long u64; typedef unsigned long long u64;
#else /* __s390x__ */
typedef signed long s64;
typedef unsigned long u64;
#endif /* __s390x__ */
typedef u32 dma_addr_t; typedef u32 dma_addr_t;
#ifndef __s390x__
typedef union { typedef union {
unsigned long long pair; unsigned long long pair;
struct { struct {
...@@ -75,7 +91,7 @@ typedef u64 sector_t; ...@@ -75,7 +91,7 @@ typedef u64 sector_t;
#define HAVE_SECTOR_T #define HAVE_SECTOR_T
#endif #endif
#endif /* ! __s390x__ */
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif #endif /* _S390_TYPES_H */
This diff is collapsed.
...@@ -261,6 +261,91 @@ ...@@ -261,6 +261,91 @@
#define NR_syscalls 263 #define NR_syscalls 263
/*
* There are some system calls that are not present on 64 bit, some
* have a different name although they do the same (e.g. __NR_chown32
* is __NR_chown on 64 bit).
*/
#ifdef __s390x__
#undef __NR_time
#undef __NR_lchown
#undef __NR_setuid
#undef __NR_getuid
#undef __NR_stime
#undef __NR_setgid
#undef __NR_getgid
#undef __NR_geteuid
#undef __NR_getegid
#undef __NR_setreuid
#undef __NR_setregid
#undef __NR_getrlimit
#undef __NR_getgroups
#undef __NR_setgroups
#undef __NR_fchown
#undef __NR_ioperm
#undef __NR_setfsuid
#undef __NR_setfsgid
#undef __NR__llseek
#undef __NR__newselect
#undef __NR_setresuid
#undef __NR_getresuid
#undef __NR_setresgid
#undef __NR_getresgid
#undef __NR_chown
#undef __NR_ugetrlimit
#undef __NR_mmap2
#undef __NR_truncate64
#undef __NR_ftruncate64
#undef __NR_stat64
#undef __NR_lstat64
#undef __NR_fstat64
#undef __NR_lchown32
#undef __NR_getuid32
#undef __NR_getgid32
#undef __NR_geteuid32
#undef __NR_getegid32
#undef __NR_setreuid32
#undef __NR_setregid32
#undef __NR_getgroups32
#undef __NR_setgroups32
#undef __NR_fchown32
#undef __NR_setresuid32
#undef __NR_getresuid32
#undef __NR_setresgid32
#undef __NR_getresgid32
#undef __NR_chown32
#undef __NR_setuid32
#undef __NR_setgid32
#undef __NR_setfsuid32
#undef __NR_setfsgid32
#undef __NR_getdents64
#undef __NR_fcntl64
#undef __NR_sendfile64
#define __NR_select 142
#define __NR_getrlimit 191 /* SuS compliant getrlimit */
#define __NR_lchown 198
#define __NR_getuid 199
#define __NR_getgid 200
#define __NR_geteuid 201
#define __NR_getegid 202
#define __NR_setreuid 203
#define __NR_setregid 204
#define __NR_getgroups 205
#define __NR_setgroups 206
#define __NR_fchown 207
#define __NR_setresuid 208
#define __NR_getresuid 209
#define __NR_setresgid 210
#define __NR_getresgid 211
#define __NR_chown 212
#define __NR_setuid 213
#define __NR_setgid 214
#define __NR_setfsuid 215
#define __NR_setfsgid 216
#endif
/* user-visible error numbers are in the range -1 - -122: see <asm-s390/errno.h> */ /* user-visible error numbers are in the range -1 - -122: see <asm-s390/errno.h> */
#define __syscall_return(type, res) \ #define __syscall_return(type, res) \
...@@ -279,10 +364,10 @@ type name(void) { \ ...@@ -279,10 +364,10 @@ type name(void) { \
register long __svcres asm("2"); \ register long __svcres asm("2"); \
long __res; \ long __res; \
__asm__ __volatile__ ( \ __asm__ __volatile__ ( \
" .if %b1 < 256\n" \ " .if %1 < 256\n" \
" svc %b1\n" \ " svc %b1\n" \
" .else\n" \ " .else\n" \
" lhi %%r1,%b1\n" \ " la %%r1,%1\n" \
" svc 0\n" \ " svc 0\n" \
" .endif" \ " .endif" \
: "=d" (__svcres) \ : "=d" (__svcres) \
...@@ -298,10 +383,10 @@ type name(type1 arg1) { \ ...@@ -298,10 +383,10 @@ type name(type1 arg1) { \
register long __svcres asm("2"); \ register long __svcres asm("2"); \
long __res; \ long __res; \
__asm__ __volatile__ ( \ __asm__ __volatile__ ( \
" .if %b1 < 256\n" \ " .if %1 < 256\n" \
" svc %b1\n" \ " svc %b1\n" \
" .else\n" \ " .else\n" \
" lhi %%r1,%b1\n" \ " la %%r1,%1\n" \
" svc 0\n" \ " svc 0\n" \
" .endif" \ " .endif" \
: "=d" (__svcres) \ : "=d" (__svcres) \
...@@ -319,10 +404,10 @@ type name(type1 arg1, type2 arg2) { \ ...@@ -319,10 +404,10 @@ type name(type1 arg1, type2 arg2) { \
register long __svcres asm("2"); \ register long __svcres asm("2"); \
long __res; \ long __res; \
__asm__ __volatile__ ( \ __asm__ __volatile__ ( \
" .if %b1 < 256\n" \ " .if %1 < 256\n" \
" svc %b1\n" \ " svc %b1\n" \
" .else\n" \ " .else\n" \
" lhi %%r1,%b1\n" \ " la %%r1,%1\n" \
" svc 0\n" \ " svc 0\n" \
" .endif" \ " .endif" \
: "=d" (__svcres) \ : "=d" (__svcres) \
...@@ -342,10 +427,10 @@ type name(type1 arg1, type2 arg2, type3 arg3) { \ ...@@ -342,10 +427,10 @@ type name(type1 arg1, type2 arg2, type3 arg3) { \
register long __svcres asm("2"); \ register long __svcres asm("2"); \
long __res; \ long __res; \
__asm__ __volatile__ ( \ __asm__ __volatile__ ( \
" .if %b1 < 256\n" \ " .if %1 < 256\n" \
" svc %b1\n" \ " svc %b1\n" \
" .else\n" \ " .else\n" \
" lhi %%r1,%b1\n" \ " la %%r1,%1\n" \
" svc 0\n" \ " svc 0\n" \
" .endif" \ " .endif" \
: "=d" (__svcres) \ : "=d" (__svcres) \
...@@ -368,10 +453,10 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ ...@@ -368,10 +453,10 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
register long __svcres asm("2"); \ register long __svcres asm("2"); \
long __res; \ long __res; \
__asm__ __volatile__ ( \ __asm__ __volatile__ ( \
" .if %b1 < 256\n" \ " .if %1 < 256\n" \
" svc %b1\n" \ " svc %b1\n" \
" .else\n" \ " .else\n" \
" lhi %%r1,%b1\n" \ " la %%r1,%1\n" \
" svc 0\n" \ " svc 0\n" \
" .endif" \ " .endif" \
: "=d" (__svcres) \ : "=d" (__svcres) \
...@@ -397,10 +482,10 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ ...@@ -397,10 +482,10 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
register long __svcres asm("2"); \ register long __svcres asm("2"); \
long __res; \ long __res; \
__asm__ __volatile__ ( \ __asm__ __volatile__ ( \
" .if %b1 < 256\n" \ " .if %1 < 256\n" \
" svc %b1\n" \ " svc %b1\n" \
" .else\n" \ " .else\n" \
" lhi %%r1,%b1\n" \ " la %%r1,%1\n" \
" svc 0\n" \ " svc 0\n" \
" .endif" \ " .endif" \
: "=d" (__svcres) \ : "=d" (__svcres) \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment